/*!

 * Karmagination 0.2 - Fast and Easy

 * http://www.karmagination.com

 * Released under the MIT, BSD, and GPL Licenses - Choose one that fit your needs

 * Copyright (c) 2009 Kean Loong Tan 

 * Start date: 2009-04-01

 * Build Time: 2009-09-23 07:19:42 AM
 * Build: 2871
 *

 * Attribution:

 * onDOMready based on many JS experts' input especially Dean Edwards, see the unminified source code for names

 * Custom events based on Dean Edwards' blog post enlightenment

 * CSS and browser detection copyright Valerio Proietti of Mootools

 * Offsets, dimensions, and extend, eq copyright John Resig of jQuery

 * Selector engine, Sizzle, founded by John Resig, copyright Dojo Foundation

 * Common Feature Test, event support detection copyright Juriy Zaytsev/kangax

 * Animation based loosely on Ryan Morr's FX library which in turn is influenced by YUI 2

 * Many thanks to John David Dalton for the support and pointers :{D

 * And to many of those that contributed to the projects above

 */

 

//start expression

(function karma_anonymous(window){ 



// speeding up reference in non-JIT bytecode browsers

var document = window.document,

	_Karma = window.Karma,

	_$ = window.$;



// Constructor Function

var Karma = this.$ = this.Karma = function( query, context ) {

	// note: if Karma has not been instatiated, this === global object, interpreted by most browsers as window

	// I did not use instance of because window instanceof leaks memory in IE, what a shame

	// if (!(this instanceof Karma)) return new Karma( query, context );

	// this pollutes FF with a contructor in window WHY?

	if (this.constructor !== Karma) return new Karma( query, context );

	

	query = query || document;

	this.context = context = context || document;

	

	// the stack to track callee Karma objects

	this.KarmaStack = [];

	

	// result can be empty

	var result = [];

	

	// if a node is passed

	if (query.nodeType || query === window) {

		this[0] = query;

		this.length = 1;

		this.query = query;

		return; // do not return 'this' because it's a constructor, return just to break from function

	}

	

	// string is most used query

	else if(typeof query == "string") {

		this.query = query = Karma.trim(query);

		if(!query.length) {

			this[0] = document;

			this.length = 1;

			this.query = query;

			return; // do not return 'this' because it's a constructor, return just to break from function

		}



		var context = this.context.ownerDocument || this.context;

		

		// if HTML string passed

		result = Karma.isHTML(query) ? Karma.HTMLtoNode(query, context) : Karma.Sizzle(query, context);

	}

	

	// onDOMready

	else if (typeof query == "function") {

		(!Karma.isReady) ? Karma.readyQueue(function readyQueue(){ query(Karma);}) :	query(Karma);

		return;

	}



	// if array, object or Karma object, or some unknown, make it into an array

	else { 

		result = query; 

		if(query.query)	this.query = query.query;

	}

	

	// push all the elements that we have gotten into the Karmagination Instance

	this.populate(result);

};



var _Object = Object, _Array = Array;

/*

//if(window.addEventListener && !window.ActiveXObject){

	var _div = document.createElement("div");

	_div.innerHTML = '<iframe name="Karmagination" src="javascript:void 0" style="display:none"></iframe>';

	var iframe = _div.firstChild;

	document.documentElement.insertBefore(iframe, document.documentElement.firstChild);

	

	var host = self.location.hostname == 'localhost' ? '' : 'document.domain = ' + self.location.hostname;

	

	frames['Karmagination'].document.write("<script>"+host+"<\/script>");

	

	_Object = frames['Karmagination'].Object;

	_Array = frames['Karmagination'].Array;

//}

*/

Karma.fn = Karma.prototype;



// use no Karmagination syntax in extend function (pure js) cause they will fail

Karma.extend = Karma.fn.extend = function() {

	// copy reference to target object

	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;



	// Handle a deep copy situation

	if ( typeof target == 'boolean' ) {

		deep = target;

		target = arguments[1] || {};

		// skip the boolean and the target

		i = 2;

	}



	// Handle case when target is a string or something (possible in deep copy)

	if ( typeof target != 'object' && typeof target != 'function' )

		target = {};



	// extend Karma itself if only one argument is passed

	if ( length == i ) {

		target = this;

		--i;

	}



	for ( ; i < length; i++ )

		// Only deal with non-null/undefined values

		if ( (options = arguments[ i ]) != null )

			// Extend the base object

			for ( var name in options ) {

				var src = target[ name ], copy = options[ name ];



				// Prevent never-ending loop

				if ( target === copy )

					continue;



				// Recurse if we're merging object values

				if ( deep && copy && typeof copy == "object" && !copy.nodeType )

					target[ name ] = Karma.extend( deep, 

						// Never move original objects, clone them

						src || ( copy.length != null ? [ ] : { } )

					, copy );



				// Don't bring in undefined values

				else if ( typeof copy != 'undefined' )

					target[ name ] = copy;

			}



	// Return the modified object

	return target;

};



Karma.fn.extend({

	// populate nodes into Karma, starting from index n

	populate: function(elements ,n) {

		n = n || 0;

		// make a clean array

		this.length = n;

		

		elements = Karma.makeArray(elements);



		// exit if no elements found

		if (!elements.length) return this;

		

		// push elements into Karma, faster way than just just a for loop

		_Array.prototype.push.apply(this, elements);

		return this;

	},

	

	// empty all elements store in Karma, starting from index n,

	wipe: function(n){

		n = n || 0;

		

		for(var i=n; i<this.length; i++)

			delete this[i];



		this.length = n;

		

		return this;

	},

	

	// stacking Karma for chainability

	stack: function(o){

		this.query = o.query;

		this.KarmaStack.push(o);

		return this;

	},

	

	// getting into the previous chain

	end: function() {

		return this.KarmaStack[0];

	},

	

	// how many elements in Karma, initially set to 0

	length: 0,

	

	// query that created the current instance of Karma

	query: null,

	

	version: 0.2	

});



Karma.extend({

	version: 0.2,

	/* special thanks to jQuery's cases so I don't have to manually hunt down the special cases myself */	 

	HTMLtoNode: function(query, context) {

		context = context.ownerDocument || context;

		//var query = Karma.cleanHTML(query);

		var tmp = context.createElement('DIV'), 

			subquery = query.substring(0, 8).toLowerCase();



		// lesson learned again and again never use Regex when indexOf can replace the job.

		// td

		if(!subquery.indexOf('<tr')) {

			query = '<table>' + query + '</table>';

			tmp.innerHTML=query;

			tmp = tmp.firstChild.firstChild;

		}

		// td or th

		else if(!subquery.indexOf("<td") || !subquery.indexOf("<th")) {

			query = '<table><tr>' + query + '</tr></table>';

			tmp.innerHTML=query;

			tmp = tmp.firstChild.firstChild.firstChild;

		}

		// legend

		else if(!subquery.indexOf("<legend")) {

			query = '<fieldset>' + query + '</fieldset>';

			tmp.innerHTML=query;

			tmp = tmp.firstChild;

		}

		// option

		else if(!subquery.indexOf("<option")) {

			query = '<select multiple="multiple">' + query + '</select>';

			tmp.innerHTML=query;

			tmp = tmp.firstChild;

		}

		

		// thead etc, well we made subquery soooo short it should not be a problem

		else if(/^<thead|tbody|tfoot|colg|capt/.test(subquery)) {

			query = '<table>' + query + '</table>';

			tmp.innerHTML=query;

			tmp = tmp.firstChild;

		}

		

		// col

		else if(!subquery.indexOf("<col")) {

			query = '<table><colgroup>' + query + '</colgroup></table>';

			tmp.innerHTML=query;

			tmp = tmp.firstChild.firstChild.firstChild;

		}

		// script and link

		else if (!subquery.indexOf("<script") || !subquery.indexOf("<link") ) {

			query = 'div<div>' + query + '</div>';

			tmp.innerHTML=query;

			tmp = tmp.lastChild;

		}



		// others

		else {

			tmp.innerHTML = query;

		}

		

		return tmp.childNodes.length ? Karma.makeArray(tmp.childNodes) : [];

		

	},

	 

	// type detection, Miller method for those special cases otherwise typeof is faster, 

	isArray: function(o){ return _Object.prototype.toString.call(o) == "[object Array]" },

	isObject: function(o){ return _Object.prototype.toString.call(o) == "[object Object]" },

	isDate: function(o){ return _Object.prototype.toString.call(o) == "[object Date]" },

	isGenericObject: function(o) { return typeof o == "object" },

	isFunction: function(o) { return typeof o == "function" },

	isString: function(o) { return typeof o == "string" },

	isNumber: function(o){ return typeof o == "number" },

	isValue: function(o){ return typeof o == "number" || typeof o == "string" },

	isBoolean: function(o){ return typeof o == "boolean" },

	// undefined munging is slower in all modern browser, use is not recommended

	isDefined: function(o) { return typeof o != "undefined" },

	// isXML: function(o) { return 'innerHTML' in (o || o.ownerDocument).documentElement },

	// unreliable detection, using documentation to prevent mistake instead

	isHTML: function(o) { return Karma.isString(o) ? /^<.+/.test(o.substring(0,3)) : false; },

	isKarma: function(o) { return o.constructor === Karma },



	

	// browser detection, TAKEN FROM MOOTOOLS with modifications, if you are new to JS, !! mean cast as boolean type

	// learned something new today from BING, a new-old IE feature detection that's probably better

	// old method !!(window.ActiveXObject && !window.opera) 

	// new method !window.addEventListener, we used that for feature detection but it turns out to be an IE detector too

	isIE: !!(!window.addEventListener && window.ActiveXObject),

	isIE6: typeof document.createElement('DIV').style.maxHeight == "undefined",

	isIE7: !!(!window.addEventListener && window.XMLHttpRequest && !document.querySelectorAll),

	isIE8: !!(!window.addEventListener && document.querySelectorAll),

	isGecko: navigator.product == 'Gecko',

	isOpera: !!window.opera,

	isWebkit: !!(!window.opera && !navigator.taintEnable && document.evaluate && navigator.product != 'Gecko'),

	

	// trim front/ending whitespaces and newlines so innerHTML won't go crazy

	/*cleanHTML: function(HTML){ return HTML.replace ? HTML.replace(/[\n\r]/g, ' ') : HTML; },*/

	

	// used internally, only works for array-like objects

	makeArray: function(o) {

		if (Karma.isArray(o)) return o; // makes sense, doesn't it?

		if (Karma.support.nodeListToArray) return _Array.prototype.slice.call(o);

		

		var ret;

		

		// some array-like objects will have length

		if (o.length) {

			var length = new Number(o.length);

			ret = new Array(length);

			while (--length >= 0) {

		        ret[length] = o[length];

		    }

		}

		else {

			ret = [];

			for(var prop in o) {

				if (o.hasOwnProperty(prop))

					ret.push(o[prop]);

			}

		}

		return ret;

	},

	

	noConflict: function(extreme){

		window.$ = _$;

		if (extreme)

			window.Karma = _Karma;

		return Karma;

	},

	

	// returns a unique set of array

	unique: function(array) {

		var ret = [];

		o:for(var i = 0, n = array.length; i < n; i++) {

			for(var x = i + 1 ; x < n; x++) {

				if(array[x] === array[i])

					continue o; 

			}

			ret.push(array[i]);

		}

		return ret;

	},

	

	// functions to fire onDOMready

	readyFunctions: [],

	

	// onDOMready yet?

	isReady: false, 

	

	// add functions to Karma.fns

	readyQueue: function(fn){

		if(Karma.isFunction(fn))

			Karma.readyFunctions.push(fn);

	},

	

	// reliable onDOMready code, thanks to Dean Edwards/Diego Perini/Byron McGregor/John Resig/Matthias Miller et al

	// view the contributors here, http://dean.edwards.name/weblog/2006/06/again/

	// modified so that onDOMready runs once for each frame it's being used, speeds up when you have multiple onDOMready statements

	ready: function(){

		var init = function() {

			if(Karma.isReady) return;

			Karma.isReady = true;

			

			// run all functions that are associated with ready

			for(var i=0; i< Karma.readyFunctions.length; i++) {

				Karma.readyFunctions[i](Karma);

			}

		}

		

		if(Karma.support.addEventListener)

			document.addEventListener('DOMContentLoaded', init, false);



		else if(document.documentElement.doScroll) {

			try {

				document.createElement('div').doScroll('left');

				return init();

			} catch(e) {}

		}

		else if (/loaded|complete/.test(document.readyState)) return init();

		 

		// loop every 50 ms is good enough

		if (!Karma.isReady) setTimeout(arguments.callee, 50);

	}

});



// added this for jQuery compatibility

Karma.browser = {

	safari: Karma.isWebkit,

	opera: Karma.isOpera,

	mozilla: Karma.isGecko,

	msie: Karma.isIE,

	version: Karma.isIE6 ? 6 : Karma.isIE7 ? 7 : ''

}

// some simulations below to feature test the capabilities of the current browser

// also populates known attribute names that are problematic

// values are stored for future use

Karma.temp = {

	div: document.createElement('DIV'),

	fragment: document.createDocumentFragment(),

	camelCase: {},

	nodeListToArray: function(){

		try { return _Array.prototype.slice.call(document.forms, 0) instanceof _Array; } catch (e) { return false; }

	},

	/*

	htmlCreation: function(){

		try { document.createElement('<input id="a" />'); } catch(e) { return false; }

		return true;

	},*/

	

	attrMap: {

		'for': 'htmlFor',

		'class': 'className',

		maxlength: 'maxLength',

		readonly: 'readOnly',

		rowspan: 'rowSpan',

		colspan: 'colSpan',

		codebase: 'codeBase',

		ismap: 'isMap',

		accesskey: 'accessKey',

		longdesc: 'longDesc',

		tabindex: 'tabIndex',

		valign: 'vAlign',

		cellspacing: 'cellSpacing',

		cellpadding: 'cellPadding',

		id: 'id',

		href: 'href',

		dir: 'dir',

		title: 'title'

	},

	

	offsets: function(){

		var body = document.body,

			container = document.createElement('div'), 

			innerDiv,

			checkDiv,

			table,

			td,

			rules,

			cur_prop,

			bodyMarginTop = document.body.style.marginTop,

			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';



		var rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };

		for ( cur_prop in rules ) container.style[cur_prop] = rules[cur_prop];



		container.innerHTML = html;

		body.insertBefore(container, body.firstChild);

		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;



		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);

		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);



		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';

		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);



		body.style.marginTop = '1px';

		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);

		body.style.marginTop = bodyMarginTop;



		body.removeChild(container);

	

	},

	

	calculatedOffsets: false

}



