wpa_cli_web 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/.bowerrc +3 -0
  2. data/lib/wpa_cli_web.rb +19 -31
  3. data/lib/wpa_cli_web/public/bower_components/house-style/.bower.json +14 -0
  4. data/lib/wpa_cli_web/public/bower_components/house-style/.bowerrc +3 -0
  5. data/lib/wpa_cli_web/public/bower_components/house-style/.gitignore +2 -0
  6. data/lib/wpa_cli_web/public/bower_components/house-style/Gemfile +6 -0
  7. data/lib/wpa_cli_web/public/bower_components/house-style/Gruntfile.js +99 -0
  8. data/lib/wpa_cli_web/public/bower_components/house-style/Guardfile +19 -0
  9. data/lib/wpa_cli_web/public/bower_components/house-style/bower.json +7 -0
  10. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/LICENSE.md +19 -0
  11. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/README.md +49 -0
  12. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/bower.json +23 -0
  13. data/lib/wpa_cli_web/public/bower_components/house-style/bower_components/normalize-css/normalize.css +396 -0
  14. data/lib/wpa_cli_web/public/bower_components/house-style/house-style.css +860 -0
  15. data/lib/wpa_cli_web/public/bower_components/house-style/house-style.min.css +1 -0
  16. data/lib/wpa_cli_web/public/bower_components/house-style/modules/base/base.css +37 -0
  17. data/lib/wpa_cli_web/public/bower_components/house-style/modules/button/button.css +26 -0
  18. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/grid.css +151 -0
  19. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/grid.png +0 -0
  20. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/images.html +208 -0
  21. data/lib/wpa_cli_web/public/bower_components/house-style/modules/grid/index.html +141 -0
  22. data/lib/wpa_cli_web/public/bower_components/house-style/modules/loading/index.html +22 -0
  23. data/lib/wpa_cli_web/public/bower_components/house-style/modules/loading/loading.css +41 -0
  24. data/lib/wpa_cli_web/public/bower_components/house-style/modules/loading/spinner.svg +11 -0
  25. data/lib/wpa_cli_web/public/bower_components/house-style/modules/masthead/bbc-blocks-white.png +0 -0
  26. data/lib/wpa_cli_web/public/bower_components/house-style/modules/masthead/index.html +20 -0
  27. data/lib/wpa_cli_web/public/bower_components/house-style/modules/masthead/masthead.css +23 -0
  28. data/lib/wpa_cli_web/public/bower_components/house-style/modules/panel/panel.css +71 -0
  29. data/lib/wpa_cli_web/public/bower_components/house-style/modules/project-header/index.html +22 -0
  30. data/lib/wpa_cli_web/public/bower_components/house-style/modules/project-header/project-header.css +37 -0
  31. data/lib/wpa_cli_web/public/bower_components/house-style/modules/table/index.html +26 -0
  32. data/lib/wpa_cli_web/public/bower_components/house-style/modules/table/table.css +6 -0
  33. data/lib/wpa_cli_web/public/bower_components/house-style/modules/transitions/transitions.css +11 -0
  34. data/lib/wpa_cli_web/public/bower_components/house-style/package.json +21 -0
  35. data/lib/wpa_cli_web/public/bower_components/house-style/vendor/prefixfree.min.js +5 -0
  36. data/lib/wpa_cli_web/public/bower_components/normalize-css/.bower.json +21 -0
  37. data/lib/wpa_cli_web/public/bower_components/normalize-css/LICENSE.md +19 -0
  38. data/lib/wpa_cli_web/public/bower_components/normalize-css/README.md +49 -0
  39. data/lib/wpa_cli_web/public/bower_components/normalize-css/bower.json +12 -0
  40. data/lib/wpa_cli_web/public/bower_components/normalize-css/normalize.css +396 -0
  41. data/lib/wpa_cli_web/public/bower_components/qwery/.bower.json +14 -0
  42. data/lib/wpa_cli_web/public/bower_components/qwery/.gitignore +3 -0
  43. data/lib/wpa_cli_web/public/bower_components/qwery/.travis.yml +10 -0
  44. data/lib/wpa_cli_web/public/bower_components/qwery/LICENSE +7 -0
  45. data/lib/wpa_cli_web/public/bower_components/qwery/Makefile +6 -0
  46. data/lib/wpa_cli_web/public/bower_components/qwery/README.md +167 -0
  47. data/lib/wpa_cli_web/public/bower_components/qwery/config/smoosh.json +35 -0
  48. data/lib/wpa_cli_web/public/bower_components/qwery/integration/ender.js +1033 -0
  49. data/lib/wpa_cli_web/public/bower_components/qwery/integration/integration.html +26 -0
  50. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/ender.js +62 -0
  51. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/package.json +14 -0
  52. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/qwery-mobile.js +79 -0
  53. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/qwery-mobile.min.js +7 -0
  54. data/lib/wpa_cli_web/public/bower_components/qwery/mobile/src/mobile.js +72 -0
  55. data/lib/wpa_cli_web/public/bower_components/qwery/package.json +25 -0
  56. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/package.json +17 -0
  57. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/qwery-pseudos.js +106 -0
  58. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/qwery-pseudos.min.js +7 -0
  59. data/lib/wpa_cli_web/public/bower_components/qwery/pseudos/src/pseudos.js +99 -0
  60. data/lib/wpa_cli_web/public/bower_components/qwery/qwery.js +369 -0
  61. data/lib/wpa_cli_web/public/bower_components/qwery/qwery.min.js +7 -0
  62. data/lib/wpa_cli_web/public/bower_components/qwery/src/copyright.js +6 -0
  63. data/lib/wpa_cli_web/public/bower_components/qwery/src/ender.js +62 -0
  64. data/lib/wpa_cli_web/public/bower_components/qwery/src/qwery.js +362 -0
  65. data/lib/wpa_cli_web/public/bower_components/qwery/tests/W3C-Selector-tests.html +1372 -0
  66. data/lib/wpa_cli_web/public/bower_components/qwery/tests/benchmarks.html +220 -0
  67. data/lib/wpa_cli_web/public/bower_components/qwery/tests/index.html +132 -0
  68. data/lib/wpa_cli_web/public/bower_components/qwery/tests/mobile.html +58 -0
  69. data/lib/wpa_cli_web/public/bower_components/qwery/tests/phantom.js +43 -0
  70. data/lib/wpa_cli_web/public/bower_components/qwery/tests/test-env.js +25 -0
  71. data/lib/wpa_cli_web/public/bower_components/qwery/tests/tests.js +533 -0
  72. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/nw.js +1680 -0
  73. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/sink.css +79 -0
  74. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/sink.js +181 -0
  75. data/lib/wpa_cli_web/public/bower_components/qwery/vendor/sizzle.js +1400 -0
  76. data/lib/wpa_cli_web/public/bower_components/reqwest/.bower.json +14 -0
  77. data/lib/wpa_cli_web/public/bower_components/reqwest/.gitignore +1 -0
  78. data/lib/wpa_cli_web/public/bower_components/reqwest/.jshintrc +61 -0
  79. data/lib/wpa_cli_web/public/bower_components/reqwest/Makefile +8 -0
  80. data/lib/wpa_cli_web/public/bower_components/reqwest/README.md +308 -0
  81. data/lib/wpa_cli_web/public/bower_components/reqwest/build.json +74 -0
  82. data/lib/wpa_cli_web/public/bower_components/reqwest/make/tests.js +89 -0
  83. data/lib/wpa_cli_web/public/bower_components/reqwest/package.json +27 -0
  84. data/lib/wpa_cli_web/public/bower_components/reqwest/reqwest.js +565 -0
  85. data/lib/wpa_cli_web/public/bower_components/reqwest/reqwest.min.js +7 -0
  86. data/lib/wpa_cli_web/public/bower_components/reqwest/src/copyright.js +6 -0
  87. data/lib/wpa_cli_web/public/bower_components/reqwest/src/ender.js +26 -0
  88. data/lib/wpa_cli_web/public/bower_components/reqwest/src/reqwest.js +559 -0
  89. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/ender.js +117 -0
  90. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/badfixtures.xml +1 -0
  91. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.html +1 -0
  92. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.js +1 -0
  93. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.json +1 -0
  94. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures.xml +1 -0
  95. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp.jsonp +1 -0
  96. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp2.jsonp +1 -0
  97. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp3.jsonp +1 -0
  98. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp_multi.jsonp +1 -0
  99. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp_multi_b.jsonp +1 -0
  100. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_jsonp_multi_c.jsonp +1 -0
  101. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/fixtures_with_prefix.json +1 -0
  102. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/fixtures/invalidJSON.json +5 -0
  103. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/tests.html +105 -0
  104. data/lib/wpa_cli_web/public/bower_components/reqwest/tests/tests.js +1723 -0
  105. data/lib/wpa_cli_web/views/access_points.erb +5 -0
  106. data/lib/wpa_cli_web/views/access_points_list.erb +19 -0
  107. data/lib/wpa_cli_web/views/layout.erb +141 -0
  108. data/lib/wpa_cli_web/views/networks_edit.erb +15 -0
  109. data/lib/wpa_cli_web/views/restart.erb +7 -0
  110. data/lib/wpa_cli_web/views/restarting.erb +14 -0
  111. data/wpa_cli_web.gemspec +1 -1
  112. metadata +111 -2
