wpa_cli_web 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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);