/*
 * Copyright (c) 2008 WeGotTickets
 * 
 * @author Clive Calmeyer
 * @version $Id$
 * @package www
 * 
 */

function $( elId ) {
	return document.getElementById( elId );
};

function $$( classname, containerElement ) {
	containerElement = containerElement || document;
	if( containerElement.getElementsByClassName ) {
		return containerElement.getElementsByClassName( classname );
	}
	var candidates = containerElement.getElementsByTagName( '*' );
	var elements = [];
	for( var i = 0, j = candidates.length; i < j; i++ ) {
		if( $hasClass( classname, candidates[i] ) ) {
			elements.push( candidate[i] );
		}
	}
	return elements;
};

function $create( tag, content, attributes, events ) {
	var el = document.createElement( tag );
	el.innerHTML = content || '';
	attributes = attributes || {};
	for( var a in attributes ) {
		el.setAttribute( a, attributes[a] );
	}
	events = events || {};
	for( var e in events ) {
		addEvent( el, e, events[e], false );
	}
	return el;
};

function $append( el, parentElement ) {
	parentElement = parentElement || document.body;
	parentElement.appendChild( el );
};

function $remove( el ) {
	el.parentNode.removeChild( el );
};

function $smite( el ) {
	if( el.events ) {
		for( var e = 0; e < el.events.length; e++ ) {
			el.events[e]();
			el.events[e] = null;
		}
		el.events = null;
	}
	$remove( el );
};

var XHR = {
	xhr: null,
	getXhr: function() {
		if( !this.xhr ) {
			var possibilities = [
			    function(){ return new XMLHttpRequest(); },
			    function(){ return new ActiveXObject('Msxml2.XMLHTTP'); },
			    function(){ return new ActiveXObject('Microsoft.XMLHTTP'); }
			]
			
			for( var i = 0; i < possibilities.length; i++ ) {
				try {
					var xhr = possibilities[i]();
				} catch( e ){}
			}
			this.xhr = xhr;
		}
		return this.xhr;
	},
	post: function( url, data, callback ) {
		var xhr = this.getXhr();
		xhr.abort();
		var qs = new QS( false );
		qs.add( data );
		qs.add( 'salt', Math.round( Math.random()*10000 ) );
		data = qs.getQueryString();
		xhr.open( 'POST', url, true );
		xhr.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" );
		xhr.setRequestHeader( "Connection", "close" );
		xhr.setRequestHeader( "Content-length", data.length );
		xhr.onreadystatechange = function() {
			if( xhr.readyState == 4 ) {
				if( xhr.status == 200 ) {
					try {
						callback( eval("(" + xhr.responseText + ")") );
					} catch( e ) {
						callback( false );
					}
				}
			}
		}
		xhr.send( data );
	},
	abort: function() {
		if( this.xhr ) {
			this.xhr.abort();
		}
	}
};

function shortDate( timeStamp ) {
	timeStamp *= 1000;
	var d = new Date( timeStamp );
	var day = d.getDate();
	var month = d.getMonth()+1;
	day = ( day < 10 ) ? '0'+day : day;
	month = ( month < 10 ) ? '0'+month : month;
	var sd = day+"/"+month;
	return sd;
};

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.parentNode;
    }
    return { x: _x, y: _y };
};

function $getClass( el ) {
	//sometimes ie6 likes to be awkward
	return el.className || el.getAttribute('class') || '';
}

function $addClass( classname, element ) {
	var cn = $getClass( element );
	if( !cn ) {
		element.className = classname;
		return;
	}
	//test for existance
	if( $hasClass( classname, element ) ) {
		return;
	}
	element.className = cn+' '+classname;
};

function $removeClass( classname, element ) {
	var cn = $getClass( element );
	var rxp = new RegExp( "\\s?\\b"+classname+"\\b", "g" );
	cn = cn.replace( rxp, '' );
	element.className = cn;
};

function $hasClass( classname, element ) {
	return ( $getClass( element ).indexOf( classname ) > -1 );
};


/* events */
function addEvent( el, eventType, handler, capturing ) {
	if( el.addEventListener ) {
		el.addEventListener( eventType, handler, capturing || false );
	} else if( el.attachEvent ) {
		var fn = function() {
			handler.call( el, normalise( window.event ) );
		};
		el.attachEvent( 'on'+eventType, fn );
	}
	function normalise( e ) {
		e.target = e.srcElement;
		e.preventDefault = function(){ e.returnValue = false };
		e.stopPropagation = function(){ e.cancelBubble = true };
		return e;
	};
	if( ! el.events ) el.events = [];
	el.events.push( function() {
		if( el.removeEventListener ) {
			el.removeEventListener( eventType, handler, capturing || false );
		} else if( el.attachEvent ) {
			el.detachEvent( 'on'+eventType, fn );
		}
	});
};