Karma.uniqueId = 0;

Karma.storage = {};



// know the current browser's capabilities, we calculate here and use everywhere without recalculating

// why isDefined is reliable here, REASON: we just created the ELEMENT and can be sure they are not polluted

Karma.support = {

	//htmlCreation: Karma.temp.htmlCreation(),

	cssText: 'cssText' in Karma.temp.div.style,

	cssFloat: 'cssFloat' in Karma.temp.div.style,

	styleFloat: 'styleFloat' in Karma.temp.div.style,

	opacity: 'opacity' in Karma.temp.div.style,

	filter: 'filter' in Karma.temp.div.style,

	outerHTML: 'outerHTML' in Karma.temp.div,

	addEventListener: 'addEventListener' in Karma.temp.div,

	attachEvent: 'attachEvent' in Karma.temp.div,

	dispatchEvent: 'dispatchEvent' in Karma.temp.div,

	fireEvent : 'fireEvent' in Karma.temp.div,

	createEvent: 'createEvent' in document,

	createEventObject: 'createEventObject' in document,

	nodeListToArray: Karma.temp.nodeListToArray(),

	currentDocIsHTML: 'innerHTML' in document.documentElement

};



// run the function to wait for onDOMready

Karma.ready();
Karma.fn.extend({

			 

	append: function(o) {

		var els = Karma(o);

		if(!this.length || !els.length) return this;



		return Karma.temp.manipulate('append', els, this, els.query);

	},

	

	appendTo: function(o) {

		var els = Karma(o);

		if(!this.length || !els.length) return this;

		

		return Karma.temp.manipulate('append', this, els, this.query, 1);

	},

	

	prepend: function(o) {

		var els = Karma(o);

		if(!this.length || !els.length) return this;



		return Karma.temp.manipulate('prepend', els, this, els.query);

	},

	

	prependTo: function(o) {

		var els = Karma(o);

		if(!this.length || !els.length) return this;

		

		return Karma.temp.manipulate('prepend', this, els, this.query, 1);

	},

	

	before: function(o) {

		var els = Karma(o);

		if(!this.length || !els.length) return this;

		

		return Karma.temp.manipulate('before', els, this, els.query);

	},

	

	insertBefore: function(o){

		var els = Karma(o);

		if(!this.length || !els.length) return this;

		

		return Karma.temp.manipulate('before', this, els, this.query, 1);

		

	},

	

	after: function(o) {

		var els = Karma(o);

		if(!this.length || !els.length) return this;

		

		return Karma.temp.manipulate('after', els, this, els.query);

	},

	

	insertAfter: function(o){

		var els = Karma(o);

		if(!this.length || !els.length) return this;



		return Karma.temp.manipulate('after', this, els, this.query, 1);

	},

	

	// removes all events attached including current node

	empty: function() {

		for (var i=0; i< this.length; i++) {

			if (Karma.support.currentDocIsHTML) {

				// no garbage collection here, we do it on unload then

				// performance comes first vs pseudo leak

				this[i].innerHTML = '';

			}

			// if is XML document

			else {

				while (this[i].firstChild) {

					// garbage collection, it's not perfect but will reduce memory usage while balancing performance

					if (this[i].firstChild.KarmaMap) Karma.storage[this[i].KarmaMap] = null;

					this[i].removeChild(this[i].firstChild);

				}

			}

		}

		return this;

	},

	

	html: function(value) {

		if(Karma.isValue(value)) {

			for (var i=0; i< this.length; i++)

				this[i].innerHTML = value;

		

			return this;

		}

		return this.length? this[0].innerHTML: null;

	},

	

	text: function(value) {

		if(Karma.isValue(value)) {

			for(var i=0; i< this.length; i++)

				this[i].innerText ?	this[i].innerText = value :	this[i].textContent = value;

			return this;

		}

		

		var text = [];

		for(var i=0; i< this.length; i++) {

			text.push(this[i].innerText || this[i].textContent);

		}

		

		return text.join(' ');

	},

	

	remove: function(query){

		var result = Karma.isString(query) ? Karma.Sizzle.filter(query, this) : this.length ? this : [];

		

		for (var i=0; i< result.length; i++) {

			if (result[i].KarmaMap) Karma.storage[result[i].KarmaMap] = null;

			result[i].parentNode.removeChild(result[i]);

		}

		

		return this;

	},

	

	// TODO: clone events

	clone: function(events){

		var clone = [],

			$child;



		for(var i=0;i<this.length;i++) {

			if (Karma.support.outerHTML) {

				clone.push(Karma(this[i].outerHTML, this[i].ownerDocument||this[i])[0]);

				$child = Karma(clone[i]);

				$child[0].KarmaMap = ++Karma.uniqueId;

				Karma.storage[$child[0].KarmaMap] = {};



				// wow outerHTML will copy even elem.KarmaMap which screwed up my rebindings

				if(events) {

					for (var ev in Karma.storage[this[i].KarmaMap].KarmaEvent) {

						Karma.storage[$child[0].KarmaMap][ev] = [];

						for (var fn in Karma.storage[this[i].KarmaMap].KarmaEvent[ev])

							Karma.storage[$child[0].KarmaMap][ev][fn] = Karma.storage[this[i].KarmaMap].KarmaEvent[ev][fn];

					}

				}

			}

			else {

				clone.push(this[i].cloneNode(true));

				$child = Karma(clone[i]);

				

				if(events) {

					for (var ev in Karma.storage[this[i].KarmaMap].KarmaEvent) 

						for (var fn in Karma.storage[this[i].KarmaMap].KarmaEvent[ev]) 

							$child.bind( ev, Karma.storage[this[i].KarmaMap].KarmaEvent[ev][fn] );

				}

			}



		}



		return Karma(clone).stack(this);

	},



	wrap: function(str){

		for(var i=0;i<this.length;i++) {

			var	cloned = Karma(str, this[i].ownerDocument||this[i]).clone()[0];

				

			this[i].parentNode.replaceChild(cloned, this[i]);

			cloned.appendChild(this[i]);

		}

		return this;

	}



});



Karma.extend(Karma.temp, {

	manipulate: function (method, child, parent, query, ret) {

		var fragment = child[0];

		

		if (child.length > 1) {

			fragment = Karma.temp.fragment.cloneNode(false);

			

			for (var i=0; i< child.length; i++)

				fragment.appendChild(child[i]);

		}

		

		if (Karma.isHTML(query)) {

			var cloned = [];

				

			for (var i=0; i< parent.length; i++) {

				var newClones = parent.length > 1 ? fragment.cloneNode(true) : fragment;

				if (ret) {

					 if(newClones.nodeType === 11) {

						var children = Karma.makeArray(newClones.childNodes);

          				for(var j=0; j < children.length; j++)

           					 cloned.push(children[j]);

					 }

       				 else

          				cloned.push(newClones);

				}

				

				if (method == 'append')

					parent[i].appendChild(newClones);

				else if (method == 'prepend')

					parent[i].insertBefore(newClones, parent[i].firstChild);

				else if (method == 'before')

					parent[i].parentNode.insertBefore(newClones, parent[i]);

				else if (method == 'after') {

					parent[i].nextSibling ? 

						parent[i].parentNode.insertBefore(newClones, parent[i].nextSibling):

						parent[i].parentNode.appendChild(newClones);

				}

			}

			

			return ret ? Karma(cloned) : parent;

		}

		else if (method == 'append')

			parent[0].appendChild(fragment);

		else if (method == 'prepend')

			parent[0].insertBefore(fragment, parent[0].firstChild);

		else if (method == 'before')

			parent[0].parentNode.insertBefore(fragment, parent[0]);

		else if (method == 'after') {

			parent[0].nextSibling ? 

				parent[0].parentNode.insertBefore(fragment, parent[0].nextSibling):

				parent[0].parentNode.appendChild(fragment);

		}

		

		return ret ? child : parent;

	}

});




