/******************************************************* 
*	2009 / genii.com.au
*	contact scott@ballyhoos.com.au
*	DOM - short hand DOM class
****************************************************** */
//	IE test
var ie  = (document.all) ? true : false;

var dom = {
		
	/*	
		gets and test if id is an object	
	*/
	id : function(id, obj)
	{
		return ( !obj ? document : obj ).getElementById(id);
	},
	
	/*
		create a simple html tag element.
	*/
	create : function(tagType, attributes)
	{
		var tag = document.createElement(tagType);
		//	add object attributes
		if( attributes ){
			//	if the id is only been requested
			if( typeof(attributes) == "string" ) attributes = {"id":attributes};
			//	add attributes to newly created element
			for(var key in attributes){
				tag[key] = attributes[key];
			}	
		}
		return  tag;
	},

	
	/*  
		quick test for object, will create one if a string via id	
	*/
	object : function(value)
	{
		return ( typeof(value) == "object" ? value : (dom.id(value) ? dom.id(value) : false) );
	},
	
	
	/*	
		Add events to an object.  can pass mulitple objects via an array	
	*/
	event : function(obj, evType, func, remove)
	{
		if( dom.isArray(obj) ){
			for (var e = 0; e < obj.length; e ++) {
				dom.event(obj[e], evType, func);
			}
		}else if( dom.object(obj) ){
			if( ie ){
				//	IE
				obj.attachEvent("on" + evType, func);
				//if( remove === true ){
				//	obj.detachEvent("on" + evType, fn);
				//}	
			}else if( obj.addEventListener ){
				//	firefox
				obj.addEventListener(evType, func, false);
				//if( remove === true ){
				//	obj.removeEventListener(evType,fn, useCapture);
				//}	
				
			}else{ 
				//	other browser
				obj['on' + evType] = func; 
			}
		}else{
			alert("Could not find the object to attach event too");
		} 
	},
	
	
	loaded : function(func, object)
	{
		//	test for image object which could be passed.
		if( typeof(object.src) == "string" && ie){
			//	if not loaded..
			if( object.complete || (typeof(object.naturalWidth) != "undefined" && object.naturalWidth != 0) ){
				if( typeof(func) == "function" ){
					//	run function.
					func();	
				}
				//
				return true;	
			}
			return setTimeout(function(){dom.loaded(func, object);}, 200);
			
		}else{
			dom.event((object ? object : window), "load", func);			
		}
		return false;
	},
	
	/*	
		get element 
	*/
	element : function(e)
	{
		if( window.event && window.event.srcElement ){
			return window.event.srcElement;
		}else if(e && e.target){
			return e.target;
		}
		return false;
	},
	
	
	/*
	allows the ablity to add a hover event to an object
	*/
	hover : function(obj, callback, delay)
	{
		var timer = false;
		obj = dom.object(obj);
		//	setup a delay in seconds if needed (2000 = 2 seconds)
		if( delay === undefined ) delay = 100;
		
		dom.event(obj, "mouseover", function(){
				timer = setTimeout(callback, delay);	
			});
		dom.event(obj, "mouseout", function(){
				 clearTimeout(timer);	
			});
	},

	
	/*	
		Cancels the onclick events.	
	*/
	cancel : function(e)
	{
		if( window.event && !window.event.returnValue ){
			window.event.returnValue = false;
			window.event.cancelBubble = true;

		}else if( e && e.preventDefault ){
			e.preventDefault();
			e.stopPropagation();
		}	
	},
	
	
	/*	
		gets node elements attributes	
	*/
	attribute : function(att, obj, ret)
	{
		// typical MS IE bug, "for" will return NULL
		// this bug extends IE5 - IE 7, when will this end? 
		if( att == "for" && document.all ){
			return ( !obj.attributes["for"].nodeValue ? false : ((!ret) ? true : obj.attributes["for"].nodeValue)) ;
		}
		return ( !obj.getAttribute(att) ? false : ((!ret) ? true : obj.getAttribute(att))) ;
	},
	
	/*
		get element/node/objects classes
	*/
	getClass : function(obj)
	{
		// tests for IE naming covention that differs from FF
		var classes = dom.attribute(((document.all) ? "className" : "class"), obj, true);
		//	return array of	all classes	
		return (classes ? classes.split(" ") : false ); 
	},
	
	/*
		does object have a class name of...xxx
	*/
	hasClass : function(classname, obj)
	{
		return (dom.inArray(classname, dom.getClass(obj)) ? true : false );
	},
	
	
	/*
		replaces an existing class with another one.
	*/
	swapClass : function(from, to, obj)
	{
		if( !dom.isArray(obj) ) obj = Array(obj);
		//	
		for(var i = 0; i < obj.length; i++) {
			if( obj[i] ) obj[i].className = obj[i].className.replace(from, to);
		}
	},
	
	
	/*
	
	*/
	addClass : function(classname, obj)
	{
		if( !dom.isArray(obj) ) obj = Array(obj);	
		//
		for(var i = 0; i < obj.length; i++) {
			//	replace it if it already exists and add new class to the object class
			if( obj[i] ) obj[i].className = obj[i].className.replace(classname, "") +" "+ classname;
		}
	},
	
	/*
		get all nodes which have the a class name of 	
	*/
	byClass : function(classname, obj, evnt, func)
	{
		//	store found class objects
		var objs = [];
		obj = dom.object(obj);
		// get all elements under passed obj
		var elems = ( !obj ? document : obj ).getElementsByTagName("*");
		for (var e = 0; e < elems.length; e ++) {
			if( dom.hasClass(classname, elems[e]) ){
				objs.push(elems[e]);
				//	pass an event trigger if needed
				if( typeof evnt == "string" ){ 
					dom.event(elems[e], evnt, func);	
				}
			}
		}
		return objs;
	},
	
	
	/*
		get a property from the css class assigned to the object
	*/
	css : function(property, obj)
	{
		obj = dom.object(obj);
		if( obj.currentStyle ){
			return obj.currentStyle[property];
		}else if(window.getComputedStyle){
			return document.defaultView.getComputedStyle(obj,null).getPropertyValue(property);
		}
		return false
	},
	
	/*
		get elements by tag type
	*/
	byTag : function(tag, obj, evnt, func)
	{
		obj = dom.object(obj);
		var collection = ( !obj ? document : obj ).getElementsByTagName(tag);
		//	convert collection to an array array?
		var tags = dom.toArray(collection);
		//	pass an event trigger if needed
		if( typeof(evnt) == "string" ){ 
			for (var t = 0; t < tags.length; t++) {
				//	execute a function on every occurance of the found tag
				dom.event(tags[t], evnt, func);	
			}
		}
		return (tags.length == 1 ? tags[0] : tags);
	},


	tag : function(tag, obj, evnt, func)
	{
		return dom.byTag(tag, obj, evnt, func);
	},

	/*
		this gets the parent object by the tag name of a child object
	*/
	byTagParent : function(tag, obj)
	{
		return ( obj.tagName.toLowerCase() == tag ? obj : dom.byTagParent(tag, obj.parentNode) ); 
	},
	
	
	parent : function(tag, obj)
	{
		return ( obj.tagName.toLowerCase() == tag ? obj : dom.byTagParent(tag, obj.parentNode) ); 
	},

	/*
		simple test for item in an array
	*/
	inArray : function(needle, haystack, returnKeys)
	{
		var keys = [];
		for(var i = 0; i < haystack.length; i++) {
			if( haystack[i] === needle ){
				if( !returnKeys ) return true;
				//	add to array
				keys.push(i);
			}
		}
		return ( returnKeys ) ? keys : false;
	},
	
	
	/*
		basic test to see if obj is an array
	*/
	isArray : function(obj)
	{
		return ((typeof(obj) == "object" && (obj instanceof Array)) ? true : false);
	},
	
	
	/*
		this converts a HTML collection to an array
	*/
	toArray : function(collection)
	{
		if( ie ){
			var arr = [];
		    for(var i=0; i < collection.length; i++){ 
		        arr.push(collection[i]); 
		    } 
		    return arr; 
		}else{
			return Array.prototype.slice.call(collection);
		}
	},
	
	
	/*
		load an external/remote js file or script into the browser
	*/
	script : function(js, callback)
	{
		//	get head element to add new js
		var head = dom.byTag("head")[0];
		if( head ){
			//	check to see if passed js is an array of objects to load
			if( dom.isArray(js) ){
				for(var i = 0; i < js.length; i++){
					dom.script(js[i]);
				}	
			}else{
				//	create a new element
				var script  = dom.create("script", {"type":"text/javascript"});
				//	check to see if a file is being requested
				if( js.search(/\.js/i) !== -1 ){
					script.src = js;
				}else{
					//	basic javascript script needed to be added
					if( ie ){
						script.text = js;
					}else{
						script.innerHTML = js;
					}
				}	
				//	is there a callback request function.
				if( callback ){
					if( ie ){
						//	IE doesn't support onload, so we use the httpRequest
						script.onreadystatechange = function(){
							if( script.readyState == "loaded" ) callback();
						};
					}else{ 
						script.onload = callback(); 
					}
				}
				head.appendChild(script);
			}
		}else{
			alert("<head> element tag not found. Cannot add javascript (dom.script)");	
		}
 	},
	
	key : function(e)
	{
		if( !e ){
			e = window.event;
		}
		return (e.keyCode ? e.keyCode : e.which);
	}

};


