Comparing version 0.1.13 to 0.1.15
var dom = exports.dom = require("./jsdom/level1/core").dom; | ||
exports.defaultLevel = dom.level1.core; | ||
var dom = exports.dom = require("./jsdom/level3").dom; | ||
exports.defaultLevel = dom.level3.html; | ||
exports.browserAugmentation = require("./jsdom/browser").browserAugmentation; | ||
@@ -9,11 +9,17 @@ exports.windowAugmentation = require("./jsdom/browser").windowAugmentation; | ||
exports.jsdom = function (html, level) { | ||
exports.jsdom = function (html, level, options) { | ||
level = level || exports.defaultLevel; | ||
var browser = exports.browserAugmentation(level); | ||
doc = new (browser.Document)(); | ||
var browser = exports.browserAugmentation(level, (options || {})); | ||
doc = new (browser.Document)(); | ||
// Author: Swizec | ||
// remove IE's expressions and expose what applies to us | ||
if (html) { | ||
html = html.replace(/<!--\[if .*\![(]*IE[)]*\]>(.+)<\!\[endif\]-->/gi, "$1"); | ||
} | ||
doc.innerHTML = html || "<html><head></head><body></body></html>"; | ||
doc.createWindow = function() { | ||
var window = exports.windowAugmentation(level, { document: doc }); | ||
doc.createWindow = function(url) { | ||
var window = exports.windowAugmentation(level, { document: doc, url: url }); | ||
if (window && | ||
@@ -20,0 +26,0 @@ window.document && |
@@ -18,2 +18,3 @@ //Make configurable from docType?? | ||
link: 1, | ||
meta: 1, | ||
param: 1, | ||
@@ -27,3 +28,16 @@ embed: 1 | ||
// REVIEW: escapeHTML and escapeAttr | ||
// based on circumstantial experience | ||
// of HTML escaping | ||
var escapeText = function(text) { | ||
return (text || "").replace(/&/g, '&') | ||
.replace(/>/g, '>') | ||
.replace(/</g, '<'); | ||
}; | ||
var escapeAttr = function(text) { | ||
return escapeText(text).replace(/\"/g, '"'); | ||
}; | ||
var styleIgnore = { | ||
@@ -49,3 +63,4 @@ top: 1, | ||
attribute = element.attributes.item(i); | ||
attributes.push(attribute.name + '="' + attribute.nodeValue + '"'); | ||
attributes.push(attribute.name + '="' + | ||
escapeAttr(attribute.nodeValue) + '"'); | ||
} | ||
@@ -68,3 +83,4 @@ //sys.puts('attributes: ' + sys.inspect(attributes)); | ||
if (use) { | ||
styleAttrs.push(i.replace(/([A-Z])/g, uncanon) + ': ' + element.style[i]); | ||
styleAttrs.push(i.replace(/([A-Z])/g, uncanon) + ': ' + | ||
escapeAttr(element.style[i])); | ||
} | ||
@@ -154,3 +170,3 @@ } | ||
} else { | ||
ret += element.nodeValue || "" ; | ||
ret += escapeText(element.nodeValue); | ||
} | ||
@@ -163,3 +179,3 @@ ret += current.end; | ||
case element.COMMENT_NODE: | ||
ret += '<!-- ' + element.nodeValue + ' -->'; | ||
ret += '<!--' + element.nodeValue + '-->'; | ||
break; | ||
@@ -166,0 +182,0 @@ case element.DOCUMENT_NODE: |
@@ -5,3 +5,2 @@ var HtmlToDom = function(parser){ | ||
// sax parser | ||
this.appendHtmlToElement = function(html, element){ | ||
@@ -27,2 +26,3 @@ | ||
0; | ||
for (i in node.attributes) | ||
@@ -34,2 +34,6 @@ { | ||
} | ||
for (var i=0; i<node.attributes.length; i++) { | ||
newElement.setAttribute(i, node.attributes.item(i)); | ||
} | ||
currentElement.appendChild(newElement); | ||
@@ -69,3 +73,3 @@ currentElement = newElement; | ||
} | ||
var parsed = parser.ParseHtml(html); | ||
@@ -112,3 +116,7 @@ | ||
if (node.type == 'tag' || node.type == 'script' || node.type == 'style') { | ||
newNode = currentDocument.createElement(node.name); | ||
try{ | ||
newNode = currentDocument.createElement(node.name); | ||
}catch (err) { | ||
//console.log("raw: "+node.raw); | ||
} | ||
} | ||
@@ -123,3 +131,11 @@ if (node.type == 'text') { | ||
for (var c in node.attribs) { | ||
newNode.setAttribute(c, node.attribs[c]); | ||
// catchin errors here helps with improperly escaped attributes | ||
// but properly fixing this should (can only?) be done in the htmlparser itself | ||
try{ | ||
newNode.setAttribute(c, node.attribs[c]); | ||
}catch(err) { | ||
//console.log("raw: "+node.raw); | ||
//console.log(node.attribs); | ||
//console.log("offender: "+node.attribs[c]); | ||
} | ||
} | ||
@@ -126,0 +142,0 @@ } |
@@ -15,3 +15,3 @@ var sys = require('sys'), | ||
options = options || {}; | ||
var window = exports.createWindow(), | ||
var window = exports.createWindow(dom, options), | ||
setupDoc = (typeof options.document === 'undefined'); | ||
@@ -27,6 +27,10 @@ | ||
if (options.document.childNodes.length === 0) { | ||
window.document.appendChild(window.document.createElement("html")); | ||
window.document.appendChild( | ||
window.document.createElement("html") | ||
); | ||
var head = window.document.createElement('head'); | ||
head.appendChild(window.document.createElement('title')); | ||
window.document.documentElement.appendChild(head); | ||
head.appendChild( | ||
window.document.createElement('title') | ||
); | ||
window.document.documentElement.appendChild( | ||
@@ -37,4 +41,6 @@ window.document.createElement('body') | ||
window.document.addEventListener = function() {}; | ||
if (!window.document.addEventListener) { | ||
window.document.addEventListener = function() {}; | ||
} | ||
window.document.compareDocumentPosition = function() {}; | ||
@@ -47,3 +53,4 @@ window.document.documentElement.style = {}; | ||
exports.createWindow = function(dom, options) { | ||
var document, | ||
options = options || {}; | ||
var document, | ||
window = { | ||
@@ -60,2 +67,4 @@ get document() { return document }, | ||
setInterval: setInterval, | ||
clearInterval: clearInterval, | ||
clearTimeout: clearTimeout, | ||
name: 'nodejs', | ||
@@ -80,3 +89,3 @@ innerWidth: 1024, | ||
window.frames = [window]; | ||
window.contentwindow = window; | ||
window.contentWindow = window; | ||
window.addEventListener2 = function(type, fn, capture) { | ||
@@ -87,14 +96,62 @@ fn.apply(window); | ||
window.getComputedStyle = function(node) { | ||
//This resolves to document.defaultView.getComputedStyle | ||
return node.style; | ||
var s = node.style, | ||
cs = {}; | ||
for (var n in s) { | ||
cs[n] = s[n]; | ||
} | ||
cs.__proto__ = { | ||
getPropertyValue: function(name) { | ||
return node.style[name]; | ||
} | ||
}; | ||
return cs; | ||
}; | ||
window.addEventListener = function() {}; | ||
window.location = { href: __filename }; | ||
window.alert = function () {}; | ||
window.blur = function () {}; | ||
window.close = function () {}; | ||
window.confirm = function () {}; | ||
window.createPopup = function () {}; | ||
window.focus = function () {}; | ||
window.moveBy = function () {}; | ||
window.moveTo = function () {}; | ||
window.open = function () {}; | ||
window.print = function () {}; | ||
window.prompt = function () {}; | ||
window.resizeBy = function () {}; | ||
window.resizeTo = function () {}; | ||
window.scroll = function () {}; | ||
window.scrollBy = function () {}; | ||
window.scrollTo = function () {}; | ||
// Author: Swizec | ||
// some scripts expect a proper window.location; try parsing it from options.url | ||
if (options.url) { | ||
var host = options.url.split("://", 2)[1].split("/", 1)[0]; | ||
window.location = { href: options.url, | ||
hash: (options.url.indexOf('#') > -1) ? "#"+options.url.split("#", 2)[1] : '', | ||
host: host, | ||
hostname: host.split(":", 2)[0], | ||
pathname: (function () { | ||
var path = options.url.split("://", 2)[1].split("/", 2)[1]; | ||
return (path) ? path.split('#', 2)[0] : ''; | ||
})(), | ||
port: (host.split(":", 2)[1]) ? host.split(":", 2)[1] : 80, | ||
protocol: options.url.split("://", 2)[0]+":", | ||
search: (options.url.indexOf('?') > -1) ? "?"+options.url.split("?", 2)[1] : '', | ||
// TODO: find a way to actually implement these | ||
reload: function () {}, | ||
replace: function () {} | ||
} | ||
}else { | ||
window.location = { href: __filename }; | ||
} | ||
window.navigator = { | ||
userAgent: 'Node.js (' + process.platform + '; U; rv:' + | ||
process.version + ')', | ||
platform: process.platform, | ||
appVersion: process.version | ||
userAgent: 'Node.js (' + process.platform + '; U; rv:' + process.version + ')', | ||
appName: 'Node.js jsDom', | ||
platform: process.platform, | ||
appVersion: process.version | ||
}; | ||
@@ -104,5 +161,45 @@ | ||
window.self = window; | ||
window.close = function() { | ||
var len = document._nodes.length, i, el; | ||
for (i = 0; i < len; i++) { | ||
el = document._nodes[i]; | ||
document._nodes[i] = null; | ||
if (el.parentNode) { | ||
el.parentNode.removeChild(el); | ||
} | ||
} | ||
delete document._attributes._parentNode; | ||
delete document._ownerDocument; | ||
delete document._children[0]._parentNode; | ||
delete document._children[0]._ownerDocument; | ||
delete document.defaultView; | ||
delete document.contentWindow; | ||
delete document.contentDocument; | ||
delete document.parentWindow; | ||
delete document._documentElement; | ||
delete window.self; | ||
delete window.window; | ||
delete window.contentWindow; | ||
delete window.document; | ||
len = window.frames.length; | ||
for (i = 0; i < len; i++) { | ||
if (window !== window.frames[i]) { | ||
window.frames[i].close(); | ||
} | ||
delete window.frames[i]; | ||
} | ||
}; | ||
return window; | ||
}; | ||
var htmlparser = null; //Caching for HTMLParser require. HUGE performace boost. | ||
/** | ||
* 5000 iterations | ||
* Without cache: ~1800+ms | ||
* With cache: ~80ms | ||
*/ | ||
var browserAugmentation = exports.browserAugmentation = function(dom, options) { | ||
@@ -120,4 +217,6 @@ | ||
try { | ||
var htmlparser = require('htmlparser'); | ||
htmltodom = new HtmlToDom(htmlparser); | ||
if (!htmlparser) {//Only require once | ||
htmlparser = require('htmlparser'); | ||
} | ||
htmltodom = new HtmlToDom(htmlparser); | ||
} catch(e) { | ||
@@ -132,4 +231,8 @@ htmltodom = new HtmlToDom(); | ||
dom.Node.prototype.addEventListener = function(){}; | ||
if (!dom.Node.prototype.__proto__.addEventListener) { | ||
dom.Node.prototype.addEventListener = function(){}; | ||
} | ||
dom.Element.prototype.getElementsByClassName = function(className) { | ||
@@ -197,3 +300,5 @@ | ||
dom.Document.prototype.__defineGetter__("title",function() { | ||
return this.getElementsByTagName('title')[0].innerHTML; | ||
// Swizec - sometimes there is no title | ||
var elements = this.getElementsByTagName('title'); | ||
return (elements.length > 0) ? elements[0].innerHTML : ''; | ||
}); | ||
@@ -225,12 +330,4 @@ | ||
var element = new dom.Element(doc, name); | ||
element.__defineSetter__("src", function(value) { | ||
var realvalue; | ||
if (value.substring(0,7) === "file://") { | ||
realvalue = value.substring(7); | ||
} else { | ||
realvalue = value; | ||
} | ||
var finish = function(data) { | ||
var realvalue; | ||
var finish = function(data) { | ||
element._text = data; | ||
@@ -248,2 +345,10 @@ process.binding('evals').Script.runInNewContext( | ||
element.__defineSetter__("src", function(value) { | ||
if (value.substring(0,7) === "file://") { | ||
realvalue = value.substring(7); | ||
} else { | ||
realvalue = value; | ||
} | ||
this._src = value; | ||
@@ -278,2 +383,6 @@ if (value.substring(0,7) === "file://") { | ||
element.__defineGetter__("src", function() { return this._src; }); | ||
element.__defineGetter__("text", function() { return this._text; }); | ||
element.__defineSetter__("text", function(data) { | ||
finish(data); | ||
}); | ||
return element; | ||
@@ -304,5 +413,2 @@ }; | ||
var nodes = htmltodom.appendHtmlToElement(html, this); | ||
//sys.puts('OUT: ' + this.outerHTML); | ||
return html; | ||
@@ -316,17 +422,50 @@ }); | ||
dom.Element.prototype.createCaption = function(str) { | ||
var el = document.createElement('caption'); | ||
el.innerHTML = str; | ||
return el; | ||
}; | ||
dom.Document.prototype.__defineGetter__("head", function() { | ||
return this.getElementsByTagName("head").item(0); | ||
}); | ||
// Author: Swizec | ||
// styleSheets is an interface to all of the css on a page | ||
// some scripts like readability.js expect this to exist | ||
dom.Document.prototype.__defineGetter__("styleSheets", function () { | ||
var styles = new Array(), | ||
nodes1 = this.getElementsByTagName("style"), | ||
nodes2 = this.head.getElementsByTagName("link"), | ||
node; | ||
dom.Element.prototype.focus = function() { | ||
}; | ||
dom.Element.prototype.blur = function() { | ||
}; | ||
function StyleSheet(node) { | ||
this.cssText = node.textContent; | ||
this.disabled = false; | ||
this.href = (node.attributes['href']) ? node.attributes['href'] : ''; | ||
this.media = (node.attributes['media']) ? node.attributes['media'] : 'screen'; | ||
this.title = node.attributes['title']; | ||
this.type = node.attributes['type']; | ||
} | ||
for (var i=0; i < nodes1.length; i++ ) { | ||
node = nodes1.item(i); | ||
styles.push(new StyleSheet(node)); | ||
} | ||
for (var i=0; i< nodes2.length; i++ ) { | ||
node = nodes2.item(i); | ||
if (node.attributes['rel'] == 'stylesheet') { | ||
styles.push(new StyleSheet(node)); | ||
} | ||
} | ||
return styles; | ||
}); | ||
dom.Element.prototype.createCaption = function(str) { | ||
var el = document.createElement('caption'); | ||
el.innerHTML = str; | ||
return el; | ||
}; | ||
dom.Element.prototype.focus = function() { }; | ||
dom.Element.prototype.blur = function() {}; | ||
dom.Element.prototype.__defineGetter__('elements', function(val) { | ||
//TODO | ||
return {}; | ||
//TODO | ||
return {}; | ||
}); | ||
@@ -339,8 +478,8 @@ | ||
dom.Element.prototype.__defineGetter__('tagName', function(val) { | ||
var t = this._tagName.toUpperCase(); | ||
//Document should not return a tagName | ||
if (this.nodeName === '#document') { | ||
t = null; | ||
} | ||
return t; | ||
var t = this._tagName.toUpperCase(); | ||
//Document should not return a tagName | ||
if (this.nodeName === '#document') { | ||
t = null; | ||
} | ||
return t; | ||
}); | ||
@@ -351,127 +490,124 @@ | ||
dom.Element.prototype.__defineSetter__("href", function(val) { | ||
this.setAttribute("href", val); | ||
this.setAttribute("href", val); | ||
}); | ||
dom.Element.prototype.__defineGetter__("href",function() { | ||
return this.getAttribute("href"); | ||
return this.getAttribute("href"); | ||
}); | ||
dom.Element.prototype.__defineSetter__("height", function(val) { | ||
this.setAttribute("height", val); | ||
this.setAttribute("height", val); | ||
}); | ||
dom.Element.prototype.__defineGetter__("height",function() { | ||
return this.getAttribute("height"); | ||
return this.getAttribute("height"); | ||
}); | ||
dom.Element.prototype.__defineSetter__("width", function(val) { | ||
this.setAttribute("width", val); | ||
this.setAttribute("width", val); | ||
}); | ||
dom.Element.prototype.__defineGetter__("width",function() { | ||
return this.getAttribute("width"); | ||
return this.getAttribute("width"); | ||
}); | ||
dom.Element.prototype.__defineSetter__("src", function(val) { | ||
this.setAttribute("src", val); | ||
this.setAttribute("src", val); | ||
}); | ||
dom.Element.prototype.__defineGetter__("src",function() { | ||
return this.getAttribute("src"); | ||
return this.getAttribute("src"); | ||
}); | ||
dom.Element.prototype.__defineSetter__("lang", function(val) { | ||
this.setAttribute("lang", val); | ||
this.setAttribute("lang", val); | ||
}); | ||
dom.Element.prototype.__defineGetter__("lang",function() { | ||
return this.getAttribute("lang"); | ||
return this.getAttribute("lang"); | ||
}); | ||
dom.Element.prototype.__defineSetter__("className", function(className) { | ||
this.setAttribute("class", className); | ||
this.setAttribute("class", className); | ||
}); | ||
dom.Element.prototype.__defineGetter__("className",function() { | ||
return this.getAttribute("class"); | ||
return this.getAttribute("class"); | ||
}); | ||
dom.Element.prototype.__defineGetter__('disabled', function() { | ||
return this.getAttribute('disabled') || false; | ||
return this.getAttribute('disabled') || false; | ||
}); | ||
dom.Element.prototype.__defineSetter__('disabled', function(val) { | ||
return this.setAttribute('disabled', val); | ||
return this.setAttribute('disabled', val); | ||
}); | ||
dom.Element.prototype.__defineGetter__('selected', function() { | ||
return this.getAttribute('selected') || false; | ||
return this.getAttribute('selected') || false; | ||
}); | ||
dom.Element.prototype.__defineSetter__('selected', function(val) { | ||
return this.setAttribute('selected', val); | ||
return this.setAttribute('selected', val); | ||
}); | ||
dom.Element.prototype.__defineGetter__('checked', function() { | ||
return this.getAttribute('checked') || false; | ||
return this.getAttribute('checked') || false; | ||
}); | ||
dom.Element.prototype.__defineSetter__('checked', function(val) { | ||
return this.setAttribute('checked', val); | ||
return this.setAttribute('checked', val); | ||
}); | ||
dom.Element.prototype.__defineGetter__('name', function() { | ||
return this.getAttribute('name'); | ||
return this.getAttribute('name'); | ||
}); | ||
dom.Element.prototype.__defineSetter__('name', function(val) { | ||
return this.setAttribute('name', val); | ||
return this.setAttribute('name', val); | ||
}); | ||
dom.Element.prototype.__defineGetter__('type', function() { | ||
return this.getAttribute('type'); | ||
return this.getAttribute('type'); | ||
}); | ||
dom.Element.prototype.__defineSetter__('type', function(val) { | ||
return this.setAttribute('type', val); | ||
return this.setAttribute('type', val); | ||
}); | ||
dom.Element.prototype.__defineGetter__('selected', function() { | ||
return this.getAttribute('selected') || false; | ||
return this.getAttribute('selected') || false; | ||
}); | ||
dom.Element.prototype.__defineSetter__('selected', function(val) { | ||
return this.setAttribute('selected', val); | ||
return this.setAttribute('selected', val); | ||
}); | ||
dom.Element.prototype.__defineGetter__('rows', function() { | ||
if (this.tagName.toUpperCase() == 'TBODY') { | ||
return this.getElementsByTagName('tr'); | ||
} else { | ||
//Throw Error | ||
} | ||
if (this.tagName.toUpperCase() == 'TBODY') { | ||
return this.getElementsByTagName('tr'); | ||
} else { | ||
//Throw Error | ||
} | ||
}); | ||
dom.Element.prototype.__defineGetter__('options', function() { | ||
if (this.tagName.toUpperCase() == 'SELECT') { | ||
return this.getElementsByTagName('option'); | ||
} else { | ||
//Throw Error | ||
} | ||
if (this.tagName.toUpperCase() == 'SELECT') { | ||
return this.getElementsByTagName('option'); | ||
} else { | ||
//Throw Error | ||
} | ||
}); | ||
dom.Element.prototype.__defineGetter__('selectedIndex', function() { | ||
if (this.tagName.toUpperCase() == 'SELECT') { | ||
var index = 0, | ||
options = this.getElementsByTagName('option'); | ||
if (this.tagName.toUpperCase() == 'SELECT') { | ||
var options = this.getElementsByTagName('option'), | ||
index = options.length > 0 ? 0 : -1; | ||
for (var i = 0; i < options.length; i++) { | ||
if (options[i].selected) { | ||
index = i; | ||
} | ||
} | ||
return index; | ||
} else { | ||
//Throw Error | ||
for (var i = 0; i < options.length; i++) { | ||
if (options[i].selected) { | ||
index = i; | ||
} | ||
} | ||
return index; | ||
} else { | ||
//Throw Error | ||
} | ||
}); | ||
@@ -505,31 +641,41 @@ | ||
dom.Element.prototype.__defineGetter__('value', function() { | ||
var val = this.getAttribute('value') || this.nodeValue; | ||
if (this.tagName.toUpperCase() == 'TEXTAREA') { | ||
val = this.innerHTML; | ||
if (this.tagName.toUpperCase() === 'TEXTAREA') { | ||
return this.innerHTML; | ||
} else if (this.tagName.toUpperCase() === 'OPTION') { | ||
return this.getAttribute('value');// || this.innerHTML; | ||
} else if (this.tagName.toUpperCase() === 'SELECT') { | ||
if (this.selectedIndex === -1) { | ||
return ''; | ||
} | ||
if (this.tagName.toUpperCase() == 'OPTION') { | ||
if (val === null) { | ||
val = this.innerHTML; | ||
} | ||
if (this.getAttribute('value') === '') { | ||
val = ''; | ||
} | ||
} | ||
if (this.tagName.toUpperCase() == 'SELECT') { | ||
var selected = this.options[this.selectedIndex]; | ||
val = ''; | ||
if (selected) { | ||
val = selected.value; | ||
} | ||
} | ||
return val; | ||
return this.options[this.selectedIndex].value; | ||
} | ||
return this.getAttribute('value') || ''; | ||
}); | ||
dom.Element.prototype.__defineSetter__('value', function(val) { | ||
if (this.nodeName.toUpperCase() === 'TEXTAREA') { | ||
this.nodeValue = this.innerHTML = val; | ||
} else if (this.nodeName.toUpperCase() === 'SELECT') { | ||
for (var i = 0; i < this.options.length; i++) { | ||
if (this.options[i].value === val) { | ||
this.selectedIndex = i; | ||
} | ||
} | ||
return; | ||
} else { | ||
//this.nodeValue = this.innerHTML = val; | ||
return this.setAttribute('value', val); | ||
} | ||
}); | ||
dom.Element.prototype.__defineGetter__('form', function() { | ||
var e = this; | ||
while (e) { | ||
if (e.nodeName.toUpperCase() == 'FORM') { | ||
return e; | ||
} | ||
e = e.parentNode; | ||
} | ||
return undefined; | ||
}); | ||
@@ -557,2 +703,3 @@ dom.Element.prototype.__defineGetter__('textContent', function() { | ||
return dom; | ||
@@ -559,0 +706,0 @@ } |
@@ -51,6 +51,7 @@ /* | ||
core.DOMException = function(code) { | ||
core.DOMException = function(code, message) { | ||
this._code = code; | ||
Error.call(this, messages[code]); | ||
this.message = messages[code]; | ||
if(message) this.message = this.message + ": " + message; | ||
if(Error.captureStackTrace) Error.captureStackTrace(this, core.DOMException); | ||
@@ -274,2 +275,7 @@ }; | ||
} | ||
// Swizec - some scripts hang here because null is not returned | ||
if (index > this._parentNode.childNodes.length) { | ||
return null; | ||
} | ||
@@ -426,13 +432,14 @@ return this._parentNode.childNodes.item(index) || null; | ||
var found = false; | ||
var found = false, child; | ||
for (var i=0;i<this._children.length;i++) { | ||
if (this._children[i] === oldChild) { | ||
found=true; | ||
child = this._children[i]; | ||
this._children.remove(i,i); | ||
oldChild._parentNode = null; | ||
if (this.id) { | ||
if (this._ownerDocument._ids) { | ||
this._ownerDocument._ids[this.id] = null; | ||
delete this._ownerDocument._ids[this.id]; | ||
if (child.id) { | ||
if (child._ownerDocument._ids) { | ||
child._ownerDocument._ids[child.id] = null; | ||
delete child._ownerDocument._ids[child.id]; | ||
} | ||
@@ -831,2 +838,3 @@ } | ||
this._tagName = tagName; | ||
}; | ||
@@ -849,3 +857,11 @@ | ||
get nodeType() { return this._nodeType;}, | ||
get attributes() { return this._attributes;}, | ||
get attributes() { | ||
// Author: Swizec | ||
// some scripts expect access to attributes by index | ||
for(var i=0; i<this._attributes.length; i++) { | ||
this._attributes[i] = this._attributes.item(i); | ||
} | ||
return this._attributes; | ||
}, | ||
get name() { return this.nodeName;}, | ||
@@ -1040,4 +1056,10 @@ /* returns string */ | ||
}; | ||
var tagRegEx = /[^\w:\d_-]+/i; | ||
var entRegEx = /[^\w\d_\-&;]+/; | ||
core.Document.prototype = { | ||
_elementBuilders : {}, | ||
_nodes: null, | ||
get contentType() { return this._contentType;}, | ||
@@ -1080,5 +1102,7 @@ get doctype() { return this._doctype || null;}, | ||
var c = [], lower = tagName.toLowerCase(), element; | ||
if (!tagName || !tagName.match || (c = tagName.match(/[^\w:\d_-]+/i))) { | ||
if (!tagName || !tagName.match || (c = tagName.match(tagRegEx))) { | ||
throw new core.DOMException(INVALID_CHARACTER_ERR, 'Invalid character in tag name: ' + c.pop()); | ||
} | ||
@@ -1097,4 +1121,4 @@ if (this._elementBuilders[lower]) { | ||
attrs = attrElement.attributes; | ||
var attr; | ||
for (var i=0;i<attrs.length;i++) { | ||
var attr, len = attrs.length; | ||
for (var i = 0; i < len; i++) { | ||
attr = this.createAttribute(attrs.item(i).name); | ||
@@ -1107,2 +1131,8 @@ attr.value = attrs.item(i).value; | ||
} | ||
if (!this._nodes) { | ||
this._nodes = []; | ||
} | ||
this._nodes.push(this); | ||
return element; | ||
@@ -1142,3 +1172,3 @@ }, //raises: function(DOMException) {}, | ||
if (target.match(/[^\w\d_-]+/) || !target || !target.length) { | ||
if (target.match(tagRegEx) || !target || !target.length) { | ||
throw new core.DOMException(INVALID_CHARACTER_ERR); | ||
@@ -1153,3 +1183,3 @@ } | ||
if (!name || !name.length || name.match(/[^\w:\d_\.-]+/) ) { | ||
throw new core.DOMException(INVALID_CHARACTER_ERR); | ||
throw new core.DOMException(INVALID_CHARACTER_ERR, "attribute name: " + name); | ||
} | ||
@@ -1171,3 +1201,3 @@ return new core.Attr(this, name,false); | ||
if (name.match(/[^\w\d_-]+/)) { | ||
if (name.match(tagRegEx)) { | ||
throw new core.DOMException(INVALID_CHARACTER_ERR); | ||
@@ -1188,3 +1218,3 @@ } | ||
if (name.match(/[^\w\d_\-&;]+/) || !name || !name.length) { | ||
if (name.match(entRegEx) || !name || !name.length) { | ||
throw new core.DOMException(INVALID_CHARACTER_ERR); | ||
@@ -1210,3 +1240,3 @@ } | ||
if (name.match(/[^\w\d_\-&;]+/) || !name || !name.length) { | ||
if (name.match(entRegEx) || !name || !name.length) { | ||
throw new core.DOMException(INVALID_CHARACTER_ERR); | ||
@@ -1230,3 +1260,3 @@ } | ||
/* returns Node */ | ||
appendChild : function(/* Node */ newChild){ | ||
appendChild: function(/* Node */ newChild){ | ||
@@ -1233,0 +1263,0 @@ // readonly |
@@ -5,5 +5,8 @@ var core = require("../level1/core").dom.level1.core, | ||
var testNamespaceName = function(ns, nsuri) { | ||
if (!ns || ns.match(/[^0-9a-z\.:\-_]/i) !== null) { | ||
throw new core.DOMException(core.INVALID_CHARACTER_ERR); | ||
if (!ns) { | ||
throw new core.DOMException(core.INVALID_CHARACTER_ERR, "namespace is undefined"); | ||
} | ||
if(ns.match(/[^0-9a-z\.:\-_]/i) !== null) { | ||
throw new core.DOMException(core.INVALID_CHARACTER_ERR, ns); | ||
} | ||
if ((ns === 'xmlns' && nsuri !== "http://www.w3.org/2000/xmlns/") || | ||
@@ -10,0 +13,0 @@ (ns === "xml" && nsuri !== "http://www.w3.org/XML/1998/namespace") || |
@@ -1,137 +0,304 @@ | ||
/* | ||
#ifndef _EVENTS_IDL_ | ||
#define _EVENTS_IDL_ | ||
/* DOM Level2 Events implemented as described here: | ||
* | ||
* http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html | ||
* | ||
*/ | ||
var core = require("./core").dom.level2.core, | ||
sys = require("sys"); | ||
#include "dom.idl" | ||
#include "views.idl" | ||
var events = {}; | ||
#pragma prefix "dom.w3c.org" | ||
module events | ||
{ | ||
events.EventException = function() { | ||
if (arguments.length > 0) { | ||
this._code = arguments[0]; | ||
} else { | ||
this._code = 0; | ||
} | ||
if (arguments.length > 1) { | ||
this._message = arguments[1]; | ||
} else { | ||
this._message = "Unspecified event type"; | ||
} | ||
Error.call(this, this._message); | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, events.EventException); | ||
} | ||
}; | ||
events.EventException.prototype = { | ||
get UNSPECIFIED_EVENT_TYPE_ERR() { return 0; }, | ||
get code() { return this._code;} | ||
}; | ||
events.EventException.prototype.__proto__ = Error.prototype; | ||
typedef dom::DOMString DOMString; | ||
typedef dom::DOMTimeStamp DOMTimeStamp; | ||
typedef dom::Node Node; | ||
events.Event = function(eventType) { | ||
this._eventType = eventType; | ||
this._type = null; | ||
this._bubbles = null; | ||
this._cancelable = null; | ||
this._target = null; | ||
this._currentTarget = null; | ||
this._eventPhase = null; | ||
this._timeStamp = null; | ||
this._preventDefault = false; | ||
this._stopPropagation = false; | ||
}; | ||
events.Event.prototype = { | ||
initEvent: function(type, bubbles, cancelable) { | ||
this._type = type; | ||
this._bubbles = bubbles; | ||
this._cancelable = cancelable; | ||
}, | ||
preventDefault: function() { | ||
if (this._cancelable) { | ||
this._preventDefault = true; | ||
} | ||
}, | ||
stopPropagation: function() { | ||
this._stopPropagation = true; | ||
}, | ||
get CAPTURING_PHASE() { return 1; }, | ||
get AT_TARGET() { return 2; }, | ||
get BUBBLING_PHASE() { return 3; }, | ||
get eventType() { return this._eventType; }, | ||
get type() { return this._type; }, | ||
get bubbles() { return this._bubbles; }, | ||
get cancelable() { return this._cancelable; }, | ||
get target() { return this._target; }, | ||
get currentTarget() { return this._currentTarget; }, | ||
get eventPhase() { return this._eventPhase; }, | ||
get timeStamp() { return this._timeStamp; } | ||
}; | ||
interface EventListener; | ||
interface Event; | ||
events.HTMLEvent = function(eventType) { | ||
events.Event.call(this, eventType); | ||
}; | ||
events.HTMLEvent.prototype.__proto__ = events.Event.prototype; | ||
// Introduced in DOM Level 2: | ||
exception EventException { | ||
unsigned short code; | ||
}; | ||
// EventExceptionCode | ||
const unsigned short UNSPECIFIED_EVENT_TYPE_ERR = 0; | ||
events.UIEvent = function(eventType) { | ||
events.Event.call(this, eventType); | ||
this.view = null; | ||
this.detail = null; | ||
}; | ||
events.UIEvent.prototype = { | ||
initUIEvent: function(type, bubbles, cancelable, view, detail) { | ||
this.initEvent(type, bubbles, cancelable); | ||
this.view = view; | ||
this.detail = detail; | ||
}, | ||
}; | ||
events.UIEvent.prototype.__proto__ = events.Event.prototype; | ||
// Introduced in DOM Level 2: | ||
interface EventTarget { | ||
void addEventListener(in DOMString type, | ||
in EventListener listener, | ||
in boolean useCapture); | ||
void removeEventListener(in DOMString type, | ||
in EventListener listener, | ||
in boolean useCapture); | ||
boolean dispatchEvent(in Event evt) | ||
raises(EventException); | ||
}; | ||
// Introduced in DOM Level 2: | ||
interface EventListener { | ||
void handleEvent(in Event evt); | ||
}; | ||
events.MouseEvent = function(eventType) { | ||
events.UIEvent.call(this, eventType); | ||
this.screenX = null; | ||
this.screenY = null; | ||
this.clientX = null; | ||
this.clientY = null; | ||
this.ctrlKey = null; | ||
this.shiftKey = null; | ||
this.altKey = null; | ||
this.metaKey = null; | ||
this.button = null; | ||
this.relatedTarget = null; | ||
}; | ||
events.MouseEvent.prototype = { | ||
initMouseEvent: function(type, | ||
bubbles, | ||
cancelable, | ||
view, | ||
detail, | ||
screenX, | ||
screenY, | ||
clientX, | ||
clientY, | ||
ctrlKey, | ||
altKey, | ||
shiftKey, | ||
metaKey, | ||
button, | ||
relatedTarget) { | ||
this.initUIEvent(type, bubbles, cancelable, view, detail); | ||
this.screenX = screenX | ||
this.screenY = screenY | ||
this.clientX = clientX | ||
this.clientY = clientY | ||
this.ctrlKey = ctrlKey | ||
this.shiftKey = shiftKey | ||
this.altKey = altKey | ||
this.metaKey = metaKey | ||
this.button = button | ||
this.relatedTarget = relatedTarget | ||
} | ||
}; | ||
events.MouseEvent.prototype.__proto__ = events.UIEvent.prototype; | ||
// Introduced in DOM Level 2: | ||
interface Event { | ||
// PhaseType | ||
const unsigned short CAPTURING_PHASE = 1; | ||
const unsigned short AT_TARGET = 2; | ||
const unsigned short BUBBLING_PHASE = 3; | ||
events.MutationEvent = function(eventType) { | ||
events.Event.call(this, eventType); | ||
this.relatedNode = null; | ||
this.prevValue = null; | ||
this.newValue = null; | ||
this.attrName = null; | ||
this.attrChange = null; | ||
}; | ||
events.MutationEvent.prototype = { | ||
initMutationEvent: function(type, | ||
bubbles, | ||
cancelable, | ||
relatedNode, | ||
prevValue, | ||
newValue, | ||
attrName, | ||
attrChange) { | ||
this.initEvent(type, bubbles, cancelable); | ||
this.relatedNode = relatedNode; | ||
this.prevValue = prevValue; | ||
this.newValue = newValue; | ||
this.attrName = attrName; | ||
this.attrChange = attrChange; | ||
}, | ||
get MODIFICATION() { return 1; }, | ||
get ADDITION() { return 2; }, | ||
get REMOVAL() { return 3; }, | ||
}; | ||
events.MutationEvent.prototype.__proto__ = events.Event.prototype; | ||
readonly attribute DOMString type; | ||
readonly attribute EventTarget target; | ||
readonly attribute EventTarget currentTarget; | ||
readonly attribute unsigned short eventPhase; | ||
readonly attribute boolean bubbles; | ||
readonly attribute boolean cancelable; | ||
readonly attribute DOMTimeStamp timeStamp; | ||
void stopPropagation(); | ||
void preventDefault(); | ||
void initEvent(in DOMString eventTypeArg, | ||
in boolean canBubbleArg, | ||
in boolean cancelableArg); | ||
}; | ||
// Introduced in DOM Level 2: | ||
interface DocumentEvent { | ||
Event createEvent(in DOMString eventType) | ||
raises(dom::DOMException); | ||
}; | ||
events.EventTarget = function() {}; | ||
events.EventTarget.prototype = { | ||
addEventListener: function(type, listener, capturing) { | ||
this._listeners = this._listeners || {}; | ||
var listeners = this._listeners[type] || {}; | ||
capturing = (capturing === true); | ||
var capturingListeners = listeners[capturing] || []; | ||
for (var i=0; i < capturingListeners.length; i++) { | ||
if (capturingListeners[i] === listener) { | ||
return; | ||
} | ||
} | ||
capturingListeners.push(listener); | ||
listeners[capturing] = capturingListeners; | ||
this._listeners[type] = listeners; | ||
}, | ||
// Introduced in DOM Level 2: | ||
interface UIEvent : Event { | ||
readonly attribute views::AbstractView view; | ||
readonly attribute long detail; | ||
void initUIEvent(in DOMString typeArg, | ||
in boolean canBubbleArg, | ||
in boolean cancelableArg, | ||
in views::AbstractView viewArg, | ||
in long detailArg); | ||
}; | ||
removeEventListener: function(type, listener, capturing) { | ||
var listeners = this._listeners && this._listeners[type]; | ||
if (!listeners) return; | ||
var capturingListeners = listeners[(capturing === true)]; | ||
if (!capturingListeners) return; | ||
for (var i=0; i < capturingListeners.length; i++) { | ||
if (capturingListeners[i] === listener) { | ||
capturingListeners.splice(i, 1); | ||
return; | ||
} | ||
} | ||
}, | ||
// Introduced in DOM Level 2: | ||
interface MouseEvent : UIEvent { | ||
readonly attribute long screenX; | ||
readonly attribute long screenY; | ||
readonly attribute long clientX; | ||
readonly attribute long clientY; | ||
readonly attribute boolean ctrlKey; | ||
readonly attribute boolean shiftKey; | ||
readonly attribute boolean altKey; | ||
readonly attribute boolean metaKey; | ||
readonly attribute unsigned short button; | ||
readonly attribute EventTarget relatedTarget; | ||
void initMouseEvent(in DOMString typeArg, | ||
in boolean canBubbleArg, | ||
in boolean cancelableArg, | ||
in views::AbstractView viewArg, | ||
in long detailArg, | ||
in long screenXArg, | ||
in long screenYArg, | ||
in long clientXArg, | ||
in long clientYArg, | ||
in boolean ctrlKeyArg, | ||
in boolean altKeyArg, | ||
in boolean shiftKeyArg, | ||
in boolean metaKeyArg, | ||
in unsigned short buttonArg, | ||
in EventTarget relatedTargetArg); | ||
}; | ||
dispatchEvent: function(event) { | ||
if (event == null) { | ||
throw new events.EventException(0, "Null event"); | ||
} | ||
if (event._type == null || event._type == "") { | ||
throw new events.EventException(0, "Uninitialized event"); | ||
} | ||
// Introduced in DOM Level 2: | ||
interface MutationEvent : Event { | ||
// attrChangeType | ||
const unsigned short MODIFICATION = 1; | ||
const unsigned short ADDITION = 2; | ||
const unsigned short REMOVAL = 3; | ||
var nextTarget = null; | ||
var targetList = []; | ||
readonly attribute Node relatedNode; | ||
readonly attribute DOMString prevValue; | ||
readonly attribute DOMString newValue; | ||
readonly attribute DOMString attrName; | ||
readonly attribute unsigned short attrChange; | ||
void initMutationEvent(in DOMString typeArg, | ||
in boolean canBubbleArg, | ||
in boolean cancelableArg, | ||
in Node relatedNodeArg, | ||
in DOMString prevValueArg, | ||
in DOMString newValueArg, | ||
in DOMString attrNameArg, | ||
in unsigned short attrChangeArg); | ||
}; | ||
function _getListeners(target, type, capturing) { | ||
var listeners = target._listeners | ||
&& target._listeners[type] | ||
&& target._listeners[type][capturing]; | ||
if (listeners && listeners.length) { | ||
return listeners; | ||
} | ||
return []; | ||
} | ||
function _dispatchEvent(event, iterator, capturing) { | ||
var target = iterator(); | ||
while (target && !event._stopPropagation) { | ||
listeners = _getListeners(target, event._type, capturing); | ||
for (var y = 0; y < listeners.length; y++) { | ||
event._currentTarget = target; | ||
try { | ||
listeners[y].call(target, event); | ||
} catch (e) { | ||
sys.log("Listener " | ||
+ sys.inspect(listeners[y]) | ||
+ "\n\n on target \n\n" | ||
+ sys.inspect(target) | ||
+ "\n\n threw error \n\n" | ||
+ sys.inspect(e) | ||
+ "\n\n handling event \n\n" | ||
+ sys.inspect(event)); | ||
} | ||
} | ||
target = iterator(); | ||
} | ||
return !event._stopPropagation; | ||
} | ||
event._target = this; | ||
//per the spec we gather the list of targets first to ensure | ||
//against dom modifications during actual event dispatch | ||
nextTarget = this.parentNode; | ||
while (nextTarget) { | ||
targetList.push(nextTarget); | ||
nextTarget = nextTarget.parentNode; | ||
} | ||
var i = targetList.length, | ||
iterator = function() { return i >=0 ? targetList[--i] : null }; | ||
event._eventPhase = event.CAPTURING_PHASE; | ||
if (!_dispatchEvent(event, iterator, true)) return event._preventDefault; | ||
i = 1; | ||
iterator = function() { return i-- ? event._target : null }; | ||
event._eventPhase = event.AT_TARGET; | ||
if (!_dispatchEvent(event, iterator, false)) return event._preventDefault; | ||
if (event._bubbles && !event._stopPropagation) { | ||
i = 0; | ||
iterator = function() { return i < targetList.length ? targetList[i++] : null }; | ||
event._eventPhase = event.BUBBLING_PHASE; | ||
_dispatchEvent(event, iterator, false); | ||
} | ||
return event._preventDefault; | ||
} | ||
}; | ||
#endif // _EVENTS_IDL_ | ||
*/ | ||
core.Node.prototype.__proto__ = events.EventTarget.prototype; | ||
core.Document.prototype.createEvent = function(eventType) { | ||
switch (eventType) { | ||
case "MutationEvents": return new events.MutationEvent(eventType); | ||
case "UIEvents": return new events.UIEvent(eventType); | ||
case "MouseEvents": return new events.MouseEvent(eventType); | ||
case "HTMLEvents": return new events.HTMLEvent(eventType); | ||
} | ||
return new events.Event(eventType); | ||
}; | ||
exports.dom = | ||
{ | ||
level2 : { | ||
core : core, | ||
events : events | ||
} | ||
}; | ||
@@ -0,1 +1,3 @@ | ||
var core = require(__dirname + "/core").dom.level2.core; | ||
/* | ||
@@ -575,2 +577,8 @@ | ||
#endif // _HTML2_IDL_ | ||
*/ | ||
*/ | ||
exports.dom = { | ||
level2 : { | ||
html : core | ||
} | ||
} |
@@ -0,59 +1,15 @@ | ||
var core = require(__dirname + "/../level2/core.js").dom.level2.core; | ||
/* | ||
/ File: dom.idl | ||
#ifndef _DOM_IDL_ | ||
#define _DOM_IDL_ | ||
#pragma prefix "w3c.org" | ||
module dom | ||
{ | ||
valuetype DOMString sequence<unsigned short>; | ||
typedef unsigned long long DOMTimeStamp; | ||
typedef any DOMUserData; | ||
typedef Object DOMObject; | ||
interface DOMImplementation; | ||
interface DocumentType; | ||
interface Document; | ||
interface NodeList; | ||
interface NamedNodeMap; | ||
interface UserDataHandler; | ||
interface Element; | ||
interface TypeInfo; | ||
interface DOMLocator; | ||
exception DOMException { | ||
unsigned short code; | ||
}; | ||
*/ | ||
// ExceptionCode | ||
const unsigned short INDEX_SIZE_ERR = 1; | ||
const unsigned short DOMSTRING_SIZE_ERR = 2; | ||
const unsigned short HIERARCHY_REQUEST_ERR = 3; | ||
const unsigned short WRONG_DOCUMENT_ERR = 4; | ||
const unsigned short INVALID_CHARACTER_ERR = 5; | ||
const unsigned short NO_DATA_ALLOWED_ERR = 6; | ||
const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7; | ||
const unsigned short NOT_FOUND_ERR = 8; | ||
const unsigned short NOT_SUPPORTED_ERR = 9; | ||
const unsigned short INUSE_ATTRIBUTE_ERR = 10; | ||
// Introduced in DOM Level 2: | ||
const unsigned short INVALID_STATE_ERR = 11; | ||
// Introduced in DOM Level 2: | ||
const unsigned short SYNTAX_ERR = 12; | ||
// Introduced in DOM Level 2: | ||
const unsigned short INVALID_MODIFICATION_ERR = 13; | ||
// Introduced in DOM Level 2: | ||
const unsigned short NAMESPACE_ERR = 14; | ||
// Introduced in DOM Level 2: | ||
const unsigned short INVALID_ACCESS_ERR = 15; | ||
// Introduced in DOM Level 3: | ||
const unsigned short VALIDATION_ERR = 16; | ||
// Introduced in DOM Level 3: | ||
const unsigned short TYPE_MISMATCH_ERR = 17; | ||
core.VALIDATION_ERR = 16; | ||
core.TYPE_MISMATCH_ERR = 17; | ||
/* | ||
// Introduced in DOM Level 3: | ||
@@ -107,32 +63,2 @@ interface DOMStringList { | ||
interface Node { | ||
// NodeType | ||
const unsigned short ELEMENT_NODE = 1; | ||
const unsigned short ATTRIBUTE_NODE = 2; | ||
const unsigned short TEXT_NODE = 3; | ||
const unsigned short CDATA_SECTION_NODE = 4; | ||
const unsigned short ENTITY_REFERENCE_NODE = 5; | ||
const unsigned short ENTITY_NODE = 6; | ||
const unsigned short PROCESSING_INSTRUCTION_NODE = 7; | ||
const unsigned short COMMENT_NODE = 8; | ||
const unsigned short DOCUMENT_NODE = 9; | ||
const unsigned short DOCUMENT_TYPE_NODE = 10; | ||
const unsigned short DOCUMENT_FRAGMENT_NODE = 11; | ||
const unsigned short NOTATION_NODE = 12; | ||
readonly attribute DOMString nodeName; | ||
attribute DOMString nodeValue; | ||
// raises(DOMException) on setting | ||
// raises(DOMException) on retrieval | ||
readonly attribute unsigned short nodeType; | ||
readonly attribute Node parentNode; | ||
readonly attribute NodeList childNodes; | ||
readonly attribute Node firstChild; | ||
readonly attribute Node lastChild; | ||
readonly attribute Node previousSibling; | ||
readonly attribute Node nextSibling; | ||
readonly attribute NamedNodeMap attributes; | ||
// Modified in DOM Level 2: | ||
readonly attribute Document ownerDocument; | ||
// Modified in DOM Level 3: | ||
@@ -156,37 +82,60 @@ Node insertBefore(in Node newChild, | ||
void normalize(); | ||
// Introduced in DOM Level 2: | ||
boolean isSupported(in DOMString feature, | ||
in DOMString version); | ||
// Introduced in DOM Level 2: | ||
readonly attribute DOMString namespaceURI; | ||
// Introduced in DOM Level 2: | ||
attribute DOMString prefix; | ||
// raises(DOMException) on setting | ||
// Introduced in DOM Level 2: | ||
readonly attribute DOMString localName; | ||
// Introduced in DOM Level 2: | ||
boolean hasAttributes(); | ||
// Introduced in DOM Level 3: | ||
readonly attribute DOMString baseURI; | ||
*/ | ||
// DocumentPosition | ||
const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; | ||
const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02; | ||
const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04; | ||
const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08; | ||
const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10; | ||
const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; | ||
// Compare Document Position | ||
var DOCUMENT_POSITION_DISCONNECTED = core.Node.prototype.DOCUMENT_POSITION_DISCONNECTED = 0x01; | ||
var DOCUMENT_POSITION_PRECEDING = core.Node.prototype.DOCUMENT_POSITION_PRECEDING = 0x02; | ||
var DOCUMENT_POSITION_FOLLOWING = core.Node.prototype.DOCUMENT_POSITION_FOLLOWING = 0x04; | ||
var DOCUMENT_POSITION_CONTAINS = core.Node.prototype.DOCUMENT_POSITION_CONTAINS = 0x08; | ||
var DOCUMENT_POSITION_CONTAINED_BY = core.Node.prototype.DOCUMENT_POSITION_CONTAINED_BY = 0x10; | ||
var DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = core.Node.prototype.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; | ||
core.Node.prototype.compareDocumentPosition = function compareDocumentPosition( otherNode ) { | ||
if( !(otherNode instanceof core.Node) ) { | ||
throw Error("Comparing position against non-Node values is not allowed") | ||
} | ||
if( this === otherNode ) return 0 | ||
if( this.ownerDocument !== otherNode.ownerDocument ) { | ||
return DOCUMENT_POSITION_DISCONNECTED | ||
} | ||
var point = this | ||
var parents = [ ] | ||
while( point ) { | ||
if( point == otherNode ) return DOCUMENT_POSITION_CONTAINS | ||
parents.push( point ) | ||
point = point.parentNode | ||
} | ||
point = otherNode | ||
while( point ) { | ||
if( point == this ) return DOCUMENT_POSITION_CONTAINED_BY | ||
var location_index = parents.indexOf( point ) | ||
if( location_index !== -1) { | ||
var smallest_common_ancestor = parents[ location_index ] | ||
var this_index = smallest_common_ancestor.childNodes.indexOf( this ) | ||
var other_index = smallest_common_ancestor.childNodes.indexOf( otherNode ) | ||
if( this_index > other_index ) { | ||
return DOCUMENT_POSITION_PRECEDING | ||
} | ||
else { | ||
return DOCUMENT_POSITION_FOLLOWING | ||
} | ||
} | ||
point = point.parentNode | ||
} | ||
return DOCUMENT_POSITION_DISCONNECTED | ||
}; | ||
/* | ||
// Introduced in DOM Level 3: | ||
unsigned short compareDocumentPosition(in Node other) | ||
raises(DOMException); | ||
// Introduced in DOM Level 3: | ||
attribute DOMString textContent; | ||
// raises(DOMException) on setting | ||
// raises(DOMException) on retrieval | ||
*/ | ||
core.Node.prototype.isSameNode = function(other) { | ||
return (other === this); | ||
}; | ||
/* | ||
// Introduced in DOM Level 3: | ||
boolean isSameNode(in Node other); | ||
// Introduced in DOM Level 3: | ||
DOMString lookupPrefix(in DOMString namespaceURI); | ||
@@ -269,4 +218,9 @@ // Introduced in DOM Level 3: | ||
readonly attribute TypeInfo schemaTypeInfo; | ||
*/ | ||
// Introduced in DOM Level 3: | ||
readonly attribute boolean isId; | ||
core.Attr.prototype.__defineGetter__('isId', function() { | ||
return (this.name.toLowerCase() === 'id'); | ||
}); | ||
/* | ||
}; | ||
@@ -382,19 +336,36 @@ | ||
}; | ||
*/ | ||
// Introduced in DOM Level 3: | ||
interface DOMError { | ||
core.DOMError = function(severity, message, type, relatedException, relatedData, location) { | ||
this._severity = severity; | ||
this._message = message; | ||
this._type = type; | ||
this._relatedException = relatedException; | ||
this._relatedData = relatedData; | ||
this._location = location; | ||
}; | ||
core.DOMError.prototype = {}; | ||
core.DOMError.prototype.SEVERITY_WARNING = 1; | ||
core.DOMError.prototype.SEVERITY_ERROR = 2; | ||
core.DOMError.prototype.SEVERITY_FATAL_ERROR = 3; | ||
core.DOMError.prototype.__defineGetter__('severity', function() { | ||
return this._severity; | ||
}); | ||
core.DOMError.prototype.__defineGetter__('message', function() { | ||
return this._message; | ||
}); | ||
core.DOMError.prototype.__defineGetter__('type', function() { | ||
return this._type; | ||
}); | ||
core.DOMError.prototype.__defineGetter__('relatedException', function() { | ||
return this._relatedException; | ||
}); | ||
core.DOMError.prototype.__defineGetter__('relatedData', function() { | ||
return this._relatedData; | ||
}); | ||
core.DOMError.prototype.__defineGetter__('location', function() { | ||
return this._location; | ||
}); | ||
// ErrorSeverity | ||
const unsigned short SEVERITY_WARNING = 1; | ||
const unsigned short SEVERITY_ERROR = 2; | ||
const unsigned short SEVERITY_FATAL_ERROR = 3; | ||
readonly attribute unsigned short severity; | ||
readonly attribute DOMString message; | ||
readonly attribute DOMString type; | ||
readonly attribute DOMObject relatedException; | ||
readonly attribute DOMObject relatedData; | ||
readonly attribute DOMLocator location; | ||
}; | ||
/* | ||
// Introduced in DOM Level 3: | ||
@@ -541,2 +512,8 @@ interface DOMErrorHandler { | ||
#endif // _DOM_IDL_ | ||
*/ | ||
*/ | ||
exports.dom = { | ||
level3 : { | ||
core: core | ||
} | ||
}; |
@@ -0,1 +1,3 @@ | ||
var events = require(__dirname + "/../level2/events").dom.level2.events; | ||
/* | ||
@@ -288,2 +290,8 @@ | ||
#endif // _EVENTS_IDL_ | ||
*/ | ||
*/ | ||
exports.dom = { | ||
level3 : { | ||
events: events | ||
} | ||
} |
{ | ||
"name": "jsdom", | ||
"version": "0.1.13", | ||
"version": "0.1.15", | ||
"description": "CommonJS implementation of the DOM intended to be platform independent and as minimal/light as possible while completely adhering to the w3c DOM specifications.", | ||
@@ -32,2 +32,6 @@ "keywords": [ | ||
"email": "aredridel@nbtsc.org" | ||
}, | ||
{ | ||
"name" : "Matthew (http://github.com/matthewpflueger/)", | ||
"email": "N.A." | ||
} | ||
@@ -57,18 +61,3 @@ ], | ||
}, | ||
"os": [ | ||
"linux", | ||
"macos", | ||
"win" | ||
], | ||
"cpu": [ | ||
"x86", | ||
"ppc", | ||
"x86_64" | ||
], | ||
"engines": [ | ||
"v8", | ||
"ejs", | ||
"node", | ||
"rhino" | ||
], | ||
"engines" : { "node" : ">=0.1.9" }, | ||
"directories": { | ||
@@ -75,0 +64,0 @@ "lib": "lib" |
@@ -25,14 +25,17 @@ var sys = require("sys"); | ||
jquerify : function() { | ||
jsdom.jQueryify(jsdom.jsdom().createWindow(), | ||
__dirname + "/../../example/jquery/jquery.js", | ||
function(window, jQuery) | ||
{ | ||
var tmpWindow = jsdom.jsdom().createWindow(), | ||
jQueryFile = __dirname + "/../../example/jquery/jquery.js", | ||
caught = false, | ||
res = null; | ||
jsdom.jQueryify(tmpWindow, jQueryFile , function(window, jQuery) { | ||
assertNotNull("jQuery should be attached to the window", window.jQuery.find); | ||
assertNotNull("jQuery should be attached to the window", jQuery.find); | ||
var caught = false; | ||
jQuery("body").html('<p id="para"><a class="link">click <em class="emph">ME</em></a></p>'); | ||
try { | ||
jQuery("#a .test", window.body); | ||
res = jQuery("#para .emph", window.document.body); | ||
} catch (e) { | ||
caught = true; | ||
} | ||
assertEquals("selector should work as expected", "ME", res.text()); | ||
assertFalse("compareDocumentPosition should not fail", caught); | ||
@@ -39,0 +42,0 @@ }); |
@@ -96,2 +96,55 @@ var sys = require("sys"); | ||
}, | ||
"level2/events" : { cases: require("./level2/events").tests, setUp : function() { | ||
mixin(global, require("../lib/jsdom/level2/events").dom.level2.events); | ||
global.builder.contentType = "text/xml"; | ||
global.builder.type = "xml"; | ||
global.builder.testDirectory = "level2/events"; | ||
} | ||
}, | ||
/* | ||
Ignoring for now.. | ||
"level2/html" : { cases: require("./level2/html").tests, setUp : function() { | ||
global.builder.contentType = "text/html"; | ||
global.builder.type = "html"; | ||
global.builder.testDirectory = "level2/html"; | ||
} | ||
},*/ | ||
"level3/core" : { cases: require("./level3/core").tests, setUp : function() { | ||
global.builder.contentType = "text/xml"; | ||
global.builder.type = "xml"; | ||
global.builder.testDirectory = "level3/core"; | ||
global.DOMErrorMonitor = function() { | ||
this.allErrors = new Array(); | ||
} | ||
global.DOMErrorMonitor.prototype.handleError = function(err) { | ||
errorMonitor.allErrors[errorMonitor.allErrors.length] = new DOMErrorImpl(err); | ||
} | ||
global.DOMErrorMonitor.prototype.assertLowerSeverity = function(id, severity) { | ||
var i; | ||
for (i = 0; i < errorMonitor.allErrors.length; i++) { | ||
if (errorMonitor.allErrors[i].severity >= severity) { | ||
assertEquals(id, severity - 1, errorMonitor.allErrors[i].severity); | ||
} | ||
} | ||
} | ||
var core = require(__dirname + "/../lib/jsdom/level3/core").dom.level3.core; | ||
global.getImplementation = function() { | ||
return { | ||
createDocument : function() { | ||
return new (core.Document)(); | ||
} | ||
}; | ||
} | ||
} | ||
},/* | ||
"level3/ls" : { cases: require("./level3/ls").tests, setUp : function() { | ||
global.builder.contentType = "text/html"; | ||
global.builder.type = "html"; | ||
global.builder.testDirectory = "level3/ls"; | ||
} | ||
} | ||
*/ | ||
"browser" : { cases: require("./browser").tests, setUp : function() { | ||
@@ -122,25 +175,4 @@ global.dom = require(__dirname + "/../lib/jsdom/level1/core").dom.level1.core; | ||
} | ||
/* | ||
Ignoring for now.. | ||
"level2/html" : { cases: require("./level2/html").tests, setUp : function() { | ||
global.builder.contentType = "text/html"; | ||
global.builder.type = "html"; | ||
global.builder.testDirectory = "level2/html"; | ||
} | ||
}, | ||
"level3/core" : { cases: require("./level3/core").tests, setUp : function() { | ||
global.builder.contentType = "text/xml"; | ||
global.builder.type = "xml"; | ||
global.builder.testDirectory = "level3/core"; | ||
} | ||
}, | ||
"level3/ls" : { cases: require("./level3/ls").tests, setUp : function() { | ||
global.builder.contentType = "text/html"; | ||
global.builder.type = "html"; | ||
global.builder.testDirectory = "level3/ls"; | ||
} | ||
} | ||
*/ | ||
}; | ||
require("mjsunit.runner/runner").run(suites); |
@@ -9,7 +9,7 @@ exports.tests = { | ||
elements.item(elements.length-1) === meta); | ||
assertTrue("meta should be stringified with a closing tag", | ||
assertTrue("meta should not be stringified with a closing tag", | ||
window.document.innerHTML.indexOf("<meta>") > -1 && | ||
window.document.innerHTML.indexOf("</meta>") > -1 | ||
window.document.innerHTML.indexOf("</meta>") === -1 | ||
); | ||
} | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
132217
76440706
215
34