jslint 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Geraud
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,17 @@
1
+ = jslint
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Geraud. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = 'jslint'
8
+ gem.summary = %Q{wrapping of jslint}
9
+ gem.description = %Q{longer description of your gem}
10
+ gem.email = 'geraud@gmail.com'
11
+ gem.homepage = "http://github.com/geraud/jslint"
12
+ gem.authors = ['Geraud Boyer']
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ gem.files += Dir['{bin}/**/*', '{lib}/**/*', '{jslint}/**/*']
16
+ gem.bindir = 'bin'
17
+ gem.executables= 'jslint'
18
+ gem.add_dependency 'json'
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ task :default => :build
26
+
27
+ # require 'spec/rake/spectask'
28
+ # Spec::Rake::SpecTask.new(:spec) do |spec|
29
+ # spec.libs << 'lib' << 'spec'
30
+ # spec.spec_files = FileList['spec/**/*_spec.rb']
31
+ # end
32
+
33
+ # Spec::Rake::SpecTask.new(:rcov) do |spec|
34
+ # spec.libs << 'lib' << 'spec'
35
+ # spec.pattern = 'spec/**/*_spec.rb'
36
+ # spec.rcov = true
37
+ # end
38
+
39
+ # task :spec => :check_dependencies
40
+
41
+ # require 'rake/rdoctask'
42
+ # Rake::RDocTask.new do |rdoc|
43
+ # version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ # rdoc.rdoc_dir = 'rdoc'
46
+ # rdoc.title = "jslint #{version}"
47
+ # rdoc.rdoc_files.include('README*')
48
+ # rdoc.rdoc_files.include('lib/**/*.rb')
49
+ # end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/bin/jslint ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'json'
4
+ require 'jslint'
5
+
6
+ config_file = File.expand_path('config/jslint.yml')
7
+ config = YAML.load_file(config_file)['jslint']
8
+
9
+ options = config['options'] || {}
10
+ predefined = config['predefined']
11
+ options['predef'] = predefined.map { |defs| defs.split(',') }.flatten.map(&:strip) unless predefined.empty?
12
+
13
+ options = config['options'].map do |option, value|
14
+ option = option.strip
15
+ case value
16
+ when true
17
+ "--#{option}"
18
+ when false
19
+ "--no-#{option}"
20
+ else
21
+ "--#{option}='#{value.to_json}'"
22
+ end
23
+ end
24
+
25
+ command = []
26
+ command << ['java', '-jar', Jslint::RhinoJar]
27
+ command << ['-f', Jslint::Scripts[:fulljslint]]
28
+ command << ['-f', Jslint::Scripts[:json2]]
29
+ command << Jslint::Scripts[:rhino]
30
+ command << [ options, ARGV.first]
31
+ command = command.flatten.join(' ')
32
+ # $stderr.puts command
33
+ exec command
data/jslint.gemspec ADDED
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{jslint}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Geraud Boyer"]
12
+ s.date = %q{2010-09-06}
13
+ s.default_executable = %q{jslint}
14
+ s.description = %q{longer description of your gem}
15
+ s.email = %q{geraud@gmail.com}
16
+ s.executables = ["jslint"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/jslint",
29
+ "jslint.gemspec",
30
+ "jslint/adsafe.js",
31
+ "jslint/fulljslint.js",
32
+ "jslint/intercept.js",
33
+ "jslint/json2.js",
34
+ "jslint/rhino.js",
35
+ "jslint/widget.js",
36
+ "lib/generators/jslint/update_config/templates/jslint.yml",
37
+ "lib/generators/jslint/update_config/update_config_generator.rb",
38
+ "lib/js-1.7R2.jar",
39
+ "lib/jslint.rb",
40
+ "lib/jslint/engine.rb",
41
+ "lib/tasks/jslint.rake",
42
+ "rhino-1.7R2-license.txt",
43
+ "spec/jslint_spec.rb",
44
+ "spec/spec.opts",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+ s.homepage = %q{http://github.com/geraud/jslint}
48
+ s.rdoc_options = ["--charset=UTF-8"]
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = %q{1.3.7}
51
+ s.summary = %q{wrapping of jslint}
52
+ s.test_files = [
53
+ "spec/jslint_spec.rb",
54
+ "spec/spec_helper.rb"
55
+ ]
56
+
57
+ if s.respond_to? :specification_version then
58
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
59
+ s.specification_version = 3
60
+
61
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
62
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
63
+ s.add_runtime_dependency(%q<json>, [">= 0"])
64
+ else
65
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
66
+ s.add_dependency(%q<json>, [">= 0"])
67
+ end
68
+ else
69
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
70
+ s.add_dependency(%q<json>, [">= 0"])
71
+ end
72
+ end
73
+
data/jslint/adsafe.js ADDED
@@ -0,0 +1,1769 @@
1
+ // adsafe.js
2
+ // 2010-07-10
3
+
4
+ // Public Domain.
5
+
6
+ // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
7
+ // SUBJECT TO CHANGE WITHOUT NOTICE.
8
+
9
+ // Original url: http://www.ADsafe.org/adsafe.js
10
+
11
+ // This file implements the core ADSAFE runtime. A site may add additional
12
+ // methods understanding that those methods will be made available to guest
13
+ // code.
14
+
15
+ // This code should be minified before deployment.
16
+ // See http://javascript.crockford.com/jsmin.html
17
+
18
+ // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
19
+ // NOT CONTROL.
20
+
21
+ /*global window*/
22
+
23
+ /*jslint browser: true, devel: true, nomen: false */
24
+
25
+ /*members "", "#", "&", "*", "+", ".", "\/", ":blur", ":checked",
26
+ ":disabled", ":enabled", ":even", ":focus", ":hidden", ":odd", ":tag",
27
+ ":text", ":trim", ":unchecked", ":visible", ">", "[", "[!=", "[$=",
28
+ "[*=", "[=", "[^=", "[|=", "[~=", _, "___ on ___", "___adsafe root___",
29
+ ___nodes___, ___star___, "_adsafe mark_", _intercept, a, abbr, acronym,
30
+ addEventListener, address, altKey, append, appendChild, apply, area,
31
+ arguments, autocomplete, b, bdo, big, blockquote, blur, br, bubble,
32
+ button, call, callee, caller, cancelBubble, canvas, caption, center,
33
+ change, charAt, charCode, check, checked, childNodes, cite, className,
34
+ clientX, clientY, clone, cloneNode, code, col, colgroup, combine,
35
+ concat, console, constructor, count, create, createDocumentFragment,
36
+ createElement, createRange, createTextNode, createTextRange, cssFloat,
37
+ ctrlKey, currentStyle, dd, defaultView, del, dfn, dir, disabled, div,
38
+ dl, dt, each, em, empty, enable, ephemeral, eval, exec, expand, explode,
39
+ fieldset, fire, firstChild, focus, font, form, fragment, fromCharCode,
40
+ get, getCheck, getClass, getComputedStyle, getContext, getElementById,
41
+ getElementsByTagName, getMark, getName, getOffsetHeight, getOffsetWidth,
42
+ getParent, getSelection, getStyle, getTagName, getTitle, getValue, go,
43
+ h1, h2, h3, h4, h5, h6, hasOwnProperty, hr, i, id, img, inRange,
44
+ indexOf, input, ins, insertBefore, isArray, kbd, key, keyCode, klass,
45
+ label, later, legend, length, li, lib, log, map, mark, menu, message,
46
+ name, nextSibling, nodeName, nodeValue, object, off, offsetHeight,
47
+ offsetWidth, ol, on, onclick, ondblclick, onfocusin, onfocusout,
48
+ onkeypress, onmousedown, onmousemove, onmouseout, onmouseover,
49
+ onmouseup, op, optgroup, option, p, parent, parentNode, postError, pre,
50
+ prepend, preventDefault, protect, prototype, push, q, remove,
51
+ removeChild, removeElement, replace, replaceNode, returnValue, row,
52
+ samp, select, selection, selectionEnd, selectionStart, set, shiftKey,
53
+ slice, small, span, srcElement, stack, stopPropagation, strong, style,
54
+ styleFloat, sub, sup, table, tag, tagName, target, tbody, td, test,
55
+ text, textarea, tfoot, th, that, thead, title, toLowerCase, toString,
56
+ toUpperCase, tr, tt, type, u, ul, unwatch, value, valueOf, var,
57
+ visibility, watch, window, writeln, x, y
58
+ */
59
+
60
+ "use strict";
61
+
62
+ var ADSAFE = (function () {
63
+
64
+ var adsafe_id, // The id of the current widget
65
+ adsafe_lib, // The script libraries loaded by the current widget
66
+
67
+ // These member names are banned from guest scripts. The ADSAFE.get and
68
+ // ADSAFE.put methods will not allow access to these properties.
69
+
70
+ banned = {
71
+ 'arguments' : true,
72
+ callee : true,
73
+ caller : true,
74
+ constructor : true,
75
+ 'eval' : true,
76
+ prototype : true,
77
+ stack : true,
78
+ unwatch : true,
79
+ valueOf : true,
80
+ watch : true
81
+ },
82
+
83
+ cache_style_object,
84
+ cache_style_node,
85
+ defaultView = document.defaultView,
86
+ ephemeral,
87
+ flipflop, // Used in :even/:odd processing
88
+ has_focus,
89
+ hunter, // Set of hunter patterns
90
+ interceptors = [],
91
+
92
+ makeableTagName = {
93
+
94
+ // This is the whitelist of elements that may be created with the .tag(tagName)
95
+ // method.
96
+
97
+ a : true,
98
+ abbr : true,
99
+ acronym : true,
100
+ address : true,
101
+ area : true,
102
+ b : true,
103
+ bdo : true,
104
+ big : true,
105
+ blockquote: true,
106
+ br : true,
107
+ button : true,
108
+ canvas : true,
109
+ caption : true,
110
+ center : true,
111
+ cite : true,
112
+ code : true,
113
+ col : true,
114
+ colgroup : true,
115
+ dd : true,
116
+ del : true,
117
+ dfn : true,
118
+ dir : true,
119
+ div : true,
120
+ dl : true,
121
+ dt : true,
122
+ em : true,
123
+ fieldset : true,
124
+ font : true,
125
+ form : true,
126
+ h1 : true,
127
+ h2 : true,
128
+ h3 : true,
129
+ h4 : true,
130
+ h5 : true,
131
+ h6 : true,
132
+ hr : true,
133
+ i : true,
134
+ img : true,
135
+ input : true,
136
+ ins : true,
137
+ kbd : true,
138
+ label : true,
139
+ legend : true,
140
+ li : true,
141
+ map : true,
142
+ menu : true,
143
+ object : true,
144
+ ol : true,
145
+ optgroup : true,
146
+ option : true,
147
+ p : true,
148
+ pre : true,
149
+ q : true,
150
+ samp : true,
151
+ select : true,
152
+ small : true,
153
+ span : true,
154
+ strong : true,
155
+ sub : true,
156
+ sup : true,
157
+ table : true,
158
+ tbody : true,
159
+ td : true,
160
+ textarea : true,
161
+ tfoot : true,
162
+ th : true,
163
+ thead : true,
164
+ tr : true,
165
+ tt : true,
166
+ u : true,
167
+ ul : true,
168
+ 'var' : true
169
+ },
170
+ name,
171
+ pecker, // set of pecker patterns
172
+ result,
173
+ star,
174
+ the_range,
175
+ value;
176
+
177
+
178
+ // The error function is called if there is a violation or confusion.
179
+ // It throws an exception.
180
+
181
+ function error(message) {
182
+ ADSAFE.log("ADsafe error: " + (message || "ADsafe violation."));
183
+ throw {
184
+ name: "ADsafe",
185
+ message: message || "ADsafe violation."
186
+ };
187
+ }
188
+
189
+
190
+ // Firefox implemented some of its array methods carelessly. If a method is
191
+ // called as a function it returns the global object. ADsafe cannot tolerate
192
+ // that, so we wrap the methods to make them safer and slower.
193
+
194
+ (function mozilla(name) {
195
+ var method = Array.prototype[name];
196
+ Array.prototype[name] = function () {
197
+ return !this || this.window ? error() : method.apply(this, arguments);
198
+ };
199
+ return mozilla;
200
+ }
201
+ ('concat')
202
+ ('every')
203
+ ('filter')
204
+ ('forEach')
205
+ ('map')
206
+ ('reduce')
207
+ ('reduceRight')
208
+ ('reverse')
209
+ ('slice')
210
+ ('some')
211
+ ('sort'));
212
+
213
+
214
+ // The reject function enforces the restriction on get and put.
215
+ // It allows access only to objects and arrays. It does not allow use of
216
+ // the banned names, or names that are not strings or positive numbers,
217
+ // or strings that start or end with _ or strings that start with -.
218
+
219
+ function reject(object, name) {
220
+ return typeof object !== 'object' || banned[name] ||
221
+ ((typeof name !== 'number' || name < 0) &&
222
+ (typeof name !== 'string' || name.charAt(0) === '_' ||
223
+ name.slice(-1) === '_' || name.charAt(0) === '-'));
224
+ }
225
+
226
+
227
+ function getStyleObject(node) {
228
+
229
+ // The getStyleObject function returns the computed style object for a node.
230
+
231
+ if (node === cache_style_node) {
232
+ return cache_style_object;
233
+ }
234
+ cache_style_node = node;
235
+ cache_style_object =
236
+ node.currentStyle || defaultView.getComputedStyle(node, '');
237
+ return cache_style_object;
238
+ }
239
+
240
+
241
+ function walkTheDOM(node, func, skip) {
242
+
243
+ // Recursively traverse the DOM tree, starting with the node, in document
244
+ // source order, calling the func on each node visisted.
245
+
246
+ if (!skip) {
247
+ func(node);
248
+ }
249
+ node = node.firstChild;
250
+ while (node) {
251
+ walkTheDOM(node, func);
252
+ node = node.nextSibling;
253
+ }
254
+ }
255
+
256
+
257
+ function purge_event_handlers(node) {
258
+
259
+ // We attach all event handlers to a '___ on ___' property. The property name
260
+ // contains spaces to insure that there is no collision with HTML attribues.
261
+ // Keeping the handlers in a single property makes it easy to remove them
262
+ // all at once. Removal is required to avoid memory leakage on IE6 and IE7.
263
+
264
+ walkTheDOM(node, function (node) {
265
+ if (node.tagName) {
266
+ node['___ on ___'] = node.change = null;
267
+ }
268
+ });
269
+ }
270
+
271
+
272
+ function parse_query(text, id) {
273
+
274
+ // Convert a query string into an array of op/name/value selectors.
275
+ // A query string is a sequence of triples wrapped in brackets; or names,
276
+ // possibly prefixed by # . & > _, or :option, or * or /. A triple is a name,
277
+ // and operator (one of [=, [!=, [*=, [~=, [|=, [$=, or [^=) and a value.
278
+
279
+ // If the id parameter is supplied, then the name following # must have the
280
+ // id as a prefix and must match the ADsafe rule for id: being all uppercase
281
+ // letters and digits with one underbar.
282
+
283
+ // A name must be all lower case and may contain digits, -, or _.
284
+
285
+ var match, // A match array
286
+ query = [], // The resulting query array
287
+ selector,
288
+ qx = id ?
289
+ /^\s*(?:([\*\/])|\[\s*([a-z][0-9a-z_\-]*)\s*(?:([!*~|$\^]?\=)\s*([0-9A-Za-z_\-*%&;.\/:!]+)\s*)?\]|#\s*([A-Z]+_[A-Z0-9]+)|:\s*([a-z]+)|([.&_>\+]?)\s*([a-z][0-9a-z\-]*))\s*/ :
290
+ /^\s*(?:([\*\/])|\[\s*([a-z][0-9a-z_\-]*)\s*(?:([!*~|$\^]?\=)\s*([0-9A-Za-z_\-*%&;.\/:!]+)\s*)?\]|#\s*([\-A-Za-z0-9_]+)|:\s*([a-z]+)|([.&_>\+]?)\s*([a-z][0-9a-z\-]*))\s*/;
291
+
292
+ // Loop over all of the selectors in the text.
293
+
294
+ do {
295
+
296
+ // The qx teases the components of one selector out of the text, ignoring
297
+ // whitespace.
298
+
299
+ // match[0] the whole selector
300
+ // match[1] * /
301
+ // match[2] attribute name
302
+ // match[3] = != *= ~= |= $= ^=
303
+ // match[4] attribute value
304
+ // match[5] # id
305
+ // match[6] : option
306
+ // match[7] . & _ > +
307
+ // match[8] name
308
+
309
+ match = qx.exec(text);
310
+ if (!match) {
311
+ return error("ADsafe: Bad query:" + text);
312
+ }
313
+
314
+ // Make a selector object and stuff it in the query.
315
+
316
+ if (match[1]) {
317
+
318
+ // The selector is * or /
319
+
320
+ selector = {
321
+ op: match[1]
322
+ };
323
+ } else if (match[2]) {
324
+
325
+ // The selector is in brackets.
326
+
327
+ selector = match[3] ? {
328
+ op: '[' + match[3],
329
+ name: match[2],
330
+ value: match[4]
331
+ } : {
332
+ op: '[',
333
+ name: match[2]
334
+ };
335
+ } else if (match[5]) {
336
+
337
+ // The selector is an id.
338
+
339
+ if (query.length > 0 || match[5].length <= id.length ||
340
+ match[5].slice(0, id.length) !== id) {
341
+ return error("ADsafe: Bad query: " + text);
342
+ }
343
+ selector = {
344
+ op: '#',
345
+ name: match[5]
346
+ };
347
+
348
+ // The selector is a colon.
349
+
350
+ } else if (match[6]) {
351
+ selector = {
352
+ op: ':' + match[6]
353
+ };
354
+
355
+ // The selector is one of > + . & _ or a naked tag name
356
+
357
+ } else {
358
+ selector = {
359
+ op: match[7],
360
+ name: match[8]
361
+ };
362
+ }
363
+
364
+ // Add the selector to the query.
365
+
366
+ query.push(selector);
367
+
368
+ // Remove the selector from the text. If there is more text, have another go.
369
+
370
+ text = text.slice(match[0].length);
371
+ } while (text);
372
+ return query;
373
+ }
374
+
375
+
376
+ hunter = {
377
+
378
+ // These functions implement the hunter behaviors.
379
+
380
+ '': function (node) {
381
+ var e = node.getElementsByTagName(name), i;
382
+ for (i = 0; i < 1000; i += 1) {
383
+ if (e[i]) {
384
+ result.push(e[i]);
385
+ } else {
386
+ break;
387
+ }
388
+ }
389
+ },
390
+ '+': function (node) {
391
+ node = node.nextSibling;
392
+ name = name.toUpperCase();
393
+ while (node && !node.tagName) {
394
+ node = node.nextSibling;
395
+ }
396
+ if (node && node.tagName === name) {
397
+ result.push(node);
398
+ }
399
+ },
400
+ '>': function (node) {
401
+ node = node.firstChild;
402
+ name = name.toUpperCase();
403
+ while (node) {
404
+ if (node.tagName === name) {
405
+ result.push(node);
406
+ }
407
+ node = node.nextSibling;
408
+ }
409
+ },
410
+ '#': function (node) {
411
+ var n = document.getElementById(name);
412
+ if (n.tagName) {
413
+ result.push(n);
414
+ }
415
+ },
416
+ '/': function (node) {
417
+ var e = node.childNodes, i;
418
+ for (i = 0; i < e.length; i += 1) {
419
+ result.push(e[i]);
420
+ }
421
+ },
422
+ '*': function (node) {
423
+ star = true;
424
+ walkTheDOM(node, function (node) {
425
+ result.push(node);
426
+ }, true);
427
+ }
428
+ };
429
+
430
+ pecker = {
431
+ '.': function (node) {
432
+ return (' ' + node.className + ' ').indexOf(' ' + name + ' ') >= 0;
433
+ },
434
+ '&': function (node) {
435
+ return node.name === name;
436
+ },
437
+ '_': function (node) {
438
+ return node.type === name;
439
+ },
440
+ '[': function (node) {
441
+ return typeof node[name] === 'string';
442
+ },
443
+ '[=': function (node) {
444
+ var member = node[name];
445
+ return typeof member === 'string' && member === value;
446
+ },
447
+ '[!=': function (node) {
448
+ var member = node[name];
449
+ return typeof member === 'string' && member !== value;
450
+ },
451
+ '[^=': function (node) {
452
+ var member = node[name];
453
+ return typeof member === 'string' &&
454
+ member.slice(0, member.length) === value;
455
+ },
456
+ '[$=': function (node) {
457
+ var member = node[name];
458
+ return typeof member === 'string' &&
459
+ member.slice(-member.length) === value;
460
+ },
461
+ '[*=': function (node) {
462
+ var member = node[name];
463
+ return typeof member === 'string' &&
464
+ member.slice.indexOf(value) >= 0;
465
+ },
466
+ '[~=': function (node) {
467
+ var member = node[name];
468
+ return typeof member === 'string' &&
469
+ (' ' + member + ' ').slice.indexOf(' ' + value + ' ') >= 0;
470
+ },
471
+ '[|=': function (node) {
472
+ var member = node[name];
473
+ return typeof member === 'string' &&
474
+ ('-' + member + '-').slice.indexOf('-' + value + '-') >= 0;
475
+ },
476
+ ':blur': function (node) {
477
+ return node !== has_focus;
478
+ },
479
+ ':checked': function (node) {
480
+ return node.checked;
481
+ },
482
+ ':disabled': function (node) {
483
+ return node.tagName && node.disabled;
484
+ },
485
+ ':enabled': function (node) {
486
+ return node.tagName && !node.disabled;
487
+ },
488
+ ':even': function (node) {
489
+ var f;
490
+ if (node.tagName) {
491
+ f = flipflop;
492
+ flipflop = !flipflop;
493
+ return f;
494
+ } else {
495
+ return false;
496
+ }
497
+ },
498
+ ':focus': function (node) {
499
+ return node === has_focus;
500
+ },
501
+ ':hidden': function (node) {
502
+ return node.tagName && getStyleObject(node).visibility !== 'visible';
503
+ },
504
+ ':odd': function (node) {
505
+ if (node.tagName) {
506
+ flipflop = !flipflop;
507
+ return flipflop;
508
+ } else {
509
+ return false;
510
+ }
511
+ },
512
+ ':tag': function (node) {
513
+ return node.tagName;
514
+ },
515
+ ':text': function (node) {
516
+ return node.nodeName === '#text';
517
+ },
518
+ ':trim': function (node) {
519
+ return node.nodeName !== '#text' || /\W/.test(node.nodeValue);
520
+ },
521
+ ':unchecked': function (node) {
522
+ return node.tagName && !node.checked;
523
+ },
524
+ ':visible': function (node) {
525
+ return node.tagName && getStyleObject(node).visibility === 'visible';
526
+ }
527
+ };
528
+
529
+
530
+ function quest(query, nodes) {
531
+ var selector, func, i, j;
532
+
533
+ // Step through each selector.
534
+
535
+ for (i = 0; i < query.length; i += 1) {
536
+ selector = query[i];
537
+ name = selector.name;
538
+ func = hunter[selector.op];
539
+
540
+ // There are two kinds of selectors: hunters and peckers. If this is a hunter,
541
+ // loop through the the nodes, passing each node to the hunter function.
542
+ // Accumulate all the nodes it finds.
543
+
544
+ if (typeof func === 'function') {
545
+ if (star) {
546
+ return error("ADsafe: Query violation: *" +
547
+ selector.op + (selector.name || ''));
548
+ }
549
+ result = [];
550
+ for (j = 0; j < nodes.length; j += 1) {
551
+ func(nodes[j]);
552
+ }
553
+ } else {
554
+
555
+ // If this is a pecker, get its function. There is a special case for
556
+ // the :first and :rest selectors because they are so simple.
557
+
558
+ value = selector.value;
559
+ flipflop = false;
560
+ func = pecker[selector.op];
561
+ if (typeof func !== 'function') {
562
+ switch (selector.op) {
563
+ case ':first':
564
+ result = nodes.slice(0, 1);
565
+ break;
566
+ case ':rest':
567
+ result = nodes.slice(1);
568
+ break;
569
+ default:
570
+ return error('ADsafe: Query violation: :' + selector.op);
571
+ }
572
+ } else {
573
+
574
+ // For the other selectors, make an array of nodes that are filtered by
575
+ // the pecker function.
576
+
577
+ result = [];
578
+ for (j = 0; j < nodes.length; j += 1) {
579
+ if (func(nodes[j])) {
580
+ result.push(nodes[j]);
581
+ }
582
+ }
583
+ }
584
+ }
585
+ nodes = result;
586
+ }
587
+ return result;
588
+ }
589
+
590
+
591
+ function make_root(root, id) {
592
+
593
+ if (id) {
594
+ if (root.tagName !== 'DIV') {
595
+ return error('ADsafe: Bad node.');
596
+ }
597
+ } else {
598
+ if (root.tagName !== 'BODY') {
599
+ return error('ADsafe: Bad node.');
600
+ }
601
+ }
602
+
603
+ // A Bunch is a container that holds zero or more dom nodes.
604
+ // It has many useful methods.
605
+
606
+ function Bunch(nodes) {
607
+ this.___nodes___ = nodes;
608
+ this.___star___ = star && nodes.length > 1;
609
+ star = false;
610
+ }
611
+
612
+ var allow_focus = true,
613
+ dom,
614
+ dom_event = function (e) {
615
+ var key,
616
+ target,
617
+ that,
618
+ the_event,
619
+ the_target,
620
+ the_actual_event = e || event,
621
+ type = the_actual_event.type;
622
+
623
+ // Get the target node and wrap it in a bunch.
624
+
625
+ the_target = the_actual_event.target ||
626
+ the_actual_event.srcElement;
627
+ target = new Bunch([the_target]);
628
+ that = target;
629
+
630
+ // Use the PPK hack to make focus bubbly on IE.
631
+ // When a widget has focus, it can use the focus method.
632
+
633
+ switch (type) {
634
+ case 'mousedown':
635
+ allow_focus = true;
636
+ if (document.selection) {
637
+ the_range = document.selection.createRange();
638
+ }
639
+ break;
640
+ case 'focus':
641
+ case 'focusin':
642
+ allow_focus = true;
643
+ has_focus = the_target;
644
+ the_actual_event.cancelBubble = false;
645
+ type = 'focus';
646
+ break;
647
+ case 'blur':
648
+ case 'focusout':
649
+ allow_focus = false;
650
+ has_focus = null;
651
+ type = 'blur';
652
+ break;
653
+ case 'keypress':
654
+ allow_focus = true;
655
+ has_focus = the_target;
656
+ key = String.fromCharCode(the_actual_event.charCode ||
657
+ the_actual_event.keyCode);
658
+ switch (key) {
659
+ case '\u000d':
660
+ case '\u000a':
661
+ type = 'enterkey';
662
+ break;
663
+ case '\u001b':
664
+ type = 'escapekey';
665
+ break;
666
+ }
667
+ break;
668
+
669
+ // This is a workaround for Safari.
670
+
671
+ case 'click':
672
+ allow_focus = true;
673
+ }
674
+ if (the_actual_event.cancelBubble &&
675
+ the_actual_event.stopPropagation) {
676
+ the_actual_event.stopPropagation();
677
+ }
678
+
679
+ // Make the event object.
680
+
681
+ the_event = {
682
+ altKey: the_actual_event.altKey,
683
+ ctrlKey: the_actual_event.ctrlKey,
684
+ bubble: function () {
685
+
686
+ // Bubble up. Get the parent of that node. It becomes the new that.
687
+ // getParent throws when bubbling is not possible.
688
+
689
+ try {
690
+ var parent = that.getParent(),
691
+ b = parent.___nodes___[0];
692
+ that = parent;
693
+ the_event.that = that;
694
+
695
+ // If that node has an event handler, fire it. Otherwise, bubble up.
696
+
697
+ if (b['___ on ___'] &&
698
+ b['___ on ___'][type]) {
699
+ that.fire(the_event);
700
+ } else {
701
+ the_event.bubble();
702
+ }
703
+ } catch (e) {
704
+ return error(e);
705
+ }
706
+ },
707
+ key: key,
708
+ preventDefault: function () {
709
+ if (the_actual_event.preventDefault) {
710
+ the_actual_event.preventDefault();
711
+ }
712
+ the_actual_event.returnValue = false;
713
+ },
714
+ shiftKey: the_actual_event.shiftKey,
715
+ target: target,
716
+ that: that,
717
+ type: type,
718
+ x: the_actual_event.clientX,
719
+ y: the_actual_event.clientY
720
+ };
721
+
722
+ // If the target has event handlers, then fire them. Otherwise, bubble up.
723
+
724
+ if (the_target['___ on ___'] &&
725
+ the_target['___ on ___'][the_event.type]) {
726
+ target.fire(the_event);
727
+ } else {
728
+ for (;;) {
729
+ the_target = the_target.parentNode;
730
+ if (!the_target) {
731
+ break;
732
+ }
733
+ if (the_target['___ on ___'] &&
734
+ the_target['___ on ___'][the_event.type]) {
735
+ that = new Bunch([the_target]);
736
+ the_event.that = that;
737
+ that.fire(the_event);
738
+ break;
739
+ }
740
+ if (the_target['___adsafe root___']) {
741
+ break;
742
+ }
743
+ }
744
+ }
745
+ if (the_event.type === 'escapekey') {
746
+ if (ephemeral) {
747
+ ephemeral.remove();
748
+ }
749
+ ephemeral = null;
750
+ }
751
+ that = the_target = the_event = the_actual_event = null;
752
+ return;
753
+ };
754
+
755
+ // Mark the node as a root. This prevents event bubbling from propogating
756
+ // past it.
757
+
758
+ root['___adsafe root___'] = '___adsafe root___';
759
+
760
+ Bunch.prototype = {
761
+ append: function (appendage) {
762
+ if (this === this.window) {
763
+ return error();
764
+ }
765
+ var b = this.___nodes___,
766
+ flag = false,
767
+ i,
768
+ j,
769
+ node,
770
+ rep;
771
+ if (b.length === 0 || !appendage) {
772
+ return this;
773
+ }
774
+ if (appendage instanceof Array) {
775
+ if (appendage.length !== b.length) {
776
+ return error('ADsafe: Array length: ' +
777
+ b.length + '-' + value.length);
778
+ }
779
+ for (i = 0; i < b.length; i += 1) {
780
+ rep = appendage[i].___nodes___;
781
+ for (j = 0; j < rep.length; j += 1) {
782
+ b[i].appendChild(rep[j]);
783
+ }
784
+ }
785
+ } else {
786
+ rep = appendage.___nodes___;
787
+ for (i = 0; i < b.length; i += 1) {
788
+ node = b[i];
789
+ for (j = 0; j < rep.length; j += 1) {
790
+ node.appendChild(flag ?
791
+ rep[j].cloneNode(true) : rep[j]);
792
+ }
793
+ flag = true;
794
+ }
795
+ }
796
+ return this;
797
+ },
798
+ blur: function () {
799
+ if (this === this.window) {
800
+ return error('ADsafe error.');
801
+ }
802
+ var b = this.___nodes___, i, node;
803
+ has_focus = null;
804
+ for (i = 0; i < b.length; i += 1) {
805
+ node = b[i];
806
+ if (node.blur) {
807
+ node.blur();
808
+ }
809
+ }
810
+ return this;
811
+ },
812
+ check: function (value) {
813
+ if (this === this.window) {
814
+ return error();
815
+ }
816
+ var b = this.___nodes___, i, node;
817
+ if (value instanceof Array) {
818
+ if (value.length !== b.length) {
819
+ return error('ADsafe: Array length: ' +
820
+ b.length + '-' + value.length);
821
+ }
822
+ for (i = 0; i < b.length; i += 1) {
823
+ node = b[i];
824
+ if (node.tagName) {
825
+ node.checked = !!value[i];
826
+ }
827
+ }
828
+ } else {
829
+ for (i = 0; i < b.length; i += 1) {
830
+ node = b[i];
831
+ if (node.tagName) {
832
+ node.checked = !!value;
833
+ }
834
+ }
835
+ }
836
+ return this;
837
+ },
838
+ count: function () {
839
+ return this.___nodes___.length;
840
+ },
841
+ each: function (func) {
842
+ var b = this.___nodes___, i;
843
+ if (this !== this.window && typeof func === 'function') {
844
+ for (i = 0; i < b.length; i += 1) {
845
+ func(new Bunch([b[i]]));
846
+ }
847
+ return this;
848
+ }
849
+ return error();
850
+ },
851
+ empty: function () {
852
+ if (this === this.window) {
853
+ return error('ADsafe error.');
854
+ }
855
+ var b = this.___nodes___, i, node;
856
+ if (value instanceof Array) {
857
+ if (value.length !== b.length) {
858
+ return error('ADsafe: Array length: ' +
859
+ b.length + '-' + value.length);
860
+ }
861
+ for (i = 0; i < b.length; i += 1) {
862
+ node = b[i];
863
+ while (node.firstChild) {
864
+ purge_event_handlers(node);
865
+ node.removeChild(node.firstChild);
866
+ }
867
+ }
868
+ } else {
869
+ for (i = 0; i < b.length; i += 1) {
870
+ node = b[i];
871
+ while (node.firstChild) {
872
+ purge_event_handlers(node);
873
+ node.removeChild(node.firstChild);
874
+ }
875
+ }
876
+ }
877
+ return this;
878
+ },
879
+ enable: function (enable) {
880
+ if (this === this.window) {
881
+ return error('ADsafe error.');
882
+ }
883
+ var b = this.___nodes___, i, node;
884
+ if (enable instanceof Array) {
885
+ if (enable.length !== b.length) {
886
+ return error('ADsafe: Array length: ' +
887
+ b.length + '-' + enable.length);
888
+ }
889
+ for (i = 0; i < b.length; i += 1) {
890
+ node = b[i];
891
+ if (node.tagName) {
892
+ node.disabled = !enable[i];
893
+ }
894
+ }
895
+ } else {
896
+ for (i = 0; i < b.length; i += 1) {
897
+ node = b[i];
898
+ if (node.tagName) {
899
+ node.disabled = !enable;
900
+ }
901
+ }
902
+ }
903
+ return this;
904
+ },
905
+ ephemeral: function () {
906
+ if (this === this.window) {
907
+ return error('ADsafe error.');
908
+ }
909
+ if (ephemeral) {
910
+ ephemeral.remove();
911
+ }
912
+ ephemeral = this;
913
+ return this;
914
+ },
915
+ explode: function () {
916
+ var a = [], b = this.___nodes___, i;
917
+ for (i = 0; i < b.length; i += 1) {
918
+ a[i] = new Bunch([b[i]]);
919
+ }
920
+ return a;
921
+ },
922
+ fire: function (event) {
923
+
924
+ // Fire an event on an object. The event can be either
925
+ // a string containing the name of the event, or an
926
+ // object containing a type property containing the
927
+ // name of the event. Handlers registered by the 'on'
928
+ // method that match the event name will be invoked.
929
+
930
+ var array,
931
+ b,
932
+ i,
933
+ j,
934
+ n,
935
+ node,
936
+ on,
937
+ type;
938
+
939
+ if (this === this.window) {
940
+ return error();
941
+ }
942
+ if (typeof event === 'string') {
943
+ type = event;
944
+ event = {type: type};
945
+ } else if (typeof event === 'object') {
946
+ type = event.type;
947
+ } else {
948
+ return error();
949
+ }
950
+ b = this.___nodes___;
951
+ n = b.length;
952
+ for (i = 0; i < n; i += 1) {
953
+ node = b[i];
954
+ on = node['___ on ___'];
955
+
956
+ // If an array of handlers exist for this event, then
957
+ // loop through it and execute the handlers in order.
958
+
959
+ if (on && on.hasOwnProperty(type)) {
960
+ array = on[type];
961
+ for (j = 0; j < array.length; j += 1) {
962
+
963
+ // Invoke a handler. Pass the event object.
964
+
965
+ array[j].call(this, event);
966
+ }
967
+ }
968
+ }
969
+ return this;
970
+ },
971
+ focus: function () {
972
+ var b = this.___nodes___;
973
+ if (this !== this.window) {
974
+ if (b.length === 1 && allow_focus) {
975
+ has_focus = b[0].focus();
976
+ return this;
977
+ }
978
+ }
979
+ return error();
980
+ },
981
+ fragment: function () {
982
+ return new Bunch([document.createDocumentFragment()]);
983
+ },
984
+ getCheck: function () {
985
+ var a = [], b = this.___nodes___, i;
986
+ for (i = 0; i < b.length; i += 1) {
987
+ a[i] = b[i].checked;
988
+ }
989
+ return a.length === 1 ? a[0] : a;
990
+ },
991
+ getClass: function () {
992
+ var a = [], b = this.___nodes___, i;
993
+ for (i = 0; i < b.length; i += 1) {
994
+ a[i] = b[i].className;
995
+ }
996
+ return a.length === 1 ? a[0] : a;
997
+ },
998
+ getMark: function () {
999
+ var a = [], b = this.___nodes___, i;
1000
+ for (i = 0; i < b.length; i += 1) {
1001
+ a[i] = b[i]['_adsafe mark_'];
1002
+ }
1003
+ return a.length === 1 ? a[0] : a;
1004
+ },
1005
+ getName: function () {
1006
+ var a = [], b = this.___nodes___, i;
1007
+ for (i = 0; i < b.length; i += 1) {
1008
+ a[i] = b[i].name;
1009
+ }
1010
+ return a.length === 1 ? a[0] : a;
1011
+ },
1012
+ getOffsetHeight: function () {
1013
+ var a = [], b = this.___nodes___, i;
1014
+ for (i = 0; i < b.length; i += 1) {
1015
+ a[i] = b[i].offsetHeight;
1016
+ }
1017
+ return a.length === 1 ? a[0] : a;
1018
+ },
1019
+ getOffsetWidth: function () {
1020
+ var a = [], b = this.___nodes___, i;
1021
+ for (i = 0; i < b.length; i += 1) {
1022
+ a[i] = b[i].offsetWidth;
1023
+ }
1024
+ return a.length === 1 ? a[0] : a;
1025
+ },
1026
+ getParent: function () {
1027
+ var a = [], b = this.___nodes___, i, n;
1028
+ for (i = 0; i < b.length; i += 1) {
1029
+ n = b[i].parentNode;
1030
+ if (n['___adsafe root___']) {
1031
+ return error('ADsafe parent violation.');
1032
+ }
1033
+ a[i] = n;
1034
+ }
1035
+ return new Bunch(a);
1036
+ },
1037
+ getSelection: function () {
1038
+ if (this === this.window) {
1039
+ return error();
1040
+ }
1041
+ var b = this.___nodes___, end, node, start, range;
1042
+ if (b.length === 1 && allow_focus) {
1043
+ node = b[0];
1044
+ if (typeof node.selectionStart === 'number') {
1045
+ start = node.selectionStart;
1046
+ end = node.selectionEnd;
1047
+ return node.value.slice(start, end);
1048
+ } else {
1049
+ range = node.createTextRange();
1050
+ range.expand('textedit');
1051
+ if (range.inRange(the_range)) {
1052
+ return the_range.text;
1053
+ }
1054
+ }
1055
+ }
1056
+ return null;
1057
+ },
1058
+ getStyle: function (name) {
1059
+ var a = [], b = this.___nodes___, i, node, s;
1060
+ for (i = 0; i < b.length; i += 1) {
1061
+ node = b[i];
1062
+ if (node.tagName) {
1063
+ s = name !== 'float' ? getStyleObject(node)[name] :
1064
+ getStyleObject(node).cssFloat ||
1065
+ getStyleObject(node).styleFloat;
1066
+ if (typeof s === 'string') {
1067
+ a[i] = s;
1068
+ }
1069
+ }
1070
+ }
1071
+ return a.length === 1 ? a[0] : a;
1072
+ },
1073
+ getTagName: function () {
1074
+ var a = [], b = this.___nodes___, i, name;
1075
+ for (i = 0; i < b.length; i += 1) {
1076
+ name = b[i].tagName;
1077
+ a[i] = typeof name === 'string' ? name.toLowerCase() : name;
1078
+ }
1079
+ return a.length === 1 ? a[0] : a;
1080
+ },
1081
+ getTitle: function () {
1082
+ var a = [], b = this.___nodes___, i;
1083
+ for (i = 0; i < b.length; i += 1) {
1084
+ a[i] = b[i].title;
1085
+ }
1086
+ return a.length === 1 ? a[0] : a;
1087
+ },
1088
+ getValue: function () {
1089
+ var a = [], b = this.___nodes___, i, node;
1090
+ for (i = 0; i < b.length; i += 1) {
1091
+ node = b[i];
1092
+ if (node.nodeName === '#text') {
1093
+ a[i] = node.nodeValue;
1094
+ } else if (node.tagName && node.type !== 'password') {
1095
+ a[i] = node.value;
1096
+ if (a[i] === undefined && node.firstChild &&
1097
+ node.firstChild.nodeName === '#text') {
1098
+ a[i] = node.firstChild.nodeValue;
1099
+ }
1100
+ }
1101
+ }
1102
+ return a.length === 1 ? a[0] : a;
1103
+ },
1104
+ klass: function (value) {
1105
+ if (this === this.window || /url/i.test(value)) {
1106
+ return error('ADsafe error.');
1107
+ }
1108
+ var b = this.___nodes___, i, node;
1109
+ if (value instanceof Array) {
1110
+ if (value.length !== b.length) {
1111
+ return error('ADsafe: Array length: ' +
1112
+ b.length + '-' + value.length);
1113
+ }
1114
+ for (i = 0; i < b.length; i += 1) {
1115
+ node = b[i];
1116
+ if (node.tagName) {
1117
+ node.className = String(value[i]);
1118
+ }
1119
+ }
1120
+ } else {
1121
+ for (i = 0; i < b.length; i += 1) {
1122
+ node = b[i];
1123
+ if (node.tagName) {
1124
+ node.className = String(value);
1125
+ }
1126
+ }
1127
+ }
1128
+ return this;
1129
+ },
1130
+ mark: function (value) {
1131
+ if (this === this.window || /url/i.test(value)) {
1132
+ return error('ADsafe error.');
1133
+ }
1134
+ var b = this.___nodes___, i, node;
1135
+ if (value instanceof Array) {
1136
+ if (value.length !== b.length) {
1137
+ return error('ADsafe: Array length: ' +
1138
+ b.length + '-' + value.length);
1139
+ }
1140
+ for (i = 0; i < b.length; i += 1) {
1141
+ node = b[i];
1142
+ if (node.tagName) {
1143
+ node['_adsafe mark_'] = value[i];
1144
+ }
1145
+ }
1146
+ } else {
1147
+ for (i = 0; i < b.length; i += 1) {
1148
+ node = b[i];
1149
+ if (node.tagName) {
1150
+ node['_adsafe mark_'] = value;
1151
+ }
1152
+ }
1153
+ }
1154
+ return this;
1155
+ },
1156
+ off: function (type) {
1157
+ if (this === this.window) {
1158
+ return error();
1159
+ }
1160
+ var b = this.___nodes___, i, node;
1161
+ for (i = 0; i < b.length; i += 1) {
1162
+ node = b[i];
1163
+ if (typeof type === 'string') {
1164
+ if (typeof node['___ on ___']) {
1165
+ node['___ on ___'][type] = null;
1166
+ }
1167
+ } else {
1168
+ node['___ on ___'] = null;
1169
+ }
1170
+ }
1171
+ return this;
1172
+ },
1173
+ on: function (type, func) {
1174
+ if (this === this.window || typeof type !== 'string' ||
1175
+ typeof func !== 'function') {
1176
+ return error();
1177
+ }
1178
+
1179
+ var b = this.___nodes___, i, node, on, ontype;
1180
+ for (i = 0; i < b.length; i += 1) {
1181
+ node = b[i];
1182
+
1183
+ // The change event does not propogate, so we must put the handler on the
1184
+ // instance.
1185
+
1186
+ if (type === 'change') {
1187
+ ontype = 'on' + type;
1188
+ if (node[ontype] !== dom_event) {
1189
+ node[ontype] = dom_event;
1190
+ }
1191
+ }
1192
+
1193
+ // Register an event. Put the function in a handler array, making one if it
1194
+ // doesn't yet exist for this type on this node.
1195
+
1196
+ on = node['___ on ___'];
1197
+ if (!on) {
1198
+ on = {};
1199
+ node['___ on ___'] = on;
1200
+ }
1201
+ if (on.hasOwnProperty(type)) {
1202
+ on[type].push(func);
1203
+ } else {
1204
+ on[type] = [func];
1205
+ }
1206
+ }
1207
+ return this;
1208
+ },
1209
+ protect: function () {
1210
+ if (this === this.window) {
1211
+ return error('ADsafe error.');
1212
+ }
1213
+ var b = this.___nodes___, i;
1214
+ for (i = 0; i < b.length; i += 1) {
1215
+ b[i]['___adsafe root___'] = '___adsafe root___';
1216
+ }
1217
+ return this;
1218
+ },
1219
+ q: function (text) {
1220
+ star = this.___star___;
1221
+ return new Bunch(quest(parse_query(text, id), this.___nodes___));
1222
+ },
1223
+ remove: function () {
1224
+ this.replace();
1225
+ },
1226
+ replace: function (replacement) {
1227
+ if (this === this.window) {
1228
+ return error();
1229
+ }
1230
+ var b = this.___nodes___,
1231
+ flag = false,
1232
+ i,
1233
+ j,
1234
+ newnode,
1235
+ node,
1236
+ parent,
1237
+ rep;
1238
+ if (b.length === 0) {
1239
+ return;
1240
+ }
1241
+ purge_event_handlers(b);
1242
+ if (!replacement ||
1243
+ replacement.length === 0 ||
1244
+ replacement.___nodes___.length === 0) {
1245
+ for (i = 0; i < b.length; i += 1) {
1246
+ node = b[i];
1247
+ purge_event_handlers(node);
1248
+ if (node.parentNode) {
1249
+ node.parentNode.removeChild(node);
1250
+ }
1251
+ }
1252
+ } else if (replacement instanceof Array) {
1253
+ if (replacement.length !== b.length) {
1254
+ return error('ADsafe: Array length: ' +
1255
+ b.length + '-' + value.length);
1256
+ }
1257
+ for (i = 0; i < b.length; i += 1) {
1258
+ node = b[i];
1259
+ parent = node.parentNode;
1260
+ purge_event_handlers(node);
1261
+ if (parent) {
1262
+ rep = replacement[i].___nodes___;
1263
+ if (rep.length > 0) {
1264
+ newnode = rep[0];
1265
+ parent.replaceNode(newnode);
1266
+ for (j = 1; j < rep.length; j += 1) {
1267
+ node = newnode;
1268
+ newnode = rep[j];
1269
+ parent.insertBefore(newnode, node.nextSibling);
1270
+ }
1271
+ } else {
1272
+ parent.removeChild(node);
1273
+ }
1274
+ }
1275
+ }
1276
+ } else {
1277
+ rep = replacement.___nodes___;
1278
+ for (i = 0; i < b.length; i += 1) {
1279
+ node = b[i];
1280
+ purge_event_handlers(node);
1281
+ if (node.parentNode) {
1282
+ newnode = flag ? rep[0].cloneNode(true) : rep[0];
1283
+ parent.replaceNode(newnode);
1284
+ for (j = 1; j < rep.length; j += 1) {
1285
+ node = newnode;
1286
+ newnode = flag ? rep[j].clone(true) : rep[j];
1287
+ parent.insertBefore(newnode, node.nextSibling);
1288
+ }
1289
+ flag = true;
1290
+ }
1291
+ }
1292
+ }
1293
+ return this;
1294
+ },
1295
+ select: function () {
1296
+ if (this === this.window) {
1297
+ return error();
1298
+ }
1299
+ var b = this.___nodes___;
1300
+ if (b.length !== 1 || !allow_focus) {
1301
+ return error();
1302
+ }
1303
+ b[0].focus();
1304
+ b[0].select();
1305
+ return this;
1306
+ },
1307
+ selection: function (string) {
1308
+ if (this === this.window) {
1309
+ return error();
1310
+ }
1311
+ var b = this.___nodes___, end, node, old, start, range;
1312
+ if (b.length === 1 && allow_focus) {
1313
+ node = b[0];
1314
+ if (typeof node.selectionStart === 'number') {
1315
+ start = node.selectionStart;
1316
+ end = node.selectionEnd;
1317
+ old = node.value;
1318
+ node.value = old.slice(0, start) + string + old.slice(end);
1319
+ node.selectionStart = node.selectionEnd = start +
1320
+ string.length;
1321
+ node.focus();
1322
+ } else {
1323
+ range = node.createTextRange();
1324
+ range.expand('textedit');
1325
+ if (range.inRange(the_range)) {
1326
+ the_range.select();
1327
+ the_range.text = string;
1328
+ the_range.select();
1329
+ }
1330
+ }
1331
+ }
1332
+ return this;
1333
+ },
1334
+ style: function (name, value) {
1335
+ if (this === this.window ||
1336
+ value === undefined || /url/i.test(value)) {
1337
+ return error();
1338
+ }
1339
+ var b = this.___nodes___,
1340
+ i,
1341
+ node,
1342
+ v;
1343
+ if (value instanceof Array) {
1344
+ if (value.length !== b.length) {
1345
+ return error('ADsafe: Array length: ' +
1346
+ b.length + '-' + value.length);
1347
+ }
1348
+ for (i = 0; i < b.length; i += 1) {
1349
+ node = b[i];
1350
+ v = String(value[i]);
1351
+ if (node.tagName) {
1352
+ if (name !== 'float') {
1353
+ node.style[name] = v;
1354
+ } else {
1355
+ node.style.cssFloat = node.style.styleFloat = v;
1356
+ }
1357
+ }
1358
+ }
1359
+ } else {
1360
+ v = String(value);
1361
+ for (i = 0; i < b.length; i += 1) {
1362
+ node = b[i];
1363
+ if (node.tagName) {
1364
+ if (name !== 'float') {
1365
+ node.style[name] = v;
1366
+ } else {
1367
+ node.style.cssFloat = node.style.styleFloat = v;
1368
+ }
1369
+ }
1370
+ }
1371
+ }
1372
+ return this;
1373
+ },
1374
+ tag: function (tag, type, name) {
1375
+ var node;
1376
+ if (typeof tag !== 'string') {
1377
+ return error();
1378
+ }
1379
+ if (makeableTagName[tag] !== true) {
1380
+ return error('ADsafe: Bad tag: ' + tag);
1381
+ }
1382
+ node = document.createElement(tag);
1383
+ if (name) {
1384
+ node.autocomplete = 'off';
1385
+ node.name = name;
1386
+ }
1387
+ if (type) {
1388
+ node.type = type;
1389
+ }
1390
+ return new Bunch([node]);
1391
+ },
1392
+ text: function (text) {
1393
+ var a, i;
1394
+ if (text instanceof Array) {
1395
+ a = [];
1396
+ for (i = 0; i < text.length; i += 1) {
1397
+ a[i] = document.createTextNode(String(text[i]));
1398
+ }
1399
+ return new Bunch(a);
1400
+ }
1401
+ return new Bunch([document.createTextNode(String(text))]);
1402
+ },
1403
+ title: function (value) {
1404
+ if (this === this.window) {
1405
+ return error('ADsafe error.');
1406
+ }
1407
+ var b = this.___nodes___, i, node;
1408
+ if (value instanceof Array) {
1409
+ if (value.length !== b.length) {
1410
+ return error('ADsafe: Array length: ' + b.length +
1411
+ '-' + value.length);
1412
+ }
1413
+ for (i = 0; i < b.length; i += 1) {
1414
+ node = b[i];
1415
+ if (node.tagName) {
1416
+ node.title = String(value[i]);
1417
+ }
1418
+ }
1419
+ } else {
1420
+ for (i = 0; i < b.length; i += 1) {
1421
+ node = b[i];
1422
+ if (node.tagName) {
1423
+ node.title = String(value);
1424
+ }
1425
+ }
1426
+ }
1427
+ return this;
1428
+ },
1429
+ value: function (value) {
1430
+ if (this === this.window || value === undefined) {
1431
+ return error();
1432
+ }
1433
+ var b = this.___nodes___, i, node;
1434
+ if (value instanceof Array && b.length === value.length) {
1435
+ for (i = 0; i < b.length; i += 1) {
1436
+ node = b[i];
1437
+ if (node.tagName) {
1438
+ if (node.type !== 'password') {
1439
+ if (typeof node.value === 'string') {
1440
+ node.value = value[i];
1441
+ } else {
1442
+ while (node.firstChild) {
1443
+ purge_event_handlers(node);
1444
+ node.removeChild(node.firstChild);
1445
+ }
1446
+ node.appendChild(document.createTextNode(
1447
+ String(value[i])));
1448
+ }
1449
+ }
1450
+ } else if (node.nodeName === '#text') {
1451
+ node.nodeValue = String(value[i]);
1452
+ }
1453
+ }
1454
+ } else {
1455
+ for (i = 0; i < b.length; i += 1) {
1456
+ node = b[i];
1457
+ if (node.tagName) {
1458
+ if (typeof node.value === 'string') {
1459
+ node.value = value;
1460
+ } else {
1461
+ while (node.firstChild) {
1462
+ purge_event_handlers(node);
1463
+ node.removeChild(node.firstChild);
1464
+ }
1465
+ node.appendChild(document.createTextNode(
1466
+ String(value)));
1467
+ }
1468
+ } else if (node.nodeName === '#text') {
1469
+ node.nodeValue = String(value);
1470
+ }
1471
+ }
1472
+ }
1473
+ return this;
1474
+ }
1475
+ };
1476
+
1477
+ // Return an ADsafe dom object.
1478
+
1479
+ dom = {
1480
+ append: function (bunch) {
1481
+ var b = bunch.___nodes___, i, n;
1482
+ for (i = 0; i < b.length; i += 1) {
1483
+ n = b[i];
1484
+ if (typeof n === 'string' || typeof n === 'number') {
1485
+ n = document.createTextNode(String(n));
1486
+ }
1487
+ root.appendChild(n);
1488
+ }
1489
+ return dom;
1490
+ },
1491
+ combine: function (array) {
1492
+ if (!array || !array.length) {
1493
+ return error('ADsafe: Bad combination.');
1494
+ }
1495
+ var b = array[0].___nodes___, i;
1496
+ for (i = i; i < array.length; i += 1) {
1497
+ b = b.concat(array[i].___nodes___);
1498
+ }
1499
+ return new Bunch(b);
1500
+ },
1501
+ count: function () {
1502
+ return 1;
1503
+ },
1504
+ ephemeral: function (bunch) {
1505
+ if (ephemeral) {
1506
+ ephemeral.remove();
1507
+ }
1508
+ ephemeral = bunch;
1509
+ return dom;
1510
+ },
1511
+ fragment: function () {
1512
+ return new Bunch([document.createDocumentFragment()]);
1513
+ },
1514
+ prepend: function (bunch) {
1515
+ var b = bunch.___nodes___, i;
1516
+ for (i = 0; i < b.length; i += 1) {
1517
+ root.insertBefore(b[i], root.firstChild);
1518
+ }
1519
+ return dom;
1520
+ },
1521
+ q: function (text) {
1522
+ star = false;
1523
+ var query = parse_query(text, id);
1524
+ if (typeof hunter[query[0].op] !== 'function') {
1525
+ return error('ADsafe: Bad query: ' + query[0]);
1526
+ }
1527
+ return new Bunch(quest(query, [root]));
1528
+ },
1529
+ remove: function () {
1530
+ purge_event_handlers(root);
1531
+ root.parent.removeElement(root);
1532
+ root = null;
1533
+ },
1534
+ row: function (values) {
1535
+ var tr = document.createElement('tr'),
1536
+ td,
1537
+ i;
1538
+ for (i = 0; i < values.length; i += 1) {
1539
+ td = document.createElement('td');
1540
+ td.appendChild(document.createTextNode(String(values[i])));
1541
+ tr.appendChild(td);
1542
+ }
1543
+ return new Bunch([tr]);
1544
+ },
1545
+ tag: function (tag, type, name) {
1546
+ var node;
1547
+ if (typeof tag !== 'string') {
1548
+ return error();
1549
+ }
1550
+ if (makeableTagName[tag] !== true) {
1551
+ return error('ADsafe: Bad tag: ' + tag);
1552
+ }
1553
+ node = document.createElement(tag);
1554
+ if (name) {
1555
+ node.autocomplete = 'off';
1556
+ node.name = name;
1557
+ }
1558
+ if (type) {
1559
+ node.type = type;
1560
+ }
1561
+ return new Bunch([node]);
1562
+ },
1563
+ text: function (text) {
1564
+ var a, i;
1565
+ if (text instanceof Array) {
1566
+ a = [];
1567
+ for (i = 0; i < text.length; i += 1) {
1568
+ a[i] = document.createTextNode(String(text[i]));
1569
+ }
1570
+ return new Bunch(a);
1571
+ }
1572
+ return new Bunch([document.createTextNode(String(text))]);
1573
+ }
1574
+ };
1575
+
1576
+ if (typeof root.addEventListener === 'function') {
1577
+ root.addEventListener('focus', dom_event, true);
1578
+ root.addEventListener('blur', dom_event, true);
1579
+ root.addEventListener('mouseover', dom_event, true);
1580
+ root.addEventListener('mouseout', dom_event, true);
1581
+ root.addEventListener('mouseup', dom_event, true);
1582
+ root.addEventListener('mousedown', dom_event, true);
1583
+ root.addEventListener('mousemove', dom_event, true);
1584
+ root.addEventListener('click', dom_event, true);
1585
+ root.addEventListener('dblclick', dom_event, true);
1586
+ root.addEventListener('keypress', dom_event, true);
1587
+ } else {
1588
+ root.onfocusin = root.onfocusout = root.onmouseover =
1589
+ root.onmouseout = root.onmouseup =
1590
+ root.onmousedown = root.onmousemove =
1591
+ root.onclick = root.ondblclick =
1592
+ root.onkeypress = dom_event;
1593
+ }
1594
+ return [dom, Bunch.prototype];
1595
+ }
1596
+
1597
+
1598
+ function F() {}
1599
+
1600
+
1601
+ // Return the ADSAFE object.
1602
+
1603
+ return {
1604
+
1605
+ create: typeof Object.create === 'function' ? Object.create : function (o) {
1606
+ F.prototype = typeof o === 'object' && o ? o : Object.prototype;
1607
+ return new F();
1608
+ },
1609
+
1610
+ // ADSAFE.get retrieves a value from an object.
1611
+
1612
+ get: function (object, name) {
1613
+ if (arguments.length === 2 && !reject(object, name)) {
1614
+ return object[name];
1615
+ }
1616
+ return error();
1617
+ },
1618
+
1619
+ // ADSAFE.go allows a guest widget to get access to a wrapped dom node and
1620
+ // approved ADsafe libraries. It is passed an id and a function. The function
1621
+ // will be passed the wrapped dom node and an object containing the libraries.
1622
+
1623
+ go: function (id, f) {
1624
+ var dom, fun, root, i, scripts;
1625
+
1626
+ // If ADSAFE.id was called, the id better match.
1627
+
1628
+ if (adsafe_id && adsafe_id !== id) {
1629
+ return error();
1630
+ }
1631
+
1632
+ // Get the dom node for the widget's div container.
1633
+
1634
+ root = document.getElementById(id);
1635
+ if (root.tagName !== 'DIV') {
1636
+ return error();
1637
+ }
1638
+ adsafe_id = null;
1639
+
1640
+ // Delete the scripts held in the div. They have all run, so we don't need
1641
+ // them any more. If the div had no scripts, then something is wrong.
1642
+ // This provides some protection against mishaps due to weakness in the
1643
+ // document.getElementById function.
1644
+
1645
+ scripts = root.getElementsByTagName('script');
1646
+ i = scripts.length - 1;
1647
+ if (i < 0) {
1648
+ return error();
1649
+ }
1650
+ do {
1651
+ root.removeChild(scripts[i]);
1652
+ i -= 1;
1653
+ } while (i >= 0);
1654
+ root = make_root(root, id);
1655
+ dom = root[0];
1656
+
1657
+
1658
+ // If the page has registered interceptors, call then.
1659
+
1660
+ for (i = 0; i < interceptors.length; i += 1) {
1661
+ fun = interceptors[i];
1662
+ if (typeof fun === 'function') {
1663
+ try {
1664
+ fun(id, dom, adsafe_lib, root[1]);
1665
+ } catch (e1) {
1666
+ ADSAFE.log(e1);
1667
+ }
1668
+ }
1669
+ }
1670
+
1671
+ // Call the supplied function.
1672
+
1673
+ try {
1674
+ f(dom, adsafe_lib);
1675
+ } catch (e2) {
1676
+ ADSAFE.log(e2);
1677
+ }
1678
+ root = null;
1679
+ adsafe_lib = null;
1680
+ },
1681
+
1682
+ // ADSAFE.id allows a guest widget to indicate that it wants to load
1683
+ // ADsafe approved libraries.
1684
+
1685
+ id: function (id) {
1686
+
1687
+ // Calls to ADSAFE.id must be balanced with calls to ADSAFE.go.
1688
+ // Only one id can be active at a time.
1689
+
1690
+ if (adsafe_id) {
1691
+ return error();
1692
+ }
1693
+ adsafe_id = id;
1694
+ adsafe_lib = {};
1695
+ },
1696
+
1697
+ // ADSAFE.isArray returns true if the operand is an array.
1698
+
1699
+ isArray: Array.isArray || function (value) {
1700
+ return Object.prototype.toString.apply(value) === '[object Array]';
1701
+ },
1702
+
1703
+
1704
+ // ADSAFE.later calls a function at a later time.
1705
+
1706
+ later: function (func, timeout) {
1707
+ if (typeof func === 'function') {
1708
+ setTimeout(func, timeout || 0);
1709
+ } else {
1710
+ return error();
1711
+ }
1712
+ },
1713
+
1714
+
1715
+ // ADSAFE.lib allows an approved ADsafe library to make itself available
1716
+ // to a widget. The library provides a name and a function. The result of
1717
+ // calling that function will be made available to the widget via the name.
1718
+
1719
+ lib: function (name, f) {
1720
+ if (!adsafe_id) {
1721
+ return error();
1722
+ }
1723
+ adsafe_lib[name] = f(adsafe_lib);
1724
+ },
1725
+
1726
+
1727
+ // ADSAFE.log is a debugging aid that spams text to the browser's log.
1728
+
1729
+ log: function log(s) {
1730
+ if (window.console) {
1731
+ console.log(s); /* Firebug */
1732
+ } else if (typeof Debug === 'object') {
1733
+ Debug.writeln(s); /* IE */
1734
+ } else if (typeof opera === 'opera') {
1735
+ opera.postError(s); /* Opera */
1736
+ }
1737
+ },
1738
+
1739
+
1740
+ // ADSAFE.remove deletes a value from an object.
1741
+
1742
+ remove: function (object, name) {
1743
+ if (arguments.length === 2 && !reject(object, name)) {
1744
+ delete object[name];
1745
+ return;
1746
+ }
1747
+ return error();
1748
+ },
1749
+
1750
+
1751
+ // ADSAFE.set stores a value in an object.
1752
+
1753
+ set: function (object, name, value) {
1754
+ if (arguments.length === 3 && !reject(object, name)) {
1755
+ object[name] = value;
1756
+ return;
1757
+ }
1758
+ return error();
1759
+ },
1760
+
1761
+ // ADSAFE._intercept allows the page to register a function that will
1762
+ // see the widget's capabilities.
1763
+
1764
+ _intercept: function (f) {
1765
+ interceptors.push(f);
1766
+ }
1767
+
1768
+ };
1769
+ }());