Karma.fn.extend({

	

	// walking the DOM, going forward or backward

	pedal: function(extreme, direction, query) {

		var elements = [];



		for (var i=0; i< this.length; i++) {

			var next=this[i][direction];



			while(next) {

				if (next.nodeType == 1) {

					elements.push(next);

					if (!extreme)

						break;

				}

				next = next[direction];

			}

	

		};

		

		elements = (Karma.isString(query)) ? Karma.Sizzle.filter(query, Karma.unique(elements)) : Karma.unique(elements);

		return Karma(elements).stack(this);

	},



	next: function(query) {

		return this.pedal(false, 'nextSibling' ,query);

	},

	

	nextAll: function(query) {

		return this.pedal(true, 'nextSibling' ,query);

	},



	prev: function(query) {

		return this.pedal(false, 'previousSibling' ,query);

	},

	

	prevAll: function(query) {

		return this.pedal(true, 'previousSibling' ,query);

	},

	

	siblings: function(query) {

		var $ = this, 

			siblings = [];

		

		for (var i=0; i< $.length; i++) {

			var origin = $[i],

				cur = $[i].parentNode;

			for(var j=0; j<cur.childNodes.length; j++) {

				var node = cur.childNodes[j]; 

				if(node.nodeType == 1 && node != origin)

					siblings.push(node);

			}

		}

		

		siblings = (Karma.isString(query)) ? Karma.Sizzle.filter(query, Karma.unique(siblings)) : Karma.unique(siblings);

		

		return Karma(siblings).stack(this);

	},

	

	parent: function(query) {

		var $ = this,

			parent = [];

			

		for (var i=0; i< $.length; i++) {

			if ($[i].parentNode)

				parent.push($[i].parentNode);

		}

	

		parent = (Karma.isString(query)) ? Karma.Sizzle.filter(query, Karma.unique(parent)) : Karma.unique(parent);

			

		return Karma(parent).stack(this);

	},

	

	ancestors: function(query) {

		var $ = this,

			ancestors = [];

		

		for (var i=0; i< $.length; i++) {

			var parent = $[i].parentNode;

			while(parent !== document) {

				ancestors.push(parent);

				parent = parent.parentNode || document;

			}

		}

		ancestors = (Karma.isString(query)) ? Karma.Sizzle.filter(query, Karma.unique(ancestors)) : Karma.unique(ancestorss);



		return Karma(ancestors).stack(this);

	},

	

	children: function(query) {

		var $ = this,

			children = [];

			

		for (var i=0; i< $.length; i++) {

			for(var j=0; j<$[i].childNodes.length; j++)

				if($[i].childNodes[j].nodeType == 1)

					children.push($[i].childNodes[j]);

		}

		

		if (Karma.isString(query))

			children = Karma.Sizzle.filter(query, children);

		

		return Karma(children).stack(this);

		

	},

	

	index: function(o){

		if (o) {

			var el = (o.nodeType) ? o : Karma(o)[0];

			return Karma.inArray(el, this);

		}

		else if (this[0]){

			return Karma.inArray(this[0], Karma(this[0].parentNode).children())

		}

		return -1;

	},

	

	slice: function(){

		return Karma(_Array.prototype.slice.apply(this, arguments)).stack(this);

	},

	

	eq: function( i ) {

		return i === -1 ?

			this.slice(i) :

			this.slice(i, +i + 1);

	},



	first: function() {

		return this.eq(0);

	},



	last: function() {

		return this.eq(-1);

	},

	

	// get elements as array, return the array

	get: function(num) {

		return Karma.isValue(num) ?

			Karma.makeArray(this) : 

			this[ num ];

	},

	

	toArray: function() {

		return this.get();

	},

	

	// possibly need to make the result unique, will see how people use the find method

	descendents: function(query) {

		var ret = [];

		for(var i=0; i<this.length; i++)

			ret = Karma.merge(ret, Karma.Sizzle(query, this[i]));

		

		return Karma(Karma.unique(ret)).stack(this);

	},

	

	filter: function(query) {

		return query ? Karma(Karma.Sizzle.filter(query, this)).stack(this) : this;

	},

	

	is: function(query) {

		return query ? !!Karma.Sizzle.filter(query, this).length : false;

	},

	

	not: function(query) {

		return query ? Karma(Karma.Sizzle(':not('+query+')', this)).stack(this) : this;

	},

	

	// adding elements

	add: function(query) {

		return query? Karma(this).populate(Karma(query), this.length).stack(this) : this;

	},

	

		// adding self to chain

	andSelf: function() {

		return this.KarmaStack.length ? Karma(this).populate(this.KarmaStack[0], this.length).stack(this): this;

	},

	

	each: function(fn){

		for (var i=0; i< this.length; i++)

			fn.call(this[i], i);

		return this;

	},

	

	map: function(fn) {

		var ret = [];

		for (var i=0; i< this.length; i++)

			ret.push(fn.call(this[i], i));

		return ret;

	},

	

	grep: function(fn) {

		var ret = [];

		for (var i=0; i< this.length; i++) {

			var result = fn.call(this[i], i);

			if (result !== false)

				ret.push(result);

		}

		return this;

	}

});



// for jQuery compatibility

Karma.fn.extend({

	find: Karma.fn.descendents,

	parents: Karma.fn.ancestors

});




Karma.fn.extend({

			 

	attr: function(prop, val){

		if(Karma.isString(prop) && (Karma.isValue(val))) {

			

			for(var i=0; i<this.length; i++) {

				if (Karma.temp.attrMap[prop] && Karma.isDefined(this[i][Karma.temp.attrMap[prop]]))

					this[i][Karma.temp.attrMap[prop]] = val;

				else if (prop == "style" && Karma.support.cssText)

					this[i].style.cssText = val;

				else {

					this[i].setAttribute(prop, val);

				}

			}

			return this;

		}

		// setting multiple property

		else if(Karma.isObject(prop)) {

			for (property in prop)

				this.attr(property, prop[property]);

			return this;

		}

		

		// getting property of first element

		return this.length? this[0].getAttribute(prop): null;

	},

	

	removeAttr: function(prop) {

		for(var i=0; i<this.length; i++) {

			if (Karma.temp.attrMap[prop] && Karma.isDefined(this[i][Karma.temp.attrMap[prop]]))

				this[i][Karma.temp.attrMap[prop]] = '';

			else if (prop == "style" && Karma.support.cssText) 

				this[i].style.cssText = '';



			try { this[i].removeAttribute(prop); } catch(e){};

		}

			

		return this;

	},

	

	data: function(key, value) {

		// key can be number or string

		// value can be anything even function except for undefined

		if(Karma.isDefined(value)) {

			for (var i=0; i< this.length; i++)

				Karma.data(this[i], key, value);

			return this;

		}

	

		return this[0] ? Karma.data(this[0], key) : null;

	},

	

	removeData: function(key) {

		if(Karma.isValue(key)) {

			for (var i=0; i< this.length; i++) {

				try { Karma.storage[this[i].KarmaMap].KarmaData[key] = null; } catch(e){}

			}

		}

		return this;

	},

	

	addClass: function(str){

		var _str = ' ' + str + ' ';

		

		for(var i=0; i< this.length; i++) {

			if (this[i].classList)

				this[i].classList.add(str);

			else {

				if( (' ' + this[i].className + ' ').indexOf(_str) < 0) 

					this[i].className.length ? this[i].className += ' ' + str : this[i].className = str;

			}

		}

			

		return this;

	},

	

	removeClass: function(str) {

		for(var i=0; i< this.length; i++)

			this[i].classList ? this[i].classList.remove(str) : this[i].className = Karma.trim(this[i].className.replace(str, ''));



		return this;

	},

	

	hasClass: function(str) {

		var _str = ' ' + str + ' ',

			ret = false;

		

		if(this.length)

			ret = this[0].classList ? this[0].classList.contains(str) : (' ' + this[0].className + ' ').indexOf(_str) >= 0;

		

		return ret;

	},

	

	toggleClass: function(str) {

		var _str = ' ' + str + ' ';

		for(var i=0; i< this.length; i++) {

			if(this[i].classList)

				this[i].classList.toggle(str);

			else {

				var classname = ' ' + this[i].className + ' ';

				this[i].className = classname.indexOf(_str) >= 0 ? classname.replace(_str, '') : classname += _str;

				this[i].className = Karma.trim(this[i].className);

			}

		}

		return this;

	},

	

	val: function(str){

		// setting values

		if(Karma.isValue(str)) { // if the str passed is a value

			for(var i=0; i< this.length; i++)

				if (Karma.isDefined(this[i].value)) // determine if the value property exists in the current element

					this[i].value = str;



			return this;

		}

		// getting value

		return (this[0] && Karma.isString(this[0].value)) ? this[0].value : null;

	},

	

	serialize: function() {

		var ret = '';

		for(var i=0; i< this.length; i++) {

			var name = this[i].getAttribute('name');

			if (name && name.length) {

				var value = this[i].value || '';

				

				if (this[i].nodeName.toLowerCase() == 'input' && this[i].getAttribute('type').toLowerCase() == 'checkbox' && !this[i].checked)

					ret += encodeURIComponent(name) + '=&';

				else

					ret += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';

			}

		}

		return ret.length ? ret.substring(0, ret.length-1) : '';

	}



});



Karma.extend({

	data: function(el, key, value) {

		// key can be number or string

		// value can be anything except for undefined

		if(Karma.isDefined(value)) {

			var map = 0;

			if (el !== window) 

				map = el.KarmaMap = el.KarmaMap || ++Karma.uniqueId;

				

			Karma.storage[map] = Karma.storage[map] || {};

			Karma.storage[map].KarmaData = Karma.storage[map].KarmaData || {};

			Karma.storage[map].KarmaData[key] = value;

		}

	

		return Karma.storage && Karma.storage[el.KarmaMap] && Karma.storage[el.KarmaMap].KarmaData && Karma.isDefined(Karma.storage[el.KarmaMap].KarmaData[key]) ? Karma.storage[el.KarmaMap].KarmaData[key] : null;

	}

});
Karma.extend({



	ajax: function(o) {



		o = Karma.extend({

			type: 'GET',

			data: null,

			url: '',

			contentType: null,

			cache: false,

			loading: function(){},

			success: function(){},

			error: function(){},

			XHR: window.XMLHttpRequest? new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP")

		 }, o);



		if (o.XHR === null || typeof o.XHR == "undefined" || !o.url.length) return;

		

		o.XHR.onreadystatechange=function(){

			try {

				if (o.XHR.readyState === 4 && !o.successDone){

					o.success(o.XHR.responseText);

					o.successDone = true;

				}

				

				if (o.XHR.status != 200 && !o.errorDone) {

					o.error(o.XHR.responseText);

					o.successDone = true;

					o.errorDone = true;

				}

			} catch(e) {};

		}

		var _url = o.url;

		if (o.type.toLowerCase() == 'get' && o.data)

			o.cache ? _url += '?karma_ts=' + new Date().getTime() + '&' + o.data : _url += '?' + o.data;

		

		

		o.XHR.open(o.type, _url, true);

		o.loading();

		

		if(o.contentType)

			o.XHR.setRequestHeader("Content-Type", o.contentType);

		

		(o.type.toLowerCase() == 'post' && o.data) ?

			o.XHR.send(o.data) :

			o.XHR.send(null);

	}



});




Karma.extend({



	getScript: function(url, success) {

		var counter = 0,

			script = [],

			isDone = false,

			mylength = url.length || 1;

		

		var callback = function(){

			counter++;

			

			if (!isDone && counter >= mylength) {

				isDone = true;

				success();

			}

		};



		for (var i = 0; i < mylength; i++) {

			script[i] = document.createElement('SCRIPT');

			script[i].type = 'text/javascript';

			script[i].src = url[i] || url;

			

			// prevent KB917927, also document.getElementsByTagName('head') is not always available

			document.documentElement.insertBefore(script[i], document.documentElement.firstChild);

			

			if (script[i].readyState) {

				script[i].onreadystatechange = function() {

					if (script[i].readyState == "loaded" || script[i].readyState == "complete") {

						script[i].onreadystatechange = null;

						callback();

					}

				}

			}

	

			else script[i].onload = callback;

		}

	}

});



Karma.include = Karma.getScript;