//event proxying, yeah baby
/*
 * @param selector - tag.class || tag || .class
 * @param eventType - click|mouseover|mouseout etc..
 * @param handler - function to run - this will be target element
 * @param container - much more efficient to specify a container
 */
function proxy( selector, eventType, handler, container ) {
	container = container || window;
	if( container.constructor === String ) {
		container = $(container);
	}
	var selector = selector.split('.');
	var tag = selector[0];
	var cls = selector[1];
	
	function match( el ) {
		if( tag && el.tagName.toLowerCase() != tag ) return false;
		if( cls && !$hasClass( cls, el ) ) return false;
		return true;
	}
	
	var proxyFn = function( e ) {
		var target = e.target;
		while( target && !match( target ) && target != container ) {
			target = target.parentNode;
		}
		if( target && target != container ) {
			handler.call( target, e );
		}
	}
	addEvent( container, eventType, proxyFn, true );
}

function domReady( fn ) {
	if( fn.constructor !== Function ) {
		return;
	}
	if( !domReady.list ) {
		domReady.list = [];
	}
	// if the DOM is already ready and the queued functions have been run
	// just run the function;
	if( fireDomReady.fired ) {
		fn();
		return;
	}
    domReady.list.push( fn );
    bindDomReady();
};

function fireDomReady() {
	if( fireDomReady.fired ) {
		return;
	}
	fireDomReady.fired = true;
	var list = domReady.list;
	for( var i = 0; i < list.length; i++ ) {
		list[i]();
	}
};

// stolen from jQuery, thanks John
function bindDomReady(){
	if ( bindDomReady.bound ) return;
	bindDomReady.bound = true;

	// Mozilla, Opera and webkit nightlies currently support this event
	if ( document.addEventListener ) {
		// Use the handy event callback
		document.addEventListener( "DOMContentLoaded", function(){
			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
			fireDomReady();
		}, false );

	// If IE event model is used
	} else if ( document.attachEvent ) {
		// ensure firing before onload,
		// maybe late but safe also for iframes
		document.attachEvent("onreadystatechange", function(){
			if ( document.readyState === "complete" ) {
				document.detachEvent( "onreadystatechange", arguments.callee );
				fireDomReady();
			}
		});

		// If IE and not an iframe
		// continually check to see if the document is ready
		if ( document.documentElement.doScroll && window == window.top ) (function(){
			//if ( jQuery.isReady ) return;

			try {
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");
			} catch( error ) {
				setTimeout( arguments.callee, 0 );
				return;
			}

			// and execute any waiting functions
			fireDomReady();
		})();
	}

	// A fallback to window.onload, that will always work
	addEvent( window, "load", fireDomReady );
};


function contains( ary, val ) {
	var l = ary.length;
	while( --l >= 0 ) {
		if( ary[l] == val ) return l;
	}
	return false;
};

//query string utility class
function QS( parsePageQueryString ){
	this.qs = {};
	if( parsePageQueryString !== false ) {
		parsePageQueryString = true;
	}

    var s = location.search.replace( /^\?|#.*$/g, '' );
    if( s && parsePageQueryString ) {
        var qsParts = s.split('&');
        var i, nv;
        for (i = 0; i < qsParts.length; i++) {
            nv = qsParts[i].split('=');
            this.qs[nv[0]] = nv[1];
        }
    }
};
QS.prototype.add = function( name, value ) {
    if( arguments.length == 1 && arguments[0].constructor == Object ) {
    	var nv, newValues = arguments[0];
    	for( nv in newValues ) {
            this.add( nv, newValues[nv] );
        }
        return;
    }
    this.qs[name] = value;
};
QS.prototype.remove = function( name ) {
    if( arguments.length == 1 && arguments[0].constructor == Array ) {
        var i, deleteNames = arguments[0];
        for( i = 0; i < deleteNames.length; i++ ) {
            this.remove( deleteNames[i] );
        }
        return;
    }
    delete this.qs[name];
};
QS.prototype.getQueryString = function() {
    var nv, q = [];
    for( nv in this.qs ) {
        q[q.length] = nv+'='+this.qs[nv];
    }
    return q.join( '&' );
};
QS.prototype.toString = QS.prototype.getQueryString;



/* monkey patching is bad mmkay? */

Function.prototype.bind = function( obj ) {
	var _this = this;
	return function() {
		return _this.apply( obj, arguments );
	};
};

String.prototype.trim = function() {
	return this.replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' );
};

// not really monkey patching, just storing this function as a property of RegExp
RegExp.escape = function( txt ) {
    if( !arguments.callee.cRxp ) {
        arguments.callee.cRxp = /(\.|\\|\+|\*|\?|\[|\^|\]|\$|\(|\)|\{|\}|\=|\!|\<|\>|\||\:)/g;
    }
    return txt.replace( arguments.callee.cRxp, "\\$1" );
};

