/*
* Envjs core-env.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig 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 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){};
/**
*
* @param {Object} event
*/
Envjs.defaultEventBehaviors = {};
/**
* 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 and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
var __context__ = Packages.org.mozilla.javascript.Context.getCurrentContext();
Envjs.platform = "Rhino";
Envjs.revision = "1.7.0.rc2";
/*
* Envjs rhino-env.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig 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;
};
/**
* Writes message to system out
* @param {Object} message
*/
Envjs.log = function(message){
print(message);
};
Envjs.lineSource = function(e){
return e&&e.rhinoException?e.rhinoException.lineSource():"(line ?)";
};
/**
* load and execute script tag text content
* @param {Object} script
*/
Envjs.loadInlineScript = function(script){
if(script.ownerDocument.ownerWindow){
Envjs.eval(
script.ownerDocument.ownerWindow,
script.text,
'eval('+script.text.substring(0,16)+'...):'+new Date().getTime()
);
}else{
Envjs.eval(
__this__,
script.text,
'eval('+script.text.substring(0,16)+'...):'+new Date().getTime()
);
}
//console.log('evaluated at scope %s \n%s',
// script.ownerDocument.ownerWindow.guid, script.text);
};
Envjs.eval = function(context, source, name){
__context__.evaluateString(
context,
source,
name,
0,
null
);
}
//Temporary patch for parser module
Packages.org.mozilla.javascript.Context.
getCurrentContext().setOptimizationLevel(-1);
/**
* Rhino provides a very succinct 'sync'
* @param {Function} fn
*/
try{
Envjs.sync = sync;
Envjs.spawn = spawn;
}catch(e){
//sync unavailable on AppEngine
Envjs.sync = function(fn){
console.log('Threadless platform, sync is safe');
return fn;
};
Envjs.spawn = function(fn){
console.log('Threadless platform, spawn shares main thread.');
return fn();
};
}
/**
* sleep thread for specified duration
* @param {Object} millseconds
*/
Envjs.sleep = function(millseconds){
try{
java.lang.Thread.currentThread().sleep(millseconds);
}catch(e){
console.log('Threadless platform, cannot sleep.');
}
};
/**
* provides callback hook for when the system exits
*/
Envjs.onExit = function(callback){
var rhino = Packages.org.mozilla.javascript,
contextFactory = __context__.getFactory(),
listener = new rhino.ContextFactory.Listener({
contextReleased: function(context){
if(context === __context__)
console.log('context released', context);
contextFactory.removeListener(this);
if(callback)
callback();
}
});
contextFactory.addListener(listener);
};
/**
* resolves location relative to doc location
* @param {Object} path
* @param {Object} path
* @param {Object} base
*/
Envjs.uri = function(path, base){
//console.log('constructing uri from path %s and base %s', path, base);
var protocol = new RegExp('(^file\:|^http\:|^https\:)'),
m = protocol.exec(path),
baseURI, absolutepath;
if(m&&m.length>1){
return (new java.net.URL(path).toString()+'')
.replace('file:/', 'file:///');
}else if(base){
baseURI = base.substring(0, base.lastIndexOf('/'));
if(baseURI.length > 0){
absolutepath = baseURI + '/' + path;
}else{
absolutepath = (new java.net.URL(new java.net.URL(base), path)+'')
.replace('file:/', 'file:///');
}
//console.log('constructed absolute path %s', absolutepath);
return absolutepath;
}else{
//return an absolute url from a url relative to the window location
//TODO: window should not be inlined here. this should be passed as a
// parameter to Envjs.location :DONE
if(document){
baseURI = document.baseURI;
if(baseURI == 'about:blank'){
//console.log('about:blank change: baseURI %s', document.baseURI);
baseURI = (java.io.File(path).toURL().toString()+'')
.replace('file:/', 'file:///');
//console.log('baseURI %s', baseURI);
return baseURI;
}else{
if(path.match(/^\//)){
//absolute path change
//console.log('absolute path change: baseURI %s', document.baseURI);
absolutepath = (new Location(baseURI)).pathname;
return baseURI.substring(0, baseURI.lastIndexOf(absolutepath)) + path;
}else{
//relative path change
//console.log('relative path change: baseURI %s', document.baseURI);
base = baseURI.substring(0, baseURI.lastIndexOf('/'));
if(base.length > 0){
return base + '/' + path;
}else{
return (new java.io.File(path).toURL().toString()+'')
.replace('file:/', 'file:///');
}
}
}
}else{
return (new java.io.File(path).toURL().toString()+'')
.replace('file:/', 'file:///');
}
}
};
/**
*
* @param {Object} fn
* @param {Object} onInterupt
*/
Envjs.runAsync = function(fn, onInterupt){
////Envjs.debug("running async");
var running = true,
run;
try{
run = Envjs.sync(function(){
fn();
Envjs.wait();
});
Envjs.spawn(run);
}catch(e){
console.log("error while running async operation", e);
try{if(onInterrupt)onInterrupt(e)}catch(ee){};
}
};
/**
* Used to write to a local file
* @param {Object} text
* @param {Object} url
*/
Envjs.writeToFile = function(text, url){
//Envjs.debug("writing text to url : " + url);
var out = new java.io.FileWriter(
new java.io.File(
new java.net.URI(url.toString())));
out.write( text, 0, text.length );
out.flush();
out.close();
};
/**
* Used to write to a local file
* @param {Object} text
* @param {Object} suffix
*/
Envjs.writeToTempFile = function(text, suffix){
//Envjs.debug("writing text to temp url : " + suffix);
// Create temp file.
var temp = java.io.File.createTempFile("envjs-tmp", suffix);
// Delete temp file when program exits.
temp.deleteOnExit();
// Write to temp file
var out = new java.io.FileWriter(temp);
out.write(text, 0, text.length);
out.close();
return temp.getAbsolutePath().toString()+'';
};
/**
* Used to delete a local file
* @param {Object} url
*/
Envjs.deleteFile = function(url){
var file = new java.io.File( new java.net.URI( url ) );
file["delete"]();
};
/**
* establishes connection and calls responsehandler
* @param {Object} xhr
* @param {Object} responseHandler
* @param {Object} data
*/
Envjs.connection = function(xhr, responseHandler, data){
var url = java.net.URL(xhr.url),
connection;
if ( /^file\:/.test(url) ) {
try{
if ( xhr.method == "PUT" ) {
var text = data || "" ;
Envjs.writeToFile(text, url);
} else if ( xhr.method == "DELETE" ) {
Envjs.deleteFile(url);
} else {
connection = url.openConnection();
connection.connect();
//try to add some canned headers that make sense
try{
if(xhr.url.match(/html$/)){
xhr.responseHeaders["Content-Type"] = 'text/html';
}else if(xhr.url.match(/.xml$/)){
xhr.responseHeaders["Content-Type"] = 'text/xml';
}else if(xhr.url.match(/.js$/)){
xhr.responseHeaders["Content-Type"] = 'text/javascript';
}else if(xhr.url.match(/.json$/)){
xhr.responseHeaders["Content-Type"] = 'application/json';
}else{
xhr.responseHeaders["Content-Type"] = 'text/plain';
}
//xhr.responseHeaders['Last-Modified'] = connection.getLastModified();
//xhr.responseHeaders['Content-Length'] = headerValue+'';
//xhr.responseHeaders['Date'] = new Date()+'';*/
}catch(e){
console.log('failed to load response headers',e);
}
}
}catch(e){
console.log('failed to open file %s %s', url, e);
connection = null;
xhr.readyState = 4;
xhr.statusText = "Local File Protocol Error";
xhr.responseText = "
"+ e+ "
";
}
} else {
connection = url.openConnection();
connection.setRequestMethod( xhr.method );
// Add headers to Java connection
for (var header in xhr.headers){
connection.addRequestProperty(header+'', xhr.headers[header]+'');
}
//write data to output stream if required
if(data&&data.length&&data.length>0){
if ( xhr.method == "PUT" || xhr.method == "POST" ) {
connection.setDoOutput(true);
var outstream = connection.getOutputStream(),
outbuffer = new java.lang.String(data).getBytes('UTF-8');
outstream.write(outbuffer, 0, outbuffer.length);
outstream.close();
}
}else{
connection.connect();
}
}
if(connection){
try{
var respheadlength = connection.getHeaderFields().size();
// Stick the response headers into responseHeaders
for (var i = 0; i < respheadlength; i++) {
var headerName = connection.getHeaderFieldKey(i);
var headerValue = connection.getHeaderField(i);
if (headerName)
xhr.responseHeaders[headerName+''] = headerValue+'';
}
}catch(e){
console.log('failed to load response headers \n%s',e);
}
xhr.readyState = 4;
xhr.status = parseInt(connection.responseCode,10) || undefined;
xhr.statusText = connection.responseMessage || "";
var contentEncoding = connection.getContentEncoding() || "utf-8",
baos = new java.io.ByteArrayOutputStream(),
buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 1024),
length,
stream = null,
responseXML = null;
try{
stream = (contentEncoding.equalsIgnoreCase("gzip") ||
contentEncoding.equalsIgnoreCase("decompress") )?
new java.util.zip.GZIPInputStream(connection.getInputStream()) :
connection.getInputStream();
}catch(e){
if (connection.getResponseCode() == 404){
console.log('failed to open connection stream \n %s %s',
e.toString(), e);
}else{
console.log('failed to open connection stream \n %s %s',
e.toString(), e);
}
stream = connection.getErrorStream();
}
while ((length = stream.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
baos.close();
stream.close();
xhr.responseText = java.nio.charset.Charset.forName("UTF-8").
decode(java.nio.ByteBuffer.wrap(baos.toByteArray())).toString()+"";
}
if(responseHandler){
//Envjs.debug('calling ajax response handler');
responseHandler();
}
};
//Since we're running in rhino I guess we can safely assume
//java is 'enabled'. I'm sure this requires more thought
//than I've given it here
Envjs.javaEnabled = true;
Envjs.tmpdir = java.lang.System.getProperty("java.io.tmpdir");
Envjs.os_name = java.lang.System.getProperty("os.name");
Envjs.os_arch = java.lang.System.getProperty("os.arch");
Envjs.os_version = java.lang.System.getProperty("os.version");
Envjs.lang = java.lang.System.getProperty("user.lang");
/**
*
* @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
frame.contentWindow = Envjs.proxy();
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);
}
};
/**
* unloadFrame
* @param {Object} frame
*/
Envjs.unloadFrame = function(frame){
var all, length, i;
try{
//clean up all the nodes
/*all = frame.contentDocument.all,
length = all.length;
for(i=0;i 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.6
* Pure JavaScript Browser Environment
* By John Resig 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.6
* Pure JavaScript Browser Environment
* By John Resig 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= 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 -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 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 quotRegEx = /"/g;
var aposRegEx = /'/g;
function __escapeXML__(str) {
str = str.replace(escAmpRegEx, "&").
replace(escLtRegEx, "<").
replace(escGtRegEx, ">").
replace(quotRegEx, """).
replace(aposRegEx, "'");
return str;
};
/*
function __escapeHTML5__(str) {
str = str.replace(escAmpRegEx, "&").
replace(escLtRegEx, "<").
replace(escGtRegEx, ">");
return str;
};
function __escapeHTML5Atribute__(str) {
str = str.replace(escAmpRegEx, "&").
replace(escLtRegEx, "<").
replace(escGtRegEx, ">").
replace(quotRegEx, """).
replace(aposRegEx, "'");
return str;
};
*/
/**
* function __unescapeXML__
* @param str : string - The string to be unescaped
* @return : string - The unescaped string
*/
var unescAmpRegEx = /&/g;
var unescLtRegEx = /</g;
var unescGtRegEx = />/g;
var unquotRegEx = /"/g;
var unaposRegEx = /'/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 "";
},
toString : function(){
return "[object CDATASection]";
}
});
/**
* @class Comment
* This represents the content of a comment, i.e., all the
* characters between the starting ''
* @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 "";
},
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",
lambda: "\u03BB",
mu: "\u03BC",
nu: "\u03BD",
xi: "\u03BE",
omicron: "\u03BF",
pi: "\u03C0",
rho: "\u03C1",
sigmaf: "\u03C2",
sigma: "\u03C3",
tau: "\u03C4",
upsilon: "\u03C5",
phi: "\u03C6",
chi: "\u03C7",
psi: "\u03C8",
omega: "\u03C9",
thetasym: "\u03D1",
upsih: "\u03D2",
piv: "\u03D6",
bull: "\u2022",
hellip: "\u2026",
prime: "\u2032",
Prime: "\u2033",
oline: "\u203E",
frasl: "\u2044",
weierp: "\u2118",
image: "\u2111",
real: "\u211C",
trade: "\u2122",
alefsym: "\u2135",
larr: "\u2190",
uarr: "\u2191",
rarr: "\u2192",
darr: "\u2193",
harr: "\u2194",
crarr: "\u21B5",
lArr: "\u21D0",
uArr: "\u21D1",
rArr: "\u21D2",
dArr: "\u21D3",
hArr: "\u21D4",
forall: "\u2200",
part: "\u2202",
exist: "\u2203",
empty: "\u2205",
nabla: "\u2207",
isin: "\u2208",
notin: "\u2209",
ni: "\u220B",
prod: "\u220F",
sum: "\u2211",
minus: "\u2212",
lowast: "\u2217",
radic: "\u221A",
prop: "\u221D",
infin: "\u221E",
ang: "\u2220",
and: "\u2227",
or: "\u2228",
cap: "\u2229",
cup: "\u222A",
intXX: "\u222B",
there4: "\u2234",
sim: "\u223C",
cong: "\u2245",
asymp: "\u2248",
ne: "\u2260",
equiv: "\u2261",
le: "\u2264",
ge: "\u2265",
sub: "\u2282",
sup: "\u2283",
nsub: "\u2284",
sube: "\u2286",
supe: "\u2287",
oplus: "\u2295",
otimes: "\u2297",
perp: "\u22A5",
sdot: "\u22C5",
lceil: "\u2308",
rceil: "\u2309",
lfloor: "\u230A",
rfloor: "\u230B",
lang: "\u2329",
rang: "\u232A",
loz: "\u25CA",
spades: "\u2660",
clubs: "\u2663",
hearts: "\u2665",
diams: "\u2666",
quot: "\u0022",
amp: "\u0026",
lt: "\u003C",
gt: "\u003E",
OElig: "\u0152",
oelig: "\u0153",
Scaron: "\u0160",
scaron: "\u0161",
Yuml: "\u0178",
circ: "\u02C6",
tilde: "\u02DC",
ensp: "\u2002",
emsp: "\u2003",
thinsp: "\u2009",
zwnj: "\u200C",
zwj: "\u200D",
lrm: "\u200E",
rlm: "\u200F",
ndash: "\u2013",
mdash: "\u2014",
lsquo: "\u2018",
rsquo: "\u2019",
sbquo: "\u201A",
ldquo: "\u201C",
rdquo: "\u201D",
bdquo: "\u201E",
dagger: "\u2020",
Dagger: "\u2021",
permil: "\u2030",
lsaquo: "\u2039",
rsaquo: "\u203A",
euro: "\u20AC",
// non-standard entities
apos: "'"
};
/**
* @author envjs team
*/
EntityReference = function() {
throw new Error("EntityReference Not Implemented" );
};
/**
* @class DOMImplementation -
* provides a number of methods for performing operations
* that are independent of any particular instance of the
* document object model.
*
* @author Jon van Noort (jon@webarcana.com.au)
*/
DOMImplementation = function() {
this.preserveWhiteSpace = false; // by default, ignore whitespace
this.namespaceAware = true; // by default, handle namespaces
this.errorChecking = true; // by default, test for exceptions
};
__extend__(DOMImplementation.prototype,{
// @param feature : string - The package name of the feature to test.
// the legal only values are "XML" and "CORE" (case-insensitive).
// @param version : string - This is the version number of the package
// name to test. In Level 1, this is the string "1.0".*
// @return : boolean
hasFeature : function(feature, version) {
var ret = false;
if (feature.toLowerCase() == "xml") {
ret = (!version || (version == "1.0") || (version == "2.0"));
}
else if (feature.toLowerCase() == "core") {
ret = (!version || (version == "2.0"));
}
else if (feature == "http://www.w3.org/TR/SVG11/feature#BasicStructure") {
ret = (version == "1.1");
}
return ret;
},
createDocumentType : function(qname, publicId, systemId){
var doctype = new DocumentType();
doctype.nodeName = qname?qname.toUpperCase():null;
doctype.publicId = publicId?publicId:null;
doctype.systemId = systemId?systemId:null;
return doctype;
},
createDocument : function(nsuri, qname, doctype){
var doc = null, documentElement;
doc = new Document(this, null);
if(doctype){
doc.doctype = doctype;
}
if(nsuri && qname){
documentElement = doc.createElementNS(nsuri, qname);
}else if(qname){
documentElement = doc.createElement(qname);
}
if(documentElement){
doc.appendChild(documentElement);
}
return doc;
},
createHTMLDocument : function(title){
var doc = new HTMLDocument($implementation, null, "");
var html = doc.createElement("html"); doc.appendChild(html);
var head = doc.createElement("head"); html.appendChild(head);
var body = doc.createElement("body"); html.appendChild(body);
var t = doc.createElement("title"); head.appendChild(t);
if( title) {
t.appendChild(doc.createTextNode(title));
}
return doc;
},
translateErrCode : function(code) {
//convert DOMException Code to human readable error message;
var msg = "";
switch (code) {
case DOMException.INDEX_SIZE_ERR : // 1
msg = "INDEX_SIZE_ERR: Index out of bounds";
break;
case DOMException.DOMSTRING_SIZE_ERR : // 2
msg = "DOMSTRING_SIZE_ERR: The resulting string is too long to fit in a DOMString";
break;
case DOMException.HIERARCHY_REQUEST_ERR : // 3
msg = "HIERARCHY_REQUEST_ERR: The Node can not be inserted at this location";
break;
case DOMException.WRONG_DOCUMENT_ERR : // 4
msg = "WRONG_DOCUMENT_ERR: The source and the destination Documents are not the same";
break;
case DOMException.INVALID_CHARACTER_ERR : // 5
msg = "INVALID_CHARACTER_ERR: The string contains an invalid character";
break;
case DOMException.NO_DATA_ALLOWED_ERR : // 6
msg = "NO_DATA_ALLOWED_ERR: This Node / NodeList does not support data";
break;
case DOMException.NO_MODIFICATION_ALLOWED_ERR : // 7
msg = "NO_MODIFICATION_ALLOWED_ERR: This object cannot be modified";
break;
case DOMException.NOT_FOUND_ERR : // 8
msg = "NOT_FOUND_ERR: The item cannot be found";
break;
case DOMException.NOT_SUPPORTED_ERR : // 9
msg = "NOT_SUPPORTED_ERR: This implementation does not support function";
break;
case DOMException.INUSE_ATTRIBUTE_ERR : // 10
msg = "INUSE_ATTRIBUTE_ERR: The Attribute has already been assigned to another Element";
break;
// Introduced in DOM Level 2:
case DOMException.INVALID_STATE_ERR : // 11
msg = "INVALID_STATE_ERR: The object is no longer usable";
break;
case DOMException.SYNTAX_ERR : // 12
msg = "SYNTAX_ERR: Syntax error";
break;
case DOMException.INVALID_MODIFICATION_ERR : // 13
msg = "INVALID_MODIFICATION_ERR: Cannot change the type of the object";
break;
case DOMException.NAMESPACE_ERR : // 14
msg = "NAMESPACE_ERR: The namespace declaration is incorrect";
break;
case DOMException.INVALID_ACCESS_ERR : // 15
msg = "INVALID_ACCESS_ERR: The object does not support this function";
break;
default :
msg = "UNKNOWN: Unknown Exception Code ("+ code +")";
}
return msg;
},
toString : function(){
return "[object DOMImplementation]";
}
});
/**
* @method DOMImplementation._isNamespaceDeclaration - Return true, if attributeName is a namespace declaration
* @author Jon van Noort (jon@webarcana.com.au)
* @param attributeName : string - the attribute name
* @return : boolean
*/
function __isNamespaceDeclaration__(attributeName) {
// test if attributeName is 'xmlns'
return (attributeName.indexOf('xmlns') > -1);
};
/**
* @method DOMImplementation._isIdDeclaration - Return true, if attributeName is an id declaration
* @author Jon van Noort (jon@webarcana.com.au)
* @param attributeName : string - the attribute name
* @return : boolean
*/
function __isIdDeclaration__(attributeName) {
// test if attributeName is 'id' (case insensitive)
return attributeName?(attributeName.toLowerCase() == 'id'):false;
};
/**
* @method DOMImplementation._isValidName - Return true,
* if name contains no invalid characters
* @author Jon van Noort (jon@webarcana.com.au)
* @param name : string - the candidate name
* @return : boolean
*/
function __isValidName__(name) {
// test if name contains only valid characters
return name.match(re_validName);
};
var re_validName = /^[a-zA-Z_:][a-zA-Z0-9\.\-_:]*$/;
/**
* @method DOMImplementation._isValidString - Return true, if string does not contain any illegal chars
* All of the characters 0 through 31 and character 127 are nonprinting control characters.
* With the exception of characters 09, 10, and 13, (Ox09, Ox0A, and Ox0D)
* Note: different from _isValidName in that ValidStrings may contain spaces
* @author Jon van Noort (jon@webarcana.com.au)
* @param name : string - the candidate string
* @return : boolean
*/
function __isValidString__(name) {
// test that string does not contains invalid characters
return (name.search(re_invalidStringChars) < 0);
};
var re_invalidStringChars = /\x01|\x02|\x03|\x04|\x05|\x06|\x07|\x08|\x0B|\x0C|\x0E|\x0F|\x10|\x11|\x12|\x13|\x14|\x15|\x16|\x17|\x18|\x19|\x1A|\x1B|\x1C|\x1D|\x1E|\x1F|\x7F/;
/**
* @method DOMImplementation._parseNSName - parse the namespace name.
* if there is no colon, the
* @author Jon van Noort (jon@webarcana.com.au)
* @param qualifiedName : string - The qualified name
* @return : NSName - [
.prefix : string - The prefix part of the qname
.namespaceName : string - The namespaceURI part of the qname
]
*/
function __parseNSName__(qualifiedName) {
var resultNSName = {};
// unless the qname has a namespaceName, the prefix is the entire String
resultNSName.prefix = qualifiedName;
resultNSName.namespaceName = "";
// split on ':'
var delimPos = qualifiedName.indexOf(':');
if (delimPos > -1) {
// get prefix
resultNSName.prefix = qualifiedName.substring(0, delimPos);
// get namespaceName
resultNSName.namespaceName = qualifiedName.substring(delimPos +1, qualifiedName.length);
}
return resultNSName;
};
/**
* @method DOMImplementation._parseQName - parse the qualified name
* @author Jon van Noort (jon@webarcana.com.au)
* @param qualifiedName : string - The qualified name
* @return : QName
*/
function __parseQName__(qualifiedName) {
var resultQName = {};
// unless the qname has a prefix, the local name is the entire String
resultQName.localName = qualifiedName;
resultQName.prefix = "";
// split on ':'
var delimPos = qualifiedName.indexOf(':');
if (delimPos > -1) {
// get prefix
resultQName.prefix = qualifiedName.substring(0, delimPos);
// get localName
resultQName.localName = qualifiedName.substring(delimPos +1, qualifiedName.length);
}
return resultQName;
};
// Local Variables:
// espresso-indent-level:4
// c-basic-offset:4
// tab-width:4
// End:
/**
* @author envjs team
*/
Notation = function() {
throw new Error("Notation Not Implemented" );
};/**
* @author thatcher
*/
Range = function(){
};
__extend__(Range.prototype, {
get startContainer(){
},
get endContainer(){
},
get startOffset(){
},
get endOffset(){
},
get collapsed(){
},
get commonAncestorContainer(){
},
setStart: function(refNode, offset){//throws RangeException
},
setEnd: function(refNode, offset){//throws RangeException
},
setStartBefore: function(refNode){//throws RangeException
},
setStartAfter: function(refNode){//throws RangeException
},
setEndBefore: function(refNode){//throws RangeException
},
setEndAfter: function(refNode){//throws RangeException
},
collapse: function(toStart){//throws RangeException
},
selectNode: function(refNode){//throws RangeException
},
selectNodeContents: function(refNode){//throws RangeException
},
compareBoundaryPoints: function(how, sourceRange){
},
deleteContents: function(){
},
extractContents: function(){
},
cloneContents: function(){
},
insertNode: function(newNode){
},
surroundContents: function(newParent){
},
cloneRange: function(){
},
toString: function(){
return '[object Range]';
},
detach: function(){
}
});
// CompareHow
Range.START_TO_START = 0;
Range.START_TO_END = 1;
Range.END_TO_END = 2;
Range.END_TO_START = 3;
/**
* @class Document - The Document interface represents the entire HTML
* or XML document. Conceptually, it is the root of the document tree,
* and provides the primary access to the document's data.
*
* @extends Node
* @param implementation : DOMImplementation - the creator Implementation
*/
Document = function(implementation, docParentWindow) {
Node.apply(this, arguments);
//TODO: Temporary!!! Cnage back to true!!!
this.async = true;
// The Document Type Declaration (see DocumentType) associated with this document
this.doctype = null;
// The DOMImplementation object that handles this document.
this.implementation = implementation
this.nodeName = "#document";
// initially false, set to true by parser
this.parsing = false;
this.baseURI = 'about:blank';
this.ownerDocument = null;
this.importing = false;
this.location = null;
};
Document.prototype = new Node;
__extend__(Document.prototype,{
get localName(){
return null;
},
get textContent(){
return null;
},
get all(){
return this.getElementsByTagName("*");
},
get documentElement(){
var i, length = this.childNodes?this.childNodes.length:0;
for(i=0;i -1 ){
valid = false;
}
if ((valid) && (!isAttribute)) {
// if the namespaceURI is not null
if (!namespaceURI) {
valid = false;
}
}
// if the qualifiedName has a prefix
if ((valid) && (qName.prefix == "")) {
valid = false;
}
}
// if the qualifiedName has a prefix that is "xml" and the namespaceURI is
// different from "http://www.w3.org/XML/1998/namespace" [Namespaces].
if ((valid) && (qName.prefix == "xml") && (namespaceURI != "http://www.w3.org/XML/1998/namespace")) {
valid = false;
}
return valid;
};
/**
* @author thatcher
*/
DOMParser = function(principle, documentURI, baseURI){};
__extend__(DOMParser.prototype,{
parseFromString: function(xmlstring, mimetype){
var doc = new Document(new DOMImplementation()),
e4;
XML.ignoreComments = false;
XML.ignoreProcessingInstructions = false;
XML.ignoreWhitespace = false;
xmlstring = xmlstring.replace(/<\?xml.*\?>/);
e4 = new XMLList(xmlstring);
__toDomNode__(e4, doc, doc);
//console.log('xml \n %s', doc.documentElement.xml);
return doc;
}
});
var __toDomNode__ = function(e4, parent, doc){
var xnode,
domnode,
children,
target,
value,
length,
element,
kind;
//console.log('converting e4x node list \n %s', e4)
for each(xnode in e4){
kind = xnode.nodeKind();
//console.log('treating node kind %s', kind);
switch(kind){
case 'element':
//console.log('creating element %s %s', xnode.localName(), xnode.namespace());
if(xnode.namespace() && (xnode.namespace()+'') !== ''){
//console.log('createElementNS %s %s',xnode.namespace()+'', xnode.localName() );
domnode = doc.createElementNS(xnode.namespace()+'', xnode.localName());
}else{
domnode = doc.createElement(xnode.name()+'');
}
parent.appendChild(domnode);
__toDomNode__(xnode.attributes(), domnode, doc);
length = xnode.children().length();
//console.log('recursing? %s', length?"yes":"no");
if(xnode.children().length()>0){
__toDomNode__(xnode.children(), domnode, doc);
}
break;
case 'attribute':
//console.log('setting attribute %s %s %s',
// xnode.localName(), xnode.namespace(), xnode.text());
if(xnode.namespace() && xnode.namespace().prefix){
//console.log("%s", xnode.namespace().prefix);
parent.setAttributeNS(xnode.namespace()+'',
xnode.namespace().prefix+':'+xnode.localName(),
xnode.text());
}else if((xnode.name()+'').match("http://www.w3.org/2000/xmlns/::")){
if(xnode.localName()!=='xmlns'){
parent.setAttributeNS('http://www.w3.org/2000/xmlns/',
'xmlns:'+xnode.localName(),
xnode.text());
}
}else{
parent.setAttribute(xnode.localName()+'', xnode.text());
}
break;
case 'text':
//console.log('creating text node : %s', xnode);
domnode = doc.createTextNode(xnode+'');
parent.appendChild(domnode);
break;
case 'comment':
//console.log('creating comment node : %s', xnode);
value = xnode+'';
domnode = doc.createComment(value.substring(4,value.length-3));
parent.appendChild(domnode);
break;
case 'processing-instruction':
//console.log('creating processing-instruction node : %s', xnode);
value = xnode+'';
target = value.split(' ')[0].substring(2);
value = value.split(' ').splice(1).join(" ").replace('?>','');
//console.log('creating processing-instruction data : %s', value);
domnode = doc.createProcessingInstruction(target, value);
parent.appendChild(domnode);
break;
}
}
}; /**
* @author envjs team
* @class XMLSerializer
*/
XMLSerializer = function() {};
__extend__(XMLSerializer.prototype, {
serializeToString: function(node){
return node.xml;
},
toString : function(){
return "[object XMLSerializer]";
}
});
/**
* @author john resig & the envjs team
* @uri http://www.envjs.com/
* @copyright 2008-2010
* @license MIT
*/
})();
/*
* Envjs event.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*
* This file simply provides the global definitions we need to
* be able to correctly implement to core browser DOM Event interfaces.
*/
var Event,
MouseEvent,
UIEvent,
KeyboardEvent,
MutationEvent,
DocumentEvent,
EventTarget,
EventException,
//nonstandard but very useful for implementing mutation events
//among other things like general profiling
Aspect;
/*
* Envjs event.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig 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 );
};/**
* Borrowed with love from:
*
* jQuery AOP - jQuery plugin to add features of aspect-oriented programming (AOP) to jQuery.
* http://jquery-aop.googlecode.com/
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Version: 1.1
*/
(function() {
var _after = 1;
var _before = 2;
var _around = 3;
var _intro = 4;
var _regexEnabled = true;
/**
* Private weaving function.
*/
var weaveOne = function(source, method, advice) {
var old = source[method];
var aspect;
if (advice.type == _after)
aspect = function() {
var returnValue = old.apply(this, arguments);
return advice.value.apply(this, [returnValue, method]);
};
else if (advice.type == _before)
aspect = function() {
advice.value.apply(this, [arguments, method]);
return old.apply(this, arguments);
};
else if (advice.type == _intro)
aspect = function() {
return advice.value.apply(this, arguments);
};
else if (advice.type == _around) {
aspect = function() {
var invocation = { object: this, args: arguments };
return advice.value.apply(invocation.object, [{ arguments: invocation.args, method: method, proceed :
function() {
return old.apply(invocation.object, invocation.args);
}
}] );
};
}
aspect.unweave = function() {
source[method] = old;
pointcut = source = aspect = old = null;
};
source[method] = aspect;
return aspect;
};
/**
* Private weaver and pointcut parser.
*/
var weave = function(pointcut, advice)
{
var source = (typeof(pointcut.target.prototype) != 'undefined') ? pointcut.target.prototype : pointcut.target;
var advices = [];
// If it's not an introduction and no method was found, try with regex...
if (advice.type != _intro && typeof(source[pointcut.method]) == 'undefined')
{
for (var method in source)
{
if (source[method] != null && source[method] instanceof Function && method.match(pointcut.method))
{
advices[advices.length] = weaveOne(source, method, advice);
}
}
if (advices.length == 0)
throw 'No method: ' + pointcut.method;
}
else
{
// Return as an array of one element
advices[0] = weaveOne(source, pointcut.method, advice);
}
return _regexEnabled ? advices : advices[0];
};
Aspect =
{
/**
* Creates an advice after the defined point-cut. The advice will be executed after the point-cut method
* has completed execution successfully, and will receive one parameter with the result of the execution.
* This function returns an array of weaved aspects (Function).
*
* @example jQuery.aop.after( {target: window, method: 'MyGlobalMethod'}, function(result) { alert('Returned: ' + result); } );
* @result Array
*
* @example jQuery.aop.after( {target: String, method: 'indexOf'}, function(index) { alert('Result found at: ' + index + ' on:' + this); } );
* @result Array
*
* @name after
* @param Map pointcut Definition of the point-cut to apply the advice. A point-cut is the definition of the object/s and method/s to be weaved.
* @option Object target Target object to be weaved.
* @option String method Name of the function to be weaved. Regex are supported, but not on built-in objects.
* @param Function advice Function containing the code that will get called after the execution of the point-cut. It receives one parameter
* with the result of the point-cut's execution.
*
* @type Array
* @cat Plugins/General
*/
after : function(pointcut, advice)
{
return weave( pointcut, { type: _after, value: advice } );
},
/**
* Creates an advice before the defined point-cut. The advice will be executed before the point-cut method
* but cannot modify the behavior of the method, or prevent its execution.
* This function returns an array of weaved aspects (Function).
*
* @example jQuery.aop.before( {target: window, method: 'MyGlobalMethod'}, function() { alert('About to execute MyGlobalMethod'); } );
* @result Array
*
* @example jQuery.aop.before( {target: String, method: 'indexOf'}, function(index) { alert('About to execute String.indexOf on: ' + this); } );
* @result Array
*
* @name before
* @param Map pointcut Definition of the point-cut to apply the advice. A point-cut is the definition of the object/s and method/s to be weaved.
* @option Object target Target object to be weaved.
* @option String method Name of the function to be weaved. Regex are supported, but not on built-in objects.
* @param Function advice Function containing the code that will get called before the execution of the point-cut.
*
* @type Array
* @cat Plugins/General
*/
before : function(pointcut, advice)
{
return weave( pointcut, { type: _before, value: advice } );
},
/**
* Creates an advice 'around' the defined point-cut. This type of advice can control the point-cut method execution by calling
* the functions '.proceed()' on the 'invocation' object, and also, can modify the arguments collection before sending them to the function call.
* This function returns an array of weaved aspects (Function).
*
* @example jQuery.aop.around( {target: window, method: 'MyGlobalMethod'}, function(invocation) {
* alert('# of Arguments: ' + invocation.arguments.length);
* return invocation.proceed();
* } );
* @result Array
*
* @example jQuery.aop.around( {target: String, method: 'indexOf'}, function(invocation) {
* alert('Searching: ' + invocation.arguments[0] + ' on: ' + this);
* return invocation.proceed();
* } );
* @result Array
*
* @example jQuery.aop.around( {target: window, method: /Get(\d+)/}, function(invocation) {
* alert('Executing ' + invocation.method);
* return invocation.proceed();
* } );
* @desc Matches all global methods starting with 'Get' and followed by a number.
* @result Array
*
*
* @name around
* @param Map pointcut Definition of the point-cut to apply the advice. A point-cut is the definition of the object/s and method/s to be weaved.
* @option Object target Target object to be weaved.
* @option String method Name of the function to be weaved. Regex are supported, but not on built-in objects.
* @param Function advice Function containing the code that will get called around the execution of the point-cut. This advice will be called with one
* argument containing one function '.proceed()', the collection of arguments '.arguments', and the matched method name '.method'.
*
* @type Array
* @cat Plugins/General
*/
around : function(pointcut, advice)
{
return weave( pointcut, { type: _around, value: advice } );
},
/**
* Creates an introduction on the defined point-cut. This type of advice replaces any existing methods with the same
* name. To restore them, just unweave it.
* This function returns an array with only one weaved aspect (Function).
*
* @example jQuery.aop.introduction( {target: window, method: 'MyGlobalMethod'}, function(result) { alert('Returned: ' + result); } );
* @result Array
*
* @example jQuery.aop.introduction( {target: String, method: 'log'}, function() { alert('Console: ' + this); } );
* @result Array
*
* @name introduction
* @param Map pointcut Definition of the point-cut to apply the advice. A point-cut is the definition of the object/s and method/s to be weaved.
* @option Object target Target object to be weaved.
* @option String method Name of the function to be weaved.
* @param Function advice Function containing the code that will be executed on the point-cut.
*
* @type Array
* @cat Plugins/General
*/
introduction : function(pointcut, advice)
{
return weave( pointcut, { type: _intro, value: advice } );
},
/**
* Configures global options.
*
* @name setup
* @param Map settings Configuration options.
* @option Boolean regexMatch Enables/disables regex matching of method names.
*
* @example jQuery.aop.setup( { regexMatch: false } );
* @desc Disable regex matching.
*
* @type Void
* @cat Plugins/General
*/
setup: function(settings)
{
_regexEnabled = settings.regexMatch;
}
};
})();
/**
*
* // Introduced in DOM Level 2:
* interface DocumentEvent {
* Event createEvent (in DOMString eventType)
* raises (DOMException);
* };
*/
DocumentEvent = function(){};
DocumentEvent.prototype.createEvent = function(eventType){
//console.debug('createEvent(%s)', eventType);
switch (eventType){
case 'Events':
return new Event();
break;
case 'HTMLEvents':
return new Event();
break;
case 'UIEvents':
return new UIEvent();
break;
case 'MouseEvents':
return new MouseEvent();
break;
case 'KeyEvents':
return new KeyboardEvent();
break;
case 'KeyboardEvent':
return new KeyboardEvent();
break;
case 'MutationEvents':
return new MutationEvent();
break;
default:
throw(new DOMException(DOMException.NOT_SUPPORTED_ERR));
}
};
Document.prototype.createEvent = DocumentEvent.prototype.createEvent;
/**
* @name EventTarget
* @w3c:domlevel 2
* @uri -//TODO: paste dom event level 2 w3c spc uri here
*/
EventTarget = function(){};
EventTarget.prototype.addEventListener = function(type, fn, phase){
__addEventListener__(this, type, fn, phase);
};
EventTarget.prototype.removeEventListener = function(type, fn){
__removeEventListener__(this, type, fn);
};
EventTarget.prototype.dispatchEvent = function(event, bubbles){
__dispatchEvent__(this, event, bubbles);
};
__extend__(Node.prototype, EventTarget.prototype);
var $events = [{}];
function __addEventListener__(target, type, fn, phase){
phase = !!phase?"CAPTURING":"BUBBLING";
if ( !target.uuid ) {
//console.log('event uuid %s %s', target, target.uuid);
target.uuid = $events.length+'';
}
if ( !$events[target.uuid] ) {
//console.log('creating listener for target: %s %s', target, target.uuid);
$events[target.uuid] = {};
}
if ( !$events[target.uuid][type] ){
//console.log('creating listener for type: %s %s %s', target, target.uuid, type);
$events[target.uuid][type] = {
CAPTURING:[],
BUBBLING:[]
};
}
if ( $events[target.uuid][type][phase].indexOf( fn ) < 0 ){
//console.log('adding event listener %s %s %s %s %s %s', target, target.uuid, type, phase,
// $events[target.uuid][type][phase].length, $events[target.uuid][type][phase].indexOf( fn ));
//console.log('creating listener for function: %s %s %s', target, target.uuid, phase);
$events[target.uuid][type][phase].push( fn );
//console.log('adding event listener %s %s %s %s %s %s', target, target.uuid, type, phase,
// $events[target.uuid][type][phase].length, $events[target.uuid][type][phase].indexOf( fn ));
}
//console.log('registered event listeners %s', $events.length);
};
function __removeEventListener__(target, type, fn, phase){
phase = !!phase?"CAPTURING":"BUBBLING";
if ( !target.uuid ) {
return;
}
if ( !$events[target.uuid] ) {
return;
}
if(type == '*'){
//used to clean all event listeners for a given node
//console.log('cleaning all event listeners for node %s %s',target, target.uuid);
delete $events[target.uuid];
$events[target.uuid] = null;
return;
}else if ( !$events[target.uuid][type] ){
return;
}
$events[target.uuid][type][phase] =
$events[target.uuid][type][phase].filter(function(f){
//console.log('removing event listener %s %s %s %s', target, type, phase, fn);
return f != fn;
});
};
var __eventuuid__ = 0;
function __dispatchEvent__(target, event, bubbles){
if(!event.uuid)
event.uuid = __eventuuid__++;
//the window scope defines the $event object, for IE(^^^) compatibility;
//$event = event;
//console.log('dispatching event %s', event.uuid);
if (bubbles == undefined || bubbles == null)
bubbles = true;
if (!event.target) {
event.target = target;
}
//console.log('dispatching? %s %s %s', target, event.type, bubbles);
if ( event.type && (target.nodeType || target === window )) {
//console.log('dispatching event %s %s %s', target, event.type, bubbles);
__captureEvent__(target, event);
event.eventPhase = Event.AT_TARGET;
if ( target.uuid && $events[target.uuid] && $events[target.uuid][event.type] ) {
event.currentTarget = target;
//console.log('dispatching %s %s %s %s', target, event.type,
// $events[target.uuid][event.type]['CAPTURING'].length);
$events[target.uuid][event.type]['CAPTURING'].forEach(function(fn){
//console.log('AT_TARGET (CAPTURING) event %s', fn);
var returnValue = fn( event );
//console.log('AT_TARGET (CAPTURING) return value %s', returnValue);
if(returnValue === false){
event.stopPropagation();
}
});
//console.log('dispatching %s %s %s %s', target, event.type,
// $events[target.uuid][event.type]['BUBBLING'].length);
$events[target.uuid][event.type]['BUBBLING'].forEach(function(fn){
//console.log('AT_TARGET (BUBBLING) event %s', fn);
var returnValue = fn( event );
//console.log('AT_TARGET (BUBBLING) return value %s', returnValue);
if(returnValue === false){
event.stopPropagation();
}
});
}
if (target["on" + event.type]) {
target["on" + event.type](event);
}
if (bubbles && !event.cancelled){
__bubbleEvent__(target, event);
}
if(!event._preventDefault){
//At this point I'm guessing that just HTMLEvents are concerned
//with default behavior being executed in a browser but I could be
//wrong as usual. The goal is much more to filter at this point
//what events have no need to be handled
console.log('triggering default behavior for %s', event.type);
if(event.type in Envjs.defaultEventBehaviors){
Envjs.defaultEventBehaviors[event.type](event);
}
}
//console.log('deleting event %s', event.uuid);
event.target = null;
event = null;
}else{
throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR);
}
};
function __captureEvent__(target, event){
var ancestorStack = [],
parent = target.parentNode;
event.eventPhase = Event.CAPTURING_PHASE;
while(parent){
if(parent.uuid && $events[parent.uuid] && $events[parent.uuid][event.type]){
ancestorStack.push(parent);
}
parent = parent.parentNode;
}
while(ancestorStack.length && !event.cancelled){
event.currentTarget = ancestorStack.pop();
if($events[event.currentTarget.uuid] && $events[event.currentTarget.uuid][event.type]){
$events[event.currentTarget.uuid][event.type]['CAPTURING'].forEach(function(fn){
var returnValue = fn( event );
if(returnValue === false){
event.stopPropagation();
}
});
}
}
};
function __bubbleEvent__(target, event){
var parent = target.parentNode;
event.eventPhase = Event.BUBBLING_PHASE;
while(parent){
if(parent.uuid && $events[parent.uuid] && $events[parent.uuid][event.type] ){
event.currentTarget = parent;
$events[event.currentTarget.uuid][event.type]['BUBBLING'].forEach(function(fn){
var returnValue = fn( event );
if(returnValue === false){
event.stopPropagation();
}
});
}
parent = parent.parentNode;
}
};
/**
* @class Event
*/
Event = function(options){
// event state is kept read-only by forcing
// a new object for each event. This may not
// be appropriate in the long run and we'll
// have to decide if we simply dont adhere to
// the read-only restriction of the specification
this._bubbles = true;
this._cancelable = true;
this._cancelled = false;
this._currentTarget = null;
this._target = null;
this._eventPhase = Event.AT_TARGET;
this._timeStamp = new Date().getTime();
this._preventDefault = false;
this._stopPropogation = false;
};
__extend__(Event.prototype,{
get bubbles(){return this._bubbles;},
get cancelable(){return this._cancelable;},
get currentTarget(){return this._currentTarget;},
set currentTarget(currentTarget){ this._currentTarget = currentTarget; },
get eventPhase(){return this._eventPhase;},
set eventPhase(eventPhase){this._eventPhase = eventPhase;},
get target(){return this._target;},
set target(target){ this._target = target;},
get timeStamp(){return this._timeStamp;},
get type(){return this._type;},
initEvent: function(type, bubbles, cancelable){
this._type=type?type:'';
this._bubbles=!!bubbles;
this._cancelable=!!cancelable;
},
preventDefault: function(){
this._preventDefault = true;
},
stopPropagation: function(){
if(this._cancelable){
this._cancelled = true;
this._bubbles = false;
}
},
get cancelled(){
return this._cancelled;
},
toString: function(){
return '[object Event]';
}
});
__extend__(Event,{
CAPTURING_PHASE : 1,
AT_TARGET : 2,
BUBBLING_PHASE : 3
});
/**
* @name UIEvent
* @param {Object} options
*/
UIEvent = function(options) {
this._view = null;
this._detail = 0;
};
UIEvent.prototype = new Event;
__extend__(UIEvent.prototype,{
get view(){
return this._view;
},
get detail(){
return this._detail;
},
initUIEvent: function(type, bubbles, cancelable, windowObject, detail){
this.initEvent(type, bubbles, cancelable);
this._detail = 0;
this._view = windowObject;
}
});
var $onblur,
$onfocus,
$onresize;
/**
* @name MouseEvent
* @w3c:domlevel 2
* @uri http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
*/
MouseEvent = function(options) {
this._screenX= 0;
this._screenY= 0;
this._clientX= 0;
this._clientY= 0;
this._ctrlKey= false;
this._metaKey= false;
this._altKey= false;
this._button= null;
this._relatedTarget= null;
};
MouseEvent.prototype = new UIEvent;
__extend__(MouseEvent.prototype,{
get screenX(){
return this._screenX;
},
get screenY(){
return this._screenY;
},
get clientX(){
return this._clientX;
},
get clientY(){
return this._clientY;
},
get ctrlKey(){
return this._ctrlKey;
},
get altKey(){
return this._altKey;
},
get shiftKey(){
return this._shiftKey;
},
get metaKey(){
return this._metaKey;
},
get button(){
return this._button;
},
get relatedTarget(){
return this._relatedTarget;
},
initMouseEvent: function(type, bubbles, cancelable, windowObject, detail,
screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey,
metaKey, button, relatedTarget){
this.initUIEvent(type, bubbles, cancelable, windowObject, detail);
this._screenX = screenX;
this._screenY = screenY;
this._clientX = clientX;
this._clientY = clientY;
this._ctrlKey = ctrlKey;
this._altKey = altKey;
this._shiftKey = shiftKey;
this._metaKey = metaKey;
this._button = button;
this._relatedTarget = relatedTarget;
}
});
/**
* Interface KeyboardEvent (introduced in DOM Level 3)
*/
KeyboardEvent = function(options) {
this._keyIdentifier = 0;
this._keyLocation = 0;
this._ctrlKey = false;
this._metaKey = false;
this._altKey = false;
this._metaKey = false;
};
KeyboardEvent.prototype = new UIEvent;
__extend__(KeyboardEvent.prototype,{
get ctrlKey(){
return this._ctrlKey;
},
get altKey(){
return this._altKey;
},
get shiftKey(){
return this._shiftKey;
},
get metaKey(){
return this._metaKey;
},
get button(){
return this._button;
},
get relatedTarget(){
return this._relatedTarget;
},
getModifiersState: function(keyIdentifier){
},
initMouseEvent: function(type, bubbles, cancelable, windowObject,
keyIdentifier, keyLocation, modifiersList, repeat){
this.initUIEvent(type, bubbles, cancelable, windowObject, 0);
this._keyIdentifier = keyIdentifier;
this._keyLocation = keyLocation;
this._modifiersList = modifiersList;
this._repeat = repeat;
}
});
KeyboardEvent.DOM_KEY_LOCATION_STANDARD = 0;
KeyboardEvent.DOM_KEY_LOCATION_LEFT = 1;
KeyboardEvent.DOM_KEY_LOCATION_RIGHT = 2;
KeyboardEvent.DOM_KEY_LOCATION_NUMPAD = 3;
KeyboardEvent.DOM_KEY_LOCATION_MOBILE = 4;
KeyboardEvent.DOM_KEY_LOCATION_JOYSTICK = 5;
//We dont fire mutation events until someone has registered for them
var __supportedMutations__ = /DOMSubtreeModified|DOMNodeInserted|DOMNodeRemoved|DOMAttrModified|DOMCharacterDataModified/;
var __fireMutationEvents__ = Aspect.before({
target: EventTarget,
method: 'addEventListener'
}, function(target, type){
if(type && type.match(__supportedMutations__)){
//unweaving removes the __addEventListener__ aspect
__fireMutationEvents__.unweave();
// These two methods are enough to cover all dom 2 manipulations
Aspect.around({
target: Node,
method:"removeChild"
}, function(invocation){
var event,
node = invocation.arguments[0];
event = node.ownerDocument.createEvent('MutationEvents');
event.initEvent('DOMNodeRemoved', true, false, node.parentNode, null, null, null, null);
node.dispatchEvent(event, false);
return invocation.proceed();
});
Aspect.around({
target: Node,
method:"appendChild"
}, function(invocation) {
var event,
node = invocation.proceed();
event = node.ownerDocument.createEvent('MutationEvents');
event.initEvent('DOMNodeInserted', true, false, node.parentNode, null, null, null, null);
node.dispatchEvent(event, false);
return node;
});
}
});
/**
* @name MutationEvent
* @param {Object} options
*/
MutationEvent = function(options) {
this._cancelable = false;
this._timeStamp = 0;
};
MutationEvent.prototype = new Event;
__extend__(MutationEvent.prototype,{
get relatedNode(){
return this._relatedNode;
},
get prevValue(){
return this._prevValue;
},
get newValue(){
return this._newValue;
},
get attrName(){
return this._attrName;
},
get attrChange(){
return this._attrChange;
},
initMutationEvent: function( type, bubbles, cancelable,
relatedNode, prevValue, newValue, attrName, attrChange ){
this._relatedNode = relatedNode;
this._prevValue = prevValue;
this._newValue = newValue;
this._attrName = attrName;
this._attrChange = attrChange;
switch(type){
case "DOMSubtreeModified":
this.initEvent(type, true, false);
break;
case "DOMNodeInserted":
this.initEvent(type, true, false);
break;
case "DOMNodeRemoved":
this.initEvent(type, true, false);
break;
case "DOMNodeRemovedFromDocument":
this.initEvent(type, false, false);
break;
case "DOMNodeInsertedIntoDocument":
this.initEvent(type, false, false);
break;
case "DOMAttrModified":
this.initEvent(type, true, false);
break;
case "DOMCharacterDataModified":
this.initEvent(type, true, false);
break;
default:
this.initEvent(type, bubbles, cancelable);
}
}
});
// constants
MutationEvent.ADDITION = 0;
MutationEvent.MODIFICATION = 1;
MutationEvent.REMOVAL = 2;
/**
* @name EventException
*/
EventException = function(code) {
this.code = code;
};
EventException.UNSPECIFIED_EVENT_TYPE_ERR = 0;
/**
* @author john resig & the envjs team
* @uri http://www.envjs.com/
* @copyright 2008-2010
* @license MIT
*/
})();
/*
* Envjs timer.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*
* Parts of the implementation were originally written by:\
* Steven Parkes
*
* requires Envjs.wait, Envjs.sleep, Envjs.WAIT_INTERVAL
*/
var setTimeout,
clearTimeout,
setInterval,
clearInterval;
/*
* Envjs timer.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
(function(){
/*
* timer.js
* implementation provided by Steven Parkes
*/
//private
var $timers = [],
EVENT_LOOP_RUNNING = false;
$timers.lock = function(fn){
Envjs.sync(fn)();
};
//private internal class
var Timer = function(fn, interval){
this.fn = fn;
this.interval = interval;
this.at = Date.now() + interval;
// allows for calling wait() from callbacks
this.running = false;
};
Timer.prototype.start = function(){};
Timer.prototype.stop = function(){};
//static
Timer.normalize = function(time) {
time = time*1;
if ( isNaN(time) || time < 0 ) {
time = 0;
}
if ( EVENT_LOOP_RUNNING && time < Timer.MIN_TIME ) {
time = Timer.MIN_TIME;
}
return time;
};
// html5 says this should be at least 4, but the parser is using
// a setTimeout for the SAX stuff which messes up the world
Timer.MIN_TIME = /* 4 */ 0;
/**
* @function setTimeout
* @param {Object} fn
* @param {Object} time
*/
setTimeout = function(fn, time){
var num;
time = Timer.normalize(time);
$timers.lock(function(){
num = $timers.length+1;
var tfn;
if (typeof fn == 'string') {
tfn = function() {
try {
eval(fn);
} catch (e) {
console.log('timer error %s %s', fn, e);
} finally {
clearInterval(num);
}
};
} else {
tfn = function() {
try {
fn();
} catch (e) {
console.log('timer error %s %s', fn, e);
} finally {
clearInterval(num);
}
};
}
//console.log("Creating timer number %s", num);
$timers[num] = new Timer(tfn, time);
$timers[num].start();
});
return num;
};
/**
* @function setInterval
* @param {Object} fn
* @param {Object} time
*/
setInterval = function(fn, time){
//console.log('setting interval %s %s', time, fn.toString().substring(0,64));
time = Timer.normalize(time);
if ( time < 10 ) {
time = 10;
}
if (typeof fn == 'string') {
var fnstr = fn;
fn = function() {
eval(fnstr);
};
}
var num;
$timers.lock(function(){
num = $timers.length+1;
//Envjs.debug("Creating timer number "+num);
$timers[num] = new Timer(fn, time);
$timers[num].start();
});
return num;
};
/**
* clearInterval
* @param {Object} num
*/
clearInterval = clearTimeout = function(num){
//console.log("clearing interval "+num);
$timers.lock(function(){
if ( $timers[num] ) {
$timers[num].stop();
delete $timers[num];
}
});
};
// wait === null/undefined: execute any timers as they fire,
// waiting until there are none left
// wait(n) (n > 0): execute any timers as they fire until there
// are none left waiting at least n ms but no more, even if there
// are future events/current threads
// wait(0): execute any immediately runnable timers and return
// wait(-n): keep sleeping until the next event is more than n ms
// in the future
//
// TODO: make a priority queue ...
Envjs.wait = function(wait) {
//console.log('wait %s', wait);
var delta_wait,
start = Date.now(),
was_running = EVENT_LOOP_RUNNING;
if (wait < 0) {
delta_wait = -wait;
wait = 0;
}
EVENT_LOOP_RUNNING = true;
if (wait !== 0 && wait !== null && wait !== undefined){
wait += Date.now();
}
var earliest,
timer,
sleep,
index,
goal,
now,
nextfn;
for (;;) {
//console.log('timer loop');
earliest = sleep = goal = now = nextfn = null;
$timers.lock(function(){
for(index in $timers){
if( isNaN(index*0) ) {
continue;
}
timer = $timers[index];
// determine timer with smallest run-at time that is
// not already running
if( !timer.running && ( !earliest || timer.at < earliest.at) ) {
earliest = timer;
}
}
});
//next sleep time
sleep = earliest && earliest.at - Date.now();
if ( earliest && sleep <= 0 ) {
nextfn = earliest.fn;
try {
//console.log('running stack %s', nextfn.toString().substring(0,64));
earliest.running = true;
nextfn();
} catch (e) {
console.log('timer error %s %s', nextfn, e);
} finally {
earliest.running = false;
}
goal = earliest.at + earliest.interval;
now = Date.now();
if ( goal < now ) {
earliest.at = now;
} else {
earliest.at = goal;
}
continue;
}
// bunch of subtle cases here ...
if ( !earliest ) {
// no events in the queue (but maybe XHR will bring in events, so ...
if ( !wait || wait < Date.now() ) {
// Loop ends if there are no events and a wait hasn't been
// requested or has expired
break;
}
// no events, but a wait requested: fall through to sleep
} else {
// there are events in the queue, but they aren't firable now
/*if ( delta_wait && sleep <= delta_wait ) {
//TODO: why waste a check on a tight
// loop if it just falls through?
// if they will happen within the next delta, fall through to sleep
} else */if ( wait === 0 || ( wait > 0 && wait < Date.now () ) ) {
// loop ends even if there are events but the user
// specifcally asked not to wait too long
break;
}
// there are events and the user wants to wait: fall through to sleep
}
// Related to ajax threads ... hopefully can go away ..
var interval = Envjs.WAIT_INTERVAL || 100;
if ( !sleep || sleep > interval ) {
sleep = interval;
}
//console.log('sleeping %s', sleep);
Envjs.sleep(sleep);
}
EVENT_LOOP_RUNNING = was_running;
};
/**
* @author john resig & the envjs team
* @uri http://www.envjs.com/
* @copyright 2008-2010
* @license MIT
*/
})();
/*
* Envjs html.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*
* This file simply provides the global definitions we need to
* be able to correctly implement to core browser DOM HTML interfaces.
*/
var HTMLDocument,
HTMLElement,
HTMLCollection,
HTMLAnchorElement,
HTMLAreaElement,
HTMLBaseElement,
HTMLQuoteElement,
HTMLBodyElement,
HTMLButtonElement,
HTMLCanvasElement,
HTMLTableColElement,
HTMLModElement,
HTMLDivElement,
HTMLFieldSetElement,
HTMLFormElement,
HTMLFrameElement,
HTMLFrameSetElement,
HTMLHeadElement,
HTMLIFrameElement,
HTMLImageElement,
HTMLInputElement,
HTMLLabelElement,
HTMLLegendElement,
HTMLLinkElement,
HTMLMapElement,
HTMLMetaElement,
HTMLObjectElement,
HTMLOptGroupElement,
HTMLOptionElement,
HTMLParamElement,
HTMLScriptElement,
HTMLSelectElement,
HTMLStyleElement,
HTMLTableElement,
HTMLTableSectionElement,
HTMLTableCellElement,
HTMLTableRowElement,
HTMLTextAreaElement,
HTMLTitleElement,
HTMLUnknownElement;
/*
* Envjs html.1.2.0.6
* Pure JavaScript Browser Environment
* By John Resig and the Envjs Team
* Copyright 2008-2010 John Resig, under the MIT License
*/
(function(){
/**
* @author ariel flesler
* http://flesler.blogspot.com/2008/11/fast-trim-function-for-javascript.html
* @param {Object} str
*/
function __trim__( str ){
return (str || "").replace( /^\s+|\s+$/g, "" );
};
/**
* @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 HTMLDocument
* The Document interface represents the entire HTML or XML document.
* Conceptually, it is the root of the document tree, and provides
* the primary access to the document's data.
*
* @extends Document
*/
HTMLDocument = function(implementation, ownerWindow, referrer) {
Document.apply(this, arguments);
this.referrer = referrer;
this.baseURI = "about:blank";
this.ownerWindow = ownerWindow;
this.head;
this.body;
};
HTMLDocument.prototype = new Document;
__extend__(HTMLDocument.prototype, {
createElement: function(tagName){
tagName = tagName.toUpperCase();
// create Element specifying 'this' as ownerDocument
// This is an html document so we need to use explicit interfaces per the
//TODO: would be much faster as a big switch
switch(tagName){
case "A":
node = new HTMLAnchorElement(this);break;
case "AREA":
node = new HTMLAreaElement(this);break;
case "BASE":
node = new HTMLBaseElement(this);break;
case "BLOCKQUOTE":
node = new HTMLQuoteElement(this);break;
case "Q":
node = new HTMLQuoteElement(this);break;
case "BODY":
node = new HTMLBodyElement(this);break;
case "BR":
node = new HTMLElement(this);break;
case "BUTTON":
node = new HTMLButtonElement(this);break;
case "CAPTION":
node = new HTMLElement(this);break;
case "COL":
node = new HTMLTableColElement(this);break;
case "COLGROUP":
node = new HTMLTableColElement(this);break;
case "DEL":
node = new HTMLModElement(this);break;
case "INS":
node = new HTMLModElement(this);break;
case "DIV":
node = new HTMLDivElement(this);break;
case "DL":
node = new HTMLElement(this);break;
case "FIELDSET":
node = new HTMLFieldSetElement(this);break;
case "FORM":
node = new HTMLFormElement(this);break;
case "FRAME":
node = new HTMLFrameElement(this);break;
case "H1":
node = new HTMLHeadElement(this);break;
case "H2":
node = new HTMLHeadElement(this);break;
case "H3":
node = new HTMLHeadElement(this);break;
case "H4":
node = new HTMLHeadElement(this);break;
case "H5":
node = new HTMLHeadElement(this);break;
case "H6":
node = new HTMLHeadElement(this);break;
case "HR":
node = new HTMLElement(this);break;
case "HTML":
node = new HTMLElement(this);break;
case "IFRAME":
node = new HTMLIFrameElement(this);break;
case "IMG":
node = new HTMLImageElement(this);break;
case "INPUT":
node = new HTMLInputElement(this);break;
case "LABEL":
node = new HTMLLabelElement(this);break;
case "LEGEND":
node = new HTMLLegendElement(this);break;
case "LI":
node = new HTMLElement(this);break;
case "LINK":
node = new HTMLLinkElement(this);break;
case "MAP":
node = new HTMLMapElement(this);break;
case "META":
node = new HTMLObjectElement(this);break;
case "OBJECT":
node = new HTMLMapElement(this);break;
case "OPTGROUP":
node = new HTMLOptGroupElement(this);break;
case "OPTION":
node = new HTMLOptionElement(this);break;
case "P":
node = new HTMLParagraphElement(this);break;
case "PARAM":
node = new HTMLParamElement(this);break;
case "PRE":
node = new HTMLElement(this);break;
case "SCRIPT":
node = new HTMLScriptElement(this);break;
case "SELECT":
node = new HTMLSelectElement(this);break;
case "STYLE":
node = new HTMLStyleElement(this);break;
case "TABLE":
node = new HTMLTableElement(this);break;
case "TBODY":
node = new HTMLTableSectionElement(this);break;
case "TFOOT":
node = new HTMLTableSectionElement(this);break;
case "THEAD":
node = new HTMLTableSectionElement(this);break;
case "TD":
node = new HTMLTableCellElement(this);break;
case "TH":
node = new HTMLTableCellElement(this);break;
case "TEXTAREA":
node = new HTMLTextAreaElement(this);break;
case "TITLE":
node = new HTMLTitleElement(this);break;
case "TR":
node = new HTMLTableRowElement(this);break;
case "UL":
node = new HTMLElement(this);break;
default:
node = new HTMLUnknownElement(this);
}
// assign values to properties (and aliases)
node.nodeName = tagName;
return node;
},
createElementNS : function (uri, local) {
//print('createElementNS :'+uri+" "+local);
if(!uri){
return this.createElement(local);
}else if ("http://www.w3.org/1999/xhtml" == uri) {
return this.createElement(local);
} else if ("http://www.w3.org/1998/Math/MathML" == uri) {
return this.createElement(local);
} else {
return Document.prototype.createElementNS.apply(this,[uri, local]);
}
},
get anchors(){
return new HTMLCollection(this.getElementsByTagName('a'));
},
get applets(){
return new HTMLCollection(this.getElementsByTagName('applet'));
},
//document.head is non-standard
get head(){
//console.log('get head');
if(!this.documentElement)
this.appendChild(this.createElement('html'));
var element = this.documentElement,
length = element.childNodes.length,
i;
//check for the presence of the head element in this html doc
for(i=0;i1?matches[1]:"";
},
set domain(value){
var i,
domainParts = this.domain.splt('.').reverse(),
newDomainParts = value.split('.').reverse();
if(newDomainParts.length > 1){
for(i=0;i 0){
event = doc.createEvent('HTMLEvents');
event.initEvent( okay ? "load" : "error", false, false );
node.dispatchEvent( event, false );
}
}catch(e){
console.log('error loading html element %s %e', node, e.toString());
}
}
break;
case 'frame':
case 'iframe':
node.contentWindow = { };
node.contentDocument = new HTMLDocument(new DOMImplementation(), node.contentWindow);
node.contentWindow.document = node.contentDocument;
try{
Window;
}catch(e){
node.contentDocument.addEventListener('DOMContentLoaded', function(){
event = node.contentDocument.createEvent('HTMLEvents');
event.initEvent("load", false, false);
node.dispatchEvent( event, false );
});
}
try{
if (node.src && node.src.length > 0){
//console.log("getting content document for (i)frame from %s", node.src);
Envjs.loadFrame(node, Envjs.uri(node.src));
event = node.contentDocument.createEvent('HTMLEvents');
event.initEvent("load", false, false);
node.dispatchEvent( event, false );
}else{
//I dont like this being here:
//TODO: better mix-in strategy so the try/catch isnt required
try{
if(Window){
Envjs.loadFrame(node);
//console.log('src/html/document.js: triggering frame load');
event = node.contentDocument.createEvent('HTMLEvents');
event.initEvent("load", false, false);
node.dispatchEvent( event, false );
}
}catch(e){}
}
}catch(e){
console.log('error loading html element %s %e', node, e.toString());
}
break;
case 'link':
if (node.href && node.href.length > 0){
// don't actually load anything, so we're "done" immediately:
event = doc.createEvent('HTMLEvents');
event.initEvent("load", false, false);
node.dispatchEvent( event, false );
}
break;
case 'img':
if (node.src && node.src.length > 0){
// don't actually load anything, so we're "done" immediately:
event = doc.createEvent('HTMLEvents');
event.initEvent("load", false, false);
node.dispatchEvent( event, false );
}
break;
default:
if(node.getAttribute('onload')){
console.log('calling attribute onload %s | %s', node.onload, node.tagName);
node.onload();
}
break;
}//switch on name
default:
break;
}//switch on ns
break;
default:
console.log('element appended: %s %s', node+'', node.namespaceURI);
}//switch on doc.parsing
return node;
});
Aspect.around({
target: Node,
method:"removeChild"
}, function(invocation) {
var event,
okay,
node = invocation.proceed(),
doc = node.ownerDocument;
if((node.nodeType !== Node.ELEMENT_NODE)){
//for now we are only handling element insertions. probably we will need
//to handle text node changes to script tags and changes to src
//attributes
if(node.nodeType !== Node.DOCUMENT_NODE && node.uuid){
//console.log('removing event listeners, %s', node, node.uuid);
node.removeEventListener('*', null, null);
}
return node;
}
//console.log('appended html element %s %s %s', node.namespaceURI, node.nodeName, node);
switch(doc.parsing){
case true:
//handled by parser if included
break;
case false:
switch(node.namespaceURI){
case null:
//fall through
case "":
//fall through
case "http://www.w3.org/1999/xhtml":
//this is interesting dillema since our event engine is
//storing the registered events in an array accessed
//by the uuid property of the node. unforunately this
//means listeners hang out way after(forever ;)) the node
//has been removed and gone out of scope.
//console.log('removing event listeners, %s', node, node.uuid);
node.removeEventListener('*', null, null);
switch(node.tagName.toLowerCase()){
case 'frame':
case 'iframe':
try{
//console.log('removing iframe document');
try{
Envjs.unloadFrame(node);
}catch(e){
console.log('error freeing resources from frame %s', e);
}
node.contentWindow = null;
node.contentDocument = null;
}catch(e){
console.log('error unloading html element %s %e', node, e.toString());
}
break;
default:
break;
}//switch on name
default:
break;
}//switch on ns
break;
default:
console.log('element appended: %s %s', node+'', node.namespaceURI);
}//switch on doc.parsing
return node;
});
/**
* @name HTMLEvents
* @w3c:domlevel 2
* @uri http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
*/
var HTMLEvents= function(){};
HTMLEvents.prototype = {
onload: function(event){
__eval__(this.getAttribute('onload')||'', this);
},
onunload: function(event){
__eval__(this.getAttribute('onunload')||'', this);
},
onabort: function(event){
__eval__(this.getAttribute('onabort')||'', this);
},
onerror: function(event){
__eval__(this.getAttribute('onerror')||'', this);
},
onselect: function(event){
__eval__(this.getAttribute('onselect')||'', this);
},
onchange: function(event){
__eval__(this.getAttribute('onchange')||'', this);
},
onsubmit: function(event){
if (__eval__(this.getAttribute('onsubmit')||'', this)) {
this.submit();
}
},
onreset: function(event){
__eval__(this.getAttribute('onreset')||'', this);
},
onfocus: function(event){
__eval__(this.getAttribute('onfocus')||'', this);
},
onblur: function(event){
__eval__(this.getAttribute('onblur')||'', this);
},
onresize: function(event){
__eval__(this.getAttribute('onresize')||'', this);
},
onscroll: function(event){
__eval__(this.getAttribute('onscroll')||'', this);
}
};
var __eval__ = function(script, node){
if (!script == ""){
// don't assemble environment if no script...
try{
eval(script);
}catch(e){
console.log('error evaluating %s', e);
}
}
};
//HTMLDocument, HTMLFramesetElement, HTMLObjectElement
var __load__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("load", false, false);
element.dispatchEvent(event);
return event;
};
//HTMLFramesetElement, HTMLBodyElement
var __unload__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("unload", false, false);
element.dispatchEvent(event);
return event;
};
//HTMLObjectElement
var __abort__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("abort", true, false);
element.dispatchEvent(event);
return event;
};
//HTMLFramesetElement, HTMLObjectElement, HTMLBodyElement
var __error__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("error", true, false);
element.dispatchEvent(event);
return event;
};
//HTMLInputElement, HTMLTextAreaElement
var __select__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("select", true, false);
element.dispatchEvent(event);
return event;
};
//HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement
var __change__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("change", true, false);
element.dispatchEvent(event);
return event;
};
//HtmlFormElement
var __submit__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("submit", true, true);
element.dispatchEvent(event);
return event;
};
//HtmlFormElement
var __reset__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("reset", false, false);
element.dispatchEvent(event);
return event;
};
//LABEL, INPUT, SELECT, TEXTAREA, and BUTTON
var __focus__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("focus", false, false);
element.dispatchEvent(event);
return event;
};
//LABEL, INPUT, SELECT, TEXTAREA, and BUTTON
var __blur__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("blur", false, false);
element.dispatchEvent(event);
return event;
};
//Window
var __resize__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("resize", true, false);
element.dispatchEvent(event);
return event;
};
//Window
var __scroll__ = function(element){
var event = new Event('HTMLEvents');
event.initEvent("scroll", true, false);
element.dispatchEvent(event);
return event;
};
/**
* @name KeyboardEvents
* @w3c:domlevel 2
* @uri http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
*/
var KeyboardEvents= function(){};
KeyboardEvents.prototype = {
onkeydown: function(event){
__eval__(this.getAttribute('onkeydown')||'', this);
},
onkeypress: function(event){
__eval__(this.getAttribute('onkeypress')||'', this);
},
onkeyup: function(event){
__eval__(this.getAttribute('onkeyup')||'', this);
}
};
var __registerKeyboardEventAttrs__ = function(elm){
if(elm.hasAttribute('onkeydown')){
elm.addEventListener('keydown', elm.onkeydown, false);
}
if(elm.hasAttribute('onkeypress')){
elm.addEventListener('keypress', elm.onkeypress, false);
}
if(elm.hasAttribute('onkeyup')){
elm.addEventListener('keyup', elm.onkeyup, false);
}
return elm;
};
//HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement
var __keydown__ = function(element){
var event = new Event('KeyboardEvents');
event.initEvent("keydown", false, false);
element.dispatchEvent(event);
};
//HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement
var __keypress__ = function(element){
var event = new Event('KeyboardEvents');
event.initEvent("keypress", false, false);
element.dispatchEvent(event);
};
//HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement
var __keyup__ = function(element){
var event = new Event('KeyboardEvents');
event.initEvent("keyup", false, false);
element.dispatchEvent(event);
};
/**
* @name MaouseEvents
* @w3c:domlevel 2
* @uri http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html
*/
var MouseEvents= function(){};
MouseEvents.prototype = {
onclick: function(event){
__eval__(this.getAttribute('onclick')||'', this);
},
ondblclick: function(event){
__eval__(this.getAttribute('ondblclick')||'', this);
},
onmousedown: function(event){
__eval__(this.getAttribute('onmousedown')||'', this);
},
onmousemove: function(event){
__eval__(this.getAttribute('onmousemove')||'', this);
},
onmouseout: function(event){
__eval__(this.getAttribute('onmouseout')||'', this);
},
onmouseover: function(event){
__eval__(this.getAttribute('onmouseover')||'', this);
},
onmouseup: function(event){
__eval__(this.getAttribute('onmouseup')||'', this);
}
};
var __registerMouseEventAttrs__ = function(elm){
if(elm.hasAttribute('onclick')){
elm.addEventListener('click', elm.onclick, false);
}
if(elm.hasAttribute('ondblclick')){
elm.addEventListener('dblclick', elm.ondblclick, false);
}
if(elm.hasAttribute('onmousedown')){
elm.addEventListener('mousedown', elm.onmousedown, false);
}
if(elm.hasAttribute('onmousemove')){
elm.addEventListener('mousemove', elm.onmousemove, false);
}
if(elm.hasAttribute('onmouseout')){
elm.addEventListener('mouseout', elm.onmouseout, false);
}
if(elm.hasAttribute('onmouseover')){
elm.addEventListener('mouseover', elm.onmouseover, false);
}
if(elm.hasAttribute('onmouseup')){
elm.addEventListener('mouseup', elm.onmouseup, false);
}
return elm;
};
var __click__ = function(element){
var event = new Event('MouseEvents');
event.initEvent("click", true, true, null, 0,
0, 0, 0, 0, false, false, false,
false, null, null);
element.dispatchEvent(event);
};
var __mousedown__ = function(element){
var event = new Event('MouseEvents');
event.initEvent("mousedown", true, true, null, 0,
0, 0, 0, 0, false, false, false,
false, null, null);
element.dispatchEvent(event);
};
var __mouseup__ = function(element){
var event = new Event('MouseEvents');
event.initEvent("mouseup", true, true, null, 0,
0, 0, 0, 0, false, false, false,
false, null, null);
element.dispatchEvent(event);
};
var __mouseover__ = function(element){
var event = new Event('MouseEvents');
event.initEvent("mouseover", true, true, null, 0,
0, 0, 0, 0, false, false, false,
false, null, null);
element.dispatchEvent(event);
};
var __mousemove__ = function(element){
var event = new Event('MouseEvents');
event.initEvent("mousemove", true, true, null, 0,
0, 0, 0, 0, false, false, false,
false, null, null);
element.dispatchEvent(event);
};
var __mouseout__ = function(element){
var event = new Event('MouseEvents');
event.initEvent("mouseout", true, true, null, 0,
0, 0, 0, 0, false, false, false,
false, null, null);
element.dispatchEvent(event);
};
/**
* HTMLElement - DOM Level 2
*/
HTMLElement = function(ownerDocument) {
Element.apply(this, arguments);
};
HTMLElement.prototype = new Element;
//TODO: Not sure where HTMLEvents belongs in the chain
// but putting it here satisfies a lowest common
// denominator.
__extend__(HTMLElement.prototype, HTMLEvents.prototype);
__extend__(HTMLElement.prototype, {
get className() {
return this.getAttribute("class")||'';
},
set className(value) {
return this.setAttribute("class",__trim__(value));
},
get dir() {
return this.getAttribute("dir")||"ltr";
},
set dir(val) {
return this.setAttribute("dir",val);
},
get id(){
return this.getAttribute('id');
},
set id(id){
this.setAttribute('id', id);
},
get innerHTML(){
var ret = "",
i;
// create string containing the concatenation of the string
// values of each child
for (i=0; i < this.childNodes.length; i++) {
if(this.childNodes[i]){
if(this.childNodes[i].nodeType === Node.ELEMENT_NODE){
ret += this.childNodes[i].xhtml;
}else if(this.childNodes[i].nodeType == Node.TEXT_NODE && i>0 &&
this.childNodes[i-1].nodeType == Node.TEXT_NODE){
//add a single space between adjacent text nodes
ret += " "+this.childNodes[i].xml;
}else{
ret += this.childNodes[i].xml;
}
}
}
return ret;
},
get lang() {
return this.getAttribute("lang");
},
set lang(val) {
return this.setAttribute("lang",val);
},
get offsetHeight(){
return Number((this.style["height"]||'').replace("px",""));
},
get offsetWidth(){
return Number((this.style["width"]||'').replace("px",""));
},
offsetLeft: 0,
offsetRight: 0,
get offsetParent(){
/* TODO */
return;
},
set offsetParent(element){
/* TODO */
return;
},
scrollHeight: 0,
scrollWidth: 0,
scrollLeft: 0,
scrollRight: 0,
get style(){
return this.getAttribute('style')||'';
},
get title() {
return this.getAttribute("title");
},
set title(value) {
return this.setAttribute("title", value);
},
get tabIndex(){
var tabindex = this.getAttribute('tabindex');
if(tabindex!==null){
return Number(tabindex);
} else {
return 0;
}
},
set tabIndex(value){
if(value===undefined||value===null)
value = 0;
this.setAttribute('tabindex',Number(value));
},
get outerHTML(){
//Not in the specs but I'll leave it here for now.
return this.xhtml;
},
scrollIntoView: function(){
/*TODO*/
return;
},
toString: function(){
return '[object HTMLElement]';
},
get xhtml() {
// HTMLDocument.xhtml is non-standard
// This is exactly like Document.xml except the tagName has to be
// lower cased. I dont like to duplicate this but its really not
// a simple work around between xml and html serialization via
// XMLSerializer (which uppercases html tags) and innerHTML (which
// lowercases tags)
var ret = "",
ns = "",
name = (this.tagName+"").toLowerCase(),
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;
for(i=0;i< attrs.length;i++){
attrstring += " "+attrs[i].name+'="'+attrs[i].xml+'"';
}
if(this.hasChildNodes()){
// serialize this Element
ret += "<" + name + ns + attrstring +">";
for(i=0;i< this.childNodes.length;i++){
ret += this.childNodes[i].xhtml ?
this.childNodes[i].xhtml :
this.childNodes[i].xml
}
ret += "" + name + ">";
}else{
switch(name){
case 'script':
ret += "<" + name + ns + attrstring +">"+name+">";
default:
ret += "<" + name + ns + attrstring +"/>";
}
}
return ret;
}
});
/*
* HTMLCollection - DOM Level 2
* Implementation Provided by Steven Wood
*/
HTMLCollection = function(nodelist, type){
__setArray__(this, []);
for (var i=0; i= 0) && (idx < this.length)) {
ret = this[idx];
}
return ret;
},
namedItem : function (name) {
if(name in this){
return this[name];
}
return null;
}
};
/*
* a set of convenience classes to centralize implementation of
* properties and methods across multiple in-form elements
*
* the hierarchy of related HTML elements and their members is as follows:
*
*
* HTMLInputCommon: common to all elements
* .form
*
*