Karma.fn.extend({



	bind: function(str, fn, livequery) {

		if (!this.length || !Karma.isString(str) || !Karma.isFunction(fn)) return this;

	

		str = str.split(/\s+/);



		x:for(var j=0; j< str.length; j++) {

			var ns = str[j].split('.');

			if (Karma.event.special[ns[0]]) {

				var args = [];

				args.push(ns[1] ? '.'+ ns[1] : '');

				for(var i = 0; i < arguments.length; i++)

					if(Karma.isFunction(arguments[i]))

						args.push(arguments[i]);

						

				Karma.event.special[ns[0]].setup.apply(this, args);

				continue x;

			}

			

			for(var i=0; i< this.length; i++) {

				if (!(this[i].nodeType == 3 || this[i].nodeType == 8)) {

					var map = 0;

					if (this[i] !== window)

						map = this[i].KarmaMap = this[i].KarmaMap || ++Karma.uniqueId;

						

					Karma.storage[map] = Karma.storage[map] || {};

					

					var $ = Karma.storage[map].KarmaEvent = Karma.storage[map].KarmaEvent || {};

					

					$[ns[0]] = $[ns[0]] || [];

					

					if(livequery) {

						var data = Karma.data(this.context, 'KarmaLive') || {};

						data[ns[0]] = data[ns[0]] || {};

						data[ns[0]][livequery] = data[ns[0]][livequery] || [];

						

						if(ns.length == 1)

							data[ns[0]][livequery].push(fn);

						

						else if(ns.length == 2)

							data[ns[0]][livequery][ns[1]] = fn;

							

						Karma.data(this.context, 'KarmaLive', data);

					}

					

					else if (ns.length == 1)

						$[ns[0]].push(fn);

	

					else if (ns.length == 2)

						$[ns[0]][ns[1]] = fn;

						

					if(Karma.event.isSupported(ns[0])) {

						if(!Karma.isFunction(this[i]['on'+ns[0]]))

							this[i]['on'+ns[0]] = Karma.event.caller;

					}

					// custom event

					else if(document.addEventListener) {

						var total = 0;

						for(var event in $[ns[0]]) {

							total++;

						}

	

						if(!total)

							this[i].addEventListener(ns[0], Karma.event.caller, false);

					}

					// custom/proprietary event for M$

					else {

						this[i].customEvents = 0;

						if(!Karma.isFunction(this[i].onpropertychange))

							this[i].onpropertychange = Karma.event.caller;

					}

				}

			}

		}

		return this;

	},

		

	unbind: function(str, fn, livequery) {

		if (!str || !this.length) return this;

		var token = str.split(/\s+/);

		

		y:for(var j=0; j< token.length; j++) {

			var ns = token[j].split('.');

			if (Karma.event.special[ns[0]]) {

				var args = [];

				args.push(ns[1] ? '.'+ ns[1] : '');

				for(var i = 0; i < arguments.length; i++)

					if(Karma.isFunction(arguments[i]))

						args.push(arguments[i]);

						

				Karma.event.special[ns[0]].teardown.apply(this, args);

				continue y;

			}

			

			for(var i=0; i< this.length; i++) {

				var map = this === window ? 0 : this[i].KarmaMap;

				var data = Karma.data(this[i], 'KarmaLive');

				if (livequery) {

					if(data && data[ns[0]] && data[ns[0]][livequery]) {

						if (ns.length > 1) {

							data[ns[0]][livequery][ns[1]] = null;

							delete data[ns[0]][livequery][ns[1]];

						}

						else if (Karma.isFunction(fn)) {

							for (var fn in data[ns[0]][livequery])

								if (data[ns[0]][livequery][fn] == fn) {

									data[ns[0]][livequery][fn] = null;

									delete data[ns[0]][livequery][fn];

								}

						}

						else if(ns.length == 1) {

							data[ns[0]][livequery] = null;

							delete data[ns[0]][livequery];

						}

					}

				}



				else if (Karma.storage[map] && Karma.storage[map].KarmaEvent) {

					var $ = Karma.storage[map].KarmaEvent;

					if (ns.length > 1 && $[ns[0]]) {

						$[ns[0]][ns[1]] = null;

						delete $[ns[0]][ns[1]];

					}

					else if (Karma.isFunction(fn)) {

						for (var prop in $[ns[0]])

							if ($[ns[0]][prop] == fn) {

								$[ns[0]][prop] = null;

								delete $[ns[0]][prop];

							}

					}

					

					else if($[ns[0]]) {

						this[i]['on'+ns[0]] = null;

						delete $[ns[0]];

					}

				}

			}

		}

		return this;

	},

	

	one: function(str, fn) {

		this.on(str, fn);

					

		if (this.data('triggerOnce') === null);

			this.data('triggerOnce', []);

		

		this.data('triggerOnce').push(fn);

		

		return this;

		

	},

	

	triggerHandler: function(eventName) {

		this.trigger(eventName, true);

	},

	

	trigger: function(eventName, prevent) {

		try {

			for(var i=0; i<this.length; i++)

				var element = this[i];



			// W3C compatible browsers

			if(Karma.support.createEvent){

				

				// Safari 3 doesn't have window.dispatchEvent()

				if(!element.dispatchEvent)

					element=document; 

				

				var curEvent= Karma.event[eventName];

				

				if(curEvent){

					var event = document.createEvent(curEvent.type);

					curEvent.init(event, {});

					

					if(prevent) {

						event.stopPropagation();

						event.preventDefault();

					}

					

					element.dispatchEvent(event);

				}

				else {

					var fakeEvent = document.createEvent("UIEvents");

					fakeEvent.initEvent(eventName, false, false);

					

					if(prevent) {

						fakeEvent.stopPropagation();

						fakeEvent.preventDefault();

					}

					

					element.dispatchEvent(fakeEvent);

				}

			}

			// m$ methods

			else if(Karma.support.createEventObject){

				if(Karma.event.support[eventName]) {

					element = (element === document || element === window ) ? document.documentElement : element;

				

					var event = document.createEventObject();

					if(prevent) {

						event.cancelBubble = true;

						event.returnValue = false;

					}

					

					/*for(var property in properties)

						event[property]=properties[property];*/

		

					element.fireEvent("on"+eventName, event);

				}

				else {

					var current = Karma(element).data('fireEvent') || [];

					current.push(eventName);

					

					Karma(element).data('fireEvent', current);

					element.customEvents++;

				}

			}



		} catch(e){};

		

		return this;

	},

	

	// preventDefault and stopPropagation might not be 100% complete for live yet

	live: function(str, fn){

		return Karma(this.context).bind(str, fn, this.query);

	},

	

	die: function(str, fn) {

		return Karma(this.context).unbind(str, fn, this.query);

	}



});



// create events for w3c browser

if(Karma.support.createEvent)