/******************************************************
*	SIMPLE DEBUGGING FUNCTION
**************************************************** */

function debug(str)
{
	var debug = dom.id("debug");
	if( debug ){
		debug.innerHTML = debug.innerHTML + str +"<br />";
	}else{
		var d = dom.create("div", "debug");	
		d.innerHTML = str +"<br />";
		var body = dom.byTag("body")[0];
		body.insertBefore(d, body.firstChild);
	}
};

String.prototype.debug = function()
{
	debug(this);	
};

/******************************************************
*	EMAIL FUNCTION
**************************************************** */
/*
function emails()
{
	var classname = "emailaddress";
	
	dom.byClassFunction(classname, false, false, 
		function(e){
			var d = dom.event(e);
			alert(d.rel);
		});
	
};
dom.event(window, "load", function() {emails();});
*/

/******************************************************
*	ARRAY PROTOTYPING	ballyhoos.com.au 2009
**************************************************** */

Array.prototype.inArray = function(needle)
{
	return dom.inArray(needle, this);
};

Array.prototype.isArray = function()
{
	return dom.isArray(this);
};

Array.prototype.merge = function(array)
{
	for(var i = 0; i < array.length; i++) {
		this.push(array[i]);
	}
};
//Array.prototype
//	HINT For HTML Collections alternatively use array.concat(array)?


