Skip to content

Instantly share code, notes, and snippets.

@cowboyd cowboyd/env.js
Created Mar 13, 2010

Embed
What would you like to do?
/*
* Envjs core-env.1.2.0.0
* Pure JavaScript Browser Environment
* By John Resig <http://ejohn.org/> and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
var Envjs = function(){
var i,
name
override = function(){
for(i=0;i<arguments.length;i++){
for ( name in arguments[i] ) {
var g = arguments[i].__lookupGetter__(name),
s = arguments[i].__lookupSetter__(name);
if ( g || s ) {
if ( g ) Envjs.__defineGetter__(name, g);
if ( s ) Envjs.__defineSetter__(name, s);
} else
Envjs[name] = arguments[i][name];
}
}
};
if(arguments.length === 1 && typeof(arguments[0]) == 'string'){
window.location = arguments[0];
}else if (arguments.length === 1 && typeof(arguments[0]) == "object"){
override(arguments[0])
}else if(arguments.length === 2){
override(arguments[1]);
window.location = arguments[0];
}
return;
},
__this__ = this;
//eg "Mozilla"
Envjs.appCodeName = "Envjs";
//eg "Gecko/20070309 Firefox/2.0.0.3"
Envjs.appName = "Resig/20070309 PilotFish/1.2.0.0";
Envjs.version = "1.6";//?
/*
* Envjs core-env.1.2.0.0
* Pure JavaScript Browser Environment
* By John Resig <http://ejohn.org/> and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
(function(){
/**
* Writes message to system out
* @param {String} message
*/
Envjs.log = function(message){};
/**
* Constants providing enumerated levels for logging in modules
*/
Envjs.DEBUG = 1;
Envjs.INFO = 2;
Envjs.WARN = 3;
Envjs.ERROR = 3;
Envjs.NONE = 3;
/**
* Writes error info out to console
* @param {Error} e
*/
Envjs.lineSource = function(e){};
/**
* describes which script src values will trigger Envjs to load
* the script like a browser would
*/
Envjs.scriptTypes = {
"text/javascript" :false,
"text/envjs" :true
};
/**
* will be called when loading a script throws an error
* @param {Object} script
* @param {Object} e
*/
Envjs.onScriptLoadError = function(script, e){
console.log('error loading script %s %s', script, e);
};
/**
* load and execute script tag text content
* @param {Object} script
*/
Envjs.loadInlineScript = function(script){
var tmpFile;
tmpFile = Envjs.writeToTempFile(script.text, 'js') ;
load(tmpFile);
};
/**
* Should evaluate script in some context
* @param {Object} context
* @param {Object} source
* @param {Object} name
*/
Envjs.eval = function(context, source, name){};
/**
* Executes a script tag
* @param {Object} script
* @param {Object} parser
*/
Envjs.loadLocalScript = function(script){
//console.log("loading script %s", script);
var types,
src,
i,
base,
filename,
xhr;
if(script.type){
types = script.type.split(";");
for(i=0;i<types.length;i++){
if(Envjs.scriptTypes[types[i]]){
//ok this script type is allowed
break;
}
if(i+1 == types.length)
return false;
}
}
try{
//handle inline scripts
if(!script.src.length){
Envjs.loadInlineScript(script);
return true;
}
}catch(e){
//Envjs.error("Error loading script.", e);
Envjs.onScriptLoadError(script, e);
return false;
}
//console.log("loading allowed external script %s", script.src);
//lets you register a function to execute
//before the script is loaded
if(Envjs.beforeScriptLoad){
for(src in Envjs.beforeScriptLoad){
if(script.src.match(src)){
Envjs.beforeScriptLoad[src](script);
}
}
}
base = "" + script.ownerDocument.location;
//filename = Envjs.uri(script.src.match(/([^\?#]*)/)[1], base );
//console.log('base %s', base);
filename = Envjs.uri(script.src, base);
try {
xhr = new XMLHttpRequest();
xhr.open("GET", filename, false/*syncronous*/);
//console.log("loading external script %s", filename);
xhr.onreadystatechange = function(){
//console.log("readyState %s", xhr.readyState);
if(xhr.readyState === 4){
//TODO this is rhino specific
Envjs.eval(
script.ownerDocument.ownerWindow,
xhr.responseText,
filename
);
}
};
xhr.send(null, false);
} catch(e) {
console.log("could not load script %s \n %s", filename, e );
Envjs.onScriptLoadError(script, e);
return false;
}
//lets you register a function to execute
//after the script is loaded
if(Envjs.afterScriptLoad){
for(src in Envjs.afterScriptLoad){
if(script.src.match(src)){
Envjs.afterScriptLoad[src](script);
}
}
}
return true;
};
/**
* synchronizes thread modifications
* @param {Function} fn
*/
Envjs.sync = function(fn){};
/**
* sleep thread for specified duration
* @param {Object} millseconds
*/
Envjs.sleep = function(millseconds){};
/**
* Interval to wait on event loop when nothing is happening
*/
Envjs.WAIT_INTERVAL = 100;//milliseconds
/**
* resolves location relative to base or window location
* @param {Object} path
* @param {Object} base
*/
Envjs.uri = function(path, base){};
/**
* Used in the XMLHttpRquest implementation to run a
* request in a seperate thread
* @param {Object} fn
*/
Envjs.runAsync = function(fn){};
/**
* Used to write to a local file
* @param {Object} text
* @param {Object} url
*/
Envjs.writeToFile = function(text, url){};
/**
* Used to write to a local file
* @param {Object} text
* @param {Object} suffix
*/
Envjs.writeToTempFile = function(text, suffix){};
/**
* Used to delete a local file
* @param {Object} url
*/
Envjs.deleteFile = function(url){};
/**
* establishes connection and calls responsehandler
* @param {Object} xhr
* @param {Object} responseHandler
* @param {Object} data
*/
Envjs.connection = function(xhr, responseHandler, data){};
/**
* Makes an object window-like by proxying object accessors
* @param {Object} scope
* @param {Object} parent
*/
Envjs.proxy = function(scope, parent, aliasList){};
Envjs.javaEnabled = false;
Envjs.tmpdir = '';
Envjs.os_name = '';
Envjs.os_arch = '';
Envjs.os_version = '';
Envjs.lang = '';
Envjs.platform = '';//how do we get the version
/**
*
* @param {Object} frameElement
* @param {Object} url
*/
Envjs.loadFrame = function(frame, url){
try {
if(frame.contentWindow){
//mark for garbage collection
frame.contentWindow = null;
}
//create a new scope for the window proxy
//platforms will need to override this function
//to make sure the scope is global-like
frame.contentWindow = (function(){return this;})();
new Window(frame.contentWindow, window);
//I dont think frames load asynchronously in firefox
//and I think the tests have verified this but for
//some reason I'm less than confident... Are there cases?
frame.contentDocument = frame.contentWindow.document;
frame.contentDocument.async = false;
if(url){
//console.log('envjs.loadFrame async %s', frame.contentDocument.async);
frame.contentWindow.location = url;
}
} catch(e) {
console.log("failed to load frame content: from %s %s", url, e);
}
};
/**
* @author john resig & the envjs team
* @uri http://www.envjs.com/
* @copyright 2008-2010
* @license MIT
*/
})();
/**
* @author envjs team
*/
var Console,
console;
/*
* Envjs console.1.2.0.0
* Pure JavaScript Browser Environment
* By John Resig <http://ejohn.org/> and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
(function(){
/**
* @author envjs team
* borrowed 99%-ish with love from firebug-lite
*/
Console = function(module){
var $level,
$logger,
$null = function(){};
if(Envjs[module] && Envjs[module].loglevel){
$level = Envjs.module.loglevel;
$logger = {
log: function(level){
logFormatted(arguments, (module)+" ");
},
debug: $level>1 ? $null: function() {
logFormatted(arguments, (module)+" debug");
},
info: $level>2 ? $null:function(){
logFormatted(arguments, (module)+" info");
},
warn: $level>3 ? $null:function(){
logFormatted(arguments, (module)+" warning");
},
error: $level>4 ? $null:function(){
logFormatted(arguments, (module)+" error");
}
};
}else{
$logger = {
log: function(level){
logFormatted(arguments, "");
},
debug: $null,
info: $null,
warn: $null,
error: $null
};
}
return $logger;
};
console = new Console("console",1);
function logFormatted(objects, className)
{
var html = [];
var format = objects[0];
var objIndex = 0;
if (typeof(format) != "string")
{
format = "";
objIndex = -1;
}
var parts = parseFormat(format);
for (var i = 0; i < parts.length; ++i)
{
var part = parts[i];
if (part && typeof(part) == "object")
{
var object = objects[++objIndex];
part.appender(object, html);
}
else
appendText(part, html);
}
for (var i = objIndex+1; i < objects.length; ++i)
{
appendText(" ", html);
var object = objects[i];
if (typeof(object) == "string")
appendText(object, html);
else
appendObject(object, html);
}
Envjs.log(html.join(' '));
}
function parseFormat(format)
{
var parts = [];
var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
for (var m = reg.exec(format); m; m = reg.exec(format))
{
var type = m[8] ? m[8] : m[5];
var appender = type in appenderMap ? appenderMap[type] : appendObject;
var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
parts.push({appender: appender, precision: precision});
format = format.substr(m.index+m[0].length);
}
parts.push(format);
return parts;
}
function escapeHTML(value)
{
return value;
}
function objectToString(object)
{
try
{
return object+"";
}
catch (exc)
{
return null;
}
}
// ********************************************************************************************
function appendText(object, html)
{
html.push(escapeHTML(objectToString(object)));
}
function appendNull(object, html)
{
html.push(escapeHTML(objectToString(object)));
}
function appendString(object, html)
{
html.push(escapeHTML(objectToString(object)));
}
function appendInteger(object, html)
{
html.push(escapeHTML(objectToString(object)));
}
function appendFloat(object, html)
{
html.push(escapeHTML(objectToString(object)));
}
function appendFunction(object, html)
{
var reName = /function ?(.*?)\(/;
var m = reName.exec(objectToString(object));
var name = m ? m[1] : "function";
html.push(escapeHTML(name));
}
function appendObject(object, html)
{
try
{
if (object == undefined)
appendNull("undefined", html);
else if (object == null)
appendNull("null", html);
else if (typeof object == "string")
appendString(object, html);
else if (typeof object == "number")
appendInteger(object, html);
else if (typeof object == "function")
appendFunction(object, html);
else if (object.nodeType == 1)
appendSelector(object, html);
else if (typeof object == "object")
appendObjectFormatted(object, html);
else
appendText(object, html);
}
catch (exc)
{
}
}
function appendObjectFormatted(object, html)
{
var text = objectToString(object);
var reObject = /\[object (.*?)\]/;
var m = reObject.exec(text);
html.push( m ? m[1] : text)
}
function appendSelector(object, html)
{
html.push(escapeHTML(object.nodeName.toLowerCase()));
if (object.id)
html.push(escapeHTML(object.id));
if (object.className)
html.push(escapeHTML(object.className));
}
function appendNode(node, html)
{
if (node.nodeType == 1)
{
html.push( node.nodeName.toLowerCase());
for (var i = 0; i < node.attributes.length; ++i)
{
var attr = node.attributes[i];
if (!attr.specified)
continue;
html.push( attr.nodeName.toLowerCase(),escapeHTML(attr.nodeValue))
}
if (node.firstChild)
{
for (var child = node.firstChild; child; child = child.nextSibling)
appendNode(child, html);
html.push( node.nodeName.toLowerCase());
}
}
else if (node.nodeType == 3)
{
html.push(escapeHTML(node.nodeValue));
}
};
/**
* @author john resig & the envjs team
* @uri http://www.envjs.com/
* @copyright 2008-2010
* @license MIT
*/
})();
/*
* Envjs dom.1.2.0.0
* Pure JavaScript Browser Environment
* By John Resig <http://ejohn.org/> and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*
* Parts of the implementation were originally written by:\
* and Jon van Noort (jon@webarcana.com.au) \
* and David Joham (djoham@yahoo.com)",\
* and Scott Severtson
*
* This file simply provides the global definitions we need to \
* be able to correctly implement to core browser DOM interfaces."
*/
var Attr,
CDATASection,
CharacterData,
Comment,
Document,
DocumentFragment,
DocumentType,
DOMException,
DOMImplementation,
Element,
Entity,
EntityReference,
NamedNodeMap,
Namespace,
Node,
NodeList,
Notation,
ProcessingInstruction,
Text,
Range,
XMLSerializer,
DOMParser;
/*
* Envjs dom.1.2.0.0
* Pure JavaScript Browser Environment
* By John Resig <http://ejohn.org/> and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
(function(){
/**
* @author john resig
*/
// Helper method for extending one object with another.
function __extend__(a,b) {
for ( var i in b ) {
var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
if ( g || s ) {
if ( g ) a.__defineGetter__(i, g);
if ( s ) a.__defineSetter__(i, s);
} else
a[i] = b[i];
} return a;
};
/**
* @author john resig
*/
//from jQuery
function __setArray__( target, array ) {
// Resetting the length to 0, then using the native Array push
// is a super-fast way to populate an object with array-like properties
target.length = 0;
Array.prototype.push.apply( target, array );
};
/**
* @class NodeList -
* provides the abstraction of an ordered collection of nodes
*
* @param ownerDocument : Document - the ownerDocument
* @param parentNode : Node - the node that the NodeList is attached to (or null)
*/
NodeList = function(ownerDocument, parentNode) {
this.length = 0;
this.parentNode = parentNode;
this.ownerDocument = ownerDocument;
this._readonly = false;
__setArray__(this, []);
};
__extend__(NodeList.prototype, {
item : function(index) {
var ret = null;
if ((index >= 0) && (index < this.length)) {
// bounds check
ret = this[index];
}
// if the index is out of bounds, default value null is returned
return ret;
},
get xml() {
var ret = "",
i;
// create string containing the concatenation of the string values of each child
for (i=0; i < this.length; i++) {
if(this[i]){
if(this[i].nodeType == Node.TEXT_NODE && i>0 &&
this[i-1].nodeType == Node.TEXT_NODE){
//add a single space between adjacent text nodes
ret += " "+this[i].xml;
}else{
ret += this[i].xml;
}
}
}
return ret;
},
toArray: function () {
var children = [],
i;
for ( i=0; i < this.length; i++) {
children.push (this[i]);
}
return children;
},
toString: function(){
return "[object NodeList]";
}
});
/**
* @method __findItemIndex__
* find the item index of the node
* @author Jon van Noort (jon@webarcana.com.au)
* @param node : Node
* @return : int
*/
var __findItemIndex__ = function (nodelist, node) {
var ret = -1, i;
for (i=0; i<nodelist.length; i++) {
// compare id to each node's _id
if (nodelist[i] === node) {
// found it!
ret = i;
break;
}
}
// if node is not found, default value -1 is returned
return ret;
};
/**
* @method __insertBefore__
* insert the specified Node into the NodeList before the specified index
* Used by Node.insertBefore(). Note: Node.insertBefore() is responsible
* for Node Pointer surgery __insertBefore__ simply modifies the internal
* data structure (Array).
* @param newChild : Node - the Node to be inserted
* @param refChildIndex : int - the array index to insert the Node before
*/
var __insertBefore__ = function(nodelist, newChild, refChildIndex) {
if ((refChildIndex >= 0) && (refChildIndex <= nodelist.length)) {
// bounds check
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// node is a DocumentFragment
// append the children of DocumentFragment
Array.prototype.splice.apply(nodelist,
[refChildIndex, 0].concat(newChild.childNodes.toArray()));
}
else {
// append the newChild
Array.prototype.splice.apply(nodelist,[refChildIndex, 0, newChild]);
}
}
};
/**
* @method __replaceChild__
* replace the specified Node in the NodeList at the specified index
* Used by Node.replaceChild(). Note: Node.replaceChild() is responsible
* for Node Pointer surgery __replaceChild__ simply modifies the internal
* data structure (Array).
*
* @param newChild : Node - the Node to be inserted
* @param refChildIndex : int - the array index to hold the Node
*/
var __replaceChild__ = function(nodelist, newChild, refChildIndex) {
var ret = null;
// bounds check
if ((refChildIndex >= 0) && (refChildIndex < nodelist.length)) {
// preserve old child for return
ret = nodelist[refChildIndex];
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// node is a DocumentFragment
// get array containing children prior to refChild
Array.prototype.splice.apply(nodelist,
[refChildIndex, 1].concat(newChild.childNodes.toArray()));
}
else {
// simply replace node in array (links between Nodes are
// made at higher level)
nodelist[refChildIndex] = newChild;
}
}
// return replaced node
return ret;
};
/**
* @method __removeChild__
* remove the specified Node in the NodeList at the specified index
* Used by Node.removeChild(). Note: Node.removeChild() is responsible
* for Node Pointer surgery __removeChild__ simply modifies the internal
* data structure (Array).
* @param refChildIndex : int - the array index holding the Node to be removed
*/
var __removeChild__ = function(nodelist, refChildIndex) {
var ret = null;
if (refChildIndex > -1) {
// found it!
// return removed node
ret = nodelist[refChildIndex];
// rebuild array without removed child
Array.prototype.splice.apply(nodelist,[refChildIndex, 1]);
}
// return removed node
return ret;
};
/**
* @method __appendChild__
* append the specified Node to the NodeList. Used by Node.appendChild().
* Note: Node.appendChild() is responsible for Node Pointer surgery
* __appendChild__ simply modifies the internal data structure (Array).
* @param newChild : Node - the Node to be inserted
*/
var __appendChild__ = function(nodelist, newChild) {
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// node is a DocumentFragment
// append the children of DocumentFragment
Array.prototype.push.apply(nodelist, newChild.childNodes.toArray() );
} else {
// simply add node to array (links between Nodes are made at higher level)
Array.prototype.push.apply(nodelist, [newChild]);
}
};
/**
* @method __cloneNodes__ -
* Returns a NodeList containing clones of the Nodes in this NodeList
* @param deep : boolean -
* If true, recursively clone the subtree under each of the nodes;
* if false, clone only the nodes themselves (and their attributes,
* if it is an Element).
* @param parentNode : Node - the new parent of the cloned NodeList
* @return : NodeList - NodeList containing clones of the Nodes in this NodeList
*/
var __cloneNodes__ = function(nodelist, deep, parentNode) {
var cloneNodeList = new NodeList(nodelist.ownerDocument, parentNode);
// create list containing clones of each child
for (var i=0; i < nodelist.length; i++) {
__appendChild__(cloneNodeList, nodelist[i].cloneNode(deep));
}
return cloneNodeList;
};
/**
* @class NamedNodeMap -
* used to represent collections of nodes that can be accessed by name
* typically a set of Element attributes
*
* @extends NodeList -
* note W3C spec says that this is not the case, but we need an item()
* method identical to NodeList's, so why not?
* @param ownerDocument : Document - the ownerDocument
* @param parentNode : Node - the node that the NamedNodeMap is attached to (or null)
*/
NamedNodeMap = function(ownerDocument, parentNode) {
NodeList.apply(this, arguments);
__setArray__(this, []);
};
NamedNodeMap.prototype = new NodeList;
__extend__(NamedNodeMap.prototype, {
add: function(name){
this[this.length] = name;
},
getNamedItem : function(name) {
var ret = null;
//console.log('NamedNodeMap getNamedItem %s', name);
// test that Named Node exists
var itemIndex = __findNamedItemIndex__(this, name);
if (itemIndex > -1) {
// found it!
ret = this[itemIndex];
}
// if node is not found, default value null is returned
return ret;
},
setNamedItem : function(arg) {
//console.log('setNamedItem %s', arg);
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if arg was not created by this Document
if (this.ownerDocument != arg.ownerDocument) {
throw(new DOMException(DOMException.WRONG_DOCUMENT_ERR));
}
// throw Exception if DOMNamedNodeMap is readonly
if (this._readonly || (this.parentNode && this.parentNode._readonly)) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if arg is already an attribute of another Element object
if (arg.ownerElement && (arg.ownerElement != this.parentNode)) {
throw(new DOMException(DOMException.INUSE_ATTRIBUTE_ERR));
}
}
//console.log('setNamedItem __findNamedItemIndex__ ');
// get item index
var itemIndex = __findNamedItemIndex__(this, arg.name);
var ret = null;
//console.log('setNamedItem __findNamedItemIndex__ %s', itemIndex);
if (itemIndex > -1) { // found it!
ret = this[itemIndex]; // use existing Attribute
// throw Exception if DOMAttr is readonly
if (__ownerDocument__(this).implementation.errorChecking && ret._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
} else {
this[itemIndex] = arg; // over-write existing NamedNode
this[arg.name.toLowerCase()] = arg;
}
} else {
// add new NamedNode
//console.log('setNamedItem add new named node map (by index)');
Array.prototype.push.apply(this, [arg]);
//console.log('setNamedItem add new named node map (by name) %s %s', arg, arg.name);
this[arg.name] = arg;
//console.log('finsished setNamedItem add new named node map (by name) %s', arg.name);
}
//console.log('setNamedItem parentNode');
arg.ownerElement = this.parentNode; // update ownerElement
// return old node or new node
//console.log('setNamedItem exit');
return ret;
},
removeNamedItem : function(name) {
var ret = null;
// test for exceptions
// throw Exception if NamedNodeMap is readonly
if (__ownerDocument__(this).implementation.errorChecking &&
(this._readonly || (this.parentNode && this.parentNode._readonly))) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// get item index
var itemIndex = __findNamedItemIndex__(this, name);
// throw Exception if there is no node named name in this map
if (__ownerDocument__(this).implementation.errorChecking && (itemIndex < 0)) {
throw(new DOMException(DOMException.NOT_FOUND_ERR));
}
// get Node
var oldNode = this[itemIndex];
//this[oldNode.name] = undefined;
// throw Exception if Node is readonly
if (__ownerDocument__(this).implementation.errorChecking && oldNode._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// return removed node
return __removeChild__(this, itemIndex);
},
getNamedItemNS : function(namespaceURI, localName) {
var ret = null;
// test that Named Node exists
var itemIndex = __findNamedItemNSIndex__(this, namespaceURI, localName);
if (itemIndex > -1) {
// found it! return NamedNode
ret = this[itemIndex];
}
// if node is not found, default value null is returned
return ret;
},
setNamedItemNS : function(arg) {
//console.log('setNamedItemNS %s', arg);
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if NamedNodeMap is readonly
if (this._readonly || (this.parentNode && this.parentNode._readonly)) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if arg was not created by this Document
if (__ownerDocument__(this) != __ownerDocument__(arg)) {
throw(new DOMException(DOMException.WRONG_DOCUMENT_ERR));
}
// throw Exception if arg is already an attribute of another Element object
if (arg.ownerElement && (arg.ownerElement != this.parentNode)) {
throw(new DOMException(DOMException.INUSE_ATTRIBUTE_ERR));
}
}
// get item index
var itemIndex = __findNamedItemNSIndex__(this, arg.namespaceURI, arg.localName);
var ret = null;
if (itemIndex > -1) {
// found it!
// use existing Attribute
ret = this[itemIndex];
// throw Exception if Attr is readonly
if (__ownerDocument__(this).implementation.errorChecking && ret._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
} else {
// over-write existing NamedNode
this[itemIndex] = arg;
}
}else {
// add new NamedNode
Array.prototype.push.apply(this, [arg]);
}
arg.ownerElement = this.parentNode;
// return old node or null
return ret;
//console.log('finished setNamedItemNS %s', arg);
},
removeNamedItemNS : function(namespaceURI, localName) {
var ret = null;
// test for exceptions
// throw Exception if NamedNodeMap is readonly
if (__ownerDocument__(this).implementation.errorChecking && (this._readonly || (this.parentNode && this.parentNode._readonly))) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// get item index
var itemIndex = __findNamedItemNSIndex__(this, namespaceURI, localName);
// throw Exception if there is no matching node in this map
if (__ownerDocument__(this).implementation.errorChecking && (itemIndex < 0)) {
throw(new DOMException(DOMException.NOT_FOUND_ERR));
}
// get Node
var oldNode = this[itemIndex];
// throw Exception if Node is readonly
if (__ownerDocument__(this).implementation.errorChecking && oldNode._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
return __removeChild__(this, itemIndex); // return removed node
},
get xml() {
var ret = "";
// create string containing concatenation of all (but last) Attribute string values (separated by spaces)
for (var i=0; i < this.length -1; i++) {
ret += this[i].xml +" ";
}
// add last Attribute to string (without trailing space)
if (this.length > 0) {
ret += this[this.length -1].xml;
}
return ret;
},
toString : function(){
return "[object NamedNodeMap]";
}
});
/**
* @method __findNamedItemIndex__
* find the item index of the node with the specified name
*
* @param name : string - the name of the required node
* @param isnsmap : if its a NamespaceNodeMap
* @return : int
*/
var __findNamedItemIndex__ = function(namednodemap, name, isnsmap) {
var ret = -1;
// loop through all nodes
for (var i=0; i<namednodemap.length; i++) {
// compare name to each node's nodeName
if(namednodemap[i].localName && name && isnsmap){
if (namednodemap[i].localName.toLowerCase() == name.toLowerCase()) {
// found it!
ret = i;
break;
}
}else{
if(namednodemap[i].name && name){
if (namednodemap[i].name.toLowerCase() == name.toLowerCase()) {
// found it!
ret = i;
break;
}
}
}
}
// if node is not found, default value -1 is returned
return ret;
};
/**
* @method __findNamedItemNSIndex__
* find the item index of the node with the specified
* namespaceURI and localName
*
* @param namespaceURI : string - the namespace URI of the required node
* @param localName : string - the local name of the required node
* @return : int
*/
var __findNamedItemNSIndex__ = function(namednodemap, namespaceURI, localName) {
var ret = -1;
// test that localName is not null
if (localName) {
// loop through all nodes
for (var i=0; i<namednodemap.length; i++) {
if(namednodemap[i].namespaceURI && namednodemap[i].localName){
// compare name to each node's namespaceURI and localName
if ((namednodemap[i].namespaceURI.toLowerCase() == namespaceURI.toLowerCase()) &&
(namednodemap[i].localName.toLowerCase() == localName.toLowerCase())) {
// found it!
ret = i;
break;
}
}
}
}
// if node is not found, default value -1 is returned
return ret;
};
/**
* @method __hasAttribute__
* Returns true if specified node exists
*
* @param name : string - the name of the required node
* @return : boolean
*/
var __hasAttribute__ = function(namednodemap, name) {
var ret = false;
// test that Named Node exists
var itemIndex = __findNamedItemIndex__(namednodemap, name);
if (itemIndex > -1) {
// found it!
ret = true;
}
// if node is not found, default value false is returned
return ret;
}
/**
* @method __hasAttributeNS__
* Returns true if specified node exists
*
* @param namespaceURI : string - the namespace URI of the required node
* @param localName : string - the local name of the required node
* @return : boolean
*/
var __hasAttributeNS__ = function(namednodemap, namespaceURI, localName) {
var ret = false;
// test that Named Node exists
var itemIndex = __findNamedItemNSIndex__(namednodemap, namespaceURI, localName);
if (itemIndex > -1) {
// found it!
ret = true;
}
// if node is not found, default value false is returned
return ret;
}
/**
* @method __cloneNamedNodes__
* Returns a NamedNodeMap containing clones of the Nodes in this NamedNodeMap
*
* @param parentNode : Node - the new parent of the cloned NodeList
* @param isnsmap : bool - is this a NamespaceNodeMap
* @return NamedNodeMap containing clones of the Nodes in this NamedNodeMap
*/
var __cloneNamedNodes__ = function(namednodemap, parentNode, isnsmap) {
var cloneNamedNodeMap = isnsmap?
new NamespaceNodeMap(namednodemap.ownerDocument, parentNode):
new NamedNodeMap(namednodemap.ownerDocument, parentNode);
// create list containing clones of all children
for (var i=0; i < namednodemap.length; i++) {
__appendChild__(cloneNamedNodeMap, namednodemap[i].cloneNode(false));
}
return cloneNamedNodeMap;
};
/**
* @class NamespaceNodeMap -
* used to represent collections of namespace nodes that can be
* accessed by name typically a set of Element attributes
*
* @extends NamedNodeMap
*
* @param ownerDocument : Document - the ownerDocument
* @param parentNode : Node - the node that the NamespaceNodeMap is attached to (or null)
*/
var NamespaceNodeMap = function(ownerDocument, parentNode) {
this.NamedNodeMap = NamedNodeMap;
this.NamedNodeMap(ownerDocument, parentNode);
__setArray__(this, []);
};
NamespaceNodeMap.prototype = new NamedNodeMap;
__extend__(NamespaceNodeMap.prototype, {
get xml() {
var ret = "",
ns,
ind;
// identify namespaces declared local to this Element (ie, not inherited)
for (ind = 0; ind < this.length; ind++) {
// if namespace declaration does not exist in the containing node's, parentNode's namespaces
ns = null;
try {
var ns = this.parentNode.parentNode._namespaces.
getNamedItem(this[ind].localName);
}catch (e) {
//breaking to prevent default namespace being inserted into return value
break;
}
if (!(ns && (""+ ns.nodeValue == ""+ this[ind].nodeValue))) {
// display the namespace declaration
ret += this[ind].xml +" ";
}
}
return ret;
}
});
/**
* @class Node -
* The Node interface is the primary datatype for the entire
* Document Object Model. It represents a single node in the
* document tree.
* @param ownerDocument : Document - The Document object associated with this node.
*/
Node = function(ownerDocument) {
this.baseURI = 'about:blank';
this.namespaceURI = null;
this.nodeName = "";
this.nodeValue = null;
// A NodeList that contains all children of this node. If there are no
// children, this is a NodeList containing no nodes. The content of the
// returned NodeList is "live" in the sense that, for instance, changes to
// the children of the node object that it was created from are immediately
// reflected in the nodes returned by the NodeList accessors; it is not a
// static snapshot of the content of the node. This is true for every
// NodeList, including the ones returned by the getElementsByTagName method.
this.childNodes = new NodeList(ownerDocument, this);
// The first child of this node. If there is no such node, this is null
this.firstChild = null;
// The last child of this node. If there is no such node, this is null.
this.lastChild = null;
// The node immediately preceding this node. If there is no such node,
// this is null.
this.previousSibling = null;
// The node immediately following this node. If there is no such node,
// this is null.
this.nextSibling = null;
this.attributes = null;
// The namespaces in scope for this node
this._namespaces = new NamespaceNodeMap(ownerDocument, this);
this._readonly = false;
//IMPORTANT: These must come last so rhino will not iterate parent
// properties before child properties. (qunit.equiv issue)
// The parent of this node. All nodes, except Document, DocumentFragment,
// and Attr may have a parent. However, if a node has just been created
// and not yet added to the tree, or if it has been removed from the tree,
// this is null
this.parentNode = null;
// The Document object associated with this node
this.ownerDocument = ownerDocument;
};
// nodeType constants
Node.ELEMENT_NODE = 1;
Node.ATTRIBUTE_NODE = 2;
Node.TEXT_NODE = 3;
Node.CDATA_SECTION_NODE = 4;
Node.ENTITY_REFERENCE_NODE = 5;
Node.ENTITY_NODE = 6;
Node.PROCESSING_INSTRUCTION_NODE = 7;
Node.COMMENT_NODE = 8;
Node.DOCUMENT_NODE = 9;
Node.DOCUMENT_TYPE_NODE = 10;
Node.DOCUMENT_FRAGMENT_NODE = 11;
Node.NOTATION_NODE = 12;
Node.NAMESPACE_NODE = 13;
Node.DOCUMENT_POSITION_EQUAL = 0x00;
Node.DOCUMENT_POSITION_DISCONNECTED = 0x01;
Node.DOCUMENT_POSITION_PRECEDING = 0x02;
Node.DOCUMENT_POSITION_FOLLOWING = 0x04;
Node.DOCUMENT_POSITION_CONTAINS = 0x08;
Node.DOCUMENT_POSITION_CONTAINED_BY = 0x10;
Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
__extend__(Node.prototype, {
get localName(){
return this.prefix?
this.nodeName.substring(this.prefix.length+1, this.nodeName.length):
this.nodeName;
},
get prefix(){
return this.nodeName.split(':').length>1?
this.nodeName.split(':')[0]:
null;
},
set prefix(value){
if(value === null){
this.nodeName = this.localName;
}else{
this.nodeName = value+':'+this.localName;
}
},
hasAttributes : function() {
if (this.attributes.length == 0) {
return false;
}else{
return true;
}
},
get textContent(){
return __recursivelyGatherText__(this);
},
set textContent(newText){
while(this.firstChild != null){
this.removeChild( this.firstChild );
}
var text = this.ownerDocument.createTextNode(newText);
this.appendChild(text);
},
insertBefore : function(newChild, refChild) {
var prevNode;
if(newChild==null){
return newChild;
}
if(refChild==null){
this.appendChild(newChild);
return this.newChild;
}
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if Node is readonly
if (this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if newChild was not created by this Document
if (__ownerDocument__(this) != __ownerDocument__(newChild)) {
throw(new DOMException(DOMException.WRONG_DOCUMENT_ERR));
}
// throw Exception if the node is an ancestor
if (__isAncestor__(this, newChild)) {
throw(new DOMException(DOMException.HIERARCHY_REQUEST_ERR));
}
}
// if refChild is specified, insert before it
if (refChild) {
// find index of refChild
var itemIndex = __findItemIndex__(this.childNodes, refChild);
// throw Exception if there is no child node with this id
if (__ownerDocument__(this).implementation.errorChecking && (itemIndex < 0)) {
throw(new DOMException(DOMException.NOT_FOUND_ERR));
}
// if the newChild is already in the tree,
var newChildParent = newChild.parentNode;
if (newChildParent) {
// remove it
newChildParent.removeChild(newChild);
}
// insert newChild into childNodes
__insertBefore__(this.childNodes, newChild, itemIndex);
// do node pointer surgery
prevNode = refChild.previousSibling;
// handle DocumentFragment
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
if (newChild.childNodes.length > 0) {
// set the parentNode of DocumentFragment's children
for (var ind = 0; ind < newChild.childNodes.length; ind++) {
newChild.childNodes[ind].parentNode = this;
}
// link refChild to last child of DocumentFragment
refChild.previousSibling = newChild.childNodes[newChild.childNodes.length-1];
}
}else {
// set the parentNode of the newChild
newChild.parentNode = this;
// link refChild to newChild
refChild.previousSibling = newChild;
}
}else {
// otherwise, append to end
prevNode = this.lastChild;
this.appendChild(newChild);
}
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// do node pointer surgery for DocumentFragment
if (newChild.childNodes.length > 0) {
if (prevNode) {
prevNode.nextSibling = newChild.childNodes[0];
}else {
// this is the first child in the list
this.firstChild = newChild.childNodes[0];
}
newChild.childNodes[0].previousSibling = prevNode;
newChild.childNodes[newChild.childNodes.length-1].nextSibling = refChild;
}
}else {
// do node pointer surgery for newChild
if (prevNode) {
prevNode.nextSibling = newChild;
}else {
// this is the first child in the list
this.firstChild = newChild;
}
newChild.previousSibling = prevNode;
newChild.nextSibling = refChild;
}
return newChild;
},
replaceChild : function(newChild, oldChild) {
var ret = null;
if(newChild==null || oldChild==null){
return oldChild;
}
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if Node is readonly
if (this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if newChild was not created by this Document
if (__ownerDocument__(this) != __ownerDocument__(newChild)) {
throw(new DOMException(DOMException.WRONG_DOCUMENT_ERR));
}
// throw Exception if the node is an ancestor
if (__isAncestor__(this, newChild)) {
throw(new DOMException(DOMException.HIERARCHY_REQUEST_ERR));
}
}
// get index of oldChild
var index = __findItemIndex__(this.childNodes, oldChild);
// throw Exception if there is no child node with this id
if (__ownerDocument__(this).implementation.errorChecking && (index < 0)) {
throw(new DOMException(DOMException.NOT_FOUND_ERR));
}
// if the newChild is already in the tree,
var newChildParent = newChild.parentNode;
if (newChildParent) {
// remove it
newChildParent.removeChild(newChild);
}
// add newChild to childNodes
ret = __replaceChild__(this.childNodes,newChild, index);
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// do node pointer surgery for Document Fragment
if (newChild.childNodes.length > 0) {
for (var ind = 0; ind < newChild.childNodes.length; ind++) {
newChild.childNodes[ind].parentNode = this;
}
if (oldChild.previousSibling) {
oldChild.previousSibling.nextSibling = newChild.childNodes[0];
} else {
this.firstChild = newChild.childNodes[0];
}
if (oldChild.nextSibling) {
oldChild.nextSibling.previousSibling = newChild;
} else {
this.lastChild = newChild.childNodes[newChild.childNodes.length-1];
}
newChild.childNodes[0].previousSibling = oldChild.previousSibling;
newChild.childNodes[newChild.childNodes.length-1].nextSibling = oldChild.nextSibling;
}
} else {
// do node pointer surgery for newChild
newChild.parentNode = this;
if (oldChild.previousSibling) {
oldChild.previousSibling.nextSibling = newChild;
}else{
this.firstChild = newChild;
}
if (oldChild.nextSibling) {
oldChild.nextSibling.previousSibling = newChild;
}else{
this.lastChild = newChild;
}
newChild.previousSibling = oldChild.previousSibling;
newChild.nextSibling = oldChild.nextSibling;
}
return ret;
},
removeChild : function(oldChild) {
if(!oldChild){
return null;
}
// throw Exception if NamedNodeMap is readonly
if (__ownerDocument__(this).implementation.errorChecking &&
(this._readonly || oldChild._readonly)) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// get index of oldChild
var itemIndex = __findItemIndex__(this.childNodes, oldChild);
// throw Exception if there is no child node with this id
if (__ownerDocument__(this).implementation.errorChecking && (itemIndex < 0)) {
throw(new DOMException(DOMException.NOT_FOUND_ERR));
}
// remove oldChild from childNodes
__removeChild__(this.childNodes, itemIndex);
// do node pointer surgery
oldChild.parentNode = null;
if (oldChild.previousSibling) {
oldChild.previousSibling.nextSibling = oldChild.nextSibling;
}else {
this.firstChild = oldChild.nextSibling;
}
if (oldChild.nextSibling) {
oldChild.nextSibling.previousSibling = oldChild.previousSibling;
}else {
this.lastChild = oldChild.previousSibling;
}
oldChild.previousSibling = null;
oldChild.nextSibling = null;
return oldChild;
},
appendChild : function(newChild) {
if(!newChild){
return null;
}
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if Node is readonly
if (this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if arg was not created by this Document
if (__ownerDocument__(this) != __ownerDocument__(this)) {
throw(new DOMException(DOMException.WRONG_DOCUMENT_ERR));
}
// throw Exception if the node is an ancestor
if (__isAncestor__(this, newChild)) {
throw(new DOMException(DOMException.HIERARCHY_REQUEST_ERR));
}
}
// if the newChild is already in the tree,
var newChildParent = newChild.parentNode;
if (newChildParent) {
// remove it
//console.debug('removing node %s', newChild);
newChildParent.removeChild(newChild);
}
// add newChild to childNodes
__appendChild__(this.childNodes, newChild);
if (newChild.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// do node pointer surgery for DocumentFragment
if (newChild.childNodes.length > 0) {
for (var ind = 0; ind < newChild.childNodes.length; ind++) {
newChild.childNodes[ind].parentNode = this;
}
if (this.lastChild) {
this.lastChild.nextSibling = newChild.childNodes[0];
newChild.childNodes[0].previousSibling = this.lastChild;
this.lastChild = newChild.childNodes[newChild.childNodes.length-1];
} else {
this.lastChild = newChild.childNodes[newChild.childNodes.length-1];
this.firstChild = newChild.childNodes[0];
}
}
} else {
// do node pointer surgery for newChild
newChild.parentNode = this;
if (this.lastChild) {
this.lastChild.nextSibling = newChild;
newChild.previousSibling = this.lastChild;
this.lastChild = newChild;
} else {
this.lastChild = newChild;
this.firstChild = newChild;
}
}
return newChild;
},
hasChildNodes : function() {
return (this.childNodes.length > 0);
},
cloneNode: function(deep) {
// use importNode to clone this Node
//do not throw any exceptions
try {
return __ownerDocument__(this).importNode(this, deep);
} catch (e) {
//there shouldn't be any exceptions, but if there are, return null
// may want to warn: $debug("could not clone node: "+e.code);
return null;
}
},
normalize : function() {
var inode;
var nodesToRemove = new NodeList();
if (this.nodeType == Node.ELEMENT_NODE || this.nodeType == Node.DOCUMENT_NODE) {
var adjacentTextNode = null;
// loop through all childNodes
for(var i = 0; i < this.childNodes.length; i++) {
inode = this.childNodes.item(i);
if (inode.nodeType == Node.TEXT_NODE) {
// this node is a text node
if (inode.length < 1) {
// this text node is empty
// add this node to the list of nodes to be remove
__appendChild__(nodesToRemove, inode);
}else {
if (adjacentTextNode) {
// previous node was also text
adjacentTextNode.appendData(inode.data);
// merge the data in adjacent text nodes
// add this node to the list of nodes to be removed
__appendChild__(nodesToRemove, inode);
} else {
// remember this node for next cycle
adjacentTextNode = inode;
}
}
} else {
// (soon to be) previous node is not a text node
adjacentTextNode = null;
// normalize non Text childNodes
inode.normalize();
}
}
// remove redundant Text Nodes
for(var i = 0; i < nodesToRemove.length; i++) {
inode = nodesToRemove.item(i);
inode.parentNode.removeChild(inode);
}
}
},
isSupported : function(feature, version) {
// use Implementation.hasFeature to determine if this feature is supported
return __ownerDocument__(this).implementation.hasFeature(feature, version);
},
getElementsByTagName : function(tagname) {
// delegate to _getElementsByTagNameRecursive
// recurse childNodes
var nodelist = new NodeList(__ownerDocument__(this));
for(var i = 0; i < this.childNodes.length; i++) {
nodeList = __getElementsByTagNameRecursive__(this.childNodes.item(i), tagname, nodelist);
}
return nodelist;
},
getElementsByTagNameNS : function(namespaceURI, localName) {
// delegate to _getElementsByTagNameNSRecursive
return __getElementsByTagNameNSRecursive__(this, namespaceURI, localName,
new NodeList(__ownerDocument__(this)));
},
importNode : function(importedNode, deep) {
var importNode;
//there is no need to perform namespace checks since everything has already gone through them
//in order to have gotten into the DOM in the first place. The following line
//turns namespace checking off in ._isValidNamespace
__ownerDocument__(this).importing = true;
if (importedNode.nodeType == Node.ELEMENT_NODE) {
if (!__ownerDocument__(this).implementation.namespaceAware) {
// create a local Element (with the name of the importedNode)
importNode = __ownerDocument__(this).createElement(importedNode.tagName);
// create attributes matching those of the importedNode
for(var i = 0; i < importedNode.attributes.length; i++) {
importNode.setAttribute(importedNode.attributes.item(i).name, importedNode.attributes.item(i).value);
}
}else {
// create a local Element (with the name & namespaceURI of the importedNode)
importNode = __ownerDocument__(this).createElementNS(importedNode.namespaceURI, importedNode.nodeName);
// create attributes matching those of the importedNode
for(var i = 0; i < importedNode.attributes.length; i++) {
importNode.setAttributeNS(importedNode.attributes.item(i).namespaceURI,
importedNode.attributes.item(i).name, importedNode.attributes.item(i).value);
}
// create namespace definitions matching those of the importedNode
for(var i = 0; i < importedNode._namespaces.length; i++) {
importNode._namespaces[i] = __ownerDocument__(this).createNamespace(importedNode._namespaces.item(i).localName);
importNode._namespaces[i].value = importedNode._namespaces.item(i).value;
}
}
} else if (importedNode.nodeType == Node.ATTRIBUTE_NODE) {
if (!__ownerDocument__(this).implementation.namespaceAware) {
// create a local Attribute (with the name of the importedAttribute)
importNode = __ownerDocument__(this).createAttribute(importedNode.name);
} else {
// create a local Attribute (with the name & namespaceURI of the importedAttribute)
importNode = __ownerDocument__(this).createAttributeNS(importedNode.namespaceURI, importedNode.nodeName);
// create namespace definitions matching those of the importedAttribute
for(var i = 0; i < importedNode._namespaces.length; i++) {
importNode._namespaces[i] = __ownerDocument__(this).createNamespace(importedNode._namespaces.item(i).localName);
importNode._namespaces[i].value = importedNode._namespaces.item(i).value;
}
}
// set the value of the local Attribute to match that of the importedAttribute
importNode.value = importedNode.value;
} else if (importedNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
// create a local DocumentFragment
importNode = __ownerDocument__(this).createDocumentFragment();
} else if (importedNode.nodeType == Node.NAMESPACE_NODE) {
// create a local NamespaceNode (with the same name & value as the importedNode)
importNode = __ownerDocument__(this).createNamespace(importedNode.nodeName);
importNode.value = importedNode.value;
} else if (importedNode.nodeType == Node.TEXT_NODE) {
// create a local TextNode (with the same data as the importedNode)
importNode = __ownerDocument__(this).createTextNode(importedNode.data);
} else if (importedNode.nodeType == Node.CDATA_SECTION_NODE) {
// create a local CDATANode (with the same data as the importedNode)
importNode = __ownerDocument__(this).createCDATASection(importedNode.data);
} else if (importedNode.nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
// create a local ProcessingInstruction (with the same target & data as the importedNode)
importNode = __ownerDocument__(this).createProcessingInstruction(importedNode.target, importedNode.data);
} else if (importedNode.nodeType == Node.COMMENT_NODE) {
// create a local Comment (with the same data as the importedNode)
importNode = __ownerDocument__(this).createComment(importedNode.data);
} else { // throw Exception if nodeType is not supported
throw(new DOMException(DOMException.NOT_SUPPORTED_ERR));
}
if (deep) {
// recurse childNodes
for(var i = 0; i < importedNode.childNodes.length; i++) {
importNode.appendChild(__ownerDocument__(this).importNode(importedNode.childNodes.item(i), true));
}
}
//reset importing
__ownerDocument__(this).importing = false;
return importNode;
},
contains : function(node){
while(node && node != this ){
node = node.parentNode;
}
return !!node;
},
compareDocumentPosition : function(b){
//console.log("comparing document position %s %s", this, b);
var i,
length,
a = this,
parent,
aparents,
bparents;
//handle a couple simpler case first
if(a === b)
return Node.DOCUMENT_POSITION_EQUAL;
if(a.ownerDocument !== b.ownerDocument)
return Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC|
Node.DOCUMENT_POSITION_FOLLOWING|
Node.DOCUMENT_POSITION_DISCONNECTED;
if(a.parentNode === b.parentNode){
length = a.parentNode.childNodes.length;
for(i=0;i<length;i++){
if(a.parentNode.childNodes[i] === a){
return Node.DOCUMENT_POSITION_FOLLOWING;
}else if(a.parentNode.childNodes[i] === b){
return Node.DOCUMENT_POSITION_PRECEDING;
}
}
}
if(a.contains(b))
return Node.DOCUMENT_POSITION_CONTAINED_BY|
Node.DOCUMENT_POSITION_FOLLOWING;
if(b.contains(a))
return Node.DOCUMENT_POSITION_CONTAINS|
Node.DOCUMENT_POSITION_PRECEDING;
aparents = [];
parent = a.parentNode;
while(parent){
aparents[aparents.length] = parent;
parent = parent.parentNode;
}
bparents = [];
parent = b.parentNode;
while(parent){
i = aparents.indexOf(parent);
if(i < 0){
bparents[bparents.length] = parent;
parent = parent.parentNode;
}else{
//i cant be 0 since we already checked for equal parentNode
if(bparents.length > aparents.length){
return Node.DOCUMENT_POSITION_FOLLOWING;
}else if(bparents.length < aparents.length){
return Node.DOCUMENT_POSITION_PRECEDING;
}else{
//common ancestor diverge point
if(i === 0)
return Node.DOCUMENT_POSITION_FOLLOWING;
else
parent = aparents[i-1];
return parent.compareDocumentPosition(bparents.pop());
}
}
}
return Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC|
Node.DOCUMENT_POSITION_DISCONNECTED;
},
toString : function(){
return "[object Node]";
}
});
/**
* @method __getElementsByTagNameRecursive__ - implements getElementsByTagName()
* @param elem : Element - The element which are checking and then recursing into
* @param tagname : string - The name of the tag to match on. The special value "*" matches all tags
* @param nodeList : NodeList - The accumulating list of matching nodes
*
* @return : NodeList
*/
var __getElementsByTagNameRecursive__ = function (elem, tagname, nodeList) {
if (elem.nodeType == Node.ELEMENT_NODE || elem.nodeType == Node.DOCUMENT_NODE) {
if(elem.nodeType !== Node.DOCUMENT_NODE &&
((elem.nodeName.toUpperCase() == tagname.toUpperCase()) ||
(tagname == "*")) ){
// add matching node to nodeList
__appendChild__(nodeList, elem);
}
// recurse childNodes
for(var i = 0; i < elem.childNodes.length; i++) {
nodeList = __getElementsByTagNameRecursive__(elem.childNodes.item(i), tagname, nodeList);
}
}
return nodeList;
};
/**
* @method __getElementsByTagNameNSRecursive__
* implements getElementsByTagName()
*
* @param elem : Element - The element which are checking and then recursing into
* @param namespaceURI : string - the namespace URI of the required node
* @param localName : string - the local name of the required node
* @param nodeList : NodeList - The accumulating list of matching nodes
*
* @return : NodeList
*/
var __getElementsByTagNameNSRecursive__ = function(elem, namespaceURI, localName, nodeList) {
if (elem.nodeType == Node.ELEMENT_NODE || elem.nodeType == Node.DOCUMENT_NODE) {
if (((elem.namespaceURI == namespaceURI) || (namespaceURI == "*")) &&
((elem.localName == localName) || (localName == "*"))) {
// add matching node to nodeList
__appendChild__(nodeList, elem);
}
// recurse childNodes
for(var i = 0; i < elem.childNodes.length; i++) {
nodeList = __getElementsByTagNameNSRecursive__(
elem.childNodes.item(i), namespaceURI, localName, nodeList);
}
}
return nodeList;
};
/**
* @method __isAncestor__ - returns true if node is ancestor of target
* @param target : Node - The node we are using as context
* @param node : Node - The candidate ancestor node
* @return : boolean
*/
var __isAncestor__ = function(target, node) {
// if this node matches, return true,
// otherwise recurse up (if there is a parentNode)
return ((target == node) || ((target.parentNode) && (__isAncestor__(target.parentNode, node))));
};
var __ownerDocument__ = function(node){
return (node.nodeType == Node.DOCUMENT_NODE)?node:node.ownerDocument;
};
var __recursivelyGatherText__ = function(aNode) {
var accumulateText = "",
idx,
node;
for (idx=0;idx < aNode.childNodes.length;idx++){
node = aNode.childNodes.item(idx);
if(node.nodeType == Node.TEXT_NODE)
accumulateText += node.data;
else
accumulateText += __recursivelyGatherText__(node);
}
return accumulateText;
};
/**
* function __escapeXML__
* @param str : string - The string to be escaped
* @return : string - The escaped string
*/
var escAmpRegEx = /&(?!(amp;|lt;|gt;|quot|apos;))/g;
var escLtRegEx = /</g;
var escGtRegEx = />/g;
var quotRegEx = /"/g;
var aposRegEx = /'/g;
function __escapeXML__(str) {
str = str.replace(escAmpRegEx, "&amp;").
replace(escLtRegEx, "&lt;").
replace(escGtRegEx, "&gt;").
replace(quotRegEx, "&quot;").
replace(aposRegEx, "&apos;");
return str;
};
/*
function __escapeHTML5__(str) {
str = str.replace(escAmpRegEx, "&amp;").
replace(escLtRegEx, "&lt;").
replace(escGtRegEx, "&gt;");
return str;
};
function __escapeHTML5Atribute__(str) {
str = str.replace(escAmpRegEx, "&amp;").
replace(escLtRegEx, "&lt;").
replace(escGtRegEx, "&gt;").
replace(quotRegEx, "&quot;").
replace(aposRegEx, "&apos;");
return str;
};
*/
/**
* function __unescapeXML__
* @param str : string - The string to be unescaped
* @return : string - The unescaped string
*/
var unescAmpRegEx = /&amp;/g;
var unescLtRegEx = /&lt;/g;
var unescGtRegEx = /&gt;/g;
var unquotRegEx = /&quot;/g;
var unaposRegEx = /&apos;/g;
function __unescapeXML__(str) {
str = str.replace(unescAmpRegEx, "&").
replace(unescLtRegEx, "<").
replace(unescGtRegEx, ">").
replace(unquotRegEx, "\"").
replace(unaposRegEx, "'");
return str;
};
/**
* @class Namespace -
* The Namespace interface represents an namespace in an Element object
*
* @param ownerDocument : The Document object associated with this node.
*/
Namespace = function(ownerDocument) {
Node.apply(this, arguments);
// the name of this attribute
this.name = "";
// If this attribute was explicitly given a value in the original document,
// this is true; otherwise, it is false.
// Note that the implementation is in charge of this attribute, not the user.
// If the user changes the value of the attribute (even if it ends up having
// the same value as the default value) then the specified flag is
// automatically flipped to true
this.specified = false;
};
Namespace.prototype = new Node;
__extend__(Namespace.prototype, {
get value(){
// the value of the attribute is returned as a string
return this.nodeValue;
},
set value(value){
this.nodeValue = value+'';
},
get nodeType(){
return Node.NAMESPACE_NODE;
},
get xml(){
var ret = "";
// serialize Namespace Declaration
if (this.nodeName != "") {
ret += this.nodeName +"=\""+ __escapeXML__(this.nodeValue) +"\"";
}
else { // handle default namespace
ret += "xmlns=\""+ __escapeXML__(this.nodeValue) +"\"";
}
return ret;
},
toString: function(){
return '[object Namespace]';
}
});
/**
* @class CharacterData - parent abstract class for Text and Comment
* @extends Node
* @param ownerDocument : The Document object associated with this node.
*/
CharacterData = function(ownerDocument) {
Node.apply(this, arguments);
};
CharacterData.prototype = new Node;
__extend__(CharacterData.prototype,{
get data(){
return this.nodeValue;
},
set data(data){
this.nodeValue = data;
},
get textContent(){
return this.nodeValue;
},
set textContent(newText){
this.nodeValue = newText;
},
get length(){return this.nodeValue.length;},
appendData: function(arg){
// throw Exception if CharacterData is readonly
if (__ownerDocument__(this).implementation.errorChecking && this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// append data
this.data = "" + this.data + arg;
},
deleteData: function(offset, count){
// throw Exception if CharacterData is readonly
if (__ownerDocument__(this).implementation.errorChecking && this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
if (this.data) {
// throw Exception if offset is negative or greater than the data length,
if (__ownerDocument__(this).implementation.errorChecking &&
((offset < 0) || (offset > this.data.length) || (count < 0))) {
throw(new DOMException(DOMException.INDEX_SIZE_ERR));
}
// delete data
if(!count || (offset + count) > this.data.length) {
this.data = this.data.substring(0, offset);
}else {
this.data = this.data.substring(0, offset).
concat(this.data.substring(offset + count));
}
}
},
insertData: function(offset, arg){
// throw Exception if CharacterData is readonly
if(__ownerDocument__(this).implementation.errorChecking && this._readonly){
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
if(this.data){
// throw Exception if offset is negative or greater than the data length,
if (__ownerDocument__(this).implementation.errorChecking &&
((offset < 0) || (offset > this.data.length))) {
throw(new DOMException(DOMException.INDEX_SIZE_ERR));
}
// insert data
this.data = this.data.substring(0, offset).concat(arg, this.data.substring(offset));
}else {
// throw Exception if offset is negative or greater than the data length,
if (__ownerDocument__(this).implementation.errorChecking && (offset != 0)) {
throw(new DOMException(DOMException.INDEX_SIZE_ERR));
}
// set data
this.data = arg;
}
},
replaceData: function(offset, count, arg){
// throw Exception if CharacterData is readonly
if (__ownerDocument__(this).implementation.errorChecking && this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
if (this.data) {
// throw Exception if offset is negative or greater than the data length,
if (__ownerDocument__(this).implementation.errorChecking &&
((offset < 0) || (offset > this.data.length) || (count < 0))) {
throw(new DOMException(DOMException.INDEX_SIZE_ERR));
}
// replace data
this.data = this.data.substring(0, offset).
concat(arg, this.data.substring(offset + count));
}else {
// set data
this.data = arg;
}
},
substringData: function(offset, count){
var ret = null;
if (this.data) {
// throw Exception if offset is negative or greater than the data length,
// or the count is negative
if (__ownerDocument__(this).implementation.errorChecking &&
((offset < 0) || (offset > this.data.length) || (count < 0))) {
throw(new DOMException(DOMException.INDEX_SIZE_ERR));
}
// if count is not specified
if (!count) {
ret = this.data.substring(offset); // default to 'end of string'
}else{
ret = this.data.substring(offset, offset + count);
}
}
return ret;
},
toString : function(){
return "[object CharacterData]";
}
});
/**
* @class Text
* The Text interface represents the textual content (termed
* character data in XML) of an Element or Attr.
* If there is no markup inside an element's content, the text is
* contained in a single object implementing the Text interface that
* is the only child of the element. If there is markup, it is
* parsed into a list of elements and Text nodes that form the
* list of children of the element.
* @extends CharacterData
* @param ownerDocument The Document object associated with this node.
*/
Text = function(ownerDocument) {
CharacterData.apply(this, arguments);
this.nodeName = "#text";
};
Text.prototype = new CharacterData;
__extend__(Text.prototype,{
get localName(){
return null;
},
// Breaks this Text node into two Text nodes at the specified offset,
// keeping both in the tree as siblings. This node then only contains
// all the content up to the offset point. And a new Text node, which
// is inserted as the next sibling of this node, contains all the
// content at and after the offset point.
splitText : function(offset) {
var data,
inode;
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if Node is readonly
if (this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if offset is negative or greater than the data length,
if ((offset < 0) || (offset > this.data.length)) {
throw(new DOMException(DOMException.INDEX_SIZE_ERR));
}
}
if (this.parentNode) {
// get remaining string (after offset)
data = this.substringData(offset);
// create new TextNode with remaining string
inode = __ownerDocument__(this).createTextNode(data);
// attach new TextNode
if (this.nextSibling) {
this.parentNode.insertBefore(inode, this.nextSibling);
} else {
this.parentNode.appendChild(inode);
}
// remove remaining string from original TextNode
this.deleteData(offset);
}
return inode;
},
get nodeType(){
return Node.TEXT_NODE;
},
get xml(){
return __escapeXML__(""+ this.nodeValue);
},
toString: function(){
return "[object Text]";
}
});
/**
* @class CDATASection
* CDATA sections are used to escape blocks of text containing
* characters that would otherwise be regarded as markup.
* The only delimiter that is recognized in a CDATA section is
* the "\]\]\>" string that ends the CDATA section
* @extends Text
* @param ownerDocument : The Document object associated with this node.
*/
CDATASection = function(ownerDocument) {
Text.apply(this, arguments);
this.nodeName = '#cdata-section';
};
CDATASection.prototype = new Text;
__extend__(CDATASection.prototype,{
get nodeType(){
return Node.CDATA_SECTION_NODE;
},
get xml(){
return "<![CDATA[" + this.nodeValue + "]]>";
},
toString : function(){
return "[object CDATASection]";
}
});
/**
* @class Comment
* This represents the content of a comment, i.e., all the
* characters between the starting '<!--' and ending '-->'
* @extends CharacterData
* @param ownerDocument : The Document object associated with this node.
*/
Comment = function(ownerDocument) {
CharacterData.apply(this, arguments);
this.nodeName = "#comment";
};
Comment.prototype = new CharacterData;
__extend__(Comment.prototype, {
get localName(){
return null;
},
get nodeType(){
return Node.COMMENT_NODE;
},
get xml(){
return "<!--" + this.nodeValue + "-->";
},
toString : function(){
return "[object Comment]";
}
});
/**
* @author envjs team
* @param {Document} onwnerDocument
*/
DocumentType = function(ownerDocument) {
Node.apply(this, arguments);
this.systemId = null;
this.publicId = null;
};
DocumentType.prototype = new Node;
__extend__({
get name(){
return this.nodeName;
},
get entities(){
return null;
},
get internalSubsets(){
return null;
},
get notations(){
return null;
},
toString : function(){
return "[object DocumentType]";
}
});
/**
* @class Attr
* The Attr interface represents an attribute in an Element object
* @extends Node
* @param ownerDocument : The Document object associated with this node.
*/
Attr = function(ownerDocument) {
Node.apply(this, arguments);
// set when Attr is added to NamedNodeMap
this.ownerElement = null;
//TODO: our implementation of Attr is incorrect because we don't
// treat the value of the attribute as a child text node.
};
Attr.prototype = new Node;
__extend__(Attr.prototype, {
// the name of this attribute
get name(){
return this.nodeName;
},
// the value of the attribute is returned as a string
get value(){
return this.nodeValue||'';
},
set value(value){
// throw Exception if Attribute is readonly
if (__ownerDocument__(this).implementation.errorChecking && this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// delegate to node
this.nodeValue = value;
},
get textContent(){
return this.nodeValue;
},
set textContent(newText){
this.nodeValue = newText;
},
get specified(){
return (this!==null&&this!=undefined);
},
get nodeType(){
return Node.ATTRIBUTE_NODE;
},
get xml(){
if(this.nodeValue)
return __escapeXML__(this.nodeValue+"");
else
return '';
},
toString : function(){
return "[object Attr]";
}
});
/**
* @class Element -
* By far the vast majority of objects (apart from text)
* that authors encounter when traversing a document are
* Element nodes.
* @extends Node
* @param ownerDocument : The Document object associated with this node.
*/
Element = function(ownerDocument) {
Node.apply(this, arguments);
this.attributes = new NamedNodeMap(this.ownerDocument, this);
};
Element.prototype = new Node;
__extend__(Element.prototype, {
// The name of the element.
get tagName(){
return this.nodeName;
},
getAttribute: function(name) {
var ret = null;
// if attribute exists, use it
var attr = this.attributes.getNamedItem(name);
if (attr) {
ret = attr.value;
}
// if Attribute exists, return its value, otherwise, return null
return ret;
},
setAttribute : function (name, value) {
// if attribute exists, use it
var attr = this.attributes.getNamedItem(name);
//console.log('attr %s', attr);
//I had to add this check because as the script initializes
//the id may be set in the constructor, and the html element
//overrides the id property with a getter/setter.
if(__ownerDocument__(this)){
if (attr===null||attr===undefined) {
// otherwise create it
attr = __ownerDocument__(this).createAttribute(name);
//console.log('attr %s', attr);
}
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if Attribute is readonly
if (attr._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if the value string contains an illegal character
if (!__isValidString__(value)) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
}
// assign values to properties (and aliases)
attr.value = value + '';
// add/replace Attribute in NamedNodeMap
this.attributes.setNamedItem(attr);
//console.log('element setNamedItem %s', attr);
}else{
console.warn('Element has no owner document '+this.tagName+
'\n\t cant set attribute ' + name + ' = '+value );
}
},
removeAttribute : function removeAttribute(name) {
// delegate to NamedNodeMap.removeNamedItem
return this.attributes.removeNamedItem(name);
},
getAttributeNode : function getAttributeNode(name) {
// delegate to NamedNodeMap.getNamedItem
return this.attributes.getNamedItem(name);
},
setAttributeNode: function(newAttr) {
// if this Attribute is an ID
if (__isIdDeclaration__(newAttr.name)) {
this.id = newAttr.value; // cache ID for getElementById()
}
// delegate to NamedNodeMap.setNamedItem
return this.attributes.setNamedItem(newAttr);
},
removeAttributeNode: function(oldAttr) {
// throw Exception if Attribute is readonly
if (__ownerDocument__(this).implementation.errorChecking && oldAttr._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// get item index
var itemIndex = this.attributes._findItemIndex(oldAttr._id);
// throw Exception if node does not exist in this map
if (__ownerDocument__(this).implementation.errorChecking && (itemIndex < 0)) {
throw(new DOMException(DOMException.NOT_FOUND_ERR));
}
return this.attributes._removeChild(itemIndex);
},
getAttributeNS : function(namespaceURI, localName) {
var ret = "";
// delegate to NAmedNodeMap.getNamedItemNS
var attr = this.attributes.getNamedItemNS(namespaceURI, localName);
if (attr) {
ret = attr.value;
}
return ret; // if Attribute exists, return its value, otherwise return ""
},
setAttributeNS : function(namespaceURI, qualifiedName, value) {
// call NamedNodeMap.getNamedItem
//console.log('setAttributeNS %s %s %s', namespaceURI, qualifiedName, value);
var attr = this.attributes.getNamedItem(namespaceURI, qualifiedName);
if (!attr) { // if Attribute exists, use it
// otherwise create it
attr = __ownerDocument__(this).createAttributeNS(namespaceURI, qualifiedName);
}
var value = value+'';
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if Attribute is readonly
if (attr._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
// throw Exception if the Namespace is invalid
if (!__isValidNamespace__(this.ownerDocument, namespaceURI, qualifiedName, true)) {
throw(new DOMException(DOMException.NAMESPACE_ERR));
}
// throw Exception if the value string contains an illegal character
if (!__isValidString__(value)) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
}
// if this Attribute is an ID
//if (__isIdDeclaration__(name)) {
// this.id = value;
//}
// assign values to properties (and aliases)
attr.value = value;
attr.nodeValue = value;
// delegate to NamedNodeMap.setNamedItem
this.attributes.setNamedItemNS(attr);
},
removeAttributeNS : function(namespaceURI, localName) {
// delegate to NamedNodeMap.removeNamedItemNS
return this.attributes.removeNamedItemNS(namespaceURI, localName);
},
getAttributeNodeNS : function(namespaceURI, localName) {
// delegate to NamedNodeMap.getNamedItemNS
return this.attributes.getNamedItemNS(namespaceURI, localName);
},
setAttributeNodeNS : function(newAttr) {
// if this Attribute is an ID
if ((newAttr.prefix == "") && __isIdDeclaration__(newAttr.name)) {
this.id = newAttr.value+''; // cache ID for getElementById()
}
// delegate to NamedNodeMap.setNamedItemNS
return this.attributes.setNamedItemNS(newAttr);
},
hasAttribute : function(name) {
// delegate to NamedNodeMap._hasAttribute
return __hasAttribute__(this.attributes,name);
},
hasAttributeNS : function(namespaceURI, localName) {
// delegate to NamedNodeMap._hasAttributeNS
return __hasAttributeNS__(this.attributes, namespaceURI, localName);
},
get nodeType(){
return Node.ELEMENT_NODE;
},
get xml() {
var ret = "",
ns = "",
attrs,
attrstring,
i;
// serialize namespace declarations
if (this.namespaceURI ){
if((this === this.ownerDocument.documentElement) ||
(!this.parentNode)||
(this.parentNode && (this.parentNode.namespaceURI !== this.namespaceURI)))
ns = ' xmlns'+(this.prefix?(':'+this.prefix):'')+
'="'+this.namespaceURI+'"';
}
// serialize Attribute declarations
attrs = this.attributes;
attrstring = "";
for(i=0;i< attrs.length;i++){
if(attrs[i].name.match('xmlns:'))
attrstring += " "+attrs[i].name+'="'+attrs[i].xml+'"';
}
for(i=0;i< attrs.length;i++){
if(!attrs[i].name.match('xmlns:'))
attrstring += " "+attrs[i].name+'="'+attrs[i].xml+'"';
}
if(this.hasChildNodes()){
// serialize this Element
ret += "<" + this.tagName + ns + attrstring +">";
ret += this.childNodes.xml;
ret += "</" + this.tagName + ">";
}else{
ret += "<" + this.tagName + ns + attrstring +"/>";
}
return ret;
},
toString : function(){
return '[object Element]';
}
});
/**
* @class DOMException - raised when an operation is impossible to perform
* @author Jon van Noort (jon@webarcana.com.au)
* @param code : int - the exception code (one of the DOMException constants)
*/
DOMException = function(code) {
this.code = code;
};
// DOMException constants
// Introduced in DOM Level 1:
DOMException.INDEX_SIZE_ERR = 1;
DOMException.DOMSTRING_SIZE_ERR = 2;
DOMException.HIERARCHY_REQUEST_ERR = 3;
DOMException.WRONG_DOCUMENT_ERR = 4;
DOMException.INVALID_CHARACTER_ERR = 5;
DOMException.NO_DATA_ALLOWED_ERR = 6;
DOMException.NO_MODIFICATION_ALLOWED_ERR = 7;
DOMException.NOT_FOUND_ERR = 8;
DOMException.NOT_SUPPORTED_ERR = 9;
DOMException.INUSE_ATTRIBUTE_ERR = 10;
// Introduced in DOM Level 2:
DOMException.INVALID_STATE_ERR = 11;
DOMException.SYNTAX_ERR = 12;
DOMException.INVALID_MODIFICATION_ERR = 13;
DOMException.NAMESPACE_ERR = 14;
DOMException.INVALID_ACCESS_ERR = 15;
/**
* @class DocumentFragment -
* DocumentFragment is a "lightweight" or "minimal" Document object.
* @extends Node
* @param ownerDocument : The Document object associated with this node.
*/
DocumentFragment = function(ownerDocument) {
Node.apply(this, arguments);
this.nodeName = "#document-fragment";
};
DocumentFragment.prototype = new Node;
__extend__(DocumentFragment.prototype,{
get nodeType(){
return Node.DOCUMENT_FRAGMENT_NODE;
},
get xml(){
var xml = "",
count = this.childNodes.length;
// create string concatenating the serialized ChildNodes
for (var i = 0; i < count; i++) {
xml += this.childNodes.item(i).xml;
}
return xml;
},
toString : function(){
return "[object DocumentFragment]";
},
get localName(){
return null;
}
});
/**
* @class ProcessingInstruction -
* The ProcessingInstruction interface represents a
* "processing instruction", used in XML as a way to
* keep processor-specific information in the text of
* the document
* @extends Node
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : The Document object associated with this node.
*/
ProcessingInstruction = function(ownerDocument) {
Node.apply(this, arguments);
};
ProcessingInstruction.prototype = new Node;
__extend__(ProcessingInstruction.prototype, {
get data(){
return this.nodeValue;
},
set data(data){
// throw Exception if Node is readonly
if (__ownerDocument__(this).errorChecking && this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
this.nodeValue = data;
},
get textContent(){
return this.data;
},
get localName(){
return null;
},
get target(){
// The target of this processing instruction.
// XML defines this as being the first token following the markup that begins the processing instruction.
// The content of this processing instruction.
return this.nodeName;
},
set target(value){
// The target of this processing instruction.
// XML defines this as being the first token following the markup that begins the processing instruction.
// The content of this processing instruction.
this.nodeName = value;
},
get nodeType(){
return Node.PROCESSING_INSTRUCTION_NODE;
},
get xml(){
return "<?" + this.nodeName +" "+ this.nodeValue + "?>";
},
toString : function(){
return "[object ProcessingInstruction]";
}
});
/**
* @author envjs team
*/
Entity = function() {
throw new Error("Entity Not Implemented" );
};
Entity.constants = {
// content taken from W3C "HTML 4.01 Specification"
// "W3C Recommendation 24 December 1999"
nbsp: "\u00A0",
iexcl: "\u00A1",
cent: "\u00A2",
pound: "\u00A3",
curren: "\u00A4",
yen: "\u00A5",
brvbar: "\u00A6",
sect: "\u00A7",
uml: "\u00A8",
copy: "\u00A9",
ordf: "\u00AA",
laquo: "\u00AB",
not: "\u00AC",
shy: "\u00AD",
reg: "\u00AE",
macr: "\u00AF",
deg: "\u00B0",
plusmn: "\u00B1",
sup2: "\u00B2",
sup3: "\u00B3",
acute: "\u00B4",
micro: "\u00B5",
para: "\u00B6",
middot: "\u00B7",
cedil: "\u00B8",
sup1: "\u00B9",
ordm: "\u00BA",
raquo: "\u00BB",
frac14: "\u00BC",
frac12: "\u00BD",
frac34: "\u00BE",
iquest: "\u00BF",
Agrave: "\u00C0",
Aacute: "\u00C1",
Acirc: "\u00C2",
Atilde: "\u00C3",
Auml: "\u00C4",
Aring: "\u00C5",
AElig: "\u00C6",
Ccedil: "\u00C7",
Egrave: "\u00C8",
Eacute: "\u00C9",
Ecirc: "\u00CA",
Euml: "\u00CB",
Igrave: "\u00CC",
Iacute: "\u00CD",
Icirc: "\u00CE",
Iuml: "\u00CF",
ETH: "\u00D0",
Ntilde: "\u00D1",
Ograve: "\u00D2",
Oacute: "\u00D3",
Ocirc: "\u00D4",
Otilde: "\u00D5",
Ouml: "\u00D6",
times: "\u00D7",
Oslash: "\u00D8",
Ugrave: "\u00D9",
Uacute: "\u00DA",
Ucirc: "\u00DB",
Uuml: "\u00DC",
Yacute: "\u00DD",
THORN: "\u00DE",
szlig: "\u00DF",
agrave: "\u00E0",
aacute: "\u00E1",
acirc: "\u00E2",
atilde: "\u00E3",
auml: "\u00E4",
aring: "\u00E5",
aelig: "\u00E6",
ccedil: "\u00E7",
egrave: "\u00E8",
eacute: "\u00E9",
ecirc: "\u00EA",
euml: "\u00EB",
igrave: "\u00EC",
iacute: "\u00ED",
icirc: "\u00EE",
iuml: "\u00EF",
eth: "\u00F0",
ntilde: "\u00F1",
ograve: "\u00F2",
oacute: "\u00F3",
ocirc: "\u00F4",
otilde: "\u00F5",
ouml: "\u00F6",
divide: "\u00F7",
oslash: "\u00F8",
ugrave: "\u00F9",
uacute: "\u00FA",
ucirc: "\u00FB",
uuml: "\u00FC",
yacute: "\u00FD",
thorn: "\u00FE",
yuml: "\u00FF",
fnof: "\u0192",
Alpha: "\u0391",
Beta: "\u0392",
Gamma: "\u0393",
Delta: "\u0394",
Epsilon: "\u0395",
Zeta: "\u0396",
Eta: "\u0397",
Theta: "\u0398",
Iota: "\u0399",
Kappa: "\u039A",
Lambda: "\u039B",
Mu: "\u039C",
Nu: "\u039D",
Xi: "\u039E",
Omicron: "\u039F",
Pi: "\u03A0",
Rho: "\u03A1",
Sigma: "\u03A3",
Tau: "\u03A4",
Upsilon: "\u03A5",
Phi: "\u03A6",
Chi: "\u03A7",
Psi: "\u03A8",
Omega: "\u03A9",
alpha: "\u03B1",
beta: "\u03B2",
gamma: "\u03B3",
delta: "\u03B4",
epsilon: "\u03B5",
zeta: "\u03B6",
eta: "\u03B7",
theta: "\u03B8",
iota: "\u03B9",
kappa: "\u03BA",