webr 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+