Karma.event = {

	load:{

		type:"HTMLEvents",

		init: function(e){

			e.initEvent("load",false,false);

		}

	},

	

	unload:{

		type:"HTMLEvents",

		init:function(e){

			e.initEvent("unload",false,false);

		}

	},

	

	select:{

		type:"HTMLEvents",

		init:function(e){

			e.initEvent("select",true,false);

		}

	},

	

	change:{

		type:"HTMLEvents",

		init:function(e){

			e.initEvent("change",true,false);

		}

	},

	

	submit:{

		type:"HTMLEvents",

		init:function(e,p){

			e.initEvent("submit",true,true);

		}

	},

	

	reset:{

		type:"HTMLEvents",

		init:function(e){

			e.initEvent("reset",true,false);

		}

	},

	

	resize:{

		type:"HTMLEvents",

		init:function(e){

			e.initEvent("resize",true,false);

		}

	},

	

	scroll:{

		type:"HTMLEvents",

		init:function(e){

			e.initEvent("scroll",true,false);

		}

	},

	

	click:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("click",true,true,window,1,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	dblclick:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("click",true,true,window,2,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	mousedown:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("mousedown",true,true,window,1,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	mouseup:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("mouseup",true,true,window,1,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	mouseover:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("mouseover",true,true,window,1,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	mousemove:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("mousemove",true,true,window,1,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	mouseout:{

		type:"MouseEvents",

		init:function(e,p){

			e.initMouseEvent("mouseout",true,true,window,1,p.screenX||0,p.screenY||0,p.clientX||0,p.clientY||0,p.ctrlKey||false,p.altKey||false,p.shiftKey||false,p.metaKey||false,p.button||0,p.relatedTarget||null);

		}

	},

	

	focusin:{

		type:"UIEvents",

		init:function(e){

			e.initUIEvent("focusin",true,false,window,1);

		}

	},

	

	focusout:{

		type:"UIEvents",

		init:function(e){

			e.initUIEvent("focusout",true,false,window,1);

		}

	},

	

	activate:{

		type:"UIEvents",

		init:function(e){

			e.initUIEvent("activate",true,true,window,1);

		}

	},

	

	focus:{

		type:"UIEvents",

		init:function(e){

			e.initUIEvent("focus",false,false,window,1);

		}

	},

	

	blur:{

		type:"UIEvents",

		init:function(e){

			e.initUIEvent("blur",false,false,window,1);

		}

	}

}



else Karma.event = {};



Karma.event.support = {};

Karma.event.special = {

	hover: {

		setup: function(ns, fn, fn2, livequery){

			this.bind('mouseover' + ns, function(e){ 

				e.stopPropagation();

				return fn.call(this, e); 

			}, livequery).bind('mouseout' + ns, function(e){ 

				e.stopPropagation();

				return fn2.call(this, e); 

			}, livequery);

		},

		teardown: function(ns, fn, fn2, livequery){

			this.unbind('mouseover' + ns, fn, livequery).unbind('mouseout'+ ns, fn2, livequery);

		}

	},

	

	mouseenter: {

		setup: function(ns, fn, livequery){

			this.bind('mouseover'+ ns, function(e) {

				e.stopPropagation();

				return fn.call(this, e); 

			}, livequery);

		},

		

		teardown: function(ns, fn, livequery){

			this.unbind('mouseover'+ ns, fn, livequery);

		}

	},

	

	mouseleave: {

		setup: function(ns, fn, livequery){

			this.bind('mouseout' + ns, function(e){

				e.stopPropagation();

				return fn.call(this, e);

			}, livequery);

		},

		

		teardown: function(ns, fn, livequery){

			this.unbind('mouseout' + ns, fn, livequery);

		}

	}

}



// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/

Karma.event.isSupported = function(eventName, element) {

	if (eventName in Karma.event.support && !element) return Karma.event.support[eventName];



	var TAGNAMES = {

			'select':'input',

			'change':'input',

			'submit':'form',

			'reset':'form',

			'error':'img',

			'load':'img',

			'abort':'img'

		}, 

	

		el = element ? 

				element : 

					TAGNAMES[eventName] ? 

						document.createElement(TAGNAMES[eventName]) : 

						Karma.temp.div,	

		

		onEventName = 'on' + eventName,

		isSupported = onEventName in el;



	

	if (!isSupported && el.setAttribute && el.removeAttribute) {

		el.setAttribute(onEventName, 'return;');

		isSupported = typeof el[onEventName] == 'function';

		

		if (onEventName in el)

        	el[onEventName] = void 0;



	}

	

	// last test

	if (!isSupported && !element) {

		isSupported = onEventName in window;

	}

	

	el = null;

	Karma.event.support[eventName] = isSupported;

	return isSupported;

}



// caller the determines how events are fired, also normalizes events

// hardest freakin bitch function to code in Karmagination

Karma.event.caller = function(e) {

	var cur_map = this === window ? 0 : this.KarmaMap;

	e = window.event || e;

	

	// some basic normalization of event

	if(!e.stopPropagation && window.event) 

		e.stopPropagation = function(){ window.event.cancelBubble = true; };

	

	if(!e.preventDefault && window.event)

		e.preventDefault = function(){ window.event.returnValue = false; };

		

	if(!e.target && e.srcElement)

		e.target = e.srcElement || document;

	

	try {

		if(e.type == 'mouseover' && !('relatedTarget' in e))

			 e.relatedTarget = e.fromElement;

	

		else if(e.type == 'mouseout' && !('relatedTarget' in e))

			e.relatedTarget = e.toElement;

			

		if(e.wheelDelta) {

			e.wheelDiff = e.wheelDelta/120;

			if(Karma.isOpera)

				e.wheelDiff = -e.wheelDiff;

		}

		else if (e.detail)

			e.wheelDiff = -e.detail/3;

			

		// fix for safari textnode

		if (e.target.nodeType == 3)

			e.target = e.target.parentNode;



		// Calculate pageX/Y if missing and clientX/Y available

		if ( e.pageX == null && e.clientX != null ) {

			var doc = document.documentElement, body = document.body;

			e.pageX = e.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);

			e.pageY = e.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);

		}

	

		// Add which for key events

		if ( !e.which && ((e.charCode || e.charCode === 0) ? e.charCode : e.keyCode) )

			e.which = e.charCode || e.keyCode;

	

		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)

		if ( !e.metaKey && e.ctrlKey )

			e.metaKey = e.ctrlKey;

	

		// Add which for click: 1 == left; 2 == middle; 3 == right

		// Note: button is not normalized, so don't use it

		if ( !e.which && e.button )

			e.which = (e.button & 1 ? 1 : ( e.button & 2 ? 3 : ( e.button & 4 ? 2 : 0 ) ));

		

	} catch(e){}

	

	var live = Karma.data(this.ownerDocument || document, 'KarmaLive');

	if (live && live[e.type]) {

		var passed = [],

			node = [],

			ancestors = [],

			cur = e.target;

		

		// get a list of ancestors e.target including e.target

		while(cur) {

			ancestors.push(cur);

			cur = cur.parentNode;

		}



		// see which live query is more specific to the e.target

		for(var query in live[e.type]) {

			var result = Karma.Sizzle.filter(query, ancestors);

			if (result.length) {

				for(var i = 0; i < ancestors.length; i++) {

					if (ancestors[i] === result[0]) {

						passed[i] = query;

						node[i] = result[0];

					}

				}

			}

		}

		

		// stop event done 99% right, WOOT

		for(var i=0; i < passed.length; i++) {

			if (passed[i] && live[e.type][passed[i]]) {

				var stopped = 0;

				for(var stacked in live[e.type][passed[i]]) {

					if(live[e.type][passed[i]][stacked].call(node[i], e) === false) {

						e.preventDefault();

						e.stopPropagation();

						stopped++;

					}

				}

				if (stopped) break;

			}

		}

	}

		

	if(e.propertyName == "customEvents") {

		var events = $(this).data('fireEvent');

		

		for(var index in events) {

			try {

				for(var functions in Karma.storage[cur_map].KarmaEvent[events[index]]) {

					if(Karma.storage[cur_map].KarmaEvent[events[index]][functions].call(this, e) === false) {

						e.stopPropagation();

						e.preventDefault();	

					}	

				}

				events[index] = null;

			} 

			catch(e){};

		}

		$(this).data('fireEvent', events);

	}

	

	else if(Karma.storage[cur_map] && Karma.storage[cur_map].KarmaEvent && Karma.storage[cur_map].KarmaEvent[e.type]) {

		for(var functions in Karma.storage[cur_map].KarmaEvent[e.type]) {

			if(Karma.storage[cur_map].KarmaEvent[e.type][functions].call(this, e) === false) {

				e.stopPropagation();

				e.preventDefault();	

			}

			

			var once = Karma(this).data('triggerOnce');

			if(once) {

				for (var i = 0; i < once.length; i++) {

					if(once[i] === Karma.storage[cur_map].KarmaEvent[e.type][functions]) {

						Karma.storage[cur_map].KarmaEvent[e.type][functions] = null;

						delete Karma.storage[cur_map].KarmaEvent[e.type][functions];

					}

				}

			}

			

		}

	}

}




Karma.fn.extend({

	style: function(property, value) {

		if (Karma.isString(property) && Karma.isValue(value))

			return this.setStyle(property, value);

			

		if (Karma.isObject(property)) {

			for(var current in property)

				this.setStyle(current, property[current]);

			return this;

		}



		return this.getStyle(property);

	},



	setStyle: function(property, value){

		if(!this.length) return this;

		

		property = Karma.camelCase(property);		



		if (property == 'opacity') {

			for (var i=0; i < this.length; i++) {

				// webkit and opera support filter, which is BS

				// lesson learnt: feature test W3C standard before proprietary standard 

				if(Karma.support.opacity) this[i].style.opacity = value;

				// if we have full opacity, better to remove it to restore the antialiasing ability of IE

				else if(Karma.support.filter) {

					// OMFG, MS needs hasLayout for opacity, or it will just work on body

					this[i].style.zoom = 1;

					this[i].style.filter = (parseInt(value, 10) == 1) ? '' : 'alpha(opacity=' + (value * 100) + ')';

				}

			}

			

			return this;

		}

		

		if (property == 'scrollTop' || property == 'scrollLeft') {

			for (var i=0; i < this.length; i++) {

				if (this[i] === document.documentElement || this[i] === document || this[i] === document.body || this[i] === window) {

					document.body[property] = value;

					document.documentElement[property] = value;

				}

				else

					this[i][property] = value;

			}

			return this;

		}

		

		if (property == 'float')

			property = Karma.support.styleFloat ? 'styleFloat' : 'cssFloat';

		

		// concat integers/integer-like strings with px;

		var curval = +value;

		if ( curval || curval === 0 ) value = curval + 'px';

		

		

		if(Karma.isString(value)) // just to be safe

		for (var i=0; i < this.length; i++)

			this[i].style[property] = value;

		

		return this;

	},

	

	getStyle: function(property) {

		if(!this.length) return null;

		

		property = Karma.camelCase(property);

		

		if (property == 'scrollTop' || property == 'scrollLeft')

			return (this[0]===document || this[0]===document.documentElement || this[0]===window)? document.body[property]: this[0][property];

		

		if (property == 'float')

			property = Karma.support.styleFloat ? 'styleFloat' : 'cssFloat';

		

		else if (property == 'opacity' && this[0].filters) {

			// i didn't want to use try catch but this mfker throws error

			try { var opacity = this[0].filters('alpha').opacity; }	catch(e){ return 1; }

			return opacity/100;

		}

		

		// check if the current node is stylable or not, i.e. window cannot be styled

		if(this[0].style) {

			// ie	

			if (this[0].currentStyle) {

				if (this[0].currentStyle[property] == 'auto' && this[0].style[property] == '') {

					if(/width|height/i.test(property)) return this.width();

					if(/left|top|right|bottom/i.test(property)) return 0;

				}



				return this[0].currentStyle[property] ? this[0].currentStyle[property] : this[0].style[property];

			}

			// w3c

			else if ( "getComputedStyle" in document.defaultView ) {

				var computed = document.defaultView.getComputedStyle(this[0], null)[property];

				

				if (!computed || !computed.length) computed = this[0].style[property];

							

				if (property.toLowerCase().indexOf('color') >= 0) {

					var color = computed.match(/rgba?\([\d\s,]+\)/);

					if (color)

						computed = Karma.rgbToHex(color[0].match(/\d{1,3}/g));

				}

				return computed;

			}

		}

		return '';

	},

	

	dimension: function(name, border){

		if(!this.length) return null;

		return this[0] === window ?

			// use document.documentElement or document.body depending on Quirks vs Standards mode

			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :

			// Get document width or height

			this[0] === document ?

				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater

				Math.max(

					document.documentElement["client" + name],

					document.body["scroll" + name], document.documentElement["scroll" + name],

					document.body["offset" + name], document.documentElement["offset" + name]

				) :

				border ?

					this[0]['offset'+name]:

					this[0]['client'+name];

	},

	

	width: function(val){

		return Karma.isValue(val) ? this.setStyle('width', val) : this.dimension('Width') - (parseInt(this.getStyle('paddingLeft'), 10) || 0) - (parseInt(this.getStyle('paddingRight'), 10) || 0);

	},

	

	height: function(val){

		return Karma.isValue(val) ? this.setStyle('height', val) : this.dimension('Height') - (parseInt(this.getStyle('paddingTop'), 10) || 0) - (parseInt(this.getStyle('paddingBottom'), 10) || 0);

	},

	

	innerWidth: function(){

		return this.dimension('Width');

	},

	

	innerHeight: function(val){

		return this.dimension('Height');

	},

	

	outerWidth: function(val, margin){

		var marginLeft = margin ? parseInt(this.css('marginLeft'), 10) || 0 : 0,

			marginRight = margin ? parseInt(this.css('marginRight'), 10) || 0 : 0;

		return this.dimension('Width', 1) + marginLeft + marginRight;

	},

	

	outerHeight: function(val, margin){

		var marginTop = margin ? parseInt(this.css('marginTop'), 10) || 0 : 0,

			marginBottom = margin ? parseInt(this.css('marginBottom'), 10) || 0 : 0;

		return this.dimension('Height', 1) + marginTop + marginBottom;

	},



	offset: function() {

		if (!this[0]) return null;

		// w3c

		Karma.calculateOffset();

		if (document.documentElement.getBoundingClientRect) {

			if ( this[0] === (this[0].ownerDocument||this[0]).body ) {

				var top = this[0].offsetTop, left = this[0].offsetLeft;

				if ( Karma.support.offsetDoesNotIncludeMarginInBodyOffset )

					top  += parseInt(this.css('marginTop'), 10) || 0,

					left += parseInt(this.css('marginLeft'), 10 ) || 0;

				return { top: top, left: left };

			}

			

			var box  = this[0].getBoundingClientRect(), 

				doc = this[0].ownerDocument || doc, 

				body = doc.body, 

				docElem = doc.documentElement,

				clientTop = docElem.clientTop || body.clientTop || 0, 

				clientLeft = docElem.clientLeft || body.clientLeft || 0,

				top  = box.top  + (self.pageYOffset || Karma.support.boxModel && docElem.scrollTop || body.scrollTop) - clientTop,

				left = box.left + (self.pageXOffset || Karma.support.boxModel && docElem.scrollTop || body.scrollLeft) - clientLeft;

			

			return { top: top, left: left };

		}

		// m$

		else {

			var elem = this[0], 

				offsetParent = elem.offsetParent, 

				prevOffsetParent = elem,

				doc = elem.ownerDocument || elem, 

				computedStyle, 

				docElem = doc.documentElement,

				body = doc.body, 

				defaultView = doc.defaultView,

				prevComputedStyle = defaultView.getComputedStyle(elem, null),

				top = elem.offsetTop, 

				left = elem.offsetLeft;

	

			while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {

				computedStyle = defaultView.getComputedStyle(elem, null);

				top -= elem.scrollTop, 

				left -= elem.scrollLeft;

				

				if ( elem === offsetParent ) {

					top += elem.offsetTop, 

					left += elem.offsetLeft;

					if ( Karma.support.offsetDoesNotAddBorder && !(Karma.support.offsetDoesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )

						top  += parseInt( computedStyle.borderTopWidth,  10) || 0,

						left += parseInt( computedStyle.borderLeftWidth, 10) || 0;

					prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;

				}

				

				if ( Karma.support.offsetSubtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )

					top  += parseInt( computedStyle.borderTopWidth,  10) || 0,

					left += parseInt( computedStyle.borderLeftWidth, 10) || 0;

				prevComputedStyle = computedStyle;

			}

	

			if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )

				top  += body.offsetTop,

				left += body.offsetLeft;

	

			if ( prevComputedStyle.position === "fixed" )

				top  += Math.max(docElem.scrollTop, body.scrollTop),

				left += Math.max(docElem.scrollLeft, body.scrollLeft);

	

			return { top: top, left: left };			

			

		}

	},

	

	position: function() {

		var left = 0, top = 0, results = null;



		if ( this[0] ) {

			// Get *real* offsetParent

			var offsetParent = this.offsetParent(),

				offsetDoc = offsetParent.ownerDocument || offsetParent,



			// Get correct offsets

			offset       = this.offset(),

			parentOffset = (offsetDoc.documentElement === offsetParent || offsetDoc.body === offsetParent) ? { top: 0, left: 0 } : offsetParent.offset();



			// Subtract element margins

			// note: when an element has margin: auto the offsetLeft and marginLeft 

			// are the same in Safari causing offset.left to incorrectly be 0

			offset.top  -= parseInt( this.css('marginTop'), 10 ) ||  0;

			offset.left -= parseInt( this.css('marginLeft'), 10 ) ||  0;



			// Add offsetParent borders

			parentOffset.top  += parseInt( Karma(offsetParent).css('borderTopWidth'), 10 ) || 0;

			parentOffset.left += parseInt( Karma(offsetParent).css('borderLeftWidth'), 10 ) || 0;



			// Subtract the two offsets

			results = {

				top:  offset.top  - parentOffset.top,

				left: offset.left - parentOffset.left

			};

		}



		return results;

	},

	

	offsetParent: function() {

		var offsetParent = this[0].offsetParent || document.body,

			offsetDoc = offsetParent.ownerDocument || offsetParent;

		while ( offsetParent && offsetParent !== offsetDoc.documentElement && offsetParent !== offsetDoc.body && Karma(offsetParent).css('position') == 'static')

			offsetParent = offsetParent.offsetParent;

		return Karma(offsetParent);

	},

	

	scrollTop: function() {

		return this.css('scrollTop');

	},

	

	scrollLeft: function() {

		return this.css('scrollLeft');

	}	

});



Karma.fn.css = Karma.fn.style;



Karma.extend({

	camelCase: function(property) {

		if (Karma.temp.camelCase[property]) {

			property = Karma.temp.camelCase[property];

		}

		else {

			property = Karma.temp.camelCase[property] = property.replace(/\-(\w)/g, function(all, letter){ return letter.toUpperCase(); });

		}

		

		return property;

	},

	

	rgbToHex: function(array){

		if (array.length < 3) return null;

		if (array.length == 4 && array[3] == 0 && !array) return 'transparent';

		var hex = [];

		for (var i = 0; i < 3; i++){

			var bit = (array[i] - 0).toString(16);

			hex.push((bit.length == 1) ? '0' + bit : bit);

		}

		return '#' + hex.join('');

	},

	

	calculateOffset: function(){

		if (Karma.temp.calculatedOffsets) return;

		

		var offset = new Karma.temp.offsets();

		Karma.extend(Karma.support, {

			offsetDoesNotAddBorder: offset.doesNotAddBorder,

			offsetDoesAddBorderForTableAndCells: offset.doesAddBorderForTableAndCells,

			offsetSubtractsBorderForOverflowNotVisible: offset.subtractsBorderForOverflowNotVisible,

			offsetDoesNotIncludeMarginInBodyOffset: offset.doesNotIncludeMarginInBodyOffset

		});

		

		Karma.temp.calculatedOffsets = true;

	}

});




Karma.fn.extend({

	stop: function(){

		for(var i = 0; i < this.length; i++) {

			var KarmaFX = Karma.data(this[i], 'KarmaFX');

			for(var iter in KarmaFX)

				clearInterval(KarmaFX[iter].timer);

		}

		

		return this.data('KarmaFX', null);

	},

	

	// do not calculate and store upfront, calculate on animating iteration hit

	// reason, css props can change in the middle

	animate: function(attributes, dur, callback, easing, step){

		if (!Karma.isGenericObject(attributes) || !this.length) return this;

		

		// do this for scoping issues with internal functions

		var els = this, duration, queue;

		

		if (Karma.isGenericObject(dur)) {

			duration = parseInt(dur.duration);

			if (!duration && duration !== 0)

				duration = 500;

				

			easing = dur.easing || Karma.easing.global;

			callback = dur.complete || null;

			step = dur.step || null;

			queue = dur.queue || true;

		}

		else {

			// default values

			duration = parseInt(dur, 10);

			if (!duration && duration !== 0)

				duration = 500;

	

			easing = easing || Karma.easing.global;

			callback = callback || null;

			step = step || null;

			queue = true;

		}

		// setup initial KarmaFX data structure

		

		

		for(var i=0; i<els.length; i++) {

			var FX = {

				start: {},

				end: {},

				duration: duration,

				callback: callback,

				attributes: attributes,

				easing: easing,

				step: step,

				queue: queue

			};



			var $cur = Karma(els[i]),

				KarmaFX = $cur.data('KarmaFX', $cur.data('KarmaFX') || []).data('KarmaFX');



			// get starting/ending attributes

			// we need to calculate end cause we are converting values like em, etc to px

			KarmaFX.push(Karma.temp.populateStartEndValues($cur, FX, attributes));

			Karma.temp.animate($cur);

		}



		return this;

	}

});



Karma.temp.populateStartEndValues = function($curEl, FX, attributes) {

	for (var prop in attributes) {

		// get the current unanimated attribute

		FX.start[prop] = $curEl.getStyle(prop);

		FX.start[prop] = +FX.start[prop] || parseInt(FX.start[prop], 10);

		

		var cur_prop = +attributes[prop];



		// get start properties and convert to integer or float

		// set the final attribute if they are in numbers, no calculation

		if (cur_prop || cur_prop === 0) {

			FX.end[prop] = cur_prop;

		}

		

		// else we have to detemine the end attributes, ie 1.6 em = how many px

		else {

			// these are strings

			//var val = Karma.trim(attributes[prop]);

			var val = attributes[prop];

			

			// need to add or substract determined from original value

			if (val.indexOf('+=') >= 0 || val.indexOf('-=') >= 0) {

			

				var cur_val = val.replace('+=','').replace('-=',''),

					temp_val = +cur_val;

				

				// number looks like strings, means all digits /\d/ or has a unit of pixel

				if (temp_val || temp_val === 0 || val.indexOf('px') > 0)

					cur_val = temp_val || parseInt(cur_val, 10);

				

				// other units, opacity, will not hit this so no problem to parseInt

				else {

					cur_val = parseInt($curEl.setStyle(prop, cur_val).getStyle(prop), 10);

					$curEl.setStyle(prop, FX.start[prop]); // revert to start value

				}

				

				FX.end[prop] = (val.indexOf('+=') == 0) ? FX.start[prop] + cur_val : FX.start[prop] - cur_val;

			}

	

			// set the final attribute if they are in pixels, no calculation

			else if (val.indexOf('px') > 0) {

				FX.end[prop] = parseInt(val, 10);

			}

			

			// all other units like em, pt

			// using parseInt cause returned value by browser is px

			else {

				FX.end[prop] = parseInt($curEl.setStyle(prop, val).getStyle(prop), 10);

				$curEl.setStyle(prop, FX.start[prop]); // revert to start value

			}

		}

	}

		

	return FX;

}



Karma.temp.animate = function($cur) {

	var KarmaFX = $cur.data('KarmaFX');

	if (KarmaFX.length == 1) {

		var iter = 0,

			startTimer = new Date().getTime(),

			endTimer = startTimer + (KarmaFX[iter].duration || 0),

			timer;

			

		KarmaFX[iter].timer = timer = setInterval(function FX_first(){

			var curTime = new Date().getTime();

			

			if (!KarmaFX)

				clearInterval(timer);

				

			// a frame value between start and end

			else if(curTime < endTimer)

				currentFrame(curTime - startTimer, KarmaFX[iter].end);

			

			// last frame

			else 

				completeAnimation();



		}, 13); // try to run every 13ms

		

		var currentFrame = function(elapsed, attr){

			for (var prop in attr) {

				var start = KarmaFX[iter].start[prop],

					end = KarmaFX[iter].end[prop],

					duration = KarmaFX[iter].duration,					

					curval = KarmaFX[iter].easing(elapsed, start, end-start, duration);

				

				$cur.setStyle(prop, curval);

				if (KarmaFX && KarmaFX[iter] && KarmaFX[iter].step)	KarmaFX[iter].step(+curval);

			}

			// just executing on every step

			//if (KarmaFX && KarmaFX[iter] && KarmaFX[iter].step)	KarmaFX[iter].step();

		}

		

		var completeAnimation = function(){

			clearInterval(timer);

			

			// set to end values;

			if(KarmaFX && KarmaFX[iter]) {

				if (KarmaFX[iter].callback)

					KarmaFX[iter].callback();

			

				$cur.css(KarmaFX[iter].end);

			}

			

			KarmaFX[iter] = null;

			iter++;

			

			// if there's no next item, do a clean up

			if(KarmaFX.length && !KarmaFX[iter]) {

				$cur.data('KarmaFX', null);

			}

			

			// start the next animation queue in stack

			else {

				var startTimer = new Date().getTime(),

					endTimer = startTimer + KarmaFX[iter].duration;

					

				for (var prop in KarmaFX[iter].end)

					Karma.temp.populateStartEndValues($cur, KarmaFX[iter], KarmaFX[iter].attributes);



				KarmaFX[iter].timer = timer = setInterval(function FX_next(){

					var curTime = new Date().getTime();

					

					if(!KarmaFX)

						clearInterval(timer);



					// a frame value between start and end

					else if(curTime < endTimer){

						currentFrame(curTime - startTimer, KarmaFX[iter].end);

					}

					// last frame

					else { 

						completeAnimation();

					}

				}, 13); // try to run every 13ms

			}

		}

	}

}



Karma.easing = {

	easeIn: function (t, b, c, d) {

    	return c*(t/=d)*t + b;

    }

};



Karma.easing.global = Karma.easing.easeIn;


Karma.extend({

			 

	// method to namespace function, taking a chapter from YUI,

	// Ariel Flesler created this function, during a discussion in jQuery mailing list when I was a n00b using eval

	// http://groups.google.com/group/jquery-en/browse_thread/thread/95d1ceabe4bda4eb/c6fd0c270f91426e?q=#c6fd0c270f91426e

	namespace: function(name, root) {

		if (Karma.isString(name)) {

			// explode namespace with delimiter

		    name = name.split(".");

			// root is defaulted to window obj

		    var ns = root || window;

			// loop through each level of the namespace

		    for (var i =0; i<name.length; i++) {

				// nm is current level name

		    	var nm = name[i];

				// if not exist, add current name as obj to parent level, assign ns (parent) to current

				ns = ns[nm] || ( ns[nm] = {} ); 

				

				if (i == name.length-1) 

					return (typeof ns == 'function' || typeof ns == 'object') ? ns: false;

			}

		}

	},

	

	each: function(o, fn){

		for (var i = 0; i < o.length; i++) {

			fn.call(o[i], i, o[i]);

		}

	},

	

	trim: function(str){

		/* Thanks to Steven Levithan's benchmark on string trimming */

		// unicode friendly string trim for older browsers that don't catch all whitespaces

		// string.trim() is in JS 1.8.1, supported by FF 3.5

		// Using Luca Guidi's string trim for non native trim method

		if(!Karma.isString(str)) return str;

		

		if(str.trim)

		   return str.trim();

		

		var ws = /[\s\xA0]/, _start = 0, end = str.length;

		while(ws.test(str.charAt(_start++)));

		while(ws.test(str.charAt(--end)));

		return str.slice(_start - 1, end + 1);

	},

			 

	grep: function(o, fn) {

		if (o.filter)

			return o.filter(fn);

		

		var ret = new Array(o.length);

		// Go through the array, only saving the items that pass the validator function

		for (var i = 0, j = 0; i < o.length; i++)

			if (fn(o[i], i) !== false)

				ret[j++] = o[i];



		return ret;

	},



	inArray: function(el, o){

		for (var i = 0; i < o.length; i++)

			if (o[i] === el)

				return i;

		return -1;

	},

	

	map: function(o, fn) {

		if (o.map)

			return o.map(fn);



		var array = new Array(o.length);

		for ( var i = 0; i < o.length; i++ ) 

			array[i] = fn(o[i], i);

		return array;



	},

	

	// merge all arrays

	merge: function(){

		return _Array.prototype.concat.apply([], arguments);

	}

});


Karma.Class = function(opts){

	

	opts.construct = opts.construct || function(){};

	

	opts.construct.adds = function(option){

		for (var prop in option)

			if (prop !== 'construct') 

				opts.construct.prototype[prop] = option[prop];

	};

	

	opts.construct.inherits = function(parent){

   		opts.construct.prototype.__proto__ = parent.prototype;

		opts.construct.prototype.parent = parent;

	}

	

	for (var prop in opts)

		if (prop !== 'construct') 

			opts.construct.prototype[prop] = opts[prop];

	

	return opts.construct;

};




/*!

 * Sizzle CSS Selector Engine - v1.0

 *  Copyright 2009, The Dojo Foundation

 *  Released under the MIT, BSD, and GPL Licenses.

 *  More information: http://sizzlejs.com/

 */

(function(){



var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,

	done = 0,

	toString = Object.prototype.toString,

	hasDuplicate = false;



var Sizzle = function(selector, context, results, seed) {

	results = results || [];

	var origContext = context = context || document;



	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {

		return [];

	}

	

	if ( !selector || typeof selector !== "string" ) {

		return results;

	}



	var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context);

	

	// Reset the position of the chunker regexp (start from head)

	chunker.lastIndex = 0;

	

	while ( (m = chunker.exec(selector)) !== null ) {

		parts.push( m[1] );

		

		if ( m[2] ) {

			extra = RegExp.rightContext;

			break;

		}

	}



	if ( parts.length > 1 && origPOS.exec( selector ) ) {

		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {

			set = posProcess( parts[0] + parts[1], context );

		} else {

			set = Expr.relative[ parts[0] ] ?

				[ context ] :

				Sizzle( parts.shift(), context );



			while ( parts.length ) {

				selector = parts.shift();



				if ( Expr.relative[ selector ] )

					selector += parts.shift();



				set = posProcess( selector, set );

			}

		}

	} else {

		// Take a shortcut and set the context if the root selector is an ID

		// (but not if it'll be faster if the inner selector is an ID)

		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&

				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {

			var ret = Sizzle.find( parts.shift(), context, contextXML );

			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];

		}



		if ( context ) {

			var ret = seed ?

				{ expr: parts.pop(), set: makeArray(seed) } :

				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );

			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;



			if ( parts.length > 0 ) {

				checkSet = makeArray(set);

			} else {

				prune = false;

			}



			while ( parts.length ) {

				var cur = parts.pop(), pop = cur;



				if ( !Expr.relative[ cur ] ) {

					cur = "";

				} else {

					pop = parts.pop();

				}



				if ( pop == null ) {

					pop = context;

				}



				Expr.relative[ cur ]( checkSet, pop, contextXML );

			}

		} else {

			checkSet = parts = [];

		}

	}



	if ( !checkSet ) {

		checkSet = set;

	}



	if ( !checkSet ) {

		throw "Syntax error, unrecognized expression: " + (cur || selector);

	}



	if ( toString.call(checkSet) === "[object Array]" ) {

		if ( !prune ) {

			results.push.apply( results, checkSet );

		} else if ( context && context.nodeType === 1 ) {

			for ( var i = 0; checkSet[i] != null; i++ ) {

				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {

					results.push( set[i] );

				}

			}

		} else {

			for ( var i = 0; checkSet[i] != null; i++ ) {

				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {

					results.push( set[i] );

				}

			}

		}

	} else {

		makeArray( checkSet, results );

	}



	if ( extra ) {

		Sizzle( extra, origContext, results, seed );

		Sizzle.uniqueSort( results );

	}



	return results;

};



Sizzle.uniqueSort = function(results){

	if ( sortOrder ) {

		hasDuplicate = false;

		results.sort(sortOrder);



		if ( hasDuplicate ) {

			for ( var i = 1; i < results.length; i++ ) {

				if ( results[i] === results[i-1] ) {

					results.splice(i--, 1);

				}

			}

		}

	}

};



Sizzle.matches = function(expr, set){

	return Sizzle(expr, null, null, set);

};



Sizzle.find = function(expr, context, isXML){

	var set, match;



	if ( !expr ) {

		return [];

	}



	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {

		var type = Expr.order[i], match;

		

		if ( (match = Expr.match[ type ].exec( expr )) ) {

			var left = RegExp.leftContext;



			if ( left.substr( left.length - 1 ) !== "\\" ) {

				match[1] = (match[1] || "").replace(/\\/g, "");

				set = Expr.find[ type ]( match, context, isXML );

				if ( set != null ) {

					expr = expr.replace( Expr.match[ type ], "" );

					break;

				}

			}

		}

	}



	if ( !set ) {

		set = context.getElementsByTagName("*");

	}



	return {set: set, expr: expr};

};



Sizzle.filter = function(expr, set, inplace, not){

	var old = expr, result = [], curLoop = set, match, anyFound,

		isXMLFilter = set && set[0] && isXML(set[0]);



	while ( expr && set.length ) {

		for ( var type in Expr.filter ) {

			if ( (match = Expr.match[ type ].exec( expr )) != null ) {

				var filter = Expr.filter[ type ], found, item;

				anyFound = false;



				if ( curLoop == result ) {

					result = [];

				}



				if ( Expr.preFilter[ type ] ) {

					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );



					if ( !match ) {

						anyFound = found = true;

					} else if ( match === true ) {

						continue;

					}

				}



				if ( match ) {

					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {

						if ( item ) {

							found = filter( item, match, i, curLoop );

							var pass = not ^ !!found;



							if ( inplace && found != null ) {

								if ( pass ) {

									anyFound = true;

								} else {

									curLoop[i] = false;

								}

							} else if ( pass ) {

								result.push( item );

								anyFound = true;

							}

						}

					}

				}



				if ( found !== undefined ) {

					if ( !inplace ) {

						curLoop = result;

					}



					expr = expr.replace( Expr.match[ type ], "" );



					if ( !anyFound ) {

						return [];

					}



					break;

				}

			}

		}



		// Improper expression

		if ( expr == old ) {

			if ( anyFound == null ) {

				throw "Syntax error, unrecognized expression: " + expr;

			} else {

				break;

			}

		}



		old = expr;

	}



	return curLoop;

};



var Expr = Sizzle.selectors = {

	order: [ "ID", "NAME", "TAG" ],

	match: {

		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,

		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,

		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,

		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,

		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,

		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,

		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,

		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/

	},

	attrMap: {

		"class": "className",

		"for": "htmlFor"

	},

	attrHandle: {

		href: function(elem){

			return elem.getAttribute("href");

		}

	},

	relative: {

		"+": function(checkSet, part, isXML){

			var isPartStr = typeof part === "string",

				isTag = isPartStr && !/\W/.test(part),

				isPartStrNotTag = isPartStr && !isTag;



			if ( isTag && !isXML ) {

				part = part.toUpperCase();

			}



			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {

				if ( (elem = checkSet[i]) ) {

					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}



					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?

						elem || false :

						elem === part;

				}

			}



			if ( isPartStrNotTag ) {

				Sizzle.filter( part, checkSet, true );

			}

		},

		">": function(checkSet, part, isXML){

			var isPartStr = typeof part === "string";



			if ( isPartStr && !/\W/.test(part) ) {

				part = isXML ? part : part.toUpperCase();



				for ( var i = 0, l = checkSet.length; i < l; i++ ) {

					var elem = checkSet[i];

					if ( elem ) {

						var parent = elem.parentNode;

						checkSet[i] = parent.nodeName === part ? parent : false;

					}

				}

			} else {

				for ( var i = 0, l = checkSet.length; i < l; i++ ) {

					var elem = checkSet[i];

					if ( elem ) {

						checkSet[i] = isPartStr ?

							elem.parentNode :

							elem.parentNode === part;

					}

				}



				if ( isPartStr ) {

					Sizzle.filter( part, checkSet, true );

				}

			}

		},

		"": function(checkSet, part, isXML){

			var doneName = done++, checkFn = dirCheck;



			if ( !/\W/.test(part) ) {

				var nodeCheck = part = isXML ? part : part.toUpperCase();

				checkFn = dirNodeCheck;

			}



			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);

		},

		"~": function(checkSet, part, isXML){

			var doneName = done++, checkFn = dirCheck;



			if ( typeof part === "string" && !/\W/.test(part) ) {

				var nodeCheck = part = isXML ? part : part.toUpperCase();

				checkFn = dirNodeCheck;

			}



			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);

		}

	},

	find: {

		ID: function(match, context, isXML){

			if ( typeof context.getElementById !== "undefined" && !isXML ) {

				var m = context.getElementById(match[1]);

				return m ? [m] : [];

			}

		},

		NAME: function(match, context, isXML){

			if ( typeof context.getElementsByName !== "undefined" ) {

				var ret = [], results = context.getElementsByName(match[1]);



				for ( var i = 0, l = results.length; i < l; i++ ) {

					if ( results[i].getAttribute("name") === match[1] ) {

						ret.push( results[i] );

					}

				}



				return ret.length === 0 ? null : ret;

			}

		},

		TAG: function(match, context){

			return context.getElementsByTagName(match[1]);

		}

	},

	preFilter: {

		CLASS: function(match, curLoop, inplace, result, not, isXML){

			match = " " + match[1].replace(/\\/g, "") + " ";



			if ( isXML ) {

				return match;

			}



			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {

				if ( elem ) {

					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {

						if ( !inplace )

							result.push( elem );

					} else if ( inplace ) {

						curLoop[i] = false;

					}

				}

			}



			return false;

		},

		ID: function(match){

			return match[1].replace(/\\/g, "");

		},

		TAG: function(match, curLoop){

			for ( var i = 0; curLoop[i] === false; i++ ){}

			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();

		},

		CHILD: function(match){

			if ( match[1] == "nth" ) {

				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'

				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(

					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||

					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);



				// calculate the numbers (first)n+(last) including if they are negative

				match[2] = (test[1] + (test[2] || 1)) - 0;

				match[3] = test[3] - 0;

			}



			// TODO: Move to normal caching system

			match[0] = done++;



			return match;

		},

		ATTR: function(match, curLoop, inplace, result, not, isXML){

			var name = match[1].replace(/\\/g, "");

			

			if ( !isXML && Expr.attrMap[name] ) {

				match[1] = Expr.attrMap[name];

			}



			if ( match[2] === "~=" ) {

				match[4] = " " + match[4] + " ";

			}



			return match;

		},

		PSEUDO: function(match, curLoop, inplace, result, not){

			if ( match[1] === "not" ) {

				// If we're dealing with a complex expression, or a simple one

				if ( chunker.exec(match[3]).length > 1 || /^\w/.test(match[3]) ) {

					match[3] = Sizzle(match[3], null, null, curLoop);

				} else {

					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);

					if ( !inplace ) {

						result.push.apply( result, ret );

					}

					return false;

				}

			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {

				return true;

			}

			

			return match;

		},

		POS: function(match){

			match.unshift( true );

			return match;

		}

	},

	filters: {

		enabled: function(elem){

			return elem.disabled === false && elem.type !== "hidden";

		},

		disabled: function(elem){

			return elem.disabled === true;

		},

		checked: function(elem){

			return elem.checked === true;

		},

		selected: function(elem){

			// Accessing this property makes selected-by-default

			// options in Safari work properly

			elem.parentNode.selectedIndex;

			return elem.selected === true;

		},

		parent: function(elem){

			return !!elem.firstChild;

		},

		empty: function(elem){

			return !elem.firstChild;

		},

		has: function(elem, i, match){

			return !!Sizzle( match[3], elem ).length;

		},

		header: function(elem){

			return /h\d/i.test( elem.nodeName );

		},

		text: function(elem){

			return "text" === elem.type;

		},

		radio: function(elem){

			return "radio" === elem.type;

		},

		checkbox: function(elem){

			return "checkbox" === elem.type;

		},

		file: function(elem){

			return "file" === elem.type;

		},

		password: function(elem){

			return "password" === elem.type;

		},

		submit: function(elem){

			return "submit" === elem.type;

		},

		image: function(elem){

			return "image" === elem.type;

		},

		reset: function(elem){

			return "reset" === elem.type;

		},

		button: function(elem){

			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";

		},

		input: function(elem){

			return /input|select|textarea|button/i.test(elem.nodeName);

		}

	},

	setFilters: {

		first: function(elem, i){

			return i === 0;

		},

		last: function(elem, i, match, array){

			return i === array.length - 1;

		},

		even: function(elem, i){

			return i % 2 === 0;

		},

		odd: function(elem, i){

			return i % 2 === 1;

		},

		lt: function(elem, i, match){

			return i < match[3] - 0;

		},

		gt: function(elem, i, match){

			return i > match[3] - 0;

		},

		nth: function(elem, i, match){

			return match[3] - 0 == i;

		},

		eq: function(elem, i, match){

			return match[3] - 0 == i;

		}

	},

	filter: {

		PSEUDO: function(elem, match, i, array){

			var name = match[1], filter = Expr.filters[ name ];



			if ( filter ) {

				return filter( elem, i, match, array );

			} else if ( name === "contains" ) {

				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;

			} else if ( name === "not" ) {

				var not = match[3];



				for ( var i = 0, l = not.length; i < l; i++ ) {

					if ( not[i] === elem ) {

						return false;

					}

				}



				return true;

			}

		},

		CHILD: function(elem, match){

			var type = match[1], node = elem;

			switch (type) {

				case 'only':

				case 'first':

					while ( (node = node.previousSibling) )  {

						if ( node.nodeType === 1 ) return false;

					}

					if ( type == 'first') return true;

					node = elem;

				case 'last':

					while ( (node = node.nextSibling) )  {

						if ( node.nodeType === 1 ) return false;

					}

					return true;

				case 'nth':

					var first = match[2], last = match[3];



					if ( first == 1 && last == 0 ) {

						return true;

					}

					

					var doneName = match[0],

						parent = elem.parentNode;

	

					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {

						var count = 0;

						for ( node = parent.firstChild; node; node = node.nextSibling ) {

							if ( node.nodeType === 1 ) {

								node.nodeIndex = ++count;

							}

						} 

						parent.sizcache = doneName;

					}

					

					var diff = elem.nodeIndex - last;

					if ( first == 0 ) {

						return diff == 0;

					} else {

						return ( diff % first == 0 && diff / first >= 0 );

					}

			}

		},

		ID: function(elem, match){

			return elem.nodeType === 1 && elem.getAttribute("id") === match;

		},

		TAG: function(elem, match){

			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;

		},

		CLASS: function(elem, match){

			return (" " + (elem.className || elem.getAttribute("class")) + " ")

				.indexOf( match ) > -1;

		},

		ATTR: function(elem, match){

			var name = match[1],

				result = Expr.attrHandle[ name ] ?

					Expr.attrHandle[ name ]( elem ) :

					elem[ name ] != null ?

						elem[ name ] :

						elem.getAttribute( name ),

				value = result + "",

				type = match[2],

				check = match[4];



			return result == null ?

				type === "!=" :

				type === "=" ?

				value === check :

				type === "*=" ?

				value.indexOf(check) >= 0 :

				type === "~=" ?

				(" " + value + " ").indexOf(check) >= 0 :

				!check ?

				value && result !== false :

				type === "!=" ?

				value != check :

				type === "^=" ?

				value.indexOf(check) === 0 :

				type === "$=" ?

				value.substr(value.length - check.length) === check :

				type === "|=" ?

				value === check || value.substr(0, check.length + 1) === check + "-" :

				false;

		},

		POS: function(elem, match, i, array){

			var name = match[2], filter = Expr.setFilters[ name ];



			if ( filter ) {

				return filter( elem, i, match, array );

			}

		}

	}

};



