selenium-core-runner 0.0.3
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.
- data/Gemfile +9 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +30 -0
- data/app/controllers/selenium_core_runner/suites_controller.rb +19 -0
- data/app/views/selenium_core_runner/suites/index.html.erb +177 -0
- data/app/views/selenium_core_runner/suites/show.html.erb +0 -0
- data/config/routes.rb +6 -0
- data/lib/selenium-core-runner/engine.rb +19 -0
- data/lib/selenium-core-runner.rb +3 -0
- data/public/selenium-core-runner/Blank.html +7 -0
- data/public/selenium-core-runner/InjectedRemoteRunner.html +8 -0
- data/public/selenium-core-runner/RemoteRunner.html +101 -0
- data/public/selenium-core-runner/SeleniumLog.html +109 -0
- data/public/selenium-core-runner/TestPrompt.html +145 -0
- data/public/selenium-core-runner/TestRunner-splash.html +55 -0
- data/public/selenium-core-runner/TestRunner.hta +177 -0
- data/public/selenium-core-runner/TestRunner.html +177 -0
- data/public/selenium-core-runner/icons/all.png +0 -0
- data/public/selenium-core-runner/icons/continue.png +0 -0
- data/public/selenium-core-runner/icons/continue_disabled.png +0 -0
- data/public/selenium-core-runner/icons/pause.png +0 -0
- data/public/selenium-core-runner/icons/pause_disabled.png +0 -0
- data/public/selenium-core-runner/icons/selected.png +0 -0
- data/public/selenium-core-runner/icons/step.png +0 -0
- data/public/selenium-core-runner/icons/step_disabled.png +0 -0
- data/public/selenium-core-runner/iedoc-core.xml +1789 -0
- data/public/selenium-core-runner/iedoc.xml +1830 -0
- data/public/selenium-core-runner/lib/cssQuery/cssQuery-p.js +6 -0
- data/public/selenium-core-runner/lib/cssQuery/src/cssQuery-level2.js +142 -0
- data/public/selenium-core-runner/lib/cssQuery/src/cssQuery-level3.js +150 -0
- data/public/selenium-core-runner/lib/cssQuery/src/cssQuery-standard.js +53 -0
- data/public/selenium-core-runner/lib/cssQuery/src/cssQuery.js +356 -0
- data/public/selenium-core-runner/lib/prototype.js +2006 -0
- data/public/selenium-core-runner/lib/scriptaculous/builder.js +101 -0
- data/public/selenium-core-runner/lib/scriptaculous/controls.js +815 -0
- data/public/selenium-core-runner/lib/scriptaculous/dragdrop.js +915 -0
- data/public/selenium-core-runner/lib/scriptaculous/effects.js +958 -0
- data/public/selenium-core-runner/lib/scriptaculous/scriptaculous.js +47 -0
- data/public/selenium-core-runner/lib/scriptaculous/slider.js +283 -0
- data/public/selenium-core-runner/lib/scriptaculous/unittest.js +383 -0
- data/public/selenium-core-runner/lib/snapsie.js +91 -0
- data/public/selenium-core-runner/scripts/find_matching_child.js +69 -0
- data/public/selenium-core-runner/scripts/htmlutils.js +1623 -0
- data/public/selenium-core-runner/scripts/injection.html +72 -0
- data/public/selenium-core-runner/scripts/selenium-api.js +3240 -0
- data/public/selenium-core-runner/scripts/selenium-browserbot.js +2333 -0
- data/public/selenium-core-runner/scripts/selenium-browserdetect.js +153 -0
- data/public/selenium-core-runner/scripts/selenium-commandhandlers.js +379 -0
- data/public/selenium-core-runner/scripts/selenium-executionloop.js +175 -0
- data/public/selenium-core-runner/scripts/selenium-logging.js +148 -0
- data/public/selenium-core-runner/scripts/selenium-remoterunner.js +695 -0
- data/public/selenium-core-runner/scripts/selenium-testrunner.js +1362 -0
- data/public/selenium-core-runner/scripts/selenium-version.js +5 -0
- data/public/selenium-core-runner/scripts/ui-doc.html +803 -0
- data/public/selenium-core-runner/scripts/ui-element.js +1627 -0
- data/public/selenium-core-runner/scripts/ui-map-sample.js +979 -0
- data/public/selenium-core-runner/scripts/user-extensions.js +3 -0
- data/public/selenium-core-runner/scripts/user-extensions.js.sample +75 -0
- data/public/selenium-core-runner/scripts/xmlextras.js +153 -0
- data/public/selenium-core-runner/selenium-logo.png +0 -0
- data/public/selenium-core-runner/selenium-test.css +43 -0
- data/public/selenium-core-runner/selenium.css +316 -0
- data/public/selenium-core-runner/xpath/dom.js +566 -0
- data/public/selenium-core-runner/xpath/javascript-xpath-0.1.11.js +2816 -0
- data/public/selenium-core-runner/xpath/util.js +549 -0
- data/public/selenium-core-runner/xpath/xmltoken.js +149 -0
- data/public/selenium-core-runner/xpath/xpath.js +2481 -0
- metadata +121 -0
@@ -0,0 +1,549 @@
|
|
1
|
+
// Copyright 2005 Google
|
2
|
+
//
|
3
|
+
// Author: Steffen Meschkat <mesch@google.com>
|
4
|
+
//
|
5
|
+
// Miscellaneous utility and placeholder functions.
|
6
|
+
|
7
|
+
// Dummy implmentation for the logging functions. Replace by something
|
8
|
+
// useful when you want to debug.
|
9
|
+
function xpathLog(msg) {};
|
10
|
+
function xsltLog(msg) {};
|
11
|
+
function xsltLogXml(msg) {};
|
12
|
+
|
13
|
+
var ajaxsltIsIE6 = navigator.appVersion.match(/MSIE 6.0/);
|
14
|
+
|
15
|
+
// Throws an exception if false.
|
16
|
+
function assert(b) {
|
17
|
+
if (!b) {
|
18
|
+
throw "Assertion failed";
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
// Splits a string s at all occurrences of character c. This is like
|
23
|
+
// the split() method of the string object, but IE omits empty
|
24
|
+
// strings, which violates the invariant (s.split(x).join(x) == s).
|
25
|
+
function stringSplit(s, c) {
|
26
|
+
var a = s.indexOf(c);
|
27
|
+
if (a == -1) {
|
28
|
+
return [ s ];
|
29
|
+
}
|
30
|
+
var parts = [];
|
31
|
+
parts.push(s.substr(0,a));
|
32
|
+
while (a != -1) {
|
33
|
+
var a1 = s.indexOf(c, a + 1);
|
34
|
+
if (a1 != -1) {
|
35
|
+
parts.push(s.substr(a + 1, a1 - a - 1));
|
36
|
+
} else {
|
37
|
+
parts.push(s.substr(a + 1));
|
38
|
+
}
|
39
|
+
a = a1;
|
40
|
+
}
|
41
|
+
return parts;
|
42
|
+
}
|
43
|
+
|
44
|
+
// The following function does what document.importNode(node, true)
|
45
|
+
// would do for us here; however that method is broken in Safari/1.3,
|
46
|
+
// so we have to emulate it.
|
47
|
+
function xmlImportNode(doc, node) {
|
48
|
+
if (node.nodeType == DOM_TEXT_NODE) {
|
49
|
+
return domCreateTextNode(doc, node.nodeValue);
|
50
|
+
|
51
|
+
} else if (node.nodeType == DOM_CDATA_SECTION_NODE) {
|
52
|
+
return domCreateCDATASection(doc, node.nodeValue);
|
53
|
+
|
54
|
+
} else if (node.nodeType == DOM_ELEMENT_NODE) {
|
55
|
+
var newNode = domCreateElement(doc, node.nodeName);
|
56
|
+
for (var i = 0; i < node.attributes.length; ++i) {
|
57
|
+
var an = node.attributes[i];
|
58
|
+
var name = an.nodeName;
|
59
|
+
var value = an.nodeValue;
|
60
|
+
domSetAttribute(newNode, name, value);
|
61
|
+
}
|
62
|
+
|
63
|
+
for (var c = node.firstChild; c; c = c.nextSibling) {
|
64
|
+
var cn = arguments.callee(doc, c);
|
65
|
+
domAppendChild(newNode, cn);
|
66
|
+
}
|
67
|
+
|
68
|
+
return newNode;
|
69
|
+
|
70
|
+
} else {
|
71
|
+
return domCreateComment(doc, node.nodeName);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
// A set data structure. It can also be used as a map (i.e. the keys
|
76
|
+
// can have values other than 1), but we don't call it map because it
|
77
|
+
// would be ambiguous in this context. Also, the map is iterable, so
|
78
|
+
// we can use it to replace for-in loops over core javascript Objects.
|
79
|
+
// For-in iteration breaks when Object.prototype is modified, which
|
80
|
+
// some clients of the maps API do.
|
81
|
+
//
|
82
|
+
// NOTE(mesch): The set keys by the string value of its element, NOT
|
83
|
+
// by the typed value. In particular, objects can't be used as keys.
|
84
|
+
//
|
85
|
+
// @constructor
|
86
|
+
function Set() {
|
87
|
+
this.keys = [];
|
88
|
+
}
|
89
|
+
|
90
|
+
Set.prototype.size = function() {
|
91
|
+
return this.keys.length;
|
92
|
+
}
|
93
|
+
|
94
|
+
// Adds the entry to the set, ignoring if it is present.
|
95
|
+
Set.prototype.add = function(key, opt_value) {
|
96
|
+
var value = opt_value || 1;
|
97
|
+
if (!this.contains(key)) {
|
98
|
+
this[':' + key] = value;
|
99
|
+
this.keys.push(key);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
// Sets the entry in the set, adding if it is not yet present.
|
104
|
+
Set.prototype.set = function(key, opt_value) {
|
105
|
+
var value = opt_value || 1;
|
106
|
+
if (!this.contains(key)) {
|
107
|
+
this[':' + key] = value;
|
108
|
+
this.keys.push(key);
|
109
|
+
} else {
|
110
|
+
this[':' + key] = value;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
// Increments the key's value by 1. This works around the fact that
|
115
|
+
// numbers are always passed by value, never by reference, so that we
|
116
|
+
// can't increment the value returned by get(), or the iterator
|
117
|
+
// argument. Sets the key's value to 1 if it doesn't exist yet.
|
118
|
+
Set.prototype.inc = function(key) {
|
119
|
+
if (!this.contains(key)) {
|
120
|
+
this[':' + key] = 1;
|
121
|
+
this.keys.push(key);
|
122
|
+
} else {
|
123
|
+
this[':' + key]++;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
Set.prototype.get = function(key) {
|
128
|
+
if (this.contains(key)) {
|
129
|
+
return this[':' + key];
|
130
|
+
} else {
|
131
|
+
var undefined;
|
132
|
+
return undefined;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
// Removes the entry from the set.
|
137
|
+
Set.prototype.remove = function(key) {
|
138
|
+
if (this.contains(key)) {
|
139
|
+
delete this[':' + key];
|
140
|
+
removeFromArray(this.keys, key, true);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
// Tests if an entry is in the set.
|
145
|
+
Set.prototype.contains = function(entry) {
|
146
|
+
return typeof this[':' + entry] != 'undefined';
|
147
|
+
}
|
148
|
+
|
149
|
+
// Gets a list of values in the set.
|
150
|
+
Set.prototype.items = function() {
|
151
|
+
var list = [];
|
152
|
+
for (var i = 0; i < this.keys.length; ++i) {
|
153
|
+
var k = this.keys[i];
|
154
|
+
var v = this[':' + k];
|
155
|
+
list.push(v);
|
156
|
+
}
|
157
|
+
return list;
|
158
|
+
}
|
159
|
+
|
160
|
+
|
161
|
+
// Invokes function f for every key value pair in the set as a method
|
162
|
+
// of the set.
|
163
|
+
Set.prototype.map = function(f) {
|
164
|
+
for (var i = 0; i < this.keys.length; ++i) {
|
165
|
+
var k = this.keys[i];
|
166
|
+
f.call(this, k, this[':' + k]);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
Set.prototype.clear = function() {
|
171
|
+
for (var i = 0; i < this.keys.length; ++i) {
|
172
|
+
delete this[':' + this.keys[i]];
|
173
|
+
}
|
174
|
+
this.keys.length = 0;
|
175
|
+
}
|
176
|
+
|
177
|
+
|
178
|
+
// Applies the given function to each element of the array, preserving
|
179
|
+
// this, and passing the index.
|
180
|
+
function mapExec(array, func) {
|
181
|
+
for (var i = 0; i < array.length; ++i) {
|
182
|
+
func.call(this, array[i], i);
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
// Returns an array that contains the return value of the given
|
187
|
+
// function applied to every element of the input array.
|
188
|
+
function mapExpr(array, func) {
|
189
|
+
var ret = [];
|
190
|
+
for (var i = 0; i < array.length; ++i) {
|
191
|
+
ret.push(func(array[i]));
|
192
|
+
}
|
193
|
+
return ret;
|
194
|
+
};
|
195
|
+
|
196
|
+
// Reverses the given array in place.
|
197
|
+
function reverseInplace(array) {
|
198
|
+
for (var i = 0; i < array.length / 2; ++i) {
|
199
|
+
var h = array[i];
|
200
|
+
var ii = array.length - i - 1;
|
201
|
+
array[i] = array[ii];
|
202
|
+
array[ii] = h;
|
203
|
+
}
|
204
|
+
}
|
205
|
+
|
206
|
+
// Removes value from array. Returns the number of instances of value
|
207
|
+
// that were removed from array.
|
208
|
+
function removeFromArray(array, value, opt_notype) {
|
209
|
+
var shift = 0;
|
210
|
+
for (var i = 0; i < array.length; ++i) {
|
211
|
+
if (array[i] === value || (opt_notype && array[i] == value)) {
|
212
|
+
array.splice(i--, 1);
|
213
|
+
shift++;
|
214
|
+
}
|
215
|
+
}
|
216
|
+
return shift;
|
217
|
+
}
|
218
|
+
|
219
|
+
// Shallow-copies an array to the end of another array
|
220
|
+
// Basically Array.concat, but works with other non-array collections
|
221
|
+
function copyArray(dst, src) {
|
222
|
+
if (!src) return;
|
223
|
+
var dstLength = dst.length;
|
224
|
+
for (var i = src.length - 1; i >= 0; --i) {
|
225
|
+
dst[i+dstLength] = src[i];
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
/**
|
230
|
+
* This is an optimization for copying attribute lists in IE. IE includes many
|
231
|
+
* extraneous properties in its DOM attribute lists, which take require
|
232
|
+
* significant extra processing when evaluating attribute steps. With this
|
233
|
+
* function, we ignore any such attributes that has an empty string value.
|
234
|
+
*/
|
235
|
+
function copyArrayIgnoringAttributesWithoutValue(dst, src)
|
236
|
+
{
|
237
|
+
if (!src) return;
|
238
|
+
for (var i = src.length - 1; i >= 0; --i) {
|
239
|
+
// this test will pass so long as the attribute has a non-empty string
|
240
|
+
// value, even if that value is "false", "0", "undefined", etc.
|
241
|
+
if (src[i].nodeValue) {
|
242
|
+
dst.push(src[i]);
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
// Returns the text value of a node; for nodes without children this
|
248
|
+
// is the nodeValue, for nodes with children this is the concatenation
|
249
|
+
// of the value of all children. Browser-specific optimizations are used by
|
250
|
+
// default; they can be disabled by passing "true" in as the second parameter.
|
251
|
+
function xmlValue(node, disallowBrowserSpecificOptimization) {
|
252
|
+
if (!node) {
|
253
|
+
return '';
|
254
|
+
}
|
255
|
+
|
256
|
+
var ret = '';
|
257
|
+
if (node.nodeType == DOM_TEXT_NODE ||
|
258
|
+
node.nodeType == DOM_CDATA_SECTION_NODE) {
|
259
|
+
ret += node.nodeValue;
|
260
|
+
|
261
|
+
} else if (node.nodeType == DOM_ATTRIBUTE_NODE) {
|
262
|
+
if (ajaxsltIsIE6) {
|
263
|
+
ret += xmlValueIE6Hack(node);
|
264
|
+
} else {
|
265
|
+
ret += node.nodeValue;
|
266
|
+
}
|
267
|
+
} else if (node.nodeType == DOM_ELEMENT_NODE ||
|
268
|
+
node.nodeType == DOM_DOCUMENT_NODE ||
|
269
|
+
node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
|
270
|
+
if (!disallowBrowserSpecificOptimization) {
|
271
|
+
// IE, Safari, Opera, and friends
|
272
|
+
var innerText = node.innerText;
|
273
|
+
if (innerText != undefined) {
|
274
|
+
return innerText;
|
275
|
+
}
|
276
|
+
// Firefox
|
277
|
+
var textContent = node.textContent;
|
278
|
+
if (textContent != undefined) {
|
279
|
+
return textContent;
|
280
|
+
}
|
281
|
+
}
|
282
|
+
// pobrecito!
|
283
|
+
var len = node.childNodes.length;
|
284
|
+
for (var i = 0; i < len; ++i) {
|
285
|
+
ret += arguments.callee(node.childNodes[i]);
|
286
|
+
}
|
287
|
+
}
|
288
|
+
return ret;
|
289
|
+
}
|
290
|
+
|
291
|
+
function xmlValueIE6Hack(node) {
|
292
|
+
// Issue 19, IE6 mangles href attribute when it's a javascript: url
|
293
|
+
var nodeName = node.nodeName;
|
294
|
+
var nodeValue = node.nodeValue;
|
295
|
+
if (nodeName.length != 4) return nodeValue;
|
296
|
+
if (!/^href$/i.test(nodeName)) return nodeValue;
|
297
|
+
if (!/^javascript:/.test(nodeValue)) return nodeValue;
|
298
|
+
return unescape(nodeValue);
|
299
|
+
}
|
300
|
+
|
301
|
+
// Returns the representation of a node as XML text.
|
302
|
+
function xmlText(node, opt_cdata) {
|
303
|
+
var buf = [];
|
304
|
+
xmlTextR(node, buf, opt_cdata);
|
305
|
+
return buf.join('');
|
306
|
+
}
|
307
|
+
|
308
|
+
function xmlTextR(node, buf, cdata) {
|
309
|
+
if (node.nodeType == DOM_TEXT_NODE) {
|
310
|
+
buf.push(xmlEscapeText(node.nodeValue));
|
311
|
+
|
312
|
+
} else if (node.nodeType == DOM_CDATA_SECTION_NODE) {
|
313
|
+
if (cdata) {
|
314
|
+
buf.push(node.nodeValue);
|
315
|
+
} else {
|
316
|
+
buf.push('<![CDATA[' + node.nodeValue + ']]>');
|
317
|
+
}
|
318
|
+
|
319
|
+
} else if (node.nodeType == DOM_COMMENT_NODE) {
|
320
|
+
buf.push('<!--' + node.nodeValue + '-->');
|
321
|
+
|
322
|
+
} else if (node.nodeType == DOM_ELEMENT_NODE) {
|
323
|
+
buf.push('<' + xmlFullNodeName(node));
|
324
|
+
for (var i = 0; i < node.attributes.length; ++i) {
|
325
|
+
var a = node.attributes[i];
|
326
|
+
if (a && a.nodeName && a.nodeValue) {
|
327
|
+
buf.push(' ' + xmlFullNodeName(a) + '="' +
|
328
|
+
xmlEscapeAttr(a.nodeValue) + '"');
|
329
|
+
}
|
330
|
+
}
|
331
|
+
|
332
|
+
if (node.childNodes.length == 0) {
|
333
|
+
buf.push('/>');
|
334
|
+
} else {
|
335
|
+
buf.push('>');
|
336
|
+
for (var i = 0; i < node.childNodes.length; ++i) {
|
337
|
+
arguments.callee(node.childNodes[i], buf, cdata);
|
338
|
+
}
|
339
|
+
buf.push('</' + xmlFullNodeName(node) + '>');
|
340
|
+
}
|
341
|
+
|
342
|
+
} else if (node.nodeType == DOM_DOCUMENT_NODE ||
|
343
|
+
node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
|
344
|
+
for (var i = 0; i < node.childNodes.length; ++i) {
|
345
|
+
arguments.callee(node.childNodes[i], buf, cdata);
|
346
|
+
}
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
function xmlFullNodeName(n) {
|
351
|
+
if (n.prefix && n.nodeName.indexOf(n.prefix + ':') != 0) {
|
352
|
+
return n.prefix + ':' + n.nodeName;
|
353
|
+
} else {
|
354
|
+
return n.nodeName;
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
// Escape XML special markup chracters: tag delimiter < > and entity
|
359
|
+
// reference start delimiter &. The escaped string can be used in XML
|
360
|
+
// text portions (i.e. between tags).
|
361
|
+
function xmlEscapeText(s) {
|
362
|
+
return ('' + s).replace(/&/g, '&').replace(/</g, '<').
|
363
|
+
replace(/>/g, '>');
|
364
|
+
}
|
365
|
+
|
366
|
+
// Escape XML special markup characters: tag delimiter < > entity
|
367
|
+
// reference start delimiter & and quotes ". The escaped string can be
|
368
|
+
// used in double quoted XML attribute value portions (i.e. in
|
369
|
+
// attributes within start tags).
|
370
|
+
function xmlEscapeAttr(s) {
|
371
|
+
return xmlEscapeText(s).replace(/\"/g, '"');
|
372
|
+
}
|
373
|
+
|
374
|
+
// Escape markup in XML text, but don't touch entity references. The
|
375
|
+
// escaped string can be used as XML text (i.e. between tags).
|
376
|
+
function xmlEscapeTags(s) {
|
377
|
+
return s.replace(/</g, '<').replace(/>/g, '>');
|
378
|
+
}
|
379
|
+
|
380
|
+
/**
|
381
|
+
* Wrapper function to access the owner document uniformly for document
|
382
|
+
* and other nodes: for the document node, the owner document is the
|
383
|
+
* node itself, for all others it's the ownerDocument property.
|
384
|
+
*
|
385
|
+
* @param {Node} node
|
386
|
+
* @return {Document}
|
387
|
+
*/
|
388
|
+
function xmlOwnerDocument(node) {
|
389
|
+
if (node.nodeType == DOM_DOCUMENT_NODE) {
|
390
|
+
return node;
|
391
|
+
} else {
|
392
|
+
return node.ownerDocument;
|
393
|
+
}
|
394
|
+
}
|
395
|
+
|
396
|
+
// Wrapper around DOM methods so we can condense their invocations.
|
397
|
+
function domGetAttribute(node, name) {
|
398
|
+
return node.getAttribute(name);
|
399
|
+
}
|
400
|
+
|
401
|
+
function domSetAttribute(node, name, value) {
|
402
|
+
return node.setAttribute(name, value);
|
403
|
+
}
|
404
|
+
|
405
|
+
function domRemoveAttribute(node, name) {
|
406
|
+
return node.removeAttribute(name);
|
407
|
+
}
|
408
|
+
|
409
|
+
function domAppendChild(node, child) {
|
410
|
+
return node.appendChild(child);
|
411
|
+
}
|
412
|
+
|
413
|
+
function domRemoveChild(node, child) {
|
414
|
+
return node.removeChild(child);
|
415
|
+
}
|
416
|
+
|
417
|
+
function domReplaceChild(node, newChild, oldChild) {
|
418
|
+
return node.replaceChild(newChild, oldChild);
|
419
|
+
}
|
420
|
+
|
421
|
+
function domInsertBefore(node, newChild, oldChild) {
|
422
|
+
return node.insertBefore(newChild, oldChild);
|
423
|
+
}
|
424
|
+
|
425
|
+
function domRemoveNode(node) {
|
426
|
+
return domRemoveChild(node.parentNode, node);
|
427
|
+
}
|
428
|
+
|
429
|
+
function domCreateTextNode(doc, text) {
|
430
|
+
return doc.createTextNode(text);
|
431
|
+
}
|
432
|
+
|
433
|
+
function domCreateElement(doc, name) {
|
434
|
+
return doc.createElement(name);
|
435
|
+
}
|
436
|
+
|
437
|
+
function domCreateAttribute(doc, name) {
|
438
|
+
return doc.createAttribute(name);
|
439
|
+
}
|
440
|
+
|
441
|
+
function domCreateCDATASection(doc, data) {
|
442
|
+
return doc.createCDATASection(data);
|
443
|
+
}
|
444
|
+
|
445
|
+
function domCreateComment(doc, text) {
|
446
|
+
return doc.createComment(text);
|
447
|
+
}
|
448
|
+
|
449
|
+
function domCreateDocumentFragment(doc) {
|
450
|
+
return doc.createDocumentFragment();
|
451
|
+
}
|
452
|
+
|
453
|
+
function domGetElementById(doc, id) {
|
454
|
+
return doc.getElementById(id);
|
455
|
+
}
|
456
|
+
|
457
|
+
// Same for window methods.
|
458
|
+
function windowSetInterval(win, fun, time) {
|
459
|
+
return win.setInterval(fun, time);
|
460
|
+
}
|
461
|
+
|
462
|
+
function windowClearInterval(win, id) {
|
463
|
+
return win.clearInterval(id);
|
464
|
+
}
|
465
|
+
|
466
|
+
/**
|
467
|
+
* Escape the special regular expression characters when the regular expression
|
468
|
+
* is specified as a string.
|
469
|
+
*
|
470
|
+
* Based on: http://simonwillison.net/2006/Jan/20/escape/
|
471
|
+
*/
|
472
|
+
RegExp.escape = (function() {
|
473
|
+
var specials = [
|
474
|
+
'/', '.', '*', '+', '?', '|', '^', '$',
|
475
|
+
'(', ')', '[', ']', '{', '}', '\\'
|
476
|
+
];
|
477
|
+
|
478
|
+
var sRE = new RegExp(
|
479
|
+
'(\\' + specials.join('|\\') + ')', 'g'
|
480
|
+
);
|
481
|
+
|
482
|
+
return function(text) {
|
483
|
+
return text.replace(sRE, '\\$1');
|
484
|
+
}
|
485
|
+
})();
|
486
|
+
|
487
|
+
/**
|
488
|
+
* Determines whether a predicate expression contains a "positional selector".
|
489
|
+
* A positional selector filters nodes from the nodelist input based on their
|
490
|
+
* position within that list. When such selectors are encountered, the
|
491
|
+
* evaluation of the predicate cannot be depth-first, because the positional
|
492
|
+
* selector may be based on the result of evaluating predicates that precede
|
493
|
+
* it.
|
494
|
+
*/
|
495
|
+
function predicateExprHasPositionalSelector(expr, isRecursiveCall) {
|
496
|
+
if (!expr) {
|
497
|
+
return false;
|
498
|
+
}
|
499
|
+
if (!isRecursiveCall && exprReturnsNumberValue(expr)) {
|
500
|
+
// this is a "proximity position"-based predicate
|
501
|
+
return true;
|
502
|
+
}
|
503
|
+
if (expr instanceof FunctionCallExpr) {
|
504
|
+
var value = expr.name.value;
|
505
|
+
return (value == 'last' || value == 'position');
|
506
|
+
}
|
507
|
+
if (expr instanceof BinaryExpr) {
|
508
|
+
return (
|
509
|
+
predicateExprHasPositionalSelector(expr.expr1, true) ||
|
510
|
+
predicateExprHasPositionalSelector(expr.expr2, true));
|
511
|
+
}
|
512
|
+
return false;
|
513
|
+
}
|
514
|
+
|
515
|
+
function exprReturnsNumberValue(expr) {
|
516
|
+
if (expr instanceof FunctionCallExpr) {
|
517
|
+
var isMember = {
|
518
|
+
last: true
|
519
|
+
, position: true
|
520
|
+
, count: true
|
521
|
+
, 'string-length': true
|
522
|
+
, number: true
|
523
|
+
, sum: true
|
524
|
+
, floor: true
|
525
|
+
, ceiling: true
|
526
|
+
, round: true
|
527
|
+
};
|
528
|
+
return isMember[expr.name.value];
|
529
|
+
}
|
530
|
+
else if (expr instanceof UnaryMinusExpr) {
|
531
|
+
return true;
|
532
|
+
}
|
533
|
+
else if (expr instanceof BinaryExpr) {
|
534
|
+
var isMember = {
|
535
|
+
'+': true
|
536
|
+
, '-': true
|
537
|
+
, '*': true
|
538
|
+
, mod: true
|
539
|
+
, div: true
|
540
|
+
};
|
541
|
+
return isMember[expr.op.value];
|
542
|
+
}
|
543
|
+
else if (expr instanceof NumberExpr) {
|
544
|
+
return true;
|
545
|
+
}
|
546
|
+
return false;
|
547
|
+
}
|
548
|
+
|
549
|
+
|
@@ -0,0 +1,149 @@
|
|
1
|
+
// Copyright 2006 Google Inc.
|
2
|
+
// All Rights Reserved
|
3
|
+
//
|
4
|
+
// Defines regular expression patterns to extract XML tokens from string.
|
5
|
+
// See <http://www.w3.org/TR/REC-xml/#sec-common-syn>,
|
6
|
+
// <http://www.w3.org/TR/xml11/#sec-common-syn> and
|
7
|
+
// <http://www.w3.org/TR/REC-xml-names/#NT-NCName> for the specifications.
|
8
|
+
//
|
9
|
+
// Author: Junji Takagi <jtakagi@google.com>
|
10
|
+
|
11
|
+
// Detect whether RegExp supports Unicode characters or not.
|
12
|
+
|
13
|
+
var REGEXP_UNICODE = function() {
|
14
|
+
var tests = [' ', '\u0120', -1, // Konquerer 3.4.0 fails here.
|
15
|
+
'!', '\u0120', -1,
|
16
|
+
'\u0120', '\u0120', 0,
|
17
|
+
'\u0121', '\u0120', -1,
|
18
|
+
'\u0121', '\u0120|\u0121', 0,
|
19
|
+
'\u0122', '\u0120|\u0121', -1,
|
20
|
+
'\u0120', '[\u0120]', 0, // Safari 2.0.3 fails here.
|
21
|
+
'\u0121', '[\u0120]', -1,
|
22
|
+
'\u0121', '[\u0120\u0121]', 0, // Safari 2.0.3 fails here.
|
23
|
+
'\u0122', '[\u0120\u0121]', -1,
|
24
|
+
'\u0121', '[\u0120-\u0121]', 0, // Safari 2.0.3 fails here.
|
25
|
+
'\u0122', '[\u0120-\u0121]', -1];
|
26
|
+
for (var i = 0; i < tests.length; i += 3) {
|
27
|
+
if (tests[i].search(new RegExp(tests[i + 1])) != tests[i + 2]) {
|
28
|
+
return false;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
return true;
|
32
|
+
}();
|
33
|
+
|
34
|
+
// Common tokens in XML 1.0 and XML 1.1.
|
35
|
+
|
36
|
+
var XML_S = '[ \t\r\n]+';
|
37
|
+
var XML_EQ = '(' + XML_S + ')?=(' + XML_S + ')?';
|
38
|
+
var XML_CHAR_REF = '&#[0-9]+;|&#x[0-9a-fA-F]+;';
|
39
|
+
|
40
|
+
// XML 1.0 tokens.
|
41
|
+
|
42
|
+
var XML10_VERSION_INFO = XML_S + 'version' + XML_EQ + '("1\\.0"|' + "'1\\.0')";
|
43
|
+
var XML10_BASE_CHAR = (REGEXP_UNICODE) ?
|
44
|
+
'\u0041-\u005a\u0061-\u007a\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff' +
|
45
|
+
'\u0100-\u0131\u0134-\u013e\u0141-\u0148\u014a-\u017e\u0180-\u01c3' +
|
46
|
+
'\u01cd-\u01f0\u01f4-\u01f5\u01fa-\u0217\u0250-\u02a8\u02bb-\u02c1\u0386' +
|
47
|
+
'\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03ce\u03d0-\u03d6\u03da\u03dc' +
|
48
|
+
'\u03de\u03e0\u03e2-\u03f3\u0401-\u040c\u040e-\u044f\u0451-\u045c' +
|
49
|
+
'\u045e-\u0481\u0490-\u04c4\u04c7-\u04c8\u04cb-\u04cc\u04d0-\u04eb' +
|
50
|
+
'\u04ee-\u04f5\u04f8-\u04f9\u0531-\u0556\u0559\u0561-\u0586\u05d0-\u05ea' +
|
51
|
+
'\u05f0-\u05f2\u0621-\u063a\u0641-\u064a\u0671-\u06b7\u06ba-\u06be' +
|
52
|
+
'\u06c0-\u06ce\u06d0-\u06d3\u06d5\u06e5-\u06e6\u0905-\u0939\u093d' +
|
53
|
+
'\u0958-\u0961\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2' +
|
54
|
+
'\u09b6-\u09b9\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u0a05-\u0a0a' +
|
55
|
+
'\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36' +
|
56
|
+
'\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8b\u0a8d' +
|
57
|
+
'\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9' +
|
58
|
+
'\u0abd\u0ae0\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30' +
|
59
|
+
'\u0b32-\u0b33\u0b36-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b85-\u0b8a' +
|
60
|
+
'\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4' +
|
61
|
+
'\u0ba8-\u0baa\u0bae-\u0bb5\u0bb7-\u0bb9\u0c05-\u0c0c\u0c0e-\u0c10' +
|
62
|
+
'\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c60-\u0c61\u0c85-\u0c8c' +
|
63
|
+
'\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cde\u0ce0-\u0ce1' +
|
64
|
+
'\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d60-\u0d61' +
|
65
|
+
'\u0e01-\u0e2e\u0e30\u0e32-\u0e33\u0e40-\u0e45\u0e81-\u0e82\u0e84' +
|
66
|
+
'\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5' +
|
67
|
+
'\u0ea7\u0eaa-\u0eab\u0ead-\u0eae\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4' +
|
68
|
+
'\u0f40-\u0f47\u0f49-\u0f69\u10a0-\u10c5\u10d0-\u10f6\u1100\u1102-\u1103' +
|
69
|
+
'\u1105-\u1107\u1109\u110b-\u110c\u110e-\u1112\u113c\u113e\u1140\u114c' +
|
70
|
+
'\u114e\u1150\u1154-\u1155\u1159\u115f-\u1161\u1163\u1165\u1167\u1169' +
|
71
|
+
'\u116d-\u116e\u1172-\u1173\u1175\u119e\u11a8\u11ab\u11ae-\u11af' +
|
72
|
+
'\u11b7-\u11b8\u11ba\u11bc-\u11c2\u11eb\u11f0\u11f9\u1e00-\u1e9b' +
|
73
|
+
'\u1ea0-\u1ef9\u1f00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d' +
|
74
|
+
'\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc' +
|
75
|
+
'\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec' +
|
76
|
+
'\u1ff2-\u1ff4\u1ff6-\u1ffc\u2126\u212a-\u212b\u212e\u2180-\u2182' +
|
77
|
+
'\u3041-\u3094\u30a1-\u30fa\u3105-\u312c\uac00-\ud7a3' :
|
78
|
+
'A-Za-z';
|
79
|
+
var XML10_IDEOGRAPHIC = (REGEXP_UNICODE) ?
|
80
|
+
'\u4e00-\u9fa5\u3007\u3021-\u3029' :
|
81
|
+
'';
|
82
|
+
var XML10_COMBINING_CHAR = (REGEXP_UNICODE) ?
|
83
|
+
'\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05a1\u05a3-\u05b9' +
|
84
|
+
'\u05bb-\u05bd\u05bf\u05c1-\u05c2\u05c4\u064b-\u0652\u0670\u06d6-\u06dc' +
|
85
|
+
'\u06dd-\u06df\u06e0-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0901-\u0903\u093c' +
|
86
|
+
'\u093e-\u094c\u094d\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09bc\u09be' +
|
87
|
+
'\u09bf\u09c0-\u09c4\u09c7-\u09c8\u09cb-\u09cd\u09d7\u09e2-\u09e3\u0a02' +
|
88
|
+
'\u0a3c\u0a3e\u0a3f\u0a40-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a70-\u0a71' +
|
89
|
+
'\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0b01-\u0b03' +
|
90
|
+
'\u0b3c\u0b3e-\u0b43\u0b47-\u0b48\u0b4b-\u0b4d\u0b56-\u0b57\u0b82-\u0b83' +
|
91
|
+
'\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0c01-\u0c03\u0c3e-\u0c44' +
|
92
|
+
'\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c82-\u0c83\u0cbe-\u0cc4' +
|
93
|
+
'\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d43' +
|
94
|
+
'\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1' +
|
95
|
+
'\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39' +
|
96
|
+
'\u0f3e\u0f3f\u0f71-\u0f84\u0f86-\u0f8b\u0f90-\u0f95\u0f97\u0f99-\u0fad' +
|
97
|
+
'\u0fb1-\u0fb7\u0fb9\u20d0-\u20dc\u20e1\u302a-\u302f\u3099\u309a' :
|
98
|
+
'';
|
99
|
+
var XML10_DIGIT = (REGEXP_UNICODE) ?
|
100
|
+
'\u0030-\u0039\u0660-\u0669\u06f0-\u06f9\u0966-\u096f\u09e6-\u09ef' +
|
101
|
+
'\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be7-\u0bef\u0c66-\u0c6f' +
|
102
|
+
'\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29' :
|
103
|
+
'0-9';
|
104
|
+
var XML10_EXTENDER = (REGEXP_UNICODE) ?
|
105
|
+
'\u00b7\u02d0\u02d1\u0387\u0640\u0e46\u0ec6\u3005\u3031-\u3035' +
|
106
|
+
'\u309d-\u309e\u30fc-\u30fe' :
|
107
|
+
'';
|
108
|
+
var XML10_LETTER = XML10_BASE_CHAR + XML10_IDEOGRAPHIC;
|
109
|
+
var XML10_NAME_CHAR = XML10_LETTER + XML10_DIGIT + '\\._:' +
|
110
|
+
XML10_COMBINING_CHAR + XML10_EXTENDER + '-';
|
111
|
+
var XML10_NAME = '[' + XML10_LETTER + '_:][' + XML10_NAME_CHAR + ']*';
|
112
|
+
|
113
|
+
var XML10_ENTITY_REF = '&' + XML10_NAME + ';';
|
114
|
+
var XML10_REFERENCE = XML10_ENTITY_REF + '|' + XML_CHAR_REF;
|
115
|
+
var XML10_ATT_VALUE = '"(([^<&"]|' + XML10_REFERENCE + ')*)"|' +
|
116
|
+
"'(([^<&']|" + XML10_REFERENCE + ")*)'";
|
117
|
+
var XML10_ATTRIBUTE =
|
118
|
+
'(' + XML10_NAME + ')' + XML_EQ + '(' + XML10_ATT_VALUE + ')';
|
119
|
+
|
120
|
+
// XML 1.1 tokens.
|
121
|
+
// TODO(jtakagi): NameStartChar also includes \u10000-\ueffff.
|
122
|
+
// ECMAScript Language Specifiction defines UnicodeEscapeSequence as
|
123
|
+
// "\u HexDigit HexDigit HexDigit HexDigit" and we may need to use
|
124
|
+
// surrogate pairs, but any browser doesn't support surrogate paris in
|
125
|
+
// character classes of regular expression, so avoid including them for now.
|
126
|
+
|
127
|
+
var XML11_VERSION_INFO = XML_S + 'version' + XML_EQ + '("1\\.1"|' + "'1\\.1')";
|
128
|
+
var XML11_NAME_START_CHAR = (REGEXP_UNICODE) ?
|
129
|
+
':A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d' +
|
130
|
+
'\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff' +
|
131
|
+
'\uf900-\ufdcf\ufdf0-\ufffd' :
|
132
|
+
':A-Z_a-z';
|
133
|
+
var XML11_NAME_CHAR = XML11_NAME_START_CHAR +
|
134
|
+
((REGEXP_UNICODE) ? '\\.0-9\u00b7\u0300-\u036f\u203f-\u2040-' : '\\.0-9-');
|
135
|
+
var XML11_NAME = '[' + XML11_NAME_START_CHAR + '][' + XML11_NAME_CHAR + ']*';
|
136
|
+
|
137
|
+
var XML11_ENTITY_REF = '&' + XML11_NAME + ';';
|
138
|
+
var XML11_REFERENCE = XML11_ENTITY_REF + '|' + XML_CHAR_REF;
|
139
|
+
var XML11_ATT_VALUE = '"(([^<&"]|' + XML11_REFERENCE + ')*)"|' +
|
140
|
+
"'(([^<&']|" + XML11_REFERENCE + ")*)'";
|
141
|
+
var XML11_ATTRIBUTE =
|
142
|
+
'(' + XML11_NAME + ')' + XML_EQ + '(' + XML11_ATT_VALUE + ')';
|
143
|
+
|
144
|
+
// XML Namespace tokens.
|
145
|
+
// Used in XML parser and XPath parser.
|
146
|
+
|
147
|
+
var XML_NC_NAME_CHAR = XML10_LETTER + XML10_DIGIT + '\\._' +
|
148
|
+
XML10_COMBINING_CHAR + XML10_EXTENDER + '-';
|
149
|
+
var XML_NC_NAME = '[' + XML10_LETTER + '_][' + XML_NC_NAME_CHAR + ']*';
|