@@ -0,0 +1,1680 @@
1
+ /*
2
+ * Copyright (C) 2007-2010 Diego Perini
3
+ * All rights reserved.
4
+ *
5
+ * nwmatcher.js - A fast CSS selector engine and matcher
6
+ *
7
+ * Author: Diego Perini <diego.perini at gmail com>
8
+ * Version: 1.2.4beta
9
+ * Created: 20070722
10
+ * Release: 20110116
11
+ *
12
+ * License:
13
+ * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE
14
+ * Download:
15
+ * http://javascript.nwbox.com/NWMatcher/nwmatcher.js
16
+ */
17
+
18
+ (function(global) {
19
+
20
+ var version = 'nwmatcher-1.2.4beta',
21
+
22
+ // processing context
23
+ doc = global.document,
24
+
25
+ // context root element
26
+ root = doc.documentElement,
27
+
28
+ // save method reference
29
+ slice = Array.prototype.slice,
30
+
31
+ // persist last selector/matcher parsing data
32
+ lastError = '',
33
+ lastSlice = '',
34
+ lastPosition = 0,
35
+ lastMatcher = '',
36
+ lastSelector = '',
37
+ isSingleMatch = false,
38
+ isSingleSelect = false,
39
+
40
+ // initialize selector/matcher loading context
41
+ lastMatchContext = doc,
42
+ lastSelectContext = doc,
43
+
44
+ // prefixes identifying id, class & pseudo-class
45
+ prefixes = '[.:#]?',
46
+
47
+ // attributes operators
48
+ // ! invalid but compat !
49
+ operators = '([~*^$|!]?={1})',
50
+
51
+ // whitespace characters
52
+ whitespace = '[\\x20\\t\\n\\r\\f]*',
53
+
54
+ // 4 combinators F E, F>E, F+E, F~E
55
+ combinators = '[\\x20]|[>+~][^>+~]',
56
+
57
+ // an+b format params for psuedo-classes
58
+ pseudoparms = '[-+]?\\d*n?[-+]?\\d*',
59
+
60
+ // CSS quoted string values
61
+ quotedvalue = '"[^"]*"' + "|'[^']*'",
62
+
63
+ // http://www.w3.org/TR/css3-syntax/#characters
64
+ // unicode/ISO 10646 characters 161 and higher
65
+ // NOTE: Safari 2.0.x crashes with escaped (\\)
66
+ // Unicode ranges in regular expressions so we
67
+ // use a negated character range class instead
68
+ encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)',
69
+
70
+ // CSS identifier syntax
71
+ identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+',
72
+
73
+ // build attribute string
74
+ attributes =
75
+ whitespace + '(' + encoding + '+:?' + encoding + '+)' +
76
+ whitespace + '(?:' + operators + whitespace + '(' +
77
+ quotedvalue + '|' + identifier + '))?' + whitespace,
78
+
79
+ // build pseudoclass string
80
+ pseudoclass = '((?:' +
81
+ // an+b parameters or quoted string
82
+ pseudoparms + '|' + quotedvalue + '|' +
83
+ // id, class, pseudo-class selector
84
+ prefixes + '|' + encoding + '+|' +
85
+ // nested HTML attribute selector
86
+ '\\[' + attributes + '\\]|' +
87
+ // nested pseudo-class selector
88
+ '\\(.+\\)|' + whitespace + '|' +
89
+ // nested pseudos/separators
90
+ ',)+)',
91
+
92
+ // placeholder for extensions
93
+ extensions = '.+',
94
+
95
+ // CSS3: syntax scanner and
96
+ // one pass validation only
97
+ // using regular expression
98
+ standardValidator =
99
+ // discard start
100
+ '(?=\s*[^>+~(){}<>])' +
101
+ // open match group
102
+ '(' +
103
+ //universal selector
104
+ '\\*' +
105
+ // id/class/tag/pseudo-class identifier
106
+ '|(?:' + prefixes + identifier + ')' +
107
+ // combinator selector
108
+ '|' + combinators +
109
+ // HTML attribute selector
110
+ '|\\[' + attributes + '\\]' +
111
+ // pseudo-classes parameters
112
+ '|\\(' + pseudoclass + '\\)' +
113
+ // dom properties selector (extension)
114
+ '|\\{' + extensions + '\\}' +
115
+ // selector group separator (comma)
116
+ '|,' +
117
+ // close match group
118
+ ')+',
119
+
120
+ // validator for standard selectors as default
121
+ reValidator = new RegExp(standardValidator, 'g'),
122
+
123
+ // validator for complex selectors in ':not()' pseudo-classes
124
+ extendedValidator = standardValidator.replace(pseudoclass, '.*'),
125
+
126
+ // whitespace is any combination of these 5 character [\x20\t\n\r\f]
127
+ // http://www.w3.org/TR/css3-selectors/#selector-syntax
128
+ reTrimSpaces = new RegExp('^' +
129
+ whitespace + '|' + whitespace + '$', 'g'),
130
+
131
+ // only allow simple selectors nested in ':not()' pseudo-classes
132
+ reSimpleNot = new RegExp('^(' +
133
+ '(?!:not)' +
134
+ '(' + prefixes +
135
+ '|' + identifier +
136
+ '|\\([^()]*\\))+' +
137
+ '|\\[' + attributes + '\\]' +
138
+ ')$'),
139
+
140
+ // skip group of round brackets
141
+ skipround = '\\([^()]+\\)|\\(.*\\)',
142
+ // skip group of curly brackets
143
+ skipcurly = '\\{[^{}]+\\}|\\{.*\\}',
144
+ // skip group of square brackets
145
+ skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]',
146
+
147
+ // skip [ ], ( ), { } groups in token tails
148
+ skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}',
149
+
150
+ // split comma groups, exclude commas from
151
+ // quotes '' "" and from brackets () [] {}
152
+ reSplitGroup = new RegExp('(' +
153
+ '[^(,)\\\\\\[\\]]+' +
154
+ '|\\[(?:' + skipsquare +
155
+ '|' + quotedvalue +
156
+ '|[^\\[\\]]+)+\\]' +
157
+ '|' + skipround +
158
+ '|' + skipcurly +
159
+ '|\\\\.' +
160
+ ')+', 'g'),
161
+
162
+ // split last, right most, selector group token
163
+ reSplitToken = new RegExp('(' +
164
+ '\\(' + pseudoclass + '\\)|' +
165
+ '\\[' + attributes + '\\]|' +
166
+ '[^\x20>+~]|\\\\.)+', 'g'),
167
+
168
+ // for pseudos, ids and in excess whitespace removal
169
+ reClassValue = new RegExp('(' + identifier + ')'),
170
+ reIdSelector = new RegExp('#(' + identifier + ')'),
171
+ reWhiteSpace = /[\x20\t\n\r\f]+/g,
172
+
173
+ // match missing R/L context
174
+ reLeftContext = /^\s*[>+~]{1}/,
175
+ reRightContext = /[>+~]{1}\s*$/,
176
+
177
+ reOptimizeSelector = new RegExp(identifier + '|^$'),
178
+
179
+ /*----------------------------- FEATURE TESTING ----------------------------*/
180
+
181
+ // detect native methods
182
+ isNative = (function() {
183
+ var s = (global.toString + '').replace(/toString/g, '');
184
+ return function(object, method) {
185
+ var m = object ? object[method] : false, r = new RegExp(method, 'g');
186
+ return !!(m && typeof m != 'string' && s === (m + '').replace(r, ''));
187
+ };
188
+ })(),
189
+
190
+ // Safari 2 missing document.compatMode property
191
+ // makes harder to detect Quirks vs. Strict mode
192
+ isQuirks =
193
+ function(document) {
194
+ return typeof document.compatMode == 'string' ?
195
+ document.compatMode.indexOf('CSS') < 0 :
196
+ (function() {
197
+ var div = document.createElement('div'),
198
+ isStrict = div.style &&
199
+ (div.style.width = 1) &&
200
+ div.style.width != '1px';
201
+ div = null;
202
+ return !isStrict;
203
+ })();
204
+ },
205
+
206
+ // XML is functional in W3C browsers
207
+ isXML = 'xmlVersion' in doc ?
208
+ function(document) {
209
+ return !!document.xmlVersion ||
210
+ (/xml$/).test(document.contentType) ||
211
+ !(/html/i).test(document.documentElement.nodeName);
212
+ } :
213
+ function(document) {
214
+ return document.firstChild.nodeType == 7 &&
215
+ (/xml/i).test(document.firstChild.nodeName) ||
216
+ !(/html/i).test(document.documentElement.nodeName);
217
+ },
218
+
219
+ // initialized with the loading context
220
+ // and reset for each selection query
221
+ isQuirksMode = isQuirks(doc),
222
+ isXMLDocument = isXML(doc),
223
+
224
+ // NATIVE_XXXXX true if method exist and is callable
225
+ // detect if DOM methods are native in browsers
226
+ NATIVE_FOCUS = isNative(doc, 'hasFocus'),
227
+ NATIVE_QSAPI = isNative(doc, 'querySelector'),
228
+ NATIVE_GEBID = isNative(doc, 'getElementById'),
229
+ NATIVE_GEBTN = isNative(root, 'getElementsByTagName'),
230
+ NATIVE_GEBCN = isNative(root, 'getElementsByClassName'),
231
+
232
+ // detect native getAttribute/hasAttribute methods,
233
+ // frameworks extend these to elements, but it seems
234
+ // this does not work for XML namespaced attributes,
235
+ // used to check both getAttribute/hasAttribute in IE
236
+ NATIVE_GET_ATTRIBUTE = isNative(root, 'getAttribute'),
237
+ NATIVE_HAS_ATTRIBUTE = isNative(root, 'hasAttribute'),
238
+
239
+ // check if slice() can convert nodelist to array
240
+ // see http://yura.thinkweb2.com/cft/
241
+ NATIVE_SLICE_PROTO =
242
+ (function() {
243
+ var isBuggy = false, id = root.id;
244
+ root.id = 'length';
245
+ try {
246
+ isBuggy = !!slice.call(doc.childNodes, 0)[0];
247
+ } catch(e) { }
248
+ root.id = id;
249
+ return isBuggy;
250
+ })(),
251
+
252
+ // supports the new traversal API
253
+ NATIVE_TRAVERSAL_API =
254
+ 'nextElementSibling' in root && 'previousElementSibling' in root,
255
+
256
+ // select Matches Selector API to use if available
257
+ NATIVE_MATCHES_SELECTOR =
258
+ isNative(root, 'matchesSelector') ? 'matchesSelector' :
259
+ isNative(root, 'msMatchesSelector') ? 'msMatchesSelector' :
260
+ isNative(root, 'mozMatchesSelector') ? 'mozMatchesSelector' :
261
+ isNative(root, 'webkitMatchesSelector') ? 'webkitMatchesSelector' : null,
262
+
263
+ // BUGGY_XXXXX true if method is feature tested and has known bugs
264
+ // detect buggy gEBID
265
+ BUGGY_GEBID = NATIVE_GEBID ?
266
+ (function() {
267
+ var isBuggy = true, x = 'x' + String(+new Date),
268
+ a = doc.createElementNS ? 'a' : '<a name="' + x + '">';
269
+ (a = doc.createElement(a)).name = x;
270
+ root.insertBefore(a, root.firstChild);
271
+ isBuggy = !!doc.getElementById(x);
272
+ root.removeChild(a);
273
+ a = null;
274
+ return isBuggy;
275
+ })() :
276
+ true,
277
+
278
+ // detect IE gEBTN comment nodes bug
279
+ BUGGY_GEBTN = NATIVE_GEBTN ?
280
+ (function() {
281
+ var isBuggy, div = doc.createElement('div');
282
+ div.appendChild(doc.createComment(''));
283
+ isBuggy = div.getElementsByTagName('*')[0];
284
+ div.removeChild(div.firstChild);
285
+ div = null;
286
+ return !!isBuggy;
287
+ })() :
288
+ true,
289
+
290
+ // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2
291
+ // caching class name results and not detecting when changed,
292
+ // tests are based on the jQuery selector test suite
293
+ BUGGY_GEBCN = NATIVE_GEBCN ?
294
+ (function() {
295
+ var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317';
296
+
297
+ // Opera tests
298
+ div.appendChild(doc.createElement('span')).
299
+ setAttribute('class', test + 'abc ' + test);
300
+ div.appendChild(doc.createElement('span')).
301
+ setAttribute('class', 'x');
302
+
303
+ isBuggy = !div.getElementsByClassName(test)[0];
304
+
305
+ // Safari test
306
+ div.lastChild.className = test;
307
+ if (!isBuggy)
308
+ isBuggy = div.getElementsByClassName(test).length !== 2;
309
+
310
+ div.removeChild(div.firstChild);
311
+ div.removeChild(div.firstChild);
312
+ div = null;
313
+ return isBuggy;
314
+ })() :
315
+ true,
316
+
317
+ // detect IE bug with dynamic attributes
318
+ BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ?
319
+ (function() {
320
+ var isBuggy, input;
321
+ (input = doc.createElement('input')).setAttribute('value', '5');
322
+ return isBuggy = input.defaultValue != 5;
323
+ })() :
324
+ true,
325
+
326
+ // detect IE bug with non-standard boolean attributes
327
+ BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ?
328
+ (function() {
329
+ var isBuggy, option = doc.createElement('option');
330
+ option.setAttribute('selected', 'selected');
331
+ isBuggy = !option.hasAttribute('selected');
332
+ return isBuggy;
333
+ })() :
334
+ true,
335
+
336
+ // detect matchesSelector correctly throw errors
337
+ BUGGY_PSEUDOS = NATIVE_MATCHES_SELECTOR ?
338
+ (function() {
339
+ var isBuggy = false;
340
+ try {
341
+ root[NATIVE_MATCHES_SELECTOR](':buggy');
342
+ isBuggy = true;
343
+ } catch(e) { }
344
+ return isBuggy;
345
+ })() :
346
+ true,
347
+
348
+ // detect Safari bug with selected option elements
349
+ BUGGY_SELECTED =
350
+ (function() {
351
+ var isBuggy, select = doc.createElement('select');
352
+ select.appendChild(doc.createElement('option'));
353
+ isBuggy = !select.firstChild.selected;
354
+ return isBuggy;
355
+ })(),
356
+
357
+ // check Seletor API implementations
358
+ RE_BUGGY_QSAPI = NATIVE_QSAPI ?
359
+ (function() {
360
+ var pattern = [ ], div = doc.createElement('div'), element;
361
+
362
+ // In quirks mode css class names are case insensitive.
363
+ // In standards mode they are case sensitive. See docs:
364
+ // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior
365
+ // http://www.whatwg.org/specs/web-apps/current-work/#selectors
366
+
367
+ // Safari 3.2 QSA doesn't work with mixedcase in quirksmode
368
+ // https://bugs.webkit.org/show_bug.cgi?id=19047
369
+ // must test the attribute selector '[class~=xxx]'
370
+ // before '.xXx' or the bug may not present itself
371
+ div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx');
372
+ div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx');
373
+ if (isQuirks(doc) &&
374
+ (div.querySelectorAll('[class~=xxx]').length != 2 ||
375
+ div.querySelectorAll('.xXx').length != 2)) {
376
+ pattern.push('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')');
377
+ }
378
+ div.removeChild(div.firstChild);
379
+ div.removeChild(div.firstChild);
380
+
381
+ // ^= $= *= operators bugs whith empty values (Opera 10 / IE8)
382
+ div.appendChild(doc.createElement('p')).setAttribute('class', '');
383
+ try {
384
+ div.querySelectorAll('[class^=""]').length == 1 &&
385
+ pattern.push('\\[\\s*.*(?=\\^=|\\$=|\\*=).*]');
386
+ } catch(e) { }
387
+ div.removeChild(div.firstChild);
388
+
389
+ // :checked bugs whith checkbox elements (Opera 10 to 10.53)
390
+ element = doc.createElement('input');
391
+ element.setAttribute('type', 'checkbox');
392
+ element.setAttribute('checked', 'checked');
393
+ div.appendChild(element);
394
+ try {
395
+ div.querySelectorAll(':checked').length == 1 ||
396
+ pattern.push(':checked');
397
+ } catch(e) { }
398
+ div.removeChild(div.firstChild);
399
+
400
+ // :checked bug with option elements (Firefox 3.6.x)
401
+ // it wrongly includes 'selected' options elements
402
+ element = doc.createElement('option');
403
+ element.setAttribute('selected', 'selected');
404
+ div.appendChild(element);
405
+ try {
406
+ div.querySelectorAll(':checked').length == 1 &&
407
+ pattern.push(':checked');
408
+ } catch(e) { }
409
+ div.removeChild(div.firstChild);
410
+
411
+ // :enabled :disabled bugs with hidden fields (Firefox 3.5 QSA bug)
412
+ // http://www.w3.org/TR/html5/interactive-elements.html#selector-enabled
413
+ // IE8 QSA has problems too and throws error with these dynamic pseudos
414
+ (element = doc.createElement('input')).setAttribute('type', 'hidden');
415
+ div.appendChild(element);
416
+ try {
417
+ div.querySelectorAll(':enabled').length === 1 &&
418
+ pattern.push(':enabled', ':disabled');
419
+ } catch(e) { }
420
+ div.removeChild(div.firstChild);
421
+
422
+ // :link bugs with hyperlinks matching (Firefox/Safari)
423
+ div.appendChild(doc.createElement('a')).setAttribute('href', 'x');
424
+ div.querySelectorAll(':link').length !== 1 && pattern.push(':link');
425
+ div.removeChild(div.firstChild);
426
+
427
+ // avoid following selectors for IE QSA
428
+ if (BUGGY_HAS_ATTRIBUTE) {
429
+ pattern.push(
430
+ // IE fails reading original values for input/textarea
431
+ '\\[\\s*value',
432
+ // IE fails reading original boolean value for controls
433
+ '\\[\\s*ismap',
434
+ '\\[\\s*checked',
435
+ '\\[\\s*disabled',
436
+ '\\[\\s*multiple',
437
+ '\\[\\s*readonly',
438
+ '\\[\\s*selected');
439
+ }
440
+
441
+ div = null;
442
+ return pattern.length ?
443
+ new RegExp(pattern.join('|')) :
444
+ { 'test': function() { return false; } };
445
+ })() :
446
+ true,
447
+
448
+ // matches pseudo-classes
449
+ RE_PSEUDOS = new RegExp(':[-\\w]+'),
450
+
451
+ // matches simple id, tag & class selectors
452
+ RE_SIMPLE_SELECTOR = new RegExp(
453
+ !(BUGGY_GEBTN && BUGGY_GEBCN) ?
454
+ '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$' :
455
+ '^#?-?[_a-zA-Z]{1}' + encoding + '*$'),
456
+
457
+ /*----------------------------- LOOKUP OBJECTS -----------------------------*/
458
+
459
+ LINK_NODES = { 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 },
460
+
461
+ QSA_NODE_TYPES = { '9': 1, '11': 1 },
462
+
463
+ // boolean attributes should return attribute name instead of true/false
464
+ ATTR_BOOLEAN = {
465
+ checked: 1, disabled: 1, ismap: 1, multiple: 1, readonly: 1, selected: 1
466
+ },
467
+
468
+ // dynamic attributes that needs to be checked against original HTML value
469
+ ATTR_DEFAULT = {
470
+ value: 'defaultValue',
471
+ checked: 'defaultChecked',
472
+ selected: 'defaultSelected'
473
+ },
474
+
475
+ // HTML to DOM namespace mapping for special case attributes (IE engines)
476
+ ATTR_MAPPING = {
477
+ 'class': 'className', 'for': 'htmlFor'
478
+ },
479
+
480
+ // attribute referencing URI data values need special treatment in IE
481
+ ATTR_URIDATA = {
482
+ 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2,
483
+ 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2
484
+ },
485
+
486
+ // HTML 5 draft specifications
487
+ // http://www.whatwg.org/specs/web-apps/current-work/#selectors
488
+ HTML_TABLE = {
489
+ // class attribute must be treated case-insensitive in HTML quirks mode
490
+ // initialized by default to Standard Mode (case-sensitive),
491
+ // set dynamically by the attribute resolver
492
+ 'class': 0,
493
+ 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1,
494
+ 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1,
495
+ 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1,
496
+ 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1,
497
+ 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1,
498
+ 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1,
499
+ 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1,
500
+ 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1
501
+ },
502
+
503
+ // the following attributes must be treated case-insensitive in XHTML mode
504
+ // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity
505
+ XHTML_TABLE = {
506
+ 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1,
507
+ 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1,
508
+ 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1,
509
+ 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1,
510
+ 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1
511
+ },
512
+
513
+ /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/
514
+
515
+ // placeholder to add functionalities
516
+ Selectors = {
517
+ // as a simple example this will check
518
+ // for chars not in standard ascii table
519
+ //
520
+ // 'mySpecialSelector': {
521
+ // 'Expression': /\u0080-\uffff/,
522
+ // 'Callback': mySelectorCallback
523
+ // }
524
+ //
525
+ // 'mySelectorCallback' will be invoked
526
+ // only after passing all other standard
527
+ // checks and only if none of them worked
528
+ },
529
+
530
+ // attribute operators
531
+ Operators = {
532
+ '=': "n=='%m'",
533
+ '^=': "n.indexOf('%m')==0",
534
+ '*=': "n.indexOf('%m')>-1",
535
+ '|=': "(n+'-').indexOf('%m-')==0",
536
+ '~=': "(' '+n+' ').indexOf(' %m ')>-1",
537
+ '$=': "n.substr(n.length-'%m'.length)=='%m'"
538
+ },
539
+
540
+ // optimization expressions
541
+ Optimize = {
542
+ ID: new RegExp('^\\*?#(' + encoding + '+)|' + skipgroup),
543
+ TAG: new RegExp('^(' + encoding + '+)|' + skipgroup),
544
+ CLASS: new RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup),
545
+ NAME: /\[\s*name\s*=\s*((["']*)([^'"()]*?)\2)?\s*\]/
546
+ },
547
+
548
+ // precompiled Regular Expressions
549
+ Patterns = {
550
+ // structural pseudo-classes and child selectors
551
+ spseudos: /^\:(root|empty|nth)?-?(first|last|only)?-?(child)?-?(of-type)?(?:\(([^\x29]*)\))?(.*)/,
552
+ // uistates + dynamic + negation pseudo-classes
553
+ dpseudos: /^\:([\w]+|[^\x00-\xa0]+)(?:\((["']*)(.*?(\(.*\))?[^'"()]*?)\2\))?(.*)/,
554
+ // element attribute matcher
555
+ attribute: new RegExp('^\\[' + attributes + '\\](.*)'),
556
+ // E > F
557
+ children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/,
558
+ // E + F
559
+ adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/,
560
+ // E ~ F
561
+ relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/,
562
+ // E F
563
+ ancestor: /^[\x20\t\n\r\f]+(.*)/,
564
+ // all
565
+ universal: /^\*(.*)/,
566
+ // id
567
+ id: new RegExp('^#(' + encoding + '+)(.*)'),
568
+ // tag
569
+ tagName: new RegExp('^(' + encoding + '+)(.*)'),
570
+ // class
571
+ className: new RegExp('^\\.(' + encoding + '+)(.*)')
572
+ },
573
+
574
+ // current CSS3 grouping of Pseudo-Classes
575
+ // they allow implementing extensions
576
+ // and improve error notifications;
577
+ // the assigned value represent current spec status:
578
+ // 3 = CSS3, 2 = CSS2, '?' = maybe implemented
579
+ CSS3PseudoClasses = {
580
+ Structural: {
581
+ 'root': 3, 'empty': 3,
582
+ 'nth-child': 3, 'nth-last-child': 3,
583
+ 'nth-of-type': 3, 'nth-last-of-type': 3,
584
+ 'first-child': 3, 'last-child': 3, 'only-child': 3,
585
+ 'first-of-type': 3, 'last-of-type': 3, 'only-of-type': 3
586
+ },
587
+ Others: {
588
+ 'link': 3, 'visited': 3,
589
+ 'target': 3, 'lang': 3, 'not': 3,
590
+ 'active': 3, 'focus': 3, 'hover': 3,
591
+ 'checked': 3, 'disabled': 3, 'enabled': 3, 'selected': 2
592
+ }
593
+ },
594
+
595
+ /*------------------------------ DOM METHODS -------------------------------*/
596
+
597
+ // concat elements to data
598
+ concatList =
599
+ function(data, elements) {
600
+ var i = -1, element;
601
+ if (data.length === 0 && Array.slice)
602
+ return Array.slice(elements);
603
+ while ((element = elements[++i]))
604
+ data[data.length] = element;
605
+ return data;
606
+ },
607
+
608
+ // concat elements to data and callback
609
+ concatCall =
610
+ function(data, elements, callback) {
611
+ var i = -1, element;
612
+ while ((element = elements[++i]))
613
+ callback(data[data.length] = element);
614
+ return data;
615
+ },
616
+
617
+ // element by id (raw)
618
+ byIdRaw =
619
+ function(id, elements) {
620
+ var i = -1, element = null;
621
+ while ((element = elements[++i])) {
622
+ if (element.getAttribute('id') == id) {
623
+ break;
624
+ }
625
+ }
626
+ return element;
627
+ },
628
+
629
+ // element by id
630
+ // @return element reference or null
631
+ byId = !BUGGY_GEBID ?
632
+ function(id, from) {
633
+ from || (from = doc);
634
+ id = id.replace(/\\/g, '');
635
+ if (isXMLDocument || from.nodeType != 9) {
636
+ return byIdRaw(id, from.getElementsByTagName('*'));
637
+ }
638
+ return from.getElementById(id);
639
+ } :
640
+ function(id, from) {
641
+ var element = null;
642
+ from || (from = doc);
643
+ id = id.replace(/\\/g, '');
644
+ if (isXMLDocument || from.nodeType != 9) {
645
+ return byIdRaw(id, from.getElementsByTagName('*'));
646
+ }
647
+ if ((element = from.getElementById(id)) &&
648
+ element.name == id && from.getElementsByName) {
649
+ return byIdRaw(id, from.getElementsByName(id));
650
+ }
651
+ return element;
652
+ },
653
+
654
+ // elements by tag (raw)
655
+ // @return array
656
+ byTagRaw = function(tag, from) {
657
+ var any = tag == '*', element = from, elements = [ ], next = element.firstChild;
658
+ any || (tag = tag.toUpperCase());
659
+ while ((element = next)) {
660
+ if (element.tagName > '@' && (any || element.tagName.toUpperCase() == tag)) {
661
+ elements[elements.length] = element;
662
+ }
663
+ if (next = element.firstChild || element.nextSibling) continue;
664
+ while (!next && (element = element.parentNode) && element != from) {
665
+ next = element.nextSibling;
666
+ }
667
+ }
668
+ return elements;
669
+ },
670
+
671
+ // elements by tag
672
+ // @return array
673
+ byTag = !BUGGY_GEBTN && NATIVE_SLICE_PROTO ?
674
+ function(tag, from) {
675
+ from || (from = doc);
676
+ return slice.call(from.getElementsByTagName ?
677
+ from.getElementsByTagName(tag) :
678
+ byTagRaw(tag, from), 0);
679
+ } :
680
+ function(tag, from) {
681
+ var i = -1, data = [ ],
682
+ element, elements = (from || doc).getElementsByTagName(tag);
683
+ if (tag == '*') {
684
+ var j = -1;
685
+ while ((element = elements[++i])) {
686
+ if (element.nodeName > '@')
687
+ data[++j] = element;
688
+ }
689
+ } else {
690
+ while ((element = elements[++i])) {
691
+ data[i] = element;
692
+ }
693
+ }
694
+ return data;
695
+ },
696
+
697
+ // elements by name
698
+ // @return array
699
+ byName =
700
+ function(name, from) {
701
+ return select('[name="' + name.replace(/\\/g, '') + '"]', from || doc);
702
+ },
703
+
704
+ // elements by class
705
+ // @return array
706
+ byClass = !BUGGY_GEBCN && NATIVE_SLICE_PROTO ?
707
+ function(className, from) {
708
+ return slice.call((from || doc).
709
+ getElementsByClassName(className.replace(/\\/g, '')), 0);
710
+ } :
711
+ function(className, from) {
712
+ from || (from = doc);
713
+ var i = -1, j = i,
714
+ data = [ ], element,
715
+ elements = byTag('*', from),
716
+ host = from.ownerDocument || from,
717
+ quirks = isQuirks(host), xml = isXML(host),
718
+ n = quirks ? className.toLowerCase() : className;
719
+ className = ' ' + n.replace(/\\/g, '') + ' ';
720
+ while ((element = elements[++i])) {
721
+ n = xml ? element.getAttribute('class') : element.className;
722
+ if (n && n.length && (' ' + (quirks ? n.toLowerCase() : n).
723
+ replace(reWhiteSpace, ' ') + ' ').indexOf(className) > -1) {
724
+ data[++j] = element;
725
+ }
726
+ }
727
+ return data;
728
+ },
729
+
730
+ // check if an element is a descendant of container
731
+ contains = 'compareDocumentPosition' in root ?
732
+ function(container, element) {
733
+ return (container.compareDocumentPosition(element) & 16) == 16;
734
+ } : 'contains' in root ?
735
+ function(container, element) {
736
+ return container !== element && container.contains(element);
737
+ } :
738
+ function(container, element) {
739
+ while ((element = element.parentNode)) {
740
+ if (element === container) return true;
741
+ }
742
+ return false;
743
+ },
744
+
745
+ // attribute value
746
+ // @return string
747
+ getAttribute = !BUGGY_GET_ATTRIBUTE ?
748
+ function(node, attribute) {
749
+ return node.getAttribute(attribute) || '';
750
+ } :
751
+ function(node, attribute) {
752
+ attribute = attribute.toLowerCase();
753
+ if (ATTR_DEFAULT[attribute] in node) {
754
+ return node[ATTR_DEFAULT[attribute]] || '';
755
+ }
756
+ return (
757
+ // specific URI data attributes (parameter 2 to fix IE bug)
758
+ ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' :
759
+ // boolean attributes should return name instead of true/false
760
+ ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : '' :
761
+ ((node = node.getAttributeNode(attribute)) && node.value) || '');
762
+ },
763
+
764
+ // attribute presence
765
+ // @return boolean
766
+ hasAttribute = !BUGGY_HAS_ATTRIBUTE ?
767
+ function(node, attribute) {
768
+ return node.hasAttribute(attribute);
769
+ } :
770
+ function(node, attribute) {
771
+ attribute = attribute.toLowerCase();
772
+ // older IE engines requires DOM mapping
773
+ // see NetFront/Playstation as an example
774
+ attribute = attribute in ATTR_MAPPING ?
775
+ ATTR_MAPPING[attribute] : attribute;
776
+ if (ATTR_DEFAULT[attribute] in node) {
777
+ return !!node[ATTR_DEFAULT[attribute]];
778
+ }
779
+ // need to get at AttributeNode first on IE
780
+ node = node.getAttributeNode(attribute);
781
+ // use both "specified" & "nodeValue" properties
782
+ return !!(node && (node.specified || node.nodeValue));
783
+ },
784
+
785
+ // check node emptyness
786
+ isEmpty =
787
+ function(node) {
788
+ node = node.firstChild;
789
+ while (node) {
790
+ if (node.nodeType == 3 || node.nodeName > '@') return false;
791
+ node = node.nextSibling;
792
+ }
793
+ return true;
794
+ },
795
+
796
+ // check if element matches the :link pseudo
797
+ // @return boolean
798
+ isLink =
799
+ function(element) {
800
+ return hasAttribute(element,'href') && LINK_NODES[element.nodeName];
801
+ },
802
+
803
+ // child position by nodeType
804
+ // @return number
805
+ nthElement =
806
+ function(element, last) {
807
+ var count = 1, succ = last ? 'nextSibling' : 'previousSibling';
808
+ while ((element = element[succ])) {
809
+ if (element.nodeName > '@') ++count;
810
+ }
811
+ return count;
812
+ },
813
+
814
+ // child position by nodeName
815
+ // @return number
816
+ nthOfType =
817
+ function(element, last) {
818
+ var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName;
819
+ while ((element = element[succ])) {
820
+ if (element.nodeName == type) ++count;
821
+ }
822
+ return count;
823
+ },
824
+
825
+ /*------------------------------- DEBUGGING --------------------------------*/
826
+
827
+ // compile selectors to ad-hoc functions resolvers
828
+ // @selector string
829
+ // @mode boolean
830
+ // false = select resolvers
831
+ // true = match resolvers
832
+ compile =
833
+ function(selector, mode) {
834
+ return compileGroup(selector, '', mode || false);
835
+ },
836
+
837
+ // set working mode
838
+ configure =
839
+ function(options) {
840
+ for (var i in options) {
841
+ if (i == 'VERBOSITY') {
842
+ VERBOSITY = !!options[i];
843
+ } else if (i == 'SIMPLENOT') {
844
+ SIMPLENOT = !!options[i];
845
+ HTMLResolvers = { };
846
+ XMLResolvers = { };
847
+ HTMLMatchers = { };
848
+ XMLMatchers = { };
849
+ USE_QSAPI = false;
850
+ reValidator = new RegExp(extendedValidator, 'g');
851
+ } else if (i == 'SHORTCUTS') {
852
+ SHORTCUTS = !!options[i];
853
+ } else if (i == 'USE_QSAPI') {
854
+ USE_QSAPI = !!options[i] && NATIVE_QSAPI;
855
+ reValidator = new RegExp(standardValidator, 'g');
856
+ }
857
+ }
858
+ },
859
+
860
+ // control user notifications
861
+ emit =
862
+ function(message) {
863
+ if (VERBOSITY) {
864
+ // FF/Safari/Opera DOMException.SYNTAX_ERR = 12
865
+ if (typeof global.DOMException !== 'undefined') {
866
+ var err = new Error();
867
+ err.name = 'SYNTAX_ERR';
868
+ err.message = '(Selectors) ' + message;
869
+ err.code = 12;
870
+ throw err;
871
+ } else {
872
+ throw new Error(12, 'SYNTAX_ERR: (Selectors) ' + message);
873
+ }
874
+ } else {
875
+ var console = global.console;
876
+ if (console && console.log) {
877
+ console.log(message);
878
+ } else {
879
+ if (/exception/i.test(message)) {
880
+ global.status = message;
881
+ global.defaultStatus = message;
882
+ } else {
883
+ global.status += message;
884
+ }
885
+ }
886
+ }
887
+ },
888
+
889
+ // by default disable complex selectors nested in
890
+ // ':not()' pseudo-classes, as for specifications
891
+ SIMPLENOT = true,
892
+
893
+ // by default do not add missing left/right context
894
+ // to selector string shortcuts like "+div" or "ul>"
895
+ SHORTCUTS = false,
896
+
897
+ // controls the engine error/warning notifications
898
+ VERBOSITY = true,
899
+
900
+ // controls enabling the Query Selector API branch
901
+ USE_QSAPI = NATIVE_QSAPI,
902
+
903
+ /*---------------------------- COMPILER METHODS ----------------------------*/
904
+
905
+ // do not change this, it is searched & replaced
906
+ // in multiple places to build compiled functions
907
+ ACCEPT_NODE = 'f&&f(c[k]);r[r.length]=c[k];continue main;',
908
+
909
+ // checks if nodeName comparisons need to be uppercased
910
+ TO_UPPER_CASE = doc.createElement('nAv').nodeName == 'nAv' ?
911
+ '.toUpperCase()' : '',
912
+
913
+ // compile a comma separated group of selector
914
+ // @mode boolean true for select, false for match
915
+ // return a compiled function
916
+ compileGroup =
917
+ function(selector, source, mode) {
918
+
919
+ var i = -1, seen = { }, token,
920
+ parts = typeof selector == 'string' ?
921
+ selector.match(reSplitGroup) : selector;
922
+
923
+ // for each selector in the group
924
+ while ((token = parts[++i])) {
925
+ token = token.replace(reTrimSpaces, '');
926
+ // avoid repeating the same token
927
+ // in comma separated group (p, p)
928
+ if (!seen[token]) {
929
+ seen[token] = true;
930
+ source += (i > 0 ? (mode ? 'e=c[k];': 'e=k;') : '') +
931
+ compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;');
932
+ }
933
+ }
934
+
935
+ if (mode) {
936
+ // for select method
937
+ return new Function('c,s,r,d,h,g,f',
938
+ 'var N,n,x=0,k=-1,e;main:while(e=c[++k]){' + source + '}return r;');
939
+ } else {
940
+ // for match method
941
+ return new Function('e,s,r,d,h,g,f',
942
+ 'var N,n,x=0,k=e;' + source + 'return false;');
943
+ }
944
+ },
945
+
946
+ // compile a CSS3 string selector into ad-hoc javascript matching function
947
+ // @return string (to be compiled)
948
+ compileSelector =
949
+ function(selector, source) {
950
+
951
+ var i, a, b, n, k, expr, match, result, status, test, type;
952
+
953
+ k = 0;
954
+
955
+ while (selector) {
956
+
957
+ // *** Universal selector
958
+ // * match all (empty block, do not remove)
959
+ if ((match = selector.match(Patterns.universal))) {
960
+ // do nothing, handled in the compiler where
961
+ // BUGGY_GEBTN return comment nodes (ex: IE)
962
+ i = true;
963
+ }
964
+
965
+ // *** ID selector
966
+ // #Foo Id case sensitive
967
+ else if ((match = selector.match(Patterns.id))) {
968
+ // document can contain conflicting elements (id/name)
969
+ // prototype selector unit need this method to recover bad HTML forms
970
+ source = 'if(' + (isXMLDocument ?
971
+ 's.getAttribute(e,"id")' :
972
+ '(e.submit?s.getAttribute(e,"id"):e.id)') +
973
+ '=="' + match[1] + '"' +
974
+ '){' + source + '}';
975
+ }
976
+
977
+ // *** Type selector
978
+ // Foo Tag (case insensitive)
979
+ else if ((match = selector.match(Patterns.tagName))) {
980
+ // both tagName and nodeName properties may be upper/lower case
981
+ // depending on their creation NAMESPACE in createElementNS()
982
+ source = 'if(e.nodeName' + (isXMLDocument ?
983
+ '=="' + match[1] + '"' : TO_UPPER_CASE +
984
+ '=="' + match[1].toUpperCase() + '"') +
985
+ '){' + source + '}';
986
+ }
987
+
988
+ // *** Class selector
989
+ // .Foo Class (case sensitive)
990
+ else if ((match = selector.match(Patterns.className))) {
991
+ // W3C CSS3 specs: element whose "class" attribute has been assigned a
992
+ // list of whitespace-separated values, see section 6.4 Class selectors
993
+ // and notes at the bottom; explicitly non-normative in this specification.
994
+ source = 'if((n=' + (isXMLDocument ?
995
+ 's.getAttribute(e,"class")' : 'e.className') +
996
+ ')&&n.length&&(" "+' + (isQuirksMode ? 'n.toLowerCase()' : 'n') +
997
+ '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' +
998
+ (isQuirksMode ? match[1].toLowerCase() : match[1]) + ' ")>-1' +
999
+ '){' + source + '}';
1000
+ }
1001
+
1002
+ // *** Attribute selector
1003
+ // [attr] [attr=value] [attr="value"] [attr='value'] and !=, *=, ~=, |=, ^=, $=
1004
+ // case sensitivity is treated differently depending on the document type (see map)
1005
+ else if ((match = selector.match(Patterns.attribute))) {
1006
+ if (match[3]) match[3] = match[3].replace(/^\x22|\x22$/g, '').replace(/^\x27|\x27$/g, '');
1007
+
1008
+ // xml namespaced attribute ?
1009
+ expr = match[1].split(':');
1010
+ expr = expr.length == 2 ? expr[1] : expr[0] + '';
1011
+
1012
+ if (match[2] && !Operators[match[2]]) {
1013
+ emit('Unsupported operator in attribute selectors "' + selector + '"');
1014
+ return '';
1015
+ }
1016
+
1017
+ // replace Operators parameter if needed
1018
+ if (match[2] && match[3] && (type = Operators[match[2]])) {
1019
+ // case treatment depends on document
1020
+ HTML_TABLE['class'] = isQuirksMode ? 1 : 0;
1021
+ // replace escaped values and HTML entities
1022
+ match[3] = match[3].replace(/\\([0-9a-f]{2,2})/, '\\x$1');
1023
+ test = (isXMLDocument ? XHTML_TABLE : HTML_TABLE)[expr.toLowerCase()];
1024
+ type = type.replace(/\%m/g, test ? match[3].toLowerCase() : match[3]);
1025
+ } else {
1026
+ test = false;
1027
+ // handle empty values
1028
+ type = match[2] == '=' ? 'n==""' : 'false';
1029
+ }
1030
+
1031
+ // build expression for has/getAttribute
1032
+ expr = 'n=s.' + (match[2] ? 'get' : 'has') +
1033
+ 'Attribute(e,"' + match[1] + '")' +
1034
+ (test ? '.toLowerCase();' : ';');
1035
+
1036
+ source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}';
1037
+ }
1038
+
1039
+ // *** Adjacent sibling combinator
1040
+ // E + F (F adiacent sibling of E)
1041
+ else if ((match = selector.match(Patterns.adjacent))) {
1042
+ k++;
1043
+ source = NATIVE_TRAVERSAL_API ?
1044
+ 'var N' + k + '=e;if(e&&(e=e.previousElementSibling)){' + source + '}e=N' + k + ';' :
1045
+ 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';';
1046
+ }
1047
+
1048
+ // *** General sibling combinator
1049
+ // E ~ F (F relative sibling of E)
1050
+ else if ((match = selector.match(Patterns.relative))) {
1051
+ k++;
1052
+ source = NATIVE_TRAVERSAL_API ?
1053
+ ('var N' + k + '=e;e=e.parentNode.firstElementChild;' +
1054
+ 'while(e&&e!=N' + k + '){' + source + 'e=e.nextElementSibling;}e=N' + k + ';') :
1055
+ ('var N' + k + '=e;e=e.parentNode.firstChild;' +
1056
+ 'while(e&&e!=N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';');
1057
+ }
1058
+
1059
+ // *** Child combinator
1060
+ // E > F (F children of E)
1061
+ else if ((match = selector.match(Patterns.children))) {
1062
+ k++;
1063
+ source = 'var N' + k + '=e;if(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';';
1064
+ }
1065
+
1066
+ // *** Descendant combinator
1067
+ // E F (E ancestor of F)
1068
+ else if ((match = selector.match(Patterns.ancestor))) {
1069
+ k++;
1070
+ source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';';
1071
+ }
1072
+
1073
+ // *** Structural pseudo-classes
1074
+ // :root, :empty,
1075
+ // :first-child, :last-child, :only-child,
1076
+ // :first-of-type, :last-of-type, :only-of-type,
1077
+ // :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-of-type()
1078
+ else if ((match = selector.match(Patterns.spseudos)) &&
1079
+ CSS3PseudoClasses.Structural[selector.match(reClassValue)[0]]) {
1080
+
1081
+ switch (match[1]) {
1082
+ case 'root':
1083
+ // element root of the document
1084
+ if (match[6]) {
1085
+ source = 'if(s.contains(e.ownerDocument.documentElement,e)){' + source + '}';
1086
+ } else {
1087
+ source = 'if(e===h){' + source + '}';
1088
+ }
1089
+ break;
1090
+
1091
+ case 'empty':
1092
+ // element that has no children
1093
+ source = 'if(s.isEmpty(e)){' + source + '}';
1094
+ break;
1095
+
1096
+ default:
1097
+ if (match[1] && match[5]) {
1098
+ if (match[5] == 'n') {
1099
+ source = 'if(e!==h){' + source + '}';
1100
+ break;
1101
+ } else if (match[5] == 'even') {
1102
+ a = 2;
1103
+ b = 0;
1104
+ } else if (match[5] == 'odd') {
1105
+ a = 2;
1106
+ b = 1;
1107
+ } else {
1108
+ // assumes correct "an+b" format, "b" before "a" to keep "n" values
1109
+ b = ((n = match[5].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0);
1110
+ a = ((n = match[5].match(/(-?\d*)n/)) ? parseInt(n[1], 10) : 0);
1111
+ if (n && n[1] == '-') a = -1;
1112
+ }
1113
+
1114
+ // build test expression out of structural pseudo (an+b) parameters
1115
+ // see here: http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
1116
+ test = b < 1 && a > 1 ? '(n-(' + b + '))%' + a + '==0' : a > +1 ?
1117
+ (match[2] == 'last') ? '(n-(' + b + '))%' + a + '==0' :
1118
+ 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ?
1119
+ (match[2] == 'last') ? '(n-(' + b + '))%' + a + '==0' :
1120
+ 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ?
1121
+ 'n==' + b :
1122
+ (match[2] == 'last') ?
1123
+ a == -1 ? 'n>=' + b : 'n<=' + b :
1124
+ a == -1 ? 'n<=' + b : 'n>=' + b;
1125
+
1126
+ // 4 cases: 1 (nth) x 4 (child, of-type, last-child, last-of-type)
1127
+ source =
1128
+ 'if(e!==h){' +
1129
+ 'n=s[' + (match[4] ? '"nthOfType"' : '"nthElement"') + ']' +
1130
+ '(e,' + (match[2] == 'last' ? 'true' : 'false') + ');' +
1131
+ 'if(' + test + '){' + source + '}' +
1132
+ '}';
1133
+
1134
+ } else {
1135
+ // 6 cases: 3 (first, last, only) x 1 (child) x 2 (-of-type)
1136
+ a = match[2] == 'first' ? 'previous' : 'next';
1137
+ n = match[2] == 'only' ? 'previous' : 'next';
1138
+ b = match[2] == 'first' || match[2] == 'last';
1139
+
1140
+ type = match[4] ? '&&n.nodeName!=e.nodeName' : '&&n.nodeName<"@"';
1141
+
1142
+ source = 'if(e!==h){' +
1143
+ ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source :
1144
+ 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}';
1145
+ }
1146
+ break;
1147
+ }
1148
+ }
1149
+
1150
+ // *** negation, user action and target pseudo-classes
1151
+ // *** UI element states and dynamic pseudo-classes
1152
+ // CSS3 :not, :checked, :enabled, :disabled, :target
1153
+ // CSS3 :active, :hover, :focus
1154
+ // CSS3 :link, :visited
1155
+ else if ((match = selector.match(Patterns.dpseudos)) &&
1156
+ CSS3PseudoClasses.Others[selector.match(reClassValue)[0]]) {
1157
+
1158
+ switch (match[1]) {
1159
+ // CSS3 negation pseudo-class
1160
+ case 'not':
1161
+ // compile nested selectors, DO NOT pass the callback parameter
1162
+ // SIMPLENOT allow disabling complex selectors nested
1163
+ // in ':not()' pseudo-classes, breaks some test units
1164
+ expr = match[3].replace(reTrimSpaces, '');
1165
+
1166
+ if (SIMPLENOT && !reSimpleNot.test(expr)) {
1167
+ // see above, log error but continue execution
1168
+ emit('Negation pseudo-class only accepts simple selectors "' + selector + '"');
1169
+ return '';
1170
+ } else {
1171
+ if ('compatMode' in doc) {
1172
+ source = 'if(!' + compileGroup(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}';
1173
+ } else {
1174
+ source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",r)){' + source +'}';
1175
+ }
1176
+ }
1177
+ break;
1178
+
1179
+ // CSS3 UI element states
1180
+ case 'checked':
1181
+ // only available for radio buttons and checkboxes
1182
+ source = 'if(typeof e.form!=="undefined"&&(/radio|checkbox/i).test(e.type)&&e.checked){' + source + '}';
1183
+ break;
1184
+ case 'disabled':
1185
+ // does not consider hidden input fields
1186
+ source = 'if(((typeof e.form!=="undefined"&&!(/hidden/i).test(e.type))||s.isLink(e))&&e.disabled){' + source + '}';
1187
+ break;
1188
+ case 'enabled':
1189
+ // does not consider hidden input fields
1190
+ source = 'if(((typeof e.form!=="undefined"&&!(/hidden/i).test(e.type))||s.isLink(e))&&!e.disabled){' + source + '}';
1191
+ break;
1192
+
1193
+ // CSS3 lang pseudo-class
1194
+ case 'lang':
1195
+ test = '';
1196
+ if (match[3]) test = match[3].substr(0, 2) + '-';
1197
+ source = 'do{(n=e.lang||"").toLowerCase();' +
1198
+ 'if((n==""&&h.lang=="' + match[3].toLowerCase() + '")||' +
1199
+ '(n&&(n=="' + match[3].toLowerCase() +
1200
+ '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' +
1201
+ '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);';
1202
+ break;
1203
+
1204
+ // CSS3 target pseudo-class
1205
+ case 'target':
1206
+ n = doc.location ? doc.location.hash : '';
1207
+ if (n) {
1208
+ source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}';
1209
+ }
1210
+ break;
1211
+
1212
+ // CSS3 dynamic pseudo-classes
1213
+ case 'link':
1214
+ source = 'if(s.isLink(e)&&!e.visited){' + source + '}';
1215
+ break;
1216
+ case 'visited':
1217
+ source = 'if(s.isLink(e)&&e.visited){' + source + '}';
1218
+ break;
1219
+
1220
+ // CSS3 user action pseudo-classes IE & FF3 have native support
1221
+ // these capabilities may be emulated by some event managers
1222
+ case 'active':
1223
+ if (isXMLDocument) break;
1224
+ source = 'if(e===d.activeElement){' + source + '}';
1225
+ break;
1226
+ case 'hover':
1227
+ if (isXMLDocument) break;
1228
+ source = 'if(e===d.hoverElement){' + source + '}';
1229
+ break;
1230
+ case 'focus':
1231
+ if (isXMLDocument) break;
1232
+ source = NATIVE_FOCUS ?
1233
+ 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href)){' + source + '}' :
1234
+ 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}';
1235
+ break;
1236
+
1237
+ // CSS2 selected pseudo-classes, not part of current CSS3 drafts
1238
+ // the 'selected' property is only available for option elements
1239
+ case 'selected':
1240
+ // fix Safari selectedIndex property bug
1241
+ expr = BUGGY_SELECTED ? '||(n=e.parentNode)&&n.options[n.selectedIndex]===e' : '';
1242
+ source = 'if(e.nodeName=="OPTION"&&(e.selected' + expr + ')){' + source + '}';
1243
+ break;
1244
+
1245
+ default:
1246
+ break;
1247
+ }
1248
+ } else {
1249
+
1250
+ // this is where external extensions are
1251
+ // invoked if expressions match selectors
1252
+ expr = false;
1253
+ status = true;
1254
+
1255
+ for (expr in Selectors) {
1256
+ if ((match = selector.match(Selectors[expr].Expression))) {
1257
+ result = Selectors[expr].Callback(match, source);
1258
+ source = result.source;
1259
+ status = result.status;
1260
+ if (status) break;
1261
+ }
1262
+ }
1263
+
1264
+ // if an extension fails to parse the selector
1265
+ // it must return a false boolean in "status"
1266
+ if (!status) {
1267
+ // log error but continue execution, don't throw real exceptions
1268
+ // because blocking following processes maybe is not a good idea
1269
+ emit('Unknown pseudo-class selector "' + selector + '"');
1270
+ return '';
1271
+ }
1272
+
1273
+ if (!expr) {
1274
+ // see above, log error but continue execution
1275
+ emit('Unknown token in selector "' + selector + '"');
1276
+ return '';
1277
+ }
1278
+
1279
+ }
1280
+
1281
+ // error if no matches found by the pattern scan
1282
+ if (!match) {
1283
+ emit('Invalid syntax in selector "' + selector + '"');
1284
+ return '';
1285
+ }
1286
+
1287
+ // ensure "match" is not null or empty since
1288
+ // we do not throw real DOMExceptions above
1289
+ selector = match && match[match.length - 1];
1290
+ }
1291
+
1292
+ return source;
1293
+ },
1294
+
1295
+ /*----------------------------- QUERY METHODS ------------------------------*/
1296
+
1297
+ // match element with selector
1298
+ // @return boolean
1299
+ match =
1300
+ function(element, selector, from, callback) {
1301
+
1302
+ var changed, parts, resolver;
1303
+
1304
+ // ensures a valid element node was passed
1305
+ if (!(element && element.nodeName > '@')) {
1306
+ emit("Invalid element argument");
1307
+ return false;
1308
+ }
1309
+
1310
+ // ensures a valid selector string was passed
1311
+ if (!selector || typeof selector != 'string') {
1312
+ emit("Invalid selector argument");
1313
+ return false;
1314
+ }
1315
+
1316
+ // if passed, check context contains element
1317
+ if (from && from.nodeType == 1) {
1318
+ if (!contains(from, element)) return false;
1319
+ } else if (from) {
1320
+ emit("Invalid context argument");
1321
+ return false;
1322
+ }
1323
+
1324
+ selector = selector.replace(reTrimSpaces, '');
1325
+
1326
+ // ensure context is set
1327
+ from || (from = doc);
1328
+
1329
+ // extract context if changed
1330
+ if (lastMatchContext != from) {
1331
+ // save passed context
1332
+ lastMatchContext = from;
1333
+ // reference element ownerDocument and document root (HTML)
1334
+ root = (doc = element.ownerDocument || element).documentElement;
1335
+ isQuirksMode = isQuirks(doc);
1336
+ isXMLDocument = isXML(doc);
1337
+ }
1338
+
1339
+ if (changed = lastMatcher != selector) {
1340
+ // process valid selector strings
1341
+ if ((parts = selector.match(reValidator)) && parts[0] == selector) {
1342
+ // save passed selector
1343
+ lastMatcher = selector;
1344
+ isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2;
1345
+ } else {
1346
+ emit('The string "' + selector + '", is not a valid CSS selector');
1347
+ return false;
1348
+ }
1349
+ }
1350
+
1351
+ // use matchesSelector API if available
1352
+ if (USE_QSAPI && element[NATIVE_MATCHES_SELECTOR] &&
1353
+ !(BUGGY_PSEUDOS && RE_PSEUDOS.test(selector)) &&
1354
+ !RE_BUGGY_QSAPI.test(selector)) {
1355
+ try {
1356
+ if (element[NATIVE_MATCHES_SELECTOR](selector)) {
1357
+ if (typeof callback == 'function') {
1358
+ callback(element);
1359
+ }
1360
+ return true;
1361
+ }
1362
+ return false;
1363
+ } catch(e) { }
1364
+ }
1365
+
1366
+ // compile matcher resolver if necessary
1367
+ resolver = (isXMLDocument && XMLMatchers[selector]) ?
1368
+ XMLMatchers[selector] : HTMLMatchers[selector] ?
1369
+ HTMLMatchers[selector] : (isXMLDocument ?
1370
+ XMLMatchers : HTMLMatchers)[selector] = isSingleMatch ?
1371
+ new Function('e,s,r,d,h,g,f', 'var N,n,x=0,k=e;' +
1372
+ compileSelector(selector, 'f&&f(k);return true;') + 'return false;') :
1373
+ compileGroup(parts || selector, '', false);
1374
+
1375
+ return resolver(element, snap, [ ], doc, root, from || doc, callback);
1376
+ },
1377
+
1378
+ // select elements matching selector
1379
+ // using new Query Selector API
1380
+ // or cross-browser client API
1381
+ // @return array
1382
+ select =
1383
+ function(selector, from, callback) {
1384
+
1385
+ var i, changed, element, elements, parts, resolver, token;
1386
+
1387
+ if (arguments.length === 0) {
1388
+ emit('Missing required selector parameters');
1389
+ return [ ];
1390
+ } else if (selector === '') {
1391
+ emit('Empty selector string');
1392
+ return [ ];
1393
+ } else if (typeof selector != 'string') {
1394
+ // QSA capable browsers do not throw
1395
+ return [ ];
1396
+ }
1397
+
1398
+ // ensure context is set
1399
+ from || (from = doc);
1400
+
1401
+ if (RE_SIMPLE_SELECTOR.test(selector)) {
1402
+ switch (selector.charAt(0)) {
1403
+ case '#':
1404
+ if ((element = byId(selector.slice(1), from))) {
1405
+ callback && callback(element);
1406
+ return [ element ];
1407
+ }
1408
+ return [ ];
1409
+ case '.':
1410
+ elements = byClass(selector.slice(1), from);
1411
+ break;
1412
+ default:
1413
+ elements = byTag(selector, from);
1414
+ break;
1415
+ }
1416
+ return callback ?
1417
+ concatCall([ ], elements, callback) : elements;
1418
+ }
1419
+
1420
+ if (USE_QSAPI && !RE_BUGGY_QSAPI.test(selector) &&
1421
+ QSA_NODE_TYPES[from.nodeType]) {
1422
+
1423
+ // clear error state
1424
+ lastError = null;
1425
+
1426
+ try {
1427
+ elements = from.querySelectorAll(selector);
1428
+ } catch(e) {
1429
+ // remember last error
1430
+ lastError = e;
1431
+ if (selector === '') throw e;
1432
+ }
1433
+
1434
+ if (elements) {
1435
+ switch (elements.length) {
1436
+ case 0:
1437
+ return [ ];
1438
+ case 1:
1439
+ element = elements.item(0);
1440
+ callback && callback(element);
1441
+ return [ element ];
1442
+ default:
1443
+ return callback ?
1444
+ concatCall([ ], elements, callback) :
1445
+ NATIVE_SLICE_PROTO ?
1446
+ slice.call(elements) :
1447
+ concatList([ ], elements);
1448
+ }
1449
+ }
1450
+ }
1451
+
1452
+ selector = selector.replace(reTrimSpaces, '');
1453
+
1454
+ if (SHORTCUTS) {
1455
+ // add left context if missing
1456
+ if (reLeftContext.test(selector)) {
1457
+ selector = from.nodeType == 9 ? '* ' + selector :
1458
+ from.id ? '#' + from.id + ' ' + selector :
1459
+ selector;
1460
+ }
1461
+ // add right context if missing
1462
+ if (reRightContext.test(selector)) {
1463
+ selector = selector + ' *';
1464
+ }
1465
+ }
1466
+
1467
+ // extract context if changed
1468
+ if (lastSelectContext != from) {
1469
+ // save passed context
1470
+ lastSelectContext = from;
1471
+ // reference context ownerDocument and document root (HTML)
1472
+ root = (doc = from.ownerDocument || from).documentElement;
1473
+ isQuirksMode = isQuirks(doc);
1474
+ isXMLDocument = isXML(doc);
1475
+ }
1476
+
1477
+ if (changed = lastSelector != selector) {
1478
+ // process valid selector strings
1479
+ if ((parts = selector.match(reValidator)) && parts[0] == selector) {
1480
+ // save passed selector
1481
+ lastSelector = selector;
1482
+ isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2;
1483
+ } else {
1484
+ emit('The string "' + selector + '", is not a valid CSS selector');
1485
+ return [ ];
1486
+ }
1487
+ }
1488
+
1489
+ // commas separators are treated sequentially to maintain order
1490
+ if (isSingleSelect && from.nodeType != 11) {
1491
+
1492
+ if (changed) {
1493
+ // get right most selector token
1494
+ parts = selector.match(reSplitToken);
1495
+ token = parts[parts.length - 1];
1496
+
1497
+ // position where token was found
1498
+ lastPosition = selector.length - token.length;
1499
+
1500
+ // only last slice before :not rules
1501
+ lastSlice = token.split(':not')[0];
1502
+ }
1503
+
1504
+ // ID optimization RTL, to reduce number of elements to visit
1505
+ if ((parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) {
1506
+ if ((element = byId(token, from))) {
1507
+ if (match(element, selector)) {
1508
+ callback && callback(element);
1509
+ return [ element ];
1510
+ }
1511
+ }
1512
+ return [ ];
1513
+ }
1514
+
1515
+ // ID optimization LTR, to reduce selection context searches
1516
+ else if ((parts = selector.match(Optimize.ID)) && (token = parts[1])) {
1517
+ if ((element = byId(token, doc))) {
1518
+ if ('#' + token == selector) {
1519
+ callback && callback(element);
1520
+ return [ element ];
1521
+ }
1522
+ if (/[>+~]/.test(selector)) {
1523
+ from = element.parentNode;
1524
+ } else {
1525
+ selector = selector.replace('#' + token, '*');
1526
+ lastPosition -= token.length + 1;
1527
+ from = element;
1528
+ }
1529
+ } else return [ ];
1530
+ }
1531
+
1532
+ if (!NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) {
1533
+ if ((elements = byTag(token, from)).length === 0) { return [ ]; }
1534
+ selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*');
1535
+ }
1536
+
1537
+ else if ((parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) {
1538
+ if ((elements = byClass(token, from)).length === 0) { return [ ]; }
1539
+ if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) {
1540
+ selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '');
1541
+ } else {
1542
+ selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*');
1543
+ }
1544
+ }
1545
+
1546
+ else if ((parts = selector.match(Optimize.CLASS)) && (token = parts[1])) {
1547
+ if ((elements = byClass(token, from)).length === 0) { return [ ]; }
1548
+ for (var z = 0, els = [ ]; elements.length > z; ++z) {
1549
+ els = concatList(els, elements[z].getElementsByTagName('*'));
1550
+ }
1551
+ elements = els;
1552
+ if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) {
1553
+ selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '');
1554
+ } else {
1555
+ selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*');
1556
+ }
1557
+ }
1558
+
1559
+ else if (NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) {
1560
+ if ((elements = byTag(token, from)).length === 0) { return [ ]; }
1561
+ selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*');
1562
+ }
1563
+
1564
+ }
1565
+
1566
+ if (!elements) {
1567
+ elements = byTag('*', from);
1568
+ }
1569
+ // end of prefiltering pass
1570
+
1571
+ // compile selector resolver if necessary
1572
+ resolver = (isXMLDocument && XMLResolvers[selector]) ?
1573
+ XMLResolvers[selector] : HTMLResolvers[selector] ?
1574
+ HTMLResolvers[selector] : (isXMLDocument ?
1575
+ XMLResolvers : HTMLResolvers)[selector] = isSingleSelect ?
1576
+ new Function('c,s,r,d,h,g,f', 'var N,n,x=0,k=-1,e;main:while(e=c[++k]){' +
1577
+ compileSelector(selector, ACCEPT_NODE) + '}return r;') :
1578
+ compileGroup(parts || selector, '', true);
1579
+
1580
+ return resolver(elements, snap, [ ], doc, root, from, callback);
1581
+ },
1582
+
1583
+ /*-------------------------------- STORAGE ---------------------------------*/
1584
+
1585
+ // compiled select functions returning collections
1586
+ HTMLResolvers = { },
1587
+ XMLResolvers = { },
1588
+
1589
+ // compiled match functions returning booleans
1590
+ HTMLMatchers = { },
1591
+ XMLMatchers = { },
1592
+
1593
+ // used to pass methods to compiled functions
1594
+ snap = {
1595
+
1596
+ // element indexing methods
1597
+ nthElement: nthElement,
1598
+ nthOfType: nthOfType,
1599
+
1600
+ // element inspection methods
1601
+ getAttribute: getAttribute,
1602
+ hasAttribute: hasAttribute,
1603
+
1604
+ // element selection methods
1605
+ byClass: byClass,
1606
+ byName: byName,
1607
+ byTag: byTag,
1608
+ byId: byId,
1609
+
1610
+ // helper/check methods
1611
+ contains: contains,
1612
+ isEmpty: isEmpty,
1613
+ isLink: isLink,
1614
+
1615
+ // selection/matching
1616
+ select: select,
1617
+ match: match
1618
+ };
1619
+
1620
+ /*------------------------------- PUBLIC API -------------------------------*/
1621
+
1622
+ global.NW || (global.NW = { });
1623
+
1624
+ NW.Dom = {
1625
+
1626
+ // retrieve element by id attr
1627
+ byId: byId,
1628
+
1629
+ // retrieve elements by tag name
1630
+ byTag: byTag,
1631
+
1632
+ // retrieve elements by name attr
1633
+ byName: byName,
1634
+
1635
+ // retrieve elements by class name
1636
+ byClass: byClass,
1637
+
1638
+ // read the value of the attribute
1639
+ // as was in the original HTML code
1640
+ getAttribute: getAttribute,
1641
+
1642
+ // check for the attribute presence
1643
+ // as was in the original HTML code
1644
+ hasAttribute: hasAttribute,
1645
+
1646
+ // element match selector, return boolean true/false
1647
+ match: match,
1648
+
1649
+ // elements matching selector, starting from element
1650
+ select: select,
1651
+
1652
+ // compile selector into ad-hoc javascript resolver
1653
+ compile: compile,
1654
+
1655
+ // check that two elements are ancestor/descendant
1656
+ contains: contains,
1657
+
1658
+ // handle selector engine configuration settings
1659
+ configure: configure,
1660
+
1661
+ // add or overwrite user defined operators
1662
+ registerOperator:
1663
+ function(symbol, resolver) {
1664
+ if (!Operators[symbol]) {
1665
+ Operators[symbol] = resolver;
1666
+ }
1667
+ },
1668
+
1669
+ // add selector patterns for user defined callbacks
1670
+ registerSelector:
1671
+ function(name, rexp, func) {
1672
+ if (!Selectors[name]) {
1673
+ Selectors[name] = { };
1674
+ Selectors[name].Expression = rexp;
1675
+ Selectors[name].Callback = func;
1676
+ }
1677
+ }
1678
+ };
1679
+
1680
+ })(this);