var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
		"(?:[\\w*_-]|\\\\.)" :
		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
	quickClass = new RegExp("^([#.]?)(" + chars + "*)");

jQuery.extend({
	expr: {
		"": "m[2]=='*'||jQuery.nodeName(a,m[2])",
		"#": "a.getAttribute('id')==m[2]",
		":": {
			lt: "i<m[3]-0",
			gt: "i>m[3]-0",
			nth: "m[3]-0==i",
			eq: "m[3]-0==i",
			first: "i==0",
			last: "i==r.length-1",
			even: "i%2==0",
			odd: "i%2",
			"first-child": "a.parentNode.getElementsByTagName('*')[0]==a",
			"last-child": "jQuery.nth(a.parentNode.lastChild,1,'previousSibling')==a",
			"only-child": "!jQuery.nth(a.parentNode.lastChild,2,'previousSibling')",
			parent: "a.firstChild",
			empty: "!a.firstChild",
			contains: "(a.textContent||a.innerText||jQuery(a).text()||'').indexOf(m[3])>=0",
			visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
			hidden: '"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden"',
			enabled: "!a.disabled",
			disabled: "a.disabled",
			checked: "a.checked",
			selected: "a.selected||jQuery.attr(a,'selected')",
			text: "'text'==a.type",
			radio: "'radio'==a.type",
			checkbox: "'checkbox'==a.type",
			file: "'file'==a.type",
			password: "'password'==a.type",
			submit: "'submit'==a.type",
			image: "'image'==a.type",
			reset: "'reset'==a.type",
			button: '"button"==a.type||jQuery.nodeName(a,"button")',
			input: "/input|select|textarea|button/i.test(a.nodeName)",
			has: "jQuery.find(m[3],a).length",
			header: "/h\\d/i.test(a.nodeName)",
			animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length"
		}
	},
	parse: [
		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
		new RegExp("^([:.#]*)(" + chars + "+)")
	],
	multiFilter: function( expr, elems, not ) {
		var old, cur = [];
		while ( expr && expr != old ) {
			old = expr;
			var f = jQuery.filter( expr, elems, not );
			expr = f.t.replace(/^\s*,\s*/, "" );
			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
		}
		return cur;
	},
	find: function( t, context ) {
		if ( typeof t != "string" )
			return [ t ];
		if ( context && context.nodeType != 1 && context.nodeType != 9)
			return [ ];
		context = context || document;
		var ret = [context], done = [], last, nodeName;
		while ( t && last != t ) {
			var r = [];
			last = t;
			t = jQuery.trim(t);
			var foundToken = false;
			var re = quickChild;
			var m = re.exec(t);
			if ( m ) {
				nodeName = m[1].toUpperCase();
				for ( var i = 0; ret[i]; i++ )
					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
							r.push( c );
				ret = r;
				t = t.replace( re, "" );
				if ( t.indexOf(" ") == 0 ) continue;
				foundToken = true;
			} else {
				re = /^([>+~])\s*(\w*)/i;
				if ( (m = re.exec(t)) != null ) {
					r = [];
					nodeName = m[2].toUpperCase(), merge = {};
					m = m[1];
					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
						for ( ; n; n = n.nextSibling )
							if ( n.nodeType == 1 ) {
								var id = jQuery.data(n);
								if ( m == "~" && merge[id] ) break;
								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
									if ( m == "~" ) merge[id] = true;
									r.push( n );
								}
								if ( m == "+" ) break;
							}
					}
					ret = r;
					t = jQuery.trim( t.replace( re, "" ) );
					foundToken = true;
				}
			}
			if ( t && !foundToken ) {
				if ( !t.indexOf(",") ) {
					if ( context == ret[0] ) ret.shift();
					done = jQuery.merge( done, ret );
					r = ret = [context];
					t = " " + t.substr(1,t.length);
				} else {
					var re2 = quickID;
					var m = re2.exec(t);
					if ( m ) {
						m = [ 0, m[2], m[3], m[1] ];
					} else {
						re2 = quickClass;
						m = re2.exec(t);
					}
					m[2] = m[2].replace(/\\/g, "");
					var elem = ret[ret.length-1];
					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
						var oid = elem.getElementById(m[2]);
						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
					} else {
						for ( var i = 0; ret[i]; i++ ) {
							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
								tag = "param";
							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
						}
						if ( m[1] == "." )
							r = jQuery.classFilter( r, m[2] );
						if ( m[1] == "#" ) {
							var tmp = [];
							for ( var i = 0; r[i]; i++ )
								if ( r[i].getAttribute("id") == m[2] ) {
									tmp = [ r[i] ];
									break;
								}
							r = tmp;
						}
						ret = r;
					}
					t = t.replace( re2, "" );
				}
			}
			if ( t ) {
				var val = jQuery.filter(t,r);
				ret = r = val.r;
				t = jQuery.trim(val.t);
			}
		}
		if ( t )
			ret = [];
		if ( ret && context == ret[0] )
			ret.shift();
		done = jQuery.merge( done, ret );
		return done;
	},
	classFilter: function(r,m,not){
		m = " " + m + " ";
		var tmp = [];
		for ( var i = 0; r[i]; i++ ) {
			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
			if ( !not && pass || not && !pass )
				tmp.push( r[i] );
		}
		return tmp;
	},
	filter: function(t,r,not) {
		var last;
		while ( t && t != last ) {
			last = t;
			var p = jQuery.parse, m;
			for ( var i = 0; p[i]; i++ ) {
				m = p[i].exec( t );
				if ( m ) {
					t = t.substring( m[0].length );
					m[2] = m[2].replace(/\\/g, "");
					break;
				}
			}
			if ( !m )
				break;
			if ( m[1] == ":" && m[2] == "not" )
				r = isSimple.test( m[3] ) ?
					jQuery.filter(m[3], r, true).r :
					jQuery( r ).not( m[3] );
			else if ( m[1] == "." )
				r = jQuery.classFilter(r, m[2], not);
			else if ( m[1] == "[" ) {
				var tmp = [], type = m[3];
				for ( var i = 0, rl = r.length; i < rl; i++ ) {
					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
					if ( z == null || /href|src|selected/.test(m[2]) )
						z = jQuery.attr(a,m[2]) || '';
					if ( (type == "" && !!z ||
						 type == "=" && z == m[5] ||
						 type == "!=" && z != m[5] ||
						 type == "^=" && z && !z.indexOf(m[5]) ||
						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
							tmp.push( a );
				}
				r = tmp;
			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
				var merge = {}, tmp = [],
					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
				for ( var i = 0, rl = r.length; i < rl; i++ ) {
					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
					if ( !merge[id] ) {
						var c = 1;
						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
							if ( n.nodeType == 1 )
								n.nodeIndex = c++;
						merge[id] = true;
					}
					var add = false;
					if ( first == 0 ) {
						if ( node.nodeIndex == last )
							add = true;
					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
						add = true;
					if ( add ^ not )
						tmp.push( node );
				}
				r = tmp;
			} else {
				var f = jQuery.expr[m[1]];
				if ( typeof f != "string" )
					f = jQuery.expr[m[1]][m[2]];
				f = eval("false||function(a,i){return " + f + "}");
				r = jQuery.grep( r, f, not );
			}
		}
		return { r: r, t: t };
	},
	dir: function( elem, dir ){
		var matched = [];
		var cur = elem[dir];
		while ( cur && cur != document ) {
			if ( cur.nodeType == 1 )
				matched.push( cur );
			cur = cur[dir];
		}
		return matched;
	},
	nth: function(cur,result,dir,elem){
		result = result || 1;
		var num = 0;
		for ( ; cur; cur = cur[dir] )
			if ( cur.nodeType == 1 && ++num == result )
				break;
		return cur;
	},
	sibling: function( n, elem ) {
		var r = [];
		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType == 1 && (!elem || n != elem) )
				r.push( n );
		}
		return r;
	}
});