/******************************************************
*	STRING PROTOTYPING	ballyhoos.com.au 2009
**************************************************** */

//	decodes json, same as ajax function decodeJson()
String.prototype.json = function()
{
	return eval('('+ this +')');
};

//	encode string value for url parsing
String.prototype.encode = function(){
	return encodeURIComponent(this);
};

String.prototype.stripTags = function(tags)
{
	if( dom.isArray() ){
		//alert(html.replace(/<script(?:.|\s)*?>|<\/script>/g, ""));
	}
	// What a tag looks like
	//var matchTag = /<(?:.|\s)*?>/g;
	// Replace the tag
	//return this.replace(matchTag, "");
};


//	trim string value
String.prototype.trim = function(specify)
{
	//	c/o - php.js
	var whitespace, l = 0, i = 0;
    var str = this + '';
    if( ! specify ){
        // default list
        whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
    } else {
        // preg_quote custom list
        specify += '';
        whitespace = specify.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
    }
     l = str.length;
    for (i = 0; i < l; i++) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    }
    l = str.length;
    for (i = l - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);
            break;
        }
    }
    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
};

//	left trim string value
String.prototype.ltrim = function(specify)
{
	//	c/o - php.js
	specify = ! specify ? ' \\s\u00A0' : (specify +'').replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
    var re = new RegExp('^[' + specify + ']+', 'g');
    return (str+'').replace(re, '');
};

//	right trim string value
String.prototype.rtrim = function(specify)
{
	//	c/o - php.js
	specify = ! specify ? ' \\s\u00A0' : (specify +'').replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
    var re = new RegExp('[' + specify + ']+$', 'g');
    return (str+'').replace(re, '');
};

String.prototype.toProperCase = function() 
{
    return this.charAt(0).toUpperCase() + this.substring(1,this.length).toLowerCase();
};

//	similar to PHP str_replace
String.prototype.strReplace = function(from, to)
{
	//	find char to replace
	var v = this;
	//	loop through as JS doesn't support muiltple finds in the the replace function
	while(v.indexOf(from) != -1){
		//	replace
		v = v.replace(from, to);
	}
	return v;
};