var origPOS = Expr.match.POS;



for ( var type in Expr.match ) {

	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );

}



var makeArray = function(array, results) {

	array = Array.prototype.slice.call( array, 0 );



	if ( results ) {

		results.push.apply( results, array );

		return results;

	}

	

	return array;

};



// Perform a simple check to determine if the browser is capable of

// converting a NodeList to an array using builtin methods.

try {

	Array.prototype.slice.call( document.documentElement.childNodes, 0 );



// Provide a fallback method if it does not work

} catch(e){

	makeArray = function(array, results) {

		var ret = results || [];



		if ( toString.call(array) === "[object Array]" ) {

			Array.prototype.push.apply( ret, array );

		} else {

			if ( typeof array.length === "number" ) {

				for ( var i = 0, l = array.length; i < l; i++ ) {

					ret.push( array[i] );

				}

			} else {

				for ( var i = 0; array[i]; i++ ) {

					ret.push( array[i] );

				}

			}

		}



		return ret;

	};

}



var sortOrder;



if ( document.documentElement.compareDocumentPosition ) {

	sortOrder = function( a, b ) {

		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;

		if ( ret === 0 ) {

			hasDuplicate = true;

		}

		return ret;

	};

} else if ( "sourceIndex" in document.documentElement ) {

	sortOrder = function( a, b ) {

		var ret = a.sourceIndex - b.sourceIndex;

		if ( ret === 0 ) {

			hasDuplicate = true;

		}

		return ret;

	};

} else if ( document.createRange ) {

	sortOrder = function( a, b ) {

		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();

		aRange.selectNode(a);

		aRange.collapse(true);

		bRange.selectNode(b);

		bRange.collapse(true);

		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);

		if ( ret === 0 ) {

			hasDuplicate = true;

		}

		return ret;

	};

}



