webr 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/README.md +4 -0
  2. data/Rakefile +19 -0
  3. data/app/webr.rb +57 -0
  4. data/bin/webr +6 -0
  5. data/ext/jasmine/lib/jasmine.js +2423 -0
  6. data/ext/jsdom/lib/jsdom.js +70 -0
  7. data/ext/jsdom/lib/jsdom/browser/domtohtml.js +198 -0
  8. data/ext/jsdom/lib/jsdom/browser/htmlencoding.js +381 -0
  9. data/ext/jsdom/lib/jsdom/browser/htmltodom.js +151 -0
  10. data/ext/jsdom/lib/jsdom/browser/index.js +484 -0
  11. data/ext/jsdom/lib/jsdom/level1/core.js +1610 -0
  12. data/ext/jsdom/lib/jsdom/level2/core.js +406 -0
  13. data/ext/jsdom/lib/jsdom/level2/events.js +358 -0
  14. data/ext/jsdom/lib/jsdom/level2/html.js +1424 -0
  15. data/ext/jsdom/lib/jsdom/level2/index.js +7 -0
  16. data/ext/jsdom/lib/jsdom/level2/languages/javascript.js +17 -0
  17. data/ext/jsdom/lib/jsdom/level3/core.js +514 -0
  18. data/ext/jsdom/lib/jsdom/level3/events.js +296 -0
  19. data/ext/jsdom/lib/jsdom/level3/html.js +5 -0
  20. data/ext/jsdom/lib/jsdom/level3/index.js +7 -0
  21. data/ext/node-htmlparser/lib/node-htmlparser.js +769 -0
  22. data/ext/node-htmlparser/lib/node-htmlparser.min.js +22 -0
  23. data/ext/request/request.js +116 -0
  24. data/js/jasmine-start.js +10 -0
  25. data/js/webr.js +97 -0
  26. data/jspec/jasmine_spec.js +23 -0
  27. data/lib/webr.rb +17 -0
  28. data/lib/webr/browser.rb +44 -0
  29. data/lib/webr/jasmine.rb +6 -0
  30. data/lib/webr/jasmine/browser.rb +15 -0
  31. data/lib/webr/jasmine/reporter.rb +16 -0
  32. data/lib/webr/jasmine/reporter/base.rb +40 -0
  33. data/lib/webr/jasmine/reporter/console.rb +79 -0
  34. data/lib/webr/jasmine/reporter/html.rb +179 -0
  35. data/lib/webr/portal.rb +19 -0
  36. data/lib/webr/runtime.rb +23 -0
  37. data/lib/webr/version.rb +3 -0
  38. data/spec/data/plain.html +13 -0
  39. data/spec/data/script-embedded.html +17 -0
  40. data/spec/data/script-external-onload.html +11 -0
  41. data/spec/data/script-external-onload.js +11 -0
  42. data/spec/data/script-external.html +11 -0
  43. data/spec/data/script-external.js +1 -0
  44. data/spec/data/script-jquery-1.4.2.html +12 -0
  45. data/spec/data/script-jquery-1.4.3.html +12 -0
  46. data/spec/data/script-jquery.js +3 -0
  47. data/spec/lib/webr/browser_spec.rb +133 -0
  48. data/spec/lib/webr/jasmine/browser_spec.rb +22 -0
  49. data/spec/lib/webr/jasmine/reporter/html_spec.rb +15 -0
  50. data/spec/spec_helper.rb +4 -0
  51. data/tasks/spec.rake +16 -0
  52. data/webr.gemspec +30 -0
  53. metadata +207 -0
