Public feed #722199

Someone

public javascript v1 · immutable
Raw Edit
·published 2007-10-01 20:45 UTC
rendered paste body
/****************************************************************************** Bija - Javascript Library and Framework [B]ija [I]sn't [J]ust [A]jax  @author: 				Matan Lurey @version: 				1.1a @projectDescription: 	Bija is a multi-use, cross-browser JavaScript library 						which enables the use of advanced DOM and Networking 						techniques on a variety of systems. 						 						The reason that something like Mootools or Prototype 						is not used is to allow only the most efficient 						and needed code to be available. 						 						Fully Supported: 						- Firefox 2.0 (Gecko) 						- Netscape  (Gecko) 						- Safari 3  (WebKit 420) 						- Opera 9 						 						Fully Supported with Work-Arounds: 						- Konqueror (Interval-Based checking of Comet data) 						 						Untested, but Compatible: 						- Safari 2 (However, uses Konqueror's method of 'push' data) 						 						Pending Tests: 						- Internet Explorer 5.5 						- Internet Explorer 6 						- Internet Explorer 7*******************************************************************************/window.Bija = {	version: "1.10a"}/** Browser Detection - Tries a non-sniffing method, if possible. *************/var Browser = {	ie7:    (document.all && !window.opera && window.XMLHttpRequest),	ie6:    (document.all && !window.opera && !window.XMLHttpRequest),	ie5:    (document.all && !window.opera && document.appendData),	ie:     (document.all && !window.opera),	webkit: (document.childNodes && !document.all && !navigator.taintEnabled),	khtml:  (navigator.userAgent.indexOf('Konqueror' != -1)),	gecko:  (!!document.getBoxObjectFor),	opera:  (!!window.opera)}// Detect WebKit 420 (Safari 3 Beta) -------------------------------------------Browser.webkit420 = (Browser.webkit && document.evaluate);/** Class Prototyping - A new face for JavaScript OOP	Ideas from Prototype, Base, and Mootools		Creating a Class:      		new Class( <methods> )	Extending a Class:     		Class.Extend( <class> <methods> )	Creating an Interface: 		new Interface( arguments = method names )	Implementing an Interface:	myClass.Implement( <interface> )	Extending a Class Object:   myClass.Extend( <methods> )*//******************************************************************************	function: Extend		@param: destination [object]			the object to copy methods to	@param: source [object]			the object to copy methods from	@return: Object*******************************************************************************/function Extend(destination, source) {	if (!source && this) return Extend(this, destination);	var safeWrite = (arguments.length > 1);	for (method in source) 		if (!safeWrite || !destination[method])			destination[method] = source[method];	return destination;}/******************************************************************************	function: Implement		@param: object [object]			the object to try the interface's methods on	@param: iface [Interface]			the Interface object	@return: Object*******************************************************************************/function Implement(object, iface) {	if (!iface && this) return Impelement(this, object);	for (var i = 0; i < iface.length; i++)		if (!isFunction(object[iface[i]]) && !isFunction(object.prototype[iface[i]]))			throw new Error("Object does not implement method Object." + iface[i]);	return object;	}// Interfaces are constructed, and are identical to, Arrays --------------------var Interface = Array;/******************************************************************************	object: Class		@constructor:		@param: methods [object]			the object to copy methods from		@return: Class*******************************************************************************/function Class(methods) {	var Klass = Class.Empty();	Extend(Klass.prototype, methods);	return Klass;}/******************************************************************************	object: Class.Extend		@constructor:		@param: object  [class]			the base class (parent class)		@param: methods [object]			the object to copy methods from		@return: Class*******************************************************************************/Extend(Class, {	Extend: function(object, methods) {		var Klass = Class.Empty();		Klass.prototype.Super = Klass.prototype = object.prototype;		Extend(Klass.prototype, object);		return Klass;	},// Internally Used Function to Create a new 'Class' ----------------------------	Empty: function() {		return function() {			if (isFunction(this.init)) { this.init.apply(this, arguments); }		}	}});/******************************************************************************	object: Abstract		@constructor:		@param: object [object]			the object to give an abstract to, allowing it to be extended		@return: Object*******************************************************************************/function Abstract(object) {	object.Extend = Extend;	return object;}/** END CLASS PROTOTYPING *****************************************************//** START UTILITY FUNCTIONS  	Utility functions are basic functions used throughout to speed up or improve 	the usage of common tasks.*//******************************************************************************	function: $		@param: el [element id]	Reads an element from the document DOM, by Id name.		We make sure the HTMLElement inherits HTMLElement.prototype. If it didn't,	it means that we cant extend the DOM, and have to inherit it on demand (IE).		@return: HTMLElement*******************************************************************************/function $(el) {	el = document.getElementById(el);	if (!el) return null;	if (!el.Bija) $e(el);	return el;}/******************************************************************************	function: $a		@param: collection [collection]	the object to convert to an Array object, to allow usage of it's methods.		@return: Array*******************************************************************************/function $a(collection) {	if (!collection) return [];	var arr = (collection.length > 1) ? Array.prototype.slice.call(collection, 0) : [ collection[0] ];	return arr;}/******************************************************************************	function: $e		@param: HTMLElement	the htmlelemnt to inherit bija's dom extensions.		@return: HTMLElement*******************************************************************************/function $e(htmlobject) {	return (htmlobject.Bija) ? htmlobject : Extend(htmlobject, Element.methods);}function $element(tag) {	return $e(document.createElement(tag));}/******************************************************************************	function: $Time		Generatese a Unix Timestamp		@return: Integer*******************************************************************************/function $time() {	return (new Date).getTime();}// isType functions -----------------------------------------------------------function isArray(obj)    {return (!!obj.sort);}function isFunction(obj) {return (typeof obj == "function");}function isString(obj)   {return (typeof obj == "string");}function isObject(obj)   {return (typeof obj == "object");}/** END UTILITY FUNCTIONS *****************************************************//** START NATIVE EXTENSIONS	We give several native objects additional functionality, or implement	functionality not yet available in their version of ECMAScript*//******************************************************************************	function: $Native		@param: Arguments being Native objects*******************************************************************************/function $Native() {	var a = arguments;	for (var i = 0; i < a.length; i++)		a[i].extend = $Native.Extend;}// Internally Used, Special Extend Event for Native Objects -------------------$Native.Extend = function(methods){	for (method in methods) if (!isFunction(this.prototype[method])) this.prototype[method] = methods[method];}// Give .Extend to all objects ------------------------------------------------$Native(Function, String, Array, Number);/** FUNCTION - Extended *******************************************************/Function.extend({	// Extend Functionality	extend: Extend,	// Implement Functionality	implement: Implement,	// Delayed Execution	delay: function(ms) {		setTimeout(function() {			this.apply(this, $a(arguments).remove(0))		}, ms);	}});/** ARRAY - Extended **********************************************************/Array.extend({	// Get an item using a method	item: function(index) {		return this[index];	},	// Remove an Item	remove: function(index) {		this.splice(index, 1);		return this;	},	// Enumerates through All	forEach: function(callback) {		var l = this.length;		for (var i = 0; i < l; i++)			callback(this[i]);		return this;	}})// Compatibility / Easy Access --------------------------------------------------Array.prototype.each = Array.prototype.forEach;/** STRING - Extended **********************************************************/String.extend({	// Contains another string	contains: function(string) {		return (this.indexOf(string) != -1);	}});/** ELEMENT - Extended *********************************************************/// Special for Cross Browser :(// Expose Safari's Prototypes ---------------------------------------------------if (window.webkit && !window.webkit420){	window.Document = {} 	window.Event = {} 	window.HTMLCollection = {} 	window.HTMLElement = {} 	window.Node = {} 	window.Document.prototype = window["[[DOMDocument]]"]; 	window.Event.prototype = window["[[DOMEvent]]"]; 	window.HTMLCollection.prototype = window["[[HTMLCollection.prototype]]"]; 	window.HTMLElement.prototype = window["[[DOMElement.prototype]]"]; 	window.Node.prototype = window["[[DOMNode.prototype]]"];}// Allow IE to manually extend -------------------------------------------------var Element = {	extend: function(methods) {		if (!Browser.ie) return Extend(HTMLElement.prototype, methods);		Extend(Element.methods, methods);	},	methods: {}}// ELEMENT - Extended ***********************************************************Element.extend({	hide: function() {		this.style.display = "none";		return this;	},	show: function() {		this.style.display = "";		return this;	},	inject: function(el) {		var el = el || document.body;		el.appendChild(this);		return this;	},	remove: function() {		this.parentNode.removeChild(this);	}});/** Generate Document.Head for Inserting Scripts and Styles ********************/document.head = document.getElementsByTagName("head").item(0);/*******************************************************************************	'Class': Events		Passes a new set of events to another object, used like "abstract"	Events(object); or Events(object.prototype);		Remeber, when "watching" HTMLElement events (click etc..), the first	object returned is the EVENT object (e).********************************************************************************/function Events(object) {	// More than one object?	if (arguments.length > 1) {		for (var i = 0; i < arguments.length; i++)				Events(arguments[i]);		return this;	}		return Extend(object, {		events: [],		fire: function(id) {			if (!this.events[id]) return this;			// Fire's an event - return a literal of 'true' to block future events from accessing			// or return an object with a parameter of modargs: true to change the arguments reciveved			var args = $a(arguments).remove(0);			for (var i = 0; i < this.events[id].length; i++) {				var result = this.events[id][i].apply(this, args);				if (result){					if (result == true) return this;					if (isArray(result)) args = result;				}			}						return this;		},		observe: function(id, callback, top) {			if (!isString(id)) return this.observeAll(id);			var Self = this;			// Does it already exist?			if (!this.events[id]) {				// No, check for DOM-needed.				if (this.addEventListener) {					this.addEventListener(id, function(e) {						if (!e) var e = window.event;						Self.fire(id, e);					}, false);				} else if (this.attachEvent) {					this.attachEvent("on"+id, function(e) {						if (!e) var e = window.event;						// Use the same property for all browsers						e.target =  e.target || e.srcElement;						e.relatedTarget = e.relatedTarget || e.fromElement || e.toElement;						e.stopPropogation = function() {							e.cancelBubble = true;						}						Self.fire(id, e);					});				} else {					// No, this isn't a DOM object. Do nothing.				}				// Setup default data				this.events[id] = [ callback ];				return this;			}						// No, add it (top or bottom)			if (!top) this.events[id].push(callback); else this.events[id].unshift(callback);			return this;		},		observeAll: function() {			for (id in obj) this.watch(id, obj[id]);			return this;		}	});}// Give Events to Window (watch load, for example) ------------------------------------------Events(window);// Also give a DOMReady functional callback -------------------------------------------------// window.observe("DOMContentLoaded") -- works natively for mozilla/opera, lets fix others// webkit, interval-based with document.readyState ------------------------------------------if (Browser.webkit) {	// Interval based checking	var _timer = setInterval(function(){		if (/loaded|complete/.test(document.readyState)) {			clearInterval(_timer);			window.fire("DOMContentLoaded");		}	}, 10);}// ie, 'defered' blank javascript -----------------------------------------------------------if (Browser.ie) {	document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");	$("__ie_onload").onreadystatechange = function() {	    if (this.readyState == "complete") {	        window.fire("DOMContentLoaded");	    }	};}/** END EVENTS *****************************************************************************//** XMLHttpRequest(), a Cross-Browser Approach *********************************************/if (!window.XMLHttpRequest && window.ActiveXObject)	window.XMLHttpRequest = function(){		return new ActiveXObject("Msxml3.XMLHTTP");	}/** Ajax object, easily request and post data **********************************************/var Ajax = new Class({	init: function() {		// Create XHR object to use		this._xhr = new XMLHttpRequest();	},	get: function(url, data) {		// Get default data		var data = data || " ";		var xhr = this._xhr;				// Make sure it's closed		if (xhr.readyState != 0) this.cancel();				// Open a connection		xhr.open( (data == " ") ? "GET" : "POST" , url, true );				// Check readyStates		xhr.onreadystatechange = function() {			if (xhr.readyState == 4)				if (xhr.status != 200 && xhr.status != 304)					xhr.fire("complete", xhr.responseText);				else					xhr.fire("error", xhr.responseText);		}				// Send data		xhr.send(data);				return this;	},	post: function(url, data) {		this._xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');		return this.get(url, data);	},	cancel: function() {		this._xhr.abort();	}});/** Comet object, 'easily' get streaming data **********************************************//** Note:	You must do browser-side userAgent checking when passing data feeds to the Comet object,	this is due to the different formats that each take. I know, I know, we could just use	<script> tags, but that by far is the least-efficent method, and I've found a native	and fast method for every browser but IE and Older WebKits/KHTML.		Server-Side methods are shown in PHP, but could be used in any language or system.	On Rise or Fall, we use a custom coded HTTP Daemon, not even a real web server.		Methods used:	// Firefox and Gecko-Powered Browsers	 * The XHR object has a property called 'multicast', meaing it can recieve multiple	   parts of data natively, without polling, and without 'filling up' with data. Perfect.	 * We use responseText, stripping off the last two characters (' <')	(SERVER-SIDE):		header("Content-Type: multipart/x-mixed-replace;boundary=comet");		flush();				while(true)			echo("--comet\nContent-Type: text/xml\n\n");			echo("<?xml version=\"1.0\" encoding=\"UTF-8\"?><data>");			echo(time());			echo("\n<data>");			flush();			sleep(1);		}		// Opera	 * Opera supports multipart/x-mixed/replace, but NOT on an xhr. We could use an iFrame,	   but we're trying to use non-hackish & efficient methods. Luckily, Opera 9 supports	   an HTML5 element called <event-source />, which allows native http streaming.	   	 (SERVER-SIDE):	 	header("Content-Type: application/x-dom-event-stream");	 	flush();	 		 	while(true)	 	   echo("Event: comet\ndata:");		   echo(time());		   flush();		   sleep(1);*/var Comet = new Class({	init: function() {		// Build the requesting object, no matter the method		var Self = this;				// GECKO *******************************************		if (Browser.gecko) {			var gadget = new XMLHttpRequest();				gadget.multipart = true;			gadget.onreadystatechange = function() {				switch (gadget.readyState) {					case 2:					 Self.fire("connected");					break;						case 3:					 Self.fire("data", gadget.responseText.substring(0, gadget.responseText.length - 2));					break;					case 4:					 Self.fire("closed");					break;				}			}			this.gadget = gadget;			return this;		}				// OPERA ********************************************		if (Browser.opera) {			var gadget = $element("event-source");			gadget.addEventListener("comet", function(event){				Self.fire("data", event.data);				}, false);			this.gadget = gadget;			return this;		}				// SAFARI 3 BETA / WEBKIT 420 **********************		if (Browser.webkit420) {			var gadget = $element("iframe");			gadget.onload = function() {				Self.fire("data", gadget.contentDocument.innerHTML);			}			this.gadget = gadget;			return this;		}	},		connect: function(url) {		// GECKO *******************************************		if (Browser.gecko) {			this.gadget.open("GET", url, true);			this.gadget.send("");			return this;		}				// OPERA *******************************************		if (Browser.opera) {			this.gadget.setAttribute("src", url);			this.gadget.inject();			return this;		}				// SAFARI 3 BETA / WEBKIT 420 **********************		if (Browser.webkit420) {			this.gadget.setAttribute("src", url);			this.gadget.inject();		}	},		disconnect: function() {		// GECKO *******************************************		if (Browser.gecko) {			this.gadget.abort();			return this;		}				// OPERA *******************************************		if (Browser.opera) {			this.gadget.remove();			this.gadget.setAttribute("src", "about:blank");		}	}		});Events(Comet.prototype);