// Check to see if the browser returns elements by name when

// querying by getElementById (and provide a workaround)

(function(){

	// We're going to inject a fake input element with a specified name

	var form = document.createElement("div"),

		id = "script" + (new Date).getTime();

	form.innerHTML = "<a name='" + id + "'/>";



	// Inject it into the root element, check its status, and remove it quickly

	var root = document.documentElement;

	root.insertBefore( form, root.firstChild );



	// The workaround has to do additional checks after a getElementById

	// Which slows things down for other browsers (hence the branching)

	if ( !!document.getElementById( id ) ) {

		Expr.find.ID = function(match, context, isXML){

			if ( typeof context.getElementById !== "undefined" && !isXML ) {

				var m = context.getElementById(match[1]);

				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];

			}

		};



		Expr.filter.ID = function(elem, match){

			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");

			return elem.nodeType === 1 && node && node.nodeValue === match;

		};

	}



	root.removeChild( form );

	root = form = null; // release memory in IE

})();



(function(){

	// Check to see if the browser returns only elements

	// when doing getElementsByTagName("*")



	// Create a fake element

	var div = document.createElement("div");

	div.appendChild( document.createComment("") );



	// Make sure no comments are found

	if ( div.getElementsByTagName("*").length > 0 ) {

		Expr.find.TAG = function(match, context){

			var results = context.getElementsByTagName(match[1]);



			// Filter out possible comments

			if ( match[1] === "*" ) {

				var tmp = [];



				for ( var i = 0; results[i]; i++ ) {

					if ( results[i].nodeType === 1 ) {

						tmp.push( results[i] );

					}

				}



				results = tmp;

			}



			return results;

		};

	}



	// Check to see if an attribute returns normalized href attributes

	div.innerHTML = "<a href='#'></a>";

	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&

			div.firstChild.getAttribute("href") !== "#" ) {

		Expr.attrHandle.href = function(elem){

			return elem.getAttribute("href", 2);

		};

	}



	div = null; // release memory in IE

})();