@@ -0,0 +1,406 @@
1
+ var core = require("../level1/core").dom.level1.core,
2
+ sys = require("sys");
3
+
4
+ var testNamespaceName = function(ns, nsuri) {
5
+ if (!ns) {
6
+ throw new core.DOMException(core.INVALID_CHARACTER_ERR, "namespace is undefined");
7
+ }
8
+ if(ns.match(/[^0-9a-z\.:\-_]/i) !== null) {
9
+ throw new core.DOMException(core.INVALID_CHARACTER_ERR, ns);
10
+ }
11
+ if ((ns === 'xmlns' && nsuri !== "http://www.w3.org/2000/xmlns/") ||
12
+ (ns === "xml" && nsuri !== "http://www.w3.org/XML/1998/namespace") ||
13
+ ns.indexOf('::') > -1 ||
14
+ nsuri === null ||
15
+ ns[ns.length-1] === ':' || // handle "namespace:"
16
+ ns[0] === ':' ||
17
+ ns.match(/.+:.+:/))
18
+ {
19
+ throw new core.DOMException(core.NAMESPACE_ERR);
20
+ }
21
+ }
22
+
23
+ var INVALID_STATE_ERR = core.INVALID_STATE_ERR = 11;
24
+ var SYNTAX_ERR = core.SYNTAX_ERR = 12
25
+ var INVALID_MODIFICATION_ERR = core.INVALID_MODIFICATION_ERR = 13;
26
+ var NAMESPACE_ERR = core.NAMESPACE_ERR = 14;
27
+ var INVALID_ACCESS_ERR = core.INVALID_ACCESS_ERR = 15;
28
+
29
+ core.DOMImplementation.prototype.createDocumentType = function(/* String */ qualifiedName,
30
+ /* String */ publicId,
31
+ /* String */ systemId)
32
+ {
33
+ testNamespaceName(qualifiedName);
34
+ var doctype = new core.DocumentType(null, qualifiedName);
35
+ doctype._publicId = publicId ? publicId : '';
36
+ doctype._systemId = systemId ? systemId : '';
37
+ return doctype;
38
+ };
39
+
40
+ /**
41
+ Creates an XML Document object of the specified type with its document element.
42
+ HTML-only DOM implementations do not need to implement this method.
43
+ */
44
+ core.DOMImplementation.prototype.createDocument = function(/* String */ namespaceURI,
45
+ /* String */ qualifiedName,
46
+ /* DocumentType */ doctype)
47
+ {
48
+ testNamespaceName(qualifiedName, namespaceURI);
49
+
50
+ if (doctype && doctype.ownerDocuemnt !== null) {
51
+ throw new core.DOMException(core.WRONG_DOCUMENT_ERR);
52
+ }
53
+
54
+ var document = new core.Document();
55
+ document.namespaceURI = namespaceURI;
56
+ document.qualifiedName = qualifiedName;
57
+ document.doctype = doctype;
58
+ document._ownerDocument = document;
59
+ return document;
60
+ };
61
+
62
+ core.Node.prototype.__defineGetter__("ownerDocument", function() {
63
+ return this._ownerDocument || null;
64
+ });
65
+
66
+ core.Node.prototype.isSupported = function(/* string */ feature,
67
+ /* string */ version)
68
+ {
69
+ return this._ownerDocument._implementation.hasFeature(feature, version);
70
+ };
71
+
72
+ core.Node.prototype._namespaceURI = null;
73
+ core.Node.prototype.__defineGetter__("namespaceURI", function() {
74
+ return this._namespaceURI || null;
75
+ });
76
+
77
+ core.Node.prototype.__defineSetter__("namespaceURI", function(value) {
78
+ this._namespaceURI = value;
79
+ });
80
+
81
+ core.Node.prototype.__defineGetter__("prefix", function() {
82
+ return this._prefix || null;
83
+ });
84
+
85
+ core.Node.prototype.__defineSetter__("prefix", function(value) {
86
+ if (this._prefix === "xmlns") {
87
+ throw new core.DOMException(core.NAMESPACE_ERR);
88
+ }
89
+ testNamespaceName(value, this._namespaceURI);
90
+
91
+ this._prefix = value;
92
+ });
93
+
94
+ core.Node.prototype.__defineGetter__("localName", function() {
95
+ return this._localName || null;
96
+ });
97
+
98
+ /* return boolean */
99
+ core.Node.prototype.hasAttributes = function() {
100
+ return (this._attributes && this._attributes.length > 0);
101
+ };
102
+
103
+
104
+ core.NamedNodeMap.prototype.getNamedItemNS = function(/* string */ namespaceURI,
105
+ /* string */ localName)
106
+ {
107
+ var defaultNode = null;
108
+ return this._map(function(item) {
109
+
110
+ if (namespaceURI === item.namespaceURI)
111
+ {
112
+ if (item.localName === localName) {
113
+ return true;
114
+ }
115
+ } else if (!namespaceURI && !defaultNode) {
116
+ defaultNode = true;
117
+ return true;
118
+ }
119
+ return false;
120
+ })[0] || null;
121
+ };
122
+
123
+ core.AttrNodeMap.prototype.setNamedItem = function(/* Node */ arg) {
124
+ if (arg.nodeType !== this._ownerDocument.ATTRIBUTE_NODE) {
125
+ throw new core.DOMException(core.HIERARCHY_REQUEST_ERR);
126
+ }
127
+
128
+ return core.NamedNodeMap.prototype.setNamedItem.call(this, arg);
129
+ };
130
+
131
+ core.NamedNodeMap.prototype.setNamedItemNS = function(/* Node */ arg)
132
+ {
133
+ var owner = this._ownerDocument;
134
+ if (this.parentNode &&
135
+ this.parentNode.parentNode &&
136
+ this.parentNode.parentNode.nodeType === owner.ENTITY_NODE)
137
+ {
138
+ throw new core.DOMException(core.NO_MODIFICATION_ALLOWED_ERR);
139
+ }
140
+
141
+ if (arg.nodeType !== owner.ATTRIBUTE_NODE) {
142
+ throw new core.DOMException(core.HIERARCHY_REQUEST_ERR);
143
+ }
144
+
145
+ if (arg.parentNode) {
146
+ throw new core.DOMException(core.INUSE_ATTRIBUTE_ERR);
147
+ }
148
+ return this.setNamedItem(arg);
149
+ };
150
+
151
+ core.NamedNodeMap.prototype.removeNamedItemNS = function(/*string */ namespaceURI,
152
+ /* string */ localName)
153
+ {
154
+ if (this.parentNode &&
155
+ this.parentNode.parentNode &&
156
+ this.parentNode.parentNode.nodeType === this._ownerDocument.ENTITY_NODE)
157
+ {
158
+ throw new core.DOMException(core.NO_MODIFICATION_ALLOWED_ERR);
159
+ }
160
+
161
+ throw new core.DOMException(core.NOT_FOUND_ERR);
162
+ };
163
+
164
+ core.Attr.prototype.__defineGetter__("ownerElement", function() {
165
+ return this._ownerElement || null;
166
+ });
167
+
168
+ core.Node.prototype.__defineSetter__("qualifiedName", function(qualifiedName) {
169
+ testNamespaceName(qualifiedName, this._namespaceURI);
170
+ qualifiedName = qualifiedName || "";
171
+ this._localName = qualifiedName.split(":")[1] || null;
172
+ this.prefix = qualifiedName.split(":")[0] || null;
173
+ this._qualifiedName = qualifiedName;
174
+ });
175
+
176
+ core.NamedNodeMap.prototype._map = function(fn) {
177
+
178
+ if (this._attributes && this._attributes.length) {
179
+ var ret = [], l = this._attributes.length, i = 0, attribute;
180
+ for(i; i<l; i++) {
181
+ attribute = this._attributes.item(i);
182
+ if (fn && fn(attribute)) {
183
+ ret.push(attribute);
184
+ }
185
+ }
186
+ return ret;
187
+ }
188
+ return [];
189
+ };
190
+
191
+ core.Element.prototype.getAttributeNS = function(/* string */ namespaceURI,
192
+ /* string */ localName)
193
+ {
194
+ var attr = this._attributes._map(function(attr) {
195
+ if (namespaceURI === attr.namespaceURI &&
196
+ attr.localName === localName)
197
+ {
198
+ return true;
199
+ }
200
+ })[0];
201
+
202
+ return (attr) ? attr.nodeValue : null;
203
+ };
204
+
205
+ core.Element.prototype.setAttributeNS = function(/* string */ namespaceURI,
206
+ /* string */ qualifiedName,
207
+ /* string */ value)
208
+ {
209
+
210
+ testNamespaceName(qualifiedName, namespaceURI);
211
+
212
+ if (qualifiedName.split(':').shift() === "xml" &&
213
+ namespaceURI !== "http://www.w3.org/XML/1998/namespace")
214
+ {
215
+ throw new core.DOMException(core.NAMESPACE_ERR);
216
+ }
217
+
218
+
219
+ var attr = this.setAttribute(qualifiedName, value);
220
+ attr.namespaceURI = namespaceURI;
221
+ var s = qualifiedName.split(':');
222
+ attr._localName = s.pop();
223
+ attr._prefix = (s.length > 0) ? s.pop() : null;
224
+
225
+
226
+ return attr;
227
+ };
228
+
229
+ core.Element.prototype.removeAttributeNS = function(/* string */ namespaceURI,
230
+ /* string */ localName)
231
+ {
232
+ var qualifiedName = this._attributes._map(function(attr) {
233
+ if (namespaceURI === attr.namespaceURI &&
234
+ attr.localName === localName)
235
+ {
236
+ return true;
237
+ }
238
+ })[0] || null;
239
+ return this.removeAttribute(qualifiedName);
240
+ };
241
+
242
+ core.Element.prototype.getAttributeNodeNS = function(/* string */ namespaceURI,
243
+ /* string */ localName)
244
+ {
245
+ return this._attributes._map(function(attr) {
246
+ if (namespaceURI === attr.namespaceURI &&
247
+ attr.localName === localName)
248
+ {
249
+ return true;
250
+ }
251
+ })[0] || null;
252
+ };
253
+
254
+ core.Element.prototype.setAttributeNodeNS = function(/* Attr */ newAttr)
255
+ {
256
+ if (newAttr.ownerElement) {
257
+ throw new core.DOMException(core.INUSE_ATTRIBUTE_ERR);
258
+ }
259
+
260
+ newAttr._ownerElement = this;
261
+ return this.setAttributeNode(newAttr);
262
+ };
263
+
264
+ core.Element.prototype.getElementsByTagNameNS = function(/* String */ namespaceURI,
265
+ /* String */ localName)
266
+ {
267
+ var nsPrefixCache = {};
268
+
269
+ function filterByTagName(child) {
270
+ if (child.nodeType && child.nodeType === this.ENTITY_REFERENCE_NODE) {
271
+ child = child._entity;
272
+ }
273
+
274
+ var localMatch = child.localName === localName,
275
+ nsMatch = child.namespaceURI === namespaceURI;
276
+ if ((localMatch || localName === "*") &&
277
+ (nsMatch || namespaceURI === "*"))
278
+ {
279
+ return true;
280
+ }
281
+ return false;
282
+ }
283
+
284
+ var disableLiveLists = this.ownerDocument &&
285
+ this.ownerDocument.implementation &&
286
+ this.ownerDocument.implementation.hasFeature("DisableLiveLists");
287
+
288
+ return new core.NodeList(core.mapper(this, filterByTagName), !disableLiveLists);
289
+ };
290
+
291
+ core.Element.prototype.hasAttribute = function(/* string */name)
292
+ {
293
+ if (!this.attributes) {
294
+ return false;
295
+ }
296
+ return this.attributes.exists(name);
297
+ };
298
+
299
+ core.Element.prototype.hasAttributeNS = function(/* string */namespaceURI,
300
+ /* string */localName)
301
+ {
302
+ if (!this._attributes ||
303
+ !this._attributes.length ||
304
+ this._attributes.length < 1)
305
+ {
306
+ return false;
307
+ }
308
+ return this.hasAttribute(localName);
309
+ };
310
+
311
+ core.DocumentType.prototype.__defineGetter__("publicId", function() {
312
+ return this._publicId || "";
313
+ });
314
+
315
+ core.DocumentType.prototype.__defineGetter__("systemId", function() {
316
+ return this._systemId || "";
317
+ });
318
+
319
+ core.DocumentType.prototype.__defineGetter__("internalSubset", function() {
320
+ return this._internalSubset || null;
321
+ });
322
+
323
+ core.Document.prototype.importNode = function(/* Node */ importedNode,
324
+ /* bool */ deep)
325
+ {
326
+ if (importedNode && importedNode.nodeType) {
327
+ if (importedNode.nodeType === this.DOCUMENT_NODE ||
328
+ importedNode.nodeType === this.DOCUMENT_TYPE_NODE) {
329
+ throw new core.DOMException(core.NOT_SUPPORTED_ERR);
330
+ }
331
+ }
332
+
333
+ var newNode = importedNode.cloneNode(deep);
334
+ newNode._ownerDocument = this;
335
+ newNode._ownerElement = null;
336
+ newNode._prefix = importedNode.prefix;
337
+ newNode._localName = importedNode.localName;
338
+ newNode._namespaceURI = importedNode.namespaceURI;
339
+ return newNode;
340
+ };
341
+
342
+ core.Document.prototype.createElementNS = function(/* string */ namespaceURI,
343
+ /* string */ qualifiedName)
344
+ {
345
+ testNamespaceName(qualifiedName, namespaceURI);
346
+
347
+ var element = this.createElement(qualifiedName),
348
+ sploded = qualifiedName.split(':');
349
+
350
+ element.namespaceURI = namespaceURI;
351
+ element.qualifiedName = qualifiedName;
352
+
353
+ element._localName = sploded.pop();
354
+
355
+ if (sploded.length > 0) {
356
+ element.prefix = sploded.pop();
357
+ } else if (namespaceURI === "http://www.w3.org/2000/xmlns/") {
358
+ element.prefix = "xmlns";
359
+ } else if (namespaceURI === "http://www.w3.org/XML/1998/namespace") {
360
+ element.prefix = "xml";
361
+ }
362
+
363
+ return element;
364
+ };
365
+
366
+ core.Document.prototype.createAttributeNS = function(/* string */ namespaceURI,
367
+ /* string */ qualifiedName)
368
+ {
369
+ testNamespaceName(qualifiedName, namespaceURI);
370
+ var attribute = this.createAttribute(qualifiedName);
371
+ attribute.qualifiedName = qualifiedName;
372
+ attribute.namespaceURI = namespaceURI;
373
+ var s = qualifiedName.split(':');
374
+ attribute._localName = s.pop();
375
+ attribute._prefix = (s.length > 0) ? s.pop() : null;
376
+ return attribute;
377
+ };
378
+
379
+ core.Element.prototype.__defineSetter__("id", function(id) {
380
+ this.setAttribute("id", id);
381
+ id = this.getAttribute("id"); //Passed validation
382
+ if (!this._ownerDocument._ids) {
383
+ this._ownerDocument._ids = {};
384
+ }
385
+ if (id === '') {
386
+ delete this._ownerDocument._ids[id];
387
+ } else {
388
+ this._ownerDocument._ids[id] = this;
389
+ }
390
+ });
391
+
392
+ core.Element.prototype.__defineGetter__("id",function() {
393
+ return this.getAttribute("id");
394
+ });
395
+
396
+ core.Document.prototype.getElementById = function(id) {
397
+ return this._ids[id] || null;
398
+ };
399
+
400
+
401
+ exports.dom =
402
+ {
403
+ level2 : {
404
+ core : core
405
+ }
406
+ };
@@ -0,0 +1,358 @@
1
+ /* DOM Level2 Events implemented as described here:
2
+ *
3
+ * http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
4
+ *
5
+ */
6
+ var core = require("./core").dom.level2.core,
7
+ sys = require("sys");
8
+
9
+ var events = {};
10
+
11
+ events.EventException = function() {
12
+ if (arguments.length > 0) {
13
+ this._code = arguments[0];
14
+ } else {
15
+ this._code = 0;
16
+ }
17
+ if (arguments.length > 1) {
18
+ this._message = arguments[1];
19
+ } else {
20
+ this._message = "Unspecified event type";
21
+ }
22
+ Error.call(this, this._message);
23
+ if (Error.captureStackTrace) {
24
+ Error.captureStackTrace(this, events.EventException);
25
+ }
26
+ };
27
+ events.EventException.prototype = {
28
+ get UNSPECIFIED_EVENT_TYPE_ERR() { return 0; },
29
+ get code() { return this._code;}
30
+ };
31
+ events.EventException.prototype.__proto__ = Error.prototype;
32
+
33
+ events.Event = function(eventType) {
34
+ this._eventType = eventType;
35
+ this._type = null;
36
+ this._bubbles = null;
37
+ this._cancelable = null;
38
+ this._target = null;
39
+ this._currentTarget = null;
40
+ this._eventPhase = null;
41
+ this._timeStamp = null;
42
+ this._preventDefault = false;
43
+ this._stopPropagation = false;
44
+ };
45
+ events.Event.prototype = {
46
+ initEvent: function(type, bubbles, cancelable) {
47
+ this._type = type;
48
+ this._bubbles = bubbles;
49
+ this._cancelable = cancelable;
50
+ },
51
+ preventDefault: function() {
52
+ if (this._cancelable) {
53
+ this._preventDefault = true;
54
+ }
55
+ },
56
+ stopPropagation: function() {
57
+ this._stopPropagation = true;
58
+ },
59
+ get CAPTURING_PHASE() { return 1; },
60
+ get AT_TARGET() { return 2; },
61
+ get BUBBLING_PHASE() { return 3; },
62
+ get eventType() { return this._eventType; },
63
+ get type() { return this._type; },
64
+ get bubbles() { return this._bubbles; },
65
+ get cancelable() { return this._cancelable; },
66
+ get target() { return this._target; },
67
+ get currentTarget() { return this._currentTarget; },
68
+ get eventPhase() { return this._eventPhase; },
69
+ get timeStamp() { return this._timeStamp; }
70
+ };
71
+
72
+ events.HTMLEvent = function(eventType) {
73
+ events.Event.call(this, eventType);
74
+ };
75
+ events.HTMLEvent.prototype.__proto__ = events.Event.prototype;
76
+
77
+
78
+ events.UIEvent = function(eventType) {
79
+ events.Event.call(this, eventType);
80
+ this.view = null;
81
+ this.detail = null;
82
+ };
83
+ events.UIEvent.prototype = {
84
+ initUIEvent: function(type, bubbles, cancelable, view, detail) {
85
+ this.initEvent(type, bubbles, cancelable);
86
+ this.view = view;
87
+ this.detail = detail;
88
+ },
89
+ };
90
+ events.UIEvent.prototype.__proto__ = events.Event.prototype;
91
+
92
+
93
+ events.MouseEvent = function(eventType) {
94
+ events.UIEvent.call(this, eventType);
95
+ this.screenX = null;
96
+ this.screenY = null;
97
+ this.clientX = null;
98
+ this.clientY = null;
99
+ this.ctrlKey = null;
100
+ this.shiftKey = null;
101
+ this.altKey = null;
102
+ this.metaKey = null;
103
+ this.button = null;
104
+ this.relatedTarget = null;
105
+ };
106
+ events.MouseEvent.prototype = {
107
+ initMouseEvent: function(type,
108
+ bubbles,
109
+ cancelable,
110
+ view,
111
+ detail,
112
+ screenX,
113
+ screenY,
114
+ clientX,
115
+ clientY,
116
+ ctrlKey,
117
+ altKey,
118
+ shiftKey,
119
+ metaKey,
120
+ button,
121
+ relatedTarget) {
122
+ this.initUIEvent(type, bubbles, cancelable, view, detail);
123
+ this.screenX = screenX
124
+ this.screenY = screenY
125
+ this.clientX = clientX
126
+ this.clientY = clientY
127
+ this.ctrlKey = ctrlKey
128
+ this.shiftKey = shiftKey
129
+ this.altKey = altKey
130
+ this.metaKey = metaKey
131
+ this.button = button
132
+ this.relatedTarget = relatedTarget
133
+ }
134
+ };
135
+ events.MouseEvent.prototype.__proto__ = events.UIEvent.prototype;
136
+
137
+
138
+ events.MutationEvent = function(eventType) {
139
+ events.Event.call(this, eventType);
140
+ this.relatedNode = null;
141
+ this.prevValue = null;
142
+ this.newValue = null;
143
+ this.attrName = null;
144
+ this.attrChange = null;
145
+ };
146
+ events.MutationEvent.prototype = {
147
+ initMutationEvent: function(type,
148
+ bubbles,
149
+ cancelable,
150
+ relatedNode,
151
+ prevValue,
152
+ newValue,
153
+ attrName,
154
+ attrChange) {
155
+ this.initEvent(type, bubbles, cancelable);
156
+ this.relatedNode = relatedNode;
157
+ this.prevValue = prevValue;
158
+ this.newValue = newValue;
159
+ this.attrName = attrName;
160
+ this.attrChange = attrChange;
161
+ },
162
+ get MODIFICATION() { return 1; },
163
+ get ADDITION() { return 2; },
164
+ get REMOVAL() { return 3; },
165
+ };
166
+ events.MutationEvent.prototype.__proto__ = events.Event.prototype;
167
+
168
+
169
+ events.EventTarget = function() {};
170
+ events.EventTarget.prototype = {
171
+ addEventListener: function(type, listener, capturing) {
172
+ this._listeners = this._listeners || {};
173
+ var listeners = this._listeners[type] || {};
174
+ capturing = (capturing === true);
175
+ var capturingListeners = listeners[capturing] || [];
176
+ for (var i=0; i < capturingListeners.length; i++) {
177
+ if (capturingListeners[i] === listener) {
178
+ return;
179
+ }
180
+ }
181
+ capturingListeners.push(listener);
182
+ listeners[capturing] = capturingListeners;
183
+ this._listeners[type] = listeners;
184
+ },
185
+
186
+ removeEventListener: function(type, listener, capturing) {
187
+ var listeners = this._listeners && this._listeners[type];
188
+ if (!listeners) return;
189
+ var capturingListeners = listeners[(capturing === true)];
190
+ if (!capturingListeners) return;
191
+ for (var i=0; i < capturingListeners.length; i++) {
192
+ if (capturingListeners[i] === listener) {
193
+ capturingListeners.splice(i, 1);
194
+ return;
195
+ }
196
+ }
197
+ },
198
+
199
+ dispatchEvent: function(event) {
200
+ if (event == null) {
201
+ throw new events.EventException(0, "Null event");
202
+ }
203
+ if (event._type == null || event._type == "") {
204
+ throw new events.EventException(0, "Uninitialized event");
205
+ }
206
+
207
+
208
+ var nextTarget = null;
209
+ var targetList = [];
210
+
211
+
212
+ function _getListeners(target, type, capturing) {
213
+ var listeners = target._listeners
214
+ && target._listeners[type]
215
+ && target._listeners[type][capturing];
216
+ if (listeners && listeners.length) {
217
+ return listeners;
218
+ }
219
+ return [];
220
+ }
221
+
222
+ function _dispatchEvent(event, iterator, capturing) {
223
+ var target = iterator();
224
+ while (target && !event._stopPropagation) {
225
+ listeners = _getListeners(target, event._type, capturing);
226
+ for (var y = 0; y < listeners.length; y++) {
227
+ event._currentTarget = target;
228
+ try {
229
+ listeners[y].call(target, event);
230
+ } catch (e) {
231
+ sys.log("Listener "
232
+ + sys.inspect(listeners[y])
233
+ + "\n\n on target \n\n"
234
+ + sys.inspect(target)
235
+ + "\n\n threw error \n\n"
236
+ + sys.inspect(e)
237
+ + "\n\n handling event \n\n"
238
+ + sys.inspect(event));
239
+ }
240
+ }
241
+ target = iterator();
242
+ }
243
+ return !event._stopPropagation;
244
+ }
245
+
246
+
247
+ event._target = this;
248
+
249
+ //per the spec we gather the list of targets first to ensure
250
+ //against dom modifications during actual event dispatch
251
+ nextTarget = this.parentNode;
252
+ while (nextTarget) {
253
+ targetList.push(nextTarget);
254
+ nextTarget = nextTarget.parentNode;
255
+ }
256
+
257
+
258
+ var i = targetList.length,
259
+ iterator = function() { return i >=0 ? targetList[--i] : null };
260
+
261
+ event._eventPhase = event.CAPTURING_PHASE;
262
+ if (!_dispatchEvent(event, iterator, true)) return event._preventDefault;
263
+
264
+
265
+ i = 1;
266
+ iterator = function() { return i-- ? event._target : null };
267
+ event._eventPhase = event.AT_TARGET;
268
+ if (!_dispatchEvent(event, iterator, false)) return event._preventDefault;
269
+
270
+
271
+ if (event._bubbles && !event._stopPropagation) {
272
+ i = 0;
273
+ iterator = function() { return i < targetList.length ? targetList[i++] : null };
274
+ event._eventPhase = event.BUBBLING_PHASE;
275
+ _dispatchEvent(event, iterator, false);
276
+ }
277
+
278
+ return event._preventDefault;
279
+ }
280
+
281
+ };
282
+
283
+
284
+ core.Node.prototype.__proto__ = events.EventTarget.prototype;
285
+
286
+ // Wrap the level-1 implementation of appendChild() to dispatch a DOMNodeInserted event
287
+ (function(level1) {
288
+ core.Node.prototype.appendChild = function(newChild) {
289
+ var ret = level1.call(this, newChild);
290
+ if (this.nodeType == 1 && this.ownerDocument) {
291
+ var ev = this.ownerDocument.createEvent("MutationEvents");
292
+ ev.initMutationEvent("DOMNodeInserted", true, false, this, null, null, null, null);
293
+ newChild.dispatchEvent(ev);
294
+ }
295
+ return ret;
296
+ };
297
+ })(core.Node.prototype.appendChild);
298
+
299
+ // Wrap the level-1 implementation of removeChild() to dispatch a DOMNodeRemoved event
300
+ (function(level1) {
301
+ core.Node.prototype.removeChild = function(oldChild) {
302
+ if (this.ownerDocument) {
303
+ var ev = this.ownerDocument.createEvent("MutationEvents");
304
+ ev.initMutationEvent("DOMNodeRemoved", true, false, this, null, null, null, null);
305
+ oldChild.dispatchEvent(ev);
306
+ }
307
+ return level1.call(this, oldChild);
308
+ };
309
+ })(core.Node.prototype.removeChild);
310
+
311
+ // Wrap the level-1 implementation to dispatch a DOMAttrModified event
312
+ (function(level1) {
313
+ core.AttrNodeMap.prototype.removeNamedItem = function(name) {
314
+ var node,
315
+ target = this._parentNode,
316
+ ev = target.ownerDocument.createEvent("MutationEvents");
317
+
318
+ node = level1.call(this, name);
319
+
320
+ ev.initMutationEvent("DOMAttrModified", true, false, this._parentNode, node.value, null, node.name, ev.REMOVAL);
321
+ target.dispatchEvent(ev);
322
+ return node;
323
+ };
324
+ })(core.AttrNodeMap.prototype.removeNamedItem);
325
+
326
+ // Wrap the level-1 implementation to dispatch a DOMAttrModified event
327
+ (function(level1) {
328
+ core.AttrNodeMap.prototype.setNamedItem = function(node) {
329
+ var target = this._parentNode,
330
+ ev = target.ownerDocument.createEvent("MutationEvents");
331
+
332
+ ev.initMutationEvent("DOMAttrModified", true, false, this._parentNode, null, node.value, node.name, ev.ADDITION);
333
+ node = level1.call(this, node);
334
+ target.dispatchEvent(ev);
335
+ return node;
336
+ };
337
+ })(core.AttrNodeMap.prototype.setNamedItem);
338
+
339
+
340
+ core.Document.prototype.createEvent = function(eventType) {
341
+ switch (eventType) {
342
+ case "MutationEvents": return new events.MutationEvent(eventType);
343
+ case "UIEvents": return new events.UIEvent(eventType);
344
+ case "MouseEvents": return new events.MouseEvent(eventType);
345
+ case "HTMLEvents": return new events.HTMLEvent(eventType);
346
+ }
347
+ return new events.Event(eventType);
348
+ };
349
+
350
+
351
+ exports.dom =
352
+ {
353
+ level2 : {
354
+ core : core,
355
+ events : events
356
+ }
357
+ };
358
+