Skip to content
This repository
Browse code

Update built-in version of Sizzle to latest revision.

  • Loading branch information...
commit 2a6914089ad6f0b398d9f4ef7032e6bab818dd51 1 parent f9d7c67
Andrew Dupont authored July 03, 2011

Showing 1 changed file with 680 additions and 282 deletions. Show diff stats Hide diff stats

  1. 962  src/sizzle.js
962  src/sizzle.js
... ...
@@ -1,29 +1,33 @@
1 1
 /*!
2  
- * Sizzle CSS Selector Engine - v1.0
3  
- *  Copyright 2009, The Dojo Foundation
  2
+ * Sizzle CSS Selector Engine
  3
+ *  Copyright 2011, The Dojo Foundation
4 4
  *  Released under the MIT, BSD, and GPL Licenses.
5 5
  *  More information: http://sizzlejs.com/
6 6
  */
7 7
 (function(){
8 8
 
9  
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
  9
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
10 10
 	done = 0,
11 11
 	toString = Object.prototype.toString,
12 12
 	hasDuplicate = false,
13  
-	baseHasDuplicate = true;
  13
+	baseHasDuplicate = true,
  14
+	rBackslash = /\\/g,
  15
+	rNonWord = /\W/;
14 16
 
15 17
 // Here we check if the JavaScript engine is using some sort of
16 18
 // optimization where it does not always call our comparision
17 19
 // function. If that is the case, discard the hasDuplicate value.
18 20
 //   Thus far that includes Google Chrome.
19  
-[0, 0].sort(function(){
  21
+[0, 0].sort(function() {
20 22
 	baseHasDuplicate = false;
21 23
 	return 0;
22 24
 });
23 25
 
24  
-var Sizzle = function(selector, context, results, seed) {
  26
+var Sizzle = function( selector, context, results, seed ) {
25 27
 	results = results || [];
26  
-	var origContext = context = context || document;
  28
+	context = context || document;
  29
+
  30
+	var origContext = context;
27 31
 
28 32
 	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
29 33
 		return [];
@@ -33,24 +37,34 @@ var Sizzle = function(selector, context, results, seed) {
33 37
 		return results;
34 38
 	}
35 39
 
36  
-	var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
  40
+	var m, set, checkSet, extra, ret, cur, pop, i,
  41
+		prune = true,
  42
+		contextXML = Sizzle.isXML( context ),
  43
+		parts = [],
37 44
 		soFar = selector;
38 45
 	
39 46
 	// Reset the position of the chunker regexp (start from head)
40  
-	while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
41  
-		soFar = m[3];
  47
+	do {
  48
+		chunker.exec( "" );
  49
+		m = chunker.exec( soFar );
  50
+
  51
+		if ( m ) {
  52
+			soFar = m[3];
42 53
 		
43  
-		parts.push( m[1] );
  54
+			parts.push( m[1] );
44 55
 		
45  
-		if ( m[2] ) {
46  
-			extra = m[3];
47  
-			break;
  56
+			if ( m[2] ) {
  57
+				extra = m[3];
  58
+				break;
  59
+			}
48 60
 		}
49  
-	}
  61
+	} while ( m );
50 62
 
51 63
 	if ( parts.length > 1 && origPOS.exec( selector ) ) {
  64
+
52 65
 		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
53 66
 			set = posProcess( parts[0] + parts[1], context );
  67
+
54 68
 		} else {
55 69
 			set = Expr.relative[ parts[0] ] ?
56 70
 				[ context ] :
@@ -59,35 +73,45 @@ var Sizzle = function(selector, context, results, seed) {
59 73
 			while ( parts.length ) {
60 74
 				selector = parts.shift();
61 75
 
62  
-				if ( Expr.relative[ selector ] )
  76
+				if ( Expr.relative[ selector ] ) {
63 77
 					selector += parts.shift();
64  
-
  78
+				}
  79
+				
65 80
 				set = posProcess( selector, set );
66 81
 			}
67 82
 		}
  83
+
68 84
 	} else {
69 85
 		// Take a shortcut and set the context if the root selector is an ID
70 86
 		// (but not if it'll be faster if the inner selector is an ID)
71 87
 		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
72 88
 				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
73  
-			var ret = Sizzle.find( parts.shift(), context, contextXML );
74  
-			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
  89
+
  90
+			ret = Sizzle.find( parts.shift(), context, contextXML );
  91
+			context = ret.expr ?
  92
+				Sizzle.filter( ret.expr, ret.set )[0] :
  93
+				ret.set[0];
75 94
 		}
76 95
 
77 96
 		if ( context ) {
78  
-			var ret = seed ?
  97
+			ret = seed ?
79 98
 				{ expr: parts.pop(), set: makeArray(seed) } :
80 99
 				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
81  
-			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
  100
+
  101
+			set = ret.expr ?
  102
+				Sizzle.filter( ret.expr, ret.set ) :
  103
+				ret.set;
82 104
 
83 105
 			if ( parts.length > 0 ) {
84  
-				checkSet = makeArray(set);
  106
+				checkSet = makeArray( set );
  107
+
85 108
 			} else {
86 109
 				prune = false;
87 110
 			}
88 111
 
89 112
 			while ( parts.length ) {
90  
-				var cur = parts.pop(), pop = cur;
  113
+				cur = parts.pop();
  114
+				pop = cur;
91 115
 
92 116
 				if ( !Expr.relative[ cur ] ) {
93 117
 					cur = "";
@@ -101,6 +125,7 @@ var Sizzle = function(selector, context, results, seed) {
101 125
 
102 126
 				Expr.relative[ cur ]( checkSet, pop, contextXML );
103 127
 			}
  128
+
104 129
 		} else {
105 130
 			checkSet = parts = [];
106 131
 		}
@@ -111,25 +136,28 @@ var Sizzle = function(selector, context, results, seed) {
111 136
 	}
112 137
 
113 138
 	if ( !checkSet ) {
114  
-		throw "Syntax error, unrecognized expression: " + (cur || selector);
  139
+		Sizzle.error( cur || selector );
115 140
 	}
116 141
 
117 142
 	if ( toString.call(checkSet) === "[object Array]" ) {
118 143
 		if ( !prune ) {
119 144
 			results.push.apply( results, checkSet );
  145
+
120 146
 		} else if ( context && context.nodeType === 1 ) {
121  
-			for ( var i = 0; checkSet[i] != null; i++ ) {
122  
-				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
  147
+			for ( i = 0; checkSet[i] != null; i++ ) {
  148
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
123 149
 					results.push( set[i] );
124 150
 				}
125 151
 			}
  152
+
126 153
 		} else {
127  
-			for ( var i = 0; checkSet[i] != null; i++ ) {
  154
+			for ( i = 0; checkSet[i] != null; i++ ) {
128 155
 				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
129 156
 					results.push( set[i] );
130 157
 				}
131 158
 			}
132 159
 		}
  160
+
133 161
 	} else {
134 162
 		makeArray( checkSet, results );
135 163
 	}
@@ -142,15 +170,15 @@ var Sizzle = function(selector, context, results, seed) {
142 170
 	return results;
143 171
 };
144 172
 
145  
-Sizzle.uniqueSort = function(results){
  173
+Sizzle.uniqueSort = function( results ) {
146 174
 	if ( sortOrder ) {
147 175
 		hasDuplicate = baseHasDuplicate;
148  
-		results.sort(sortOrder);
  176
+		results.sort( sortOrder );
149 177
 
150 178
 		if ( hasDuplicate ) {
151 179
 			for ( var i = 1; i < results.length; i++ ) {
152  
-				if ( results[i] === results[i-1] ) {
153  
-					results.splice(i--, 1);
  180
+				if ( results[i] === results[ i - 1 ] ) {
  181
+					results.splice( i--, 1 );
154 182
 				}
155 183
 			}
156 184
 		}
@@ -159,27 +187,33 @@ Sizzle.uniqueSort = function(results){
159 187
 	return results;
160 188
 };
161 189
 
162  
-Sizzle.matches = function(expr, set){
163  
-	return Sizzle(expr, null, null, set);
  190
+Sizzle.matches = function( expr, set ) {
  191
+	return Sizzle( expr, null, null, set );
  192
+};
  193
+
  194
+Sizzle.matchesSelector = function( node, expr ) {
  195
+	return Sizzle( expr, null, null, [node] ).length > 0;
164 196
 };
165 197
 
166  
-Sizzle.find = function(expr, context, isXML){
167  
-	var set, match;
  198
+Sizzle.find = function( expr, context, isXML ) {
  199
+	var set;
168 200
 
169 201
 	if ( !expr ) {
170 202
 		return [];
171 203
 	}
172 204
 
173 205
 	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
174  
-		var type = Expr.order[i], match;
  206
+		var match,
  207
+			type = Expr.order[i];
175 208
 		
176 209
 		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
177 210
 			var left = match[1];
178  
-			match.splice(1,1);
  211
+			match.splice( 1, 1 );
179 212
 
180 213
 			if ( left.substr( left.length - 1 ) !== "\\" ) {
181  
-				match[1] = (match[1] || "").replace(/\\/g, "");
  214
+				match[1] = (match[1] || "").replace( rBackslash, "" );
182 215
 				set = Expr.find[ type ]( match, context, isXML );
  216
+
183 217
 				if ( set != null ) {
184 218
 					expr = expr.replace( Expr.match[ type ], "" );
185 219
 					break;
@@ -189,23 +223,37 @@ Sizzle.find = function(expr, context, isXML){
189 223
 	}
190 224
 
191 225
 	if ( !set ) {
192  
-		set = context.getElementsByTagName("*");
  226
+		set = typeof context.getElementsByTagName !== "undefined" ?
  227
+			context.getElementsByTagName( "*" ) :
  228
+			[];
193 229
 	}
194 230
 
195  
-	return {set: set, expr: expr};
  231
+	return { set: set, expr: expr };
196 232
 };
197 233
 
198  
-Sizzle.filter = function(expr, set, inplace, not){
199  
-	var old = expr, result = [], curLoop = set, match, anyFound,
200  
-		isXMLFilter = set && set[0] && isXML(set[0]);
  234
+Sizzle.filter = function( expr, set, inplace, not ) {
  235
+	var match, anyFound,
  236
+		old = expr,
  237
+		result = [],
  238
+		curLoop = set,
  239
+		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
201 240
 
202 241
 	while ( expr && set.length ) {
203 242
 		for ( var type in Expr.filter ) {
204  
-			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
205  
-				var filter = Expr.filter[ type ], found, item;
  243
+			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
  244
+				var found, item,
  245
+					filter = Expr.filter[ type ],
  246
+					left = match[1];
  247
+
206 248
 				anyFound = false;
207 249
 
208  
-				if ( curLoop == result ) {
  250
+				match.splice(1,1);
  251
+
  252
+				if ( left.substr( left.length - 1 ) === "\\" ) {
  253
+					continue;
  254
+				}
  255
+
  256
+				if ( curLoop === result ) {
209 257
 					result = [];
210 258
 				}
211 259
 
@@ -214,6 +262,7 @@ Sizzle.filter = function(expr, set, inplace, not){
214 262
 
215 263
 					if ( !match ) {
216 264
 						anyFound = found = true;
  265
+
217 266
 					} else if ( match === true ) {
218 267
 						continue;
219 268
 					}
@@ -228,9 +277,11 @@ Sizzle.filter = function(expr, set, inplace, not){
228 277
 							if ( inplace && found != null ) {
229 278
 								if ( pass ) {
230 279
 									anyFound = true;
  280
+
231 281
 								} else {
232 282
 									curLoop[i] = false;
233 283
 								}
  284
+
234 285
 							} else if ( pass ) {
235 286
 								result.push( item );
236 287
 								anyFound = true;
@@ -256,9 +307,10 @@ Sizzle.filter = function(expr, set, inplace, not){
256 307
 		}
257 308
 
258 309
 		// Improper expression
259  
-		if ( expr == old ) {
  310
+		if ( expr === old ) {
260 311
 			if ( anyFound == null ) {
261  
-				throw "Syntax error, unrecognized expression: " + expr;
  312
+				Sizzle.error( expr );
  313
+
262 314
 			} else {
263 315
 				break;
264 316
 			}
@@ -270,43 +322,55 @@ Sizzle.filter = function(expr, set, inplace, not){
270 322
 	return curLoop;
271 323
 };
272 324
 
  325
+Sizzle.error = function( msg ) {
  326
+	throw "Syntax error, unrecognized expression: " + msg;
  327
+};
  328
+
273 329
 var Expr = Sizzle.selectors = {
274 330
 	order: [ "ID", "NAME", "TAG" ],
  331
+
275 332
 	match: {
276  
-		ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
277  
-		CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
278  
-		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
279  
-		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
280  
-		TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
281  
-		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
282  
-		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
283  
-		PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
  333
+		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
  334
+		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
  335
+		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
  336
+		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
  337
+		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
  338
+		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
  339
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
  340
+		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
284 341
 	},
  342
+
285 343
 	leftMatch: {},
  344
+
286 345
 	attrMap: {
287 346
 		"class": "className",
288 347
 		"for": "htmlFor"
289 348
 	},
  349
+
290 350
 	attrHandle: {
291  
-		href: function(elem){
292  
-			return elem.getAttribute("href");
  351
+		href: function( elem ) {
  352
+			return elem.getAttribute( "href" );
  353
+		},
  354
+		type: function( elem ) {
  355
+			return elem.getAttribute( "type" );
293 356
 		}
294 357
 	},
  358
+
295 359
 	relative: {
296  
-		"+": function(checkSet, part, isXML){
  360
+		"+": function(checkSet, part){
297 361
 			var isPartStr = typeof part === "string",
298  
-				isTag = isPartStr && !/\W/.test(part),
  362
+				isTag = isPartStr && !rNonWord.test( part ),
299 363
 				isPartStrNotTag = isPartStr && !isTag;
300 364
 
301  
-			if ( isTag && !isXML ) {
302  
-				part = part.toUpperCase();
  365
+			if ( isTag ) {
  366
+				part = part.toLowerCase();
303 367
 			}
304 368
 
305 369
 			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
306 370
 				if ( (elem = checkSet[i]) ) {
307 371
 					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
308 372
 
309  
-					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
  373
+					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
310 374
 						elem || false :
311 375
 						elem === part;
312 376
 				}
@@ -316,22 +380,29 @@ var Expr = Sizzle.selectors = {
316 380
 				Sizzle.filter( part, checkSet, true );
317 381
 			}
318 382
 		},
319  
-		">": function(checkSet, part, isXML){
320  
-			var isPartStr = typeof part === "string";
321 383
 
322  
-			if ( isPartStr && !/\W/.test(part) ) {
323  
-				part = isXML ? part : part.toUpperCase();
  384
+		">": function( checkSet, part ) {
  385
+			var elem,
  386
+				isPartStr = typeof part === "string",
  387
+				i = 0,
  388
+				l = checkSet.length;
  389
+
  390
+			if ( isPartStr && !rNonWord.test( part ) ) {
  391
+				part = part.toLowerCase();
  392
+
  393
+				for ( ; i < l; i++ ) {
  394
+					elem = checkSet[i];
324 395
 
325  
-				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
326  
-					var elem = checkSet[i];
327 396
 					if ( elem ) {
328 397
 						var parent = elem.parentNode;
329  
-						checkSet[i] = parent.nodeName === part ? parent : false;
  398
+						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
330 399
 					}
331 400
 				}
  401
+
332 402
 			} else {
333  
-				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
334  
-					var elem = checkSet[i];
  403
+				for ( ; i < l; i++ ) {
  404
+					elem = checkSet[i];
  405
+
335 406
 					if ( elem ) {
336 407
 						checkSet[i] = isPartStr ?
337 408
 							elem.parentNode :
@@ -344,37 +415,50 @@ var Expr = Sizzle.selectors = {
344 415
 				}
345 416
 			}
346 417
 		},
  418
+
347 419
 		"": function(checkSet, part, isXML){
348  
-			var doneName = done++, checkFn = dirCheck;
  420
+			var nodeCheck,
  421
+				doneName = done++,
  422
+				checkFn = dirCheck;
349 423
 
350  
-			if ( !/\W/.test(part) ) {
351  
-				var nodeCheck = part = isXML ? part : part.toUpperCase();
  424
+			if ( typeof part === "string" && !rNonWord.test( part ) ) {
  425
+				part = part.toLowerCase();
  426
+				nodeCheck = part;
352 427
 				checkFn = dirNodeCheck;
353 428
 			}
354 429
 
355  
-			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
  430
+			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
356 431
 		},
357  
-		"~": function(checkSet, part, isXML){
358  
-			var doneName = done++, checkFn = dirCheck;
359 432
 
360  
-			if ( typeof part === "string" && !/\W/.test(part) ) {
361  
-				var nodeCheck = part = isXML ? part : part.toUpperCase();
  433
+		"~": function( checkSet, part, isXML ) {
  434
+			var nodeCheck,
  435
+				doneName = done++,
  436
+				checkFn = dirCheck;
  437
+
  438
+			if ( typeof part === "string" && !rNonWord.test( part ) ) {
  439
+				part = part.toLowerCase();
  440
+				nodeCheck = part;
362 441
 				checkFn = dirNodeCheck;
363 442
 			}
364 443
 
365  
-			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
  444
+			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
366 445
 		}
367 446
 	},
  447
+
368 448
 	find: {
369  
-		ID: function(match, context, isXML){
  449
+		ID: function( match, context, isXML ) {
370 450
 			if ( typeof context.getElementById !== "undefined" && !isXML ) {
371 451
 				var m = context.getElementById(match[1]);
372  
-				return m ? [m] : [];
  452
+				// Check parentNode to catch when Blackberry 4.6 returns
  453
+				// nodes that are no longer in the document #6963
  454
+				return m && m.parentNode ? [m] : [];
373 455
 			}
374 456
 		},
375  
-		NAME: function(match, context, isXML){
  457
+
  458
+		NAME: function( match, context ) {
376 459
 			if ( typeof context.getElementsByName !== "undefined" ) {
377  
-				var ret = [], results = context.getElementsByName(match[1]);
  460
+				var ret = [],
  461
+					results = context.getElementsByName( match[1] );
378 462
 
379 463
 				for ( var i = 0, l = results.length; i < l; i++ ) {
380 464
 					if ( results[i].getAttribute("name") === match[1] ) {
@@ -385,13 +469,16 @@ var Expr = Sizzle.selectors = {
385 469
 				return ret.length === 0 ? null : ret;
386 470
 			}
387 471
 		},
388  
-		TAG: function(match, context){
389  
-			return context.getElementsByTagName(match[1]);
  472
+
  473
+		TAG: function( match, context ) {
  474
+			if ( typeof context.getElementsByTagName !== "undefined" ) {
  475
+				return context.getElementsByTagName( match[1] );
  476
+			}
390 477
 		}
391 478
 	},
392 479
 	preFilter: {
393  
-		CLASS: function(match, curLoop, inplace, result, not, isXML){
394  
-			match = " " + match[1].replace(/\\/g, "") + " ";
  480
+		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
  481
+			match = " " + match[1].replace( rBackslash, "" ) + " ";
395 482
 
396 483
 			if ( isXML ) {
397 484
 				return match;
@@ -399,9 +486,11 @@ var Expr = Sizzle.selectors = {
399 486
 
400 487
 			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
401 488
 				if ( elem ) {
402  
-					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
403  
-						if ( !inplace )
  489
+					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
  490
+						if ( !inplace ) {
404 491
 							result.push( elem );
  492
+						}
  493
+
405 494
 					} else if ( inplace ) {
406 495
 						curLoop[i] = false;
407 496
 					}
@@ -410,190 +499,271 @@ var Expr = Sizzle.selectors = {
410 499
 
411 500
 			return false;
412 501
 		},
413  
-		ID: function(match){
414  
-			return match[1].replace(/\\/g, "");
  502
+
  503
+		ID: function( match ) {
  504
+			return match[1].replace( rBackslash, "" );
415 505
 		},
416  
-		TAG: function(match, curLoop){
417  
-			for ( var i = 0; curLoop[i] === false; i++ ){}
418  
-			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
  506
+
  507
+		TAG: function( match, curLoop ) {
  508
+			return match[1].replace( rBackslash, "" ).toLowerCase();
419 509
 		},
420  
-		CHILD: function(match){
421  
-			if ( match[1] == "nth" ) {
  510
+
  511
+		CHILD: function( match ) {
  512
+			if ( match[1] === "nth" ) {
  513
+				if ( !match[2] ) {
  514
+					Sizzle.error( match[0] );
  515
+				}
  516
+
  517
+				match[2] = match[2].replace(/^\+|\s*/g, '');
  518
+
422 519
 				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
423  
-				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
424  
-					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
  520
+				var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
  521
+					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
425 522
 					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
426 523
 
427 524
 				// calculate the numbers (first)n+(last) including if they are negative
428 525
 				match[2] = (test[1] + (test[2] || 1)) - 0;
429 526
 				match[3] = test[3] - 0;
430 527
 			}
  528
+			else if ( match[2] ) {
  529
+				Sizzle.error( match[0] );
  530
+			}
431 531
 
432 532
 			// TODO: Move to normal caching system
433 533
 			match[0] = done++;
434 534
 
435 535
 			return match;
436 536
 		},
437  
-		ATTR: function(match, curLoop, inplace, result, not, isXML){
438  
-			var name = match[1].replace(/\\/g, "");
  537
+
  538
+		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
  539
+			var name = match[1] = match[1].replace( rBackslash, "" );
439 540
 			
440 541
 			if ( !isXML && Expr.attrMap[name] ) {
441 542
 				match[1] = Expr.attrMap[name];
442 543
 			}
443 544
 
  545
+			// Handle if an un-quoted value was used
  546
+			match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
  547
+
444 548
 			if ( match[2] === "~=" ) {
445 549
 				match[4] = " " + match[4] + " ";
446 550
 			}
447 551
 
448 552
 			return match;
449 553
 		},
450  
-		PSEUDO: function(match, curLoop, inplace, result, not){
  554
+
  555
+		PSEUDO: function( match, curLoop, inplace, result, not ) {
451 556
 			if ( match[1] === "not" ) {
452 557
 				// If we're dealing with a complex expression, or a simple one
453 558
 				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
454 559
 					match[3] = Sizzle(match[3], null, null, curLoop);
  560
+
455 561
 				} else {
456 562
 					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
  563
+
457 564
 					if ( !inplace ) {
458 565
 						result.push.apply( result, ret );
459 566
 					}
  567
+
460 568
 					return false;
461 569
 				}
  570
+
462 571
 			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
463 572
 				return true;
464 573
 			}
465 574
 			
466 575
 			return match;
467 576
 		},
468  
-		POS: function(match){
  577
+
  578
+		POS: function( match ) {
469 579
 			match.unshift( true );
  580
+
470 581
 			return match;
471 582
 		}
472 583
 	},
  584
+	
473 585
 	filters: {
474  
-		enabled: function(elem){
  586
+		enabled: function( elem ) {
475 587
 			return elem.disabled === false && elem.type !== "hidden";
476 588
 		},
477  
-		disabled: function(elem){
  589
+
  590
+		disabled: function( elem ) {
478 591
 			return elem.disabled === true;
479 592
 		},
480  
-		checked: function(elem){
  593
+
  594
+		checked: function( elem ) {
481 595
 			return elem.checked === true;
482 596
 		},
483  
-		selected: function(elem){
  597
+		
  598
+		selected: function( elem ) {
484 599
 			// Accessing this property makes selected-by-default
485 600
 			// options in Safari work properly
486  
-			elem.parentNode.selectedIndex;
  601
+			if ( elem.parentNode ) {
  602
+				elem.parentNode.selectedIndex;
  603
+			}
  604
+			
487 605
 			return elem.selected === true;
488 606
 		},
489  
-		parent: function(elem){
  607
+
  608
+		parent: function( elem ) {
490 609
 			return !!elem.firstChild;
491 610
 		},
492  
-		empty: function(elem){
  611
+
  612
+		empty: function( elem ) {
493 613
 			return !elem.firstChild;
494 614
 		},
495  
-		has: function(elem, i, match){
  615
+
  616
+		has: function( elem, i, match ) {
496 617
 			return !!Sizzle( match[3], elem ).length;
497 618
 		},
498  
-		header: function(elem){
499  
-			return /h\d/i.test( elem.nodeName );
  619
+
  620
+		header: function( elem ) {
  621
+			return (/h\d/i).test( elem.nodeName );
500 622
 		},
501  
-		text: function(elem){
502  
-			return "text" === elem.type;
  623
+
  624
+		text: function( elem ) {
  625
+			var attr = elem.getAttribute( "type" ), type = elem.type;
  626
+			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
  627
+			// use getAttribute instead to test this case
  628
+			return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
503 629
 		},
504  
-		radio: function(elem){
505  
-			return "radio" === elem.type;
  630
+
  631
+		radio: function( elem ) {
  632
+			return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
506 633
 		},
507  
-		checkbox: function(elem){
508  
-			return "checkbox" === elem.type;
  634
+
  635
+		checkbox: function( elem ) {
  636
+			return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
509 637
 		},
510  
-		file: function(elem){
511  
-			return "file" === elem.type;
  638
+
  639
+		file: function( elem ) {
  640
+			return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
  641
+		},
  642
+
  643
+		password: function( elem ) {
  644
+			return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
512 645
 		},
513  
-		password: function(elem){
514  
-			return "password" === elem.type;
  646
+
  647
+		submit: function( elem ) {
  648
+			var name = elem.nodeName.toLowerCase();
  649
+			return (name === "input" || name === "button") && "submit" === elem.type;
515 650
 		},
516  
-		submit: function(elem){
517  
-			return "submit" === elem.type;
  651
+
  652
+		image: function( elem ) {
  653
+			return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
518 654
 		},
519  
-		image: function(elem){
520  
-			return "image" === elem.type;
  655
+
  656
+		reset: function( elem ) {
  657
+			var name = elem.nodeName.toLowerCase();
  658
+			return (name === "input" || name === "button") && "reset" === elem.type;
521 659
 		},
522  
-		reset: function(elem){
523  
-			return "reset" === elem.type;
  660
+
  661
+		button: function( elem ) {
  662
+			var name = elem.nodeName.toLowerCase();
  663
+			return name === "input" && "button" === elem.type || name === "button";
524 664
 		},
525  
-		button: function(elem){
526  
-			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
  665
+
  666
+		input: function( elem ) {
  667
+			return (/input|select|textarea|button/i).test( elem.nodeName );
527 668
 		},
528  
-		input: function(elem){
529  
-			return /input|select|textarea|button/i.test(elem.nodeName);
  669
+
  670
+		focus: function( elem ) {
  671
+			return elem === elem.ownerDocument.activeElement;
530 672
 		}
531 673
 	},
532 674
 	setFilters: {
533  
-		first: function(elem, i){
  675
+		first: function( elem, i ) {
534 676
 			return i === 0;
535 677
 		},
536  
-		last: function(elem, i, match, array){
  678
+
  679
+		last: function( elem, i, match, array ) {
537 680
 			return i === array.length - 1;
538 681
 		},
539  
-		even: function(elem, i){
  682
+
  683
+		even: function( elem, i ) {
540 684
 			return i % 2 === 0;
541 685
 		},
542  
-		odd: function(elem, i){
  686
+
  687
+		odd: function( elem, i ) {
543 688
 			return i % 2 === 1;
544 689
 		},
545  
-		lt: function(elem, i, match){
  690
+
  691
+		lt: function( elem, i, match ) {
546 692
 			return i < match[3] - 0;
547 693
 		},
548  
-		gt: function(elem, i, match){
  694
+
  695
+		gt: function( elem, i, match ) {
549 696
 			return i > match[3] - 0;
550 697
 		},
551  
-		nth: function(elem, i, match){
552  
-			return match[3] - 0 == i;
  698
+
  699
+		nth: function( elem, i, match ) {
  700
+			return match[3] - 0 === i;
553 701
 		},
554  
-		eq: function(elem, i, match){
555  
-			return match[3] - 0 == i;
  702
+
  703
+		eq: function( elem, i, match ) {
  704
+			return match[3] - 0 === i;
556 705
 		}
557 706
 	},
558 707
 	filter: {
559  
-		PSEUDO: function(elem, match, i, array){
560  
-			var name = match[1], filter = Expr.filters[ name ];
  708
+		PSEUDO: function( elem, match, i, array ) {
  709
+			var name = match[1],
  710
+				filter = Expr.filters[ name ];
561 711
 
562 712
 			if ( filter ) {
563 713
 				return filter( elem, i, match, array );
  714
+
564 715
 			} else if ( name === "contains" ) {
565  
-				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
  716
+				return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
  717
+
566 718
 			} else if ( name === "not" ) {
567 719
 				var not = match[3];
568 720
 
569  
-				for ( var i = 0, l = not.length; i < l; i++ ) {
570  
-					if ( not[i] === elem ) {
  721
+				for ( var j = 0, l = not.length; j < l; j++ ) {
  722
+					if ( not[j] === elem ) {
571 723
 						return false;
572 724
 					}
573 725
 				}
574 726
 
575 727
 				return true;
  728
+
  729
+			} else {
  730
+				Sizzle.error( name );
576 731
 			}
577 732
 		},
578  
-		CHILD: function(elem, match){
579  
-			var type = match[1], node = elem;
580  
-			switch (type) {
581  
-				case 'only':
582  
-				case 'first':
583  
-					while ( (node = node.previousSibling) )  {
584  
-						if ( node.nodeType === 1 ) return false;
  733
+
  734
+		CHILD: function( elem, match ) {
  735
+			var type = match[1],
  736
+				node = elem;
  737
+
  738
+			switch ( type ) {
  739
+				case "only":
  740
+				case "first":
  741
+					while ( (node = node.previousSibling) )	 {
  742
+						if ( node.nodeType === 1 ) { 
  743
+							return false; 
  744
+						}
585 745
 					}
586  
-					if ( type == 'first') return true;
  746
+
  747
+					if ( type === "first" ) { 
  748
+						return true; 
  749
+					}
  750
+
587 751
 					node = elem;
588  
-				case 'last':
589  
-					while ( (node = node.nextSibling) )  {
590  
-						if ( node.nodeType === 1 ) return false;
  752
+
  753
+				case "last":
  754
+					while ( (node = node.nextSibling) )	 {
  755
+						if ( node.nodeType === 1 ) { 
  756
+							return false; 
  757
+						}
591 758
 					}
  759
+
592 760
 					return true;
593  
-				case 'nth':
594  
-					var first = match[2], last = match[3];
595 761
 
596  
-					if ( first == 1 && last == 0 ) {
  762
+				case "nth":
  763
+					var first = match[2],
  764
+						last = match[3];
  765
+
  766
+					if ( first === 1 && last === 0 ) {
597 767
 						return true;
598 768
 					}
599 769
 					
@@ -602,33 +772,41 @@ var Expr = Sizzle.selectors = {
602 772
 	
603 773
 					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
604 774
 						var count = 0;
  775
+						
605 776
 						for ( node = parent.firstChild; node; node = node.nextSibling ) {
606 777
 							if ( node.nodeType === 1 ) {
607 778
 								node.nodeIndex = ++count;
608 779
 							}
609 780
 						} 
  781
+
610 782
 						parent.sizcache = doneName;
611 783
 					}
612 784
 					
613 785
 					var diff = elem.nodeIndex - last;
614  
-					if ( first == 0 ) {
615  
-						return diff == 0;
  786
+
  787
+					if ( first === 0 ) {
  788
+						return diff === 0;
  789
+
616 790
 					} else {
617  
-						return ( diff % first == 0 && diff / first >= 0 );
  791
+						return ( diff % first === 0 && diff / first >= 0 );
618 792
 					}
619 793
 			}
620 794
 		},
621  
-		ID: function(elem, match){
  795
+
  796
+		ID: function( elem, match ) {
622 797
 			return elem.nodeType === 1 && elem.getAttribute("id") === match;
623 798
 		},
624  
-		TAG: function(elem, match){
625  
-			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
  799
+
  800
+		TAG: function( elem, match ) {
  801
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
626 802
 		},
627  
-		CLASS: function(elem, match){
  803
+		
  804
+		CLASS: function( elem, match ) {
628 805
 			return (" " + (elem.className || elem.getAttribute("class")) + " ")
629 806
 				.indexOf( match ) > -1;
630 807
 		},
631  
-		ATTR: function(elem, match){
  808
+
  809
+		ATTR: function( elem, match ) {
632 810
 			var name = match[1],
633 811
 				result = Expr.attrHandle[ name ] ?
634 812
 					Expr.attrHandle[ name ]( elem ) :
@@ -650,7 +828,7 @@ var Expr = Sizzle.selectors = {
650 828
 				!check ?
651 829
 				value && result !== false :
652 830
 				type === "!=" ?
653  
-				value != check :
  831
+				value !== check :
654 832
 				type === "^=" ?
655 833
 				value.indexOf(check) === 0 :
656 834
 				type === "$=" ?
@@ -659,8 +837,10 @@ var Expr = Sizzle.selectors = {
659 837
 				value === check || value.substr(0, check.length + 1) === check + "-" :
660 838
 				false;
661 839
 		},
662  
-		POS: function(elem, match, i, array){
663  
-			var name = match[2], filter = Expr.setFilters[ name ];
  840
+
  841
+		POS: function( elem, match, i, array ) {
  842
+			var name = match[2],
  843
+				filter = Expr.setFilters[ name ];
664 844
 
665 845
 			if ( filter ) {
666 846
 				return filter( elem, i, match, array );
@@ -669,14 +849,17 @@ var Expr = Sizzle.selectors = {
669 849
 	}
670 850
 };
671 851
 
672  
-var origPOS = Expr.match.POS;
  852
+var origPOS = Expr.match.POS,
  853
+	fescape = function(all, num){
  854
+		return "\\" + (num - 0 + 1);
  855
+	};
673 856
 
674 857
 for ( var type in Expr.match ) {
675  
-	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
676  
-	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
  858
+	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
  859
+	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
677 860
 }
678 861
 
679  
-var makeArray = function(array, results) {
  862
+var makeArray = function( array, results ) {
680 863
 	array = Array.prototype.slice.call( array, 0 );
681 864
 
682 865
 	if ( results ) {
@@ -689,23 +872,28 @@ var makeArray = function(array, results) {
689 872
 
690 873
 // Perform a simple check to determine if the browser is capable of
691 874
 // converting a NodeList to an array using builtin methods.
  875
+// Also verifies that the returned array holds DOM nodes
  876
+// (which is not the case in the Blackberry browser)
692 877
 try {
693  
-	Array.prototype.slice.call( document.documentElement.childNodes, 0 );
  878
+	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
694 879
 
695 880
 // Provide a fallback method if it does not work
696  
-} catch(e){
697  
-	makeArray = function(array, results) {
698  
-		var ret = results || [];
  881
+} catch( e ) {
  882
+	makeArray = function( array, results ) {
  883
+		var i = 0,
  884
+			ret = results || [];
699 885
 
700 886
 		if ( toString.call(array) === "[object Array]" ) {
701 887
 			Array.prototype.push.apply( ret, array );
  888
+
702 889
 		} else {
703 890
 			if ( typeof array.length === "number" ) {
704  
-				for ( var i = 0, l = array.length; i < l; i++ ) {
  891
+				for ( var l = array.length; i < l; i++ ) {
705 892
 					ret.push( array[i] );
706 893
 				}
  894
+
707 895
 			} else {
708  
-				for ( var i = 0; array[i]; i++ ) {
  896
+				for ( ; array[i]; i++ ) {
709 897
 					ret.push( array[i] );
710 898
 				}
711 899
 			}
@@ -715,90 +903,161 @@ try {
715 903
 	};
716 904
 }
717 905
 
718  
-var sortOrder;
  906
+var sortOrder, siblingCheck;
719 907
 
720 908
 if ( document.documentElement.compareDocumentPosition ) {
721 909
 	sortOrder = function( a, b ) {
722  
-		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
723  
-			if ( a == b ) {
724  
-				hasDuplicate = true;
725  
-			}
  910
+		if ( a === b ) {
  911
+			hasDuplicate = true;
726 912
 			return 0;
727 913
 		}
728 914
 
729  
-		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
730  
-		if ( ret === 0 ) {
731  
-			hasDuplicate = true;
  915
+		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
  916
+			return a.compareDocumentPosition ? -1 : 1;
732 917
 		}
733  
-		return ret;
  918
+
  919
+		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
734 920
 	};
735  
-} else if ( "sourceIndex" in document.documentElement ) {
  921
+
  922
+} else {
736 923
 	sortOrder = function( a, b ) {
737  
-		if ( !a.sourceIndex || !b.sourceIndex ) {
738  
-			if ( a == b ) {
739  
-				hasDuplicate = true;
740  
-			}
  924
+		// The nodes are identical, we can exit early
  925
+		if ( a === b ) {
  926
+			hasDuplicate = true;
741 927
 			return 0;
  928
+
  929
+		// Fallback to using sourceIndex (in IE) if it's available on both nodes
  930
+		} else if ( a.sourceIndex && b.sourceIndex ) {
  931
+			return a.sourceIndex - b.sourceIndex;
742 932
 		}
743 933
 
744  
-		var ret = a.sourceIndex - b.sourceIndex;
745  
-		if ( ret === 0 ) {
746  
-			hasDuplicate = true;
  934
+		var al, bl,
  935
+			ap = [],
  936
+			bp = [],
  937
+			aup = a.parentNode,
  938
+			bup = b.parentNode,
  939
+			cur = aup;
  940
+
  941
+		// If the nodes are siblings (or identical) we can do a quick check
  942
+		if ( aup === bup ) {
  943
+			return siblingCheck( a, b );
  944
+
  945
+		// If no parents were found then the nodes are disconnected
  946
+		} else if ( !aup ) {
  947
+			return -1;
  948
+
  949
+		} else if ( !bup ) {
  950
+			return 1;
747 951
 		}
748  
-		return ret;
749  
-	};
750  
-} else if ( document.createRange ) {
751  
-	sortOrder = function( a, b ) {
752  
-		if ( !a.ownerDocument || !b.ownerDocument ) {
753  
-			if ( a == b ) {
754  
-				hasDuplicate = true;
  952
+
  953
+		// Otherwise they're somewhere else in the tree so we need
  954
+		// to build up a full list of the parentNodes for comparison
  955
+		while ( cur ) {
  956
+			ap.unshift( cur );
  957
+			cur = cur.parentNode;
  958
+		}
  959
+
  960
+		cur = bup;
  961
+
  962
+		while ( cur ) {
  963
+			bp.unshift( cur );
  964
+			cur = cur.parentNode;
  965
+		}
  966
+
  967
+		al = ap.length;
  968
+		bl = bp.length;
  969
+
  970
+		// Start walking down the tree looking for a discrepancy
  971
+		for ( var i = 0; i < al && i < bl; i++ ) {
  972
+			if ( ap[i] !== bp[i] ) {
  973
+				return siblingCheck( ap[i], bp[i] );
755 974
 			}
756  
-			return 0;
757 975
 		}
758 976
 
759  
-		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
760  
-		aRange.setStart(a, 0);
761  
-		aRange.setEnd(a, 0);
762  
-		bRange.setStart(b, 0);
763  
-		bRange.setEnd(b, 0);
764  
-		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
765  
-		if ( ret === 0 ) {
766  
-			hasDuplicate = true;
  977
+		// We ended someplace up the tree so do a sibling check
  978
+		return i === al ?
  979
+			siblingCheck( a, bp[i], -1 ) :
  980
+			siblingCheck( ap[i], b, 1 );
  981
+	};
  982
+
  983
+	siblingCheck = function( a, b, ret ) {
  984
+		if ( a === b ) {
  985
+			return ret;
767 986
 		}
768  
-		return ret;
  987
+
  988
+		var cur = a.nextSibling;
  989
+
  990
+		while ( cur ) {
  991
+			if ( cur === b ) {
  992
+				return -1;
  993
+			}
  994
+
  995
+			cur = cur.nextSibling;
  996
+		}
  997
+
  998
+		return 1;
769 999
 	};
770 1000
 }
771 1001
 
  1002
+// Utility function for retreiving the text value of an array of DOM nodes
  1003
+Sizzle.getText = function( elems ) {
  1004
+	var ret = "", elem;
  1005
+
  1006
+	for ( var i = 0; elems[i]; i++ ) {
  1007
+		elem = elems[i];
  1008
+
  1009
+		// Get the text from text nodes and CDATA nodes
  1010
+		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
  1011
+			ret += elem.nodeValue;
  1012
+
  1013
+		// Traverse everything else, except comment nodes
  1014
+		} else if ( elem.nodeType !== 8 ) {
  1015
+			ret += Sizzle.getText( elem.childNodes );
  1016
+		}
  1017
+	}
  1018
+
  1019
+	return ret;
  1020
+};
  1021
+
772 1022
 // Check to see if the browser returns elements by name when
773 1023
 // querying by getElementById (and provide a workaround)
774 1024
 (function(){
775 1025
 	// We're going to inject a fake input element with a specified name
776 1026
 	var form = document.createElement("div"),
777  
-		id = "script" + (new Date).getTime();
  1027
+		id = "script" + (new Date()).getTime(),
  1028
+		root = document.documentElement;
  1029
+
778 1030
 	form.innerHTML = "<a name='" + id + "'/>";
779 1031
 
780 1032
 	// Inject it into the root element, check its status, and remove it quickly
781  
-	var root = document.documentElement;
782 1033
 	root.insertBefore( form, root.firstChild );
783 1034
 
784 1035
 	// The workaround has to do additional checks after a getElementById
785 1036
 	// Which slows things down for other browsers (hence the branching)
786  
-	if ( !!document.getElementById( id ) ) {
787  
-		Expr.find.ID = function(match, context, isXML){
  1037
+	if ( document.getElementById( id ) ) {
  1038
+		Expr.find.ID = function( match, context, isXML ) {
788 1039
 			if ( typeof context.getElementById !== "undefined" && !isXML ) {
789 1040
 				var m = context.getElementById(match[1]);
790  
-				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
  1041
+
  1042
+				return m ?
  1043
+					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
  1044
+						[m] :
  1045
+						undefined :
  1046
+					[];
791 1047
 			}
792 1048
 		};
793 1049
 
794  
-		Expr.filter.ID = function(elem, match){
  1050
+		Expr.filter.ID = function( elem, match ) {
795 1051
 			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
  1052
+
796 1053