if ( document.querySelectorAll ) (function(){

	var oldSizzle = Sizzle, div = document.createElement("div");

	div.innerHTML = "<p class='TEST'></p>";



	// Safari can't handle uppercase or unicode characters when

	// in quirks mode.

	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {

		return;

	}

	

	Sizzle = function(query, context, extra, seed){

		context = context || document;



		// Only use querySelectorAll on non-XML documents

		// (ID selectors don't work in non-HTML documents)

		if ( !seed && context.nodeType === 9 && !isXML(context) ) {

			try {

				return makeArray( context.querySelectorAll(query), extra );

			} catch(e){}

		}

		

		return oldSizzle(query, context, extra, seed);

	};



	for ( var prop in oldSizzle ) {

		Sizzle[ prop ] = oldSizzle[ prop ];

	}



	div = null; // release memory in IE

})();



if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){

	var div = document.createElement("div");

	div.innerHTML = "<div class='test e'></div><div class='test'></div>";



	// Opera can't find a second classname (in 9.6)

	if ( div.getElementsByClassName("e").length === 0 )

		return;



	// Safari caches class attributes, doesn't catch changes (in 3.2)

	div.lastChild.className = "e";



	if ( div.getElementsByClassName("e").length === 1 )

		return;



	Expr.order.splice(1, 0, "CLASS");

	Expr.find.CLASS = function(match, context, isXML) {

		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {

			return context.getElementsByClassName(match[1]);

		}

	};



	div = null; // release memory in IE

})();



function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {

	var sibDir = dir == "previousSibling" && !isXML;

	for ( var i = 0, l = checkSet.length; i < l; i++ ) {

		var elem = checkSet[i];

		if ( elem ) {

			if ( sibDir && elem.nodeType === 1 ){

				elem.sizcache = doneName;

				elem.sizset = i;

			}

			elem = elem[dir];

			var match = false;



			while ( elem ) {

				if ( elem.sizcache === doneName ) {

					match = checkSet[elem.sizset];

					break;

				}



				if ( elem.nodeType === 1 && !isXML ){

					elem.sizcache = doneName;

					elem.sizset = i;

				}



				if ( elem.nodeName === cur ) {

					match = elem;

					break;

				}



				elem = elem[dir];

			}



			checkSet[i] = match;

		}

	}

}



function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {

	var sibDir = dir == "previousSibling" && !isXML;

	for ( var i = 0, l = checkSet.length; i < l; i++ ) {

		var elem = checkSet[i];

		if ( elem ) {

			if ( sibDir && elem.nodeType === 1 ) {

				elem.sizcache = doneName;

				elem.sizset = i;

			}

			elem = elem[dir];

			var match = false;



			while ( elem ) {

				if ( elem.sizcache === doneName ) {

					match = checkSet[elem.sizset];

					break;

				}



				if ( elem.nodeType === 1 ) {

					if ( !isXML ) {

						elem.sizcache = doneName;

						elem.sizset = i;

					}

					if ( typeof cur !== "string" ) {

						if ( elem === cur ) {

							match = true;

							break;

						}



					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {

						match = elem;

						break;

					}

				}



				elem = elem[dir];

			}



			checkSet[i] = match;

		}

	}

}



var contains = document.compareDocumentPosition ?  function(a, b){

	return a.compareDocumentPosition(b) & 16;

} : function(a, b){

	return a !== b && (a.contains ? a.contains(b) : true);

};



var isXML = function(elem){

	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||

		!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";

};



var posProcess = function(selector, context){

	var tmpSet = [], later = "", match,

		root = context.nodeType ? [context] : context;



	// Position selectors must be done after the filter

	// And so must :not(positional) so we move all PSEUDOs to the end

	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {

		later += match[0];

		selector = selector.replace( Expr.match.PSEUDO, "" );

	}



	selector = Expr.relative[selector] ? selector + "*" : selector;



	for ( var i = 0, l = root.length; i < l; i++ ) {

		Sizzle( selector, root[i], tmpSet );

	}



	return Sizzle.filter( later, tmpSet );

};



// EXPOSE



Karma.Sizzle = Sizzle;



})();


Karma.each( ("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error,hover").split(","), function(i, name){

	// Handle event binding

	Karma.fn[name] = function(fn){

		var args = [name].concat(Karma.makeArray(arguments));

		return arguments.length ? this.bind.apply(this, args) : this.trigger(name);

	};

});



Karma(function first_onload(){ 

	// predetermine boxModel

	if (document.body) {

		var div = document.createElement("div");

		div.style.width = div.style.paddingLeft = "1px";

		document.body.appendChild( div );

		Karma.support.boxModel = div.offsetWidth == 2;

		document.body.removeChild( div ).style.display = 'none';

	}

	

	/*try{

		iframe.src = '';

		document.documentElement.removeChild(iframe); // remove the iframe

	} catch(e){};*/

	

	// cleaning up the mess	

	Karma(window).bind('unload', function(){ 

		Karma.storage = null;

		Karma.event.caller = null;

		window.onunload = null;

	});

});
// Remember Karma.Sizzle = Sizzle;



// 2 filters below from the jQuery project

Karma.Sizzle.selectors.filters.visible = function(el){

	return el.offsetWidth > 0 || el.offsetHeight > 0;

};



Karma.Sizzle.selectors.filters.hidden = function(el){

	return el.offsetWidth === 0 && el.offsetHeight === 0;

};



Karma.Sizzle.selectors.filters.animated = function(el){

	return Karma(el).data('KarmaFX');

};




})(this);

