1
0
Fork 0
mirror of https://github.com/perlbot/perlbuut synced 2025-06-07 18:55:44 -04:00
perlbuut/deps/.svn/text-base/env.js.svn-base
2009-12-05 00:02:04 -05:00

9895 lines
300 KiB
Text

/*
* Pure JavaScript Browser Environment
* By John Resig <http://ejohn.org/>
* Copyright 2008 John Resig, under the MIT License
*/
// The Window Object
var __this__ = this;
this.__defineGetter__('window', function(){
return __this__;
});
try{
(function($w, $env){
/*
* window.js
* - this file will be wrapped in a closure providing the window object as $w
*/
// a logger or empty function available to all modules.
var $log = $env.log,
$debug = $env.debug,
$info = $env.info,
$warn = $env.warn,
$error = $env.error;
//The version of this application
var $version = "0.1";
//This should be hooked to git or svn or whatever
var $revision = "0.0.0.0";
//These descriptions of window properties are taken loosely David Flanagan's
//'JavaScript - The Definitive Guide' (O'Reilly)
/**> $cookies - see cookie.js <*/
// read only boolean specifies whether the window has been closed
var $closed = false;
// a read/write string that specifies the default message that appears in the status line
var $defaultStatus = "Done";
// a read-only reference to the Document object belonging to this window
/**> $document - See document.js <*/
//IE only, refers to the most recent event object - this maybe be removed after review
var $event = null;
//A read-only array of window objects
var $frames = [];
// a read-only reference to the History object
/**> $history - see location.js <**/
// read-only properties that specify the height and width, in pixels
var $innerHeight = 600, $innerWidth = 800;
// a read-only reference to the Location object. the location object does expose read/write properties
/**> $location - see location.js <**/
// a read only property specifying the name of the window. Can be set when using open()
// and may be used when specifying the target attribute of links
var $name = 'Resig Env Browser';
// a read-only reference to the Navigator object
/**> $navigator - see navigator.js <**/
// a read/write reference to the Window object that contained the script that called open() to
//open this browser window. This property is valid only for top-level window objects.
var $opener;
// Read-only properties that specify the total height and width, in pixels, of the browser window.
// These dimensions include the height and width of the menu bar, toolbars, scrollbars, window
// borders and so on. These properties are not supported by IE and IE offers no alternative
// properties;
var $outerHeight = $innerHeight, $outerWidth = $innerWidth;
// Read-only properties that specify the number of pixels that the current document has been scrolled
//to the right and down. These are not supported by IE.
var $pageXOffset = 0, $pageYOffset = 0;
//A read-only reference to the Window object that contains this window or frame. If the window is
// a top-level window, parent refers to the window itself. If this window is a frame, this property
// refers to the window or frame that conatins it.
var $parent;
// a read-only refernce to the Screen object that specifies information about the screen:
// the number of available pixels and the number of available colors.
/**> $screen - see screen.js <**/
// read only properties that specify the coordinates of the upper-left corner of the screen.
var $screenX = 0, $screenY = 0;
var $screenLeft = $screenX, $screenTop = $screenY;
// a read-only refernce to this window itself.
var $self;
// a read/write string that specifies the current contents of the status line.
var $status = '';
// a read-only reference to the top-level window that contains this window. If this
// window is a top-level window it is simply a refernce to itself. If this window
// is a frame, the top property refers to the top-level window that contains the frame.
var $top;
// the window property is identical to the self property.
var $window = $w;
$debug("Initializing Window.");
__extend__($w,{
get closed(){return $closed;},
get defaultStatus(){return $defaultStatus;},
set defaultStatus(_defaultStatus){$defaultStatus = _defaultStatus;},
//get document(){return $document;}, - see document.js
get event(){return $event;},
get frames(){return $frames;},
//get history(){return $history;}, - see location.js
get innerHeight(){return $innerHeight;},
get innerWidth(){return $innerWidth;},
get clientHeight(){return $innerHeight;},
get clientWidth(){return $innerWidth;},
//get location(){return $location;}, see location.js
get name(){return $name;},
//get navigator(){return $navigator;}, see navigator.js
get opener(){return $opener;},
get outerHeight(){return $outerHeight;},
get outerWidth(){return $outerWidth;},
get pageXOffest(){return $pageXOffset;},
get pageYOffset(){return $pageYOffset;},
get parent(){return $parent;},
//get screen(){return $screen;}, see screen.js
get screenLeft(){return $screenLeft;},
get screenTop(){return $screenTop;},
get screenX(){return $screenX;},
get screenY(){return $screenY;},
get self(){return $self;},
get status(){return $status;},
set status(_status){$status = _status;},
get top(){return $top || $window;},
get window(){return $window;}
});
$w.open = function(url, name, features, replace){
//TODO
};
$w.close = function(){
//TODO
};
/* Time related functions - see timer.js
* - clearTimeout
* - clearInterval
* - setTimeout
* - setInterval
*/
/*
* Events related functions - see event.js
* - addEventListener
* - attachEvent
* - detachEvent
* - removeEventListener
*
* These functions are identical to the Element equivalents.
*/
/*
* UIEvents related functions - see uievent.js
* - blur
* - focus
*
* These functions are identical to the Element equivalents.
*/
/* Dialog related functions - see dialog.js
* - alert
* - confirm
* - prompt
*/
/* Screen related functions - see screen.js
* - moveBy
* - moveTo
* - print
* - resizeBy
* - resizeTo
* - scrollBy
* - scrollTo
*/
/* CSS related functions - see css.js
* - getComputedStyle
*/
/*
* Shared utility methods
*/
// 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;
};
// from ariel flesler http://flesler.blogspot.com/2008/11/fast-trim-function-for-javascript.html
// this might be a good utility function to provide in the env.core
// as in might be useful to the parser and other areas as well
function trim( str ){
return (str || "").replace( /^\s+|\s+$/g, "" );
};
/*function trim( str ){
var start = -1,
end = str.length;
/*jsl:ignore*
while( str.charCodeAt(--end) < 33 );
while( str.charCodeAt(++start) < 33 );
/*jsl:end*
return str.slice( start, end + 1 );
};*/
//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 );
};
$debug("Defining NodeList");
/*
* NodeList - DOM Level 2
*/
/**
* @class DOMNodeList - provides the abstraction of an ordered collection of nodes
*
* @author Jon van Noort (jon@webarcana.com.au)
*
* @param ownerDocument : DOMDocument - the ownerDocument
* @param parentNode : DOMNode - the node that the DOMNodeList is attached to (or null)
*/
var DOMNodeList = function(ownerDocument, parentNode) {
this.length = 0;
this.parentNode = parentNode;
this.ownerDocument = ownerDocument;
this._readonly = false;
__setArray__(this, []);
};
__extend__(DOMNodeList.prototype, {
item : function(index) {
var ret = null;
//$log("NodeList item("+index+") = " + this[index]);
if ((index >= 0) && (index < this.length)) { // bounds check
ret = this[index]; // return selected Node
}
return ret; // if the index is out of bounds, default value null is returned
},
get xml() {
var ret = "";
// create string containing the concatenation of the string values of each child
for (var i=0; i < this.length; i++) {
if(this[i]){
if(this[i].nodeType == DOMNode.TEXT_NODE && i>0 && this[i-1].nodeType == DOMNode.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 = [];
for ( var i=0; i < this.length; i++) {
children.push (this[i]);
}
return children;
},
toString: function(){
return "[ "+(this.length > 0?Array.prototype.join.apply(this, [", "]):"Empty NodeList")+" ]";
}
});
/**
* @method DOMNodeList._findItemIndex - find the item index of the node with the specified internal id
* @author Jon van Noort (jon@webarcana.com.au)
* @param id : int - unique internal id
* @return : int
*/
var __findItemIndex__ = function (nodelist, id) {
var ret = -1;
// test that id is valid
if (id > -1) {
for (var i=0; i<nodelist.length; i++) {
// compare id to each node's _id
if (nodelist[i]._id == id) { // found it!
ret = i;
break;
}
}
}
return ret; // if node is not found, default value -1 is returned
};
/**
* @method DOMNodeList._insertBefore - insert the specified Node into the NodeList before the specified index
* Used by DOMNode.insertBefore(). Note: DOMNode.insertBefore() is responsible for Node Pointer surgery
* DOMNodeList._insertBefore() simply modifies the internal data structure (Array).
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param newChild : DOMNode - the Node to be inserted
* @param refChildIndex : int - the array index to insert the Node before
*/
var __insertBefore__ = function(nodelist, newChild, refChildIndex) {
if ((refChildIndex >= 0) && (refChildIndex < nodelist.length)) { // bounds check
if (newChild.nodeType == DOMNode.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 DOMNodeList._replaceChild - replace the specified Node in the NodeList at the specified index
* Used by DOMNode.replaceChild(). Note: DOMNode.replaceChild() is responsible for Node Pointer surgery
* DOMNodeList._replaceChild() simply modifies the internal data structure (Array).
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param newChild : DOMNode - the Node to be inserted
* @param refChildIndex : int - the array index to hold the Node
*/
var __replaceChild__ = function(nodelist, newChild, refChildIndex) {
var ret = null;
if ((refChildIndex >= 0) && (refChildIndex < nodelist.length)) { // bounds check
ret = nodelist[refChildIndex]; // preserve old child for return
if (newChild.nodeType == DOMNode.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 ret; // return replaced node
};
/**
* @method DOMNodeList._removeChild - remove the specified Node in the NodeList at the specified index
* Used by DOMNode.removeChild(). Note: DOMNode.removeChild() is responsible for Node Pointer surgery
* DOMNodeList._replaceChild() simply modifies the internal data structure (Array).
*
* @author Jon van Noort (jon@webarcana.com.au)
* @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!
ret = nodelist[refChildIndex]; // return removed node
// rebuild array without removed child
Array.prototype.splice.apply(nodelist,[refChildIndex, 1]);
}
return ret; // return removed node
};
/**
* @method DOMNodeList._appendChild - append the specified Node to the NodeList
* Used by DOMNode.appendChild(). Note: DOMNode.appendChild() is responsible for Node Pointer surgery
* DOMNodeList._appendChild() simply modifies the internal data structure (Array).
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param newChild : DOMNode - the Node to be inserted
*/
var __appendChild__ = function(nodelist, newChild) {
if (newChild.nodeType == DOMNode.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 DOMNodeList._cloneNodes - Returns a NodeList containing clones of the Nodes in this NodeList
*
* @author Jon van Noort (jon@webarcana.com.au)
* @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 : DOMNode - the new parent of the cloned NodeList
* @return : DOMNodeList - NodeList containing clones of the Nodes in this NodeList
*/
var __cloneNodes__ = function(nodelist, deep, parentNode) {
var cloneNodeList = new DOMNodeList(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;
};
$w.NodeList = DOMNodeList;
/**
* @class DOMNamedNodeMap - used to represent collections of nodes that can be accessed by name
* typically a set of Element attributes
*
* @extends DOMNodeList - note W3C spec says that this is not the case,
* but we need an item() method identicle to DOMNodeList's, so why not?
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : DOMDocument - the ownerDocument
* @param parentNode : DOMNode - the node that the DOMNamedNodeMap is attached to (or null)
*/
var DOMNamedNodeMap = function(ownerDocument, parentNode) {
//$log("\t\tcreating dom namednodemap");
this.DOMNodeList = DOMNodeList;
this.DOMNodeList(ownerDocument, parentNode);
__setArray__(this, []);
};
DOMNamedNodeMap.prototype = new DOMNodeList;
__extend__(DOMNamedNodeMap.prototype, {
getNamedItem : function(name) {
var ret = null;
// test that Named Node exists
var itemIndex = __findNamedItemIndex__(this, name);
if (itemIndex > -1) { // found it!
ret = this[itemIndex]; // return NamedNode
}
return ret; // if node is not found, default value null is returned
},
setNamedItem : function(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));
}
}
// get item index
var itemIndex = __findNamedItemIndex__(this, arg.name);
var ret = null;
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] = arg;
}
} else {
// add new NamedNode
Array.prototype.push.apply(this, [arg]);
this[arg.name] = arg;
}
arg.ownerElement = this.parentNode; // update ownerElement
return ret; // return old node or null
},
removeNamedItem : function(name) {
var ret = null;
// test for exceptions
// throw Exception if DOMNamedNodeMap 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!
ret = this[itemIndex]; // return NamedNode
}
return ret; // if node is not found, default value null is returned
},
setNamedItemNS : function(arg) {
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// 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 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!
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
}
}else {
// add new NamedNode
Array.prototype.push.apply(this, [arg]);
}
arg.ownerElement = this.parentNode;
return ret; // return old node or null
},
removeNamedItemNS : function(namespaceURI, localName) {
var ret = null;
// test for exceptions
// throw Exception if DOMNamedNodeMap 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;
}
});
/**
* @method DOMNamedNodeMap._findNamedItemIndex - find the item index of the node with the specified name
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param name : string - the name of the required node
* @param isnsmap : if its a DOMNamespaceNodeMap
* @return : int
*/
var __findNamedItemIndex__ = function(namednodemap, name, isnsmap) {
var ret = -1;
// loop through all nodes
for (var i=0; i<namednodemap.length; i++) {
// compare name to each node's nodeName
if(isnsmap){
if (namednodemap[i].localName == localName) { // found it!
ret = i;
break;
}
}else{
if (namednodemap[i].name == name) { // found it!
ret = i;
break;
}
}
}
return ret; // if node is not found, default value -1 is returned
};
/**
* @method DOMNamedNodeMap._findNamedItemNSIndex - find the item index of the node with the specified namespaceURI and localName
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param namespaceURI : string - the namespace URI of the required node
* @param localName : string - the local name of the required node
* @return : int
*/
var __findNamedItemNSIndex__ = function(namednodemap, namespaceURI, localName) {
var ret = -1;
// test that localName is not null
if (localName) {
// loop through all nodes
for (var i=0; i<namednodemap.length; i++) {
// compare name to each node's namespaceURI and localName
if ((namednodemap[i].namespaceURI == namespaceURI) && (namednodemap[i].localName == localName)) {
ret = i; // found it!
break;
}
}
}
return ret; // if node is not found, default value -1 is returned
};
/**
* @method DOMNamedNodeMap._hasAttribute - Returns true if specified node exists
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param name : string - the name of the required node
* @return : boolean
*/
var __hasAttribute__ = function(namednodemap, name) {
var ret = false;
// test that Named Node exists
var itemIndex = __findNamedItemIndex__(namednodemap, name);
if (itemIndex > -1) { // found it!
ret = true; // return true
}
return ret; // if node is not found, default value false is returned
}
/**
* @method DOMNamedNodeMap._hasAttributeNS - Returns true if specified node exists
*
* @author Jon van Noort (jon@webarcana.com.au)
* @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; // return true
}
return ret; // if node is not found, default value false is returned
}
/**
* @method DOMNamedNodeMap._cloneNodes - Returns a NamedNodeMap containing clones of the Nodes in this NamedNodeMap
*
* @author Jon van Noort (jon@webarcana.com.au)
* @param parentNode : DOMNode - the new parent of the cloned NodeList
* @param isnsmap : bool - is this a DOMNamespaceNodeMap
* @return : DOMNamedNodeMap - NamedNodeMap containing clones of the Nodes in this DOMNamedNodeMap
*/
var __cloneNamedNodes__ = function(namednodemap, parentNode, isnsmap) {
var cloneNamedNodeMap = isnsmap?
new DOMNamespaceNodeMap(namednodemap.ownerDocument, parentNode):
new DOMNamedNodeMap(namednodemap.ownerDocument, parentNode);
// create list containing clones of all children
for (var i=0; i < namednodemap.length; i++) {
$debug("cloning node in named node map :" + namednodemap[i]);
__appendChild__(cloneNamedNodeMap, namednodemap[i].cloneNode(false));
}
return cloneNamedNodeMap;
};
/**
* @class DOMNamespaceNodeMap - used to represent collections of namespace nodes that can be accessed by name
* typically a set of Element attributes
*
* @extends DOMNamedNodeMap
*
* @author Jon van Noort (jon@webarcana.com.au)
*
* @param ownerDocument : DOMDocument - the ownerDocument
* @param parentNode : DOMNode - the node that the DOMNamespaceNodeMap is attached to (or null)
*/
var DOMNamespaceNodeMap = function(ownerDocument, parentNode) {
//$log("\t\t\tcreating dom namespacednodemap");
this.DOMNamedNodeMap = DOMNamedNodeMap;
this.DOMNamedNodeMap(ownerDocument, parentNode);
__setArray__(this, []);
};
DOMNamespaceNodeMap.prototype = new DOMNamedNodeMap;
__extend__(DOMNamespaceNodeMap.prototype, {
get xml() {
var ret = "";
// identify namespaces declared local to this Element (ie, not inherited)
for (var ind = 0; ind < this.length; ind++) {
// if namespace declaration does not exist in the containing node's, parentNode's namespaces
var 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;
}
});
$debug("Defining Node");
/*
* Node - DOM Level 2
*/
/**
* @class DOMNode - The Node interface is the primary datatype for the entire Document Object Model.
* It represents a single node in the document tree.
* @author Jon van Noort (jon@webarcana.com.au), David Joham (djoham@yahoo.com) and Scott Severtson
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMNode = function(ownerDocument) {
if (ownerDocument) {
this._id = ownerDocument._genId(); // generate unique internal id
}
this.namespaceURI = ""; // The namespace URI of this node (Level 2)
this.prefix = ""; // The namespace prefix of this node (Level 2)
this.localName = ""; // The localName of this node (Level 2)
this.nodeName = ""; // The name of this node
this.nodeValue = null; // The value of this node
this.className = ""; // The CSS class name of this node.
// 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;
// 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 DOMNodeList(ownerDocument, this);
this.firstChild = null; // The first child of this node. If there is no such node, this is null
this.lastChild = null; // The last child of this node. If there is no such node, this is null.
this.previousSibling = null; // The node immediately preceding this node. If there is no such node, this is null.
this.nextSibling = null; // The node immediately following this node. If there is no such node, this is null.
this.ownerDocument = ownerDocument; // The Document object associated with this node
this.attributes = new DOMNamedNodeMap(this.ownerDocument, this);
this._namespaces = new DOMNamespaceNodeMap(ownerDocument, this); // The namespaces in scope for this node
this._readonly = false;
};
// nodeType constants
DOMNode.ELEMENT_NODE = 1;
DOMNode.ATTRIBUTE_NODE = 2;
DOMNode.TEXT_NODE = 3;
DOMNode.CDATA_SECTION_NODE = 4;
DOMNode.ENTITY_REFERENCE_NODE = 5;
DOMNode.ENTITY_NODE = 6;
DOMNode.PROCESSING_INSTRUCTION_NODE = 7;
DOMNode.COMMENT_NODE = 8;
DOMNode.DOCUMENT_NODE = 9;
DOMNode.DOCUMENT_TYPE_NODE = 10;
DOMNode.DOCUMENT_FRAGMENT_NODE = 11;
DOMNode.NOTATION_NODE = 12;
DOMNode.NAMESPACE_NODE = 13;
__extend__(DOMNode.prototype, {
hasAttributes : function() {
if (this.attributes.length == 0) {
return false;
}else{
return true;
}
},
insertBefore : function(newChild, refChild) {
var prevNode;
if(newChild==null || refChild==null){
return newChild;
}
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if DOMNode 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) { // if refChild is specified, insert before it
// find index of refChild
var itemIndex = __findItemIndex__(this.childNodes, refChild._id);
// 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,
__findItemIndex__(this.childNodes, refChild._id));
// do node pointer surgery
prevNode = refChild.previousSibling;
// handle DocumentFragment
if (newChild.nodeType == DOMNode.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 {
newChild.parentNode = this; // set the parentNode of the newChild
refChild.previousSibling = newChild; // link refChild to newChild
}
}else { // otherwise, append to end
prevNode = this.lastChild;
this.appendChild(newChild);
}
if (newChild.nodeType == DOMNode.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 DOMNode 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._id);
// 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 == DOMNode.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 DOMNamedNodeMap 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._id);
// 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
newChildParent.removeChild(newChild);
}
// add newChild to childNodes
__appendChild__(this.childNodes, newChild);
if (newChild.nodeType == DOMNode.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
return null;
}
},
normalize : function() {
var inode;
var nodesToRemove = new DOMNodeList();
if (this.nodeType == DOMNode.ELEMENT_NODE || this.nodeType == DOMNode.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 == DOMNode.TEXT_NODE) { // this node is a text node
if (inode.length < 1) { // this text node is empty
__appendChild__(nodesToRemove, inode); // add this node to the list of nodes to be remove
}else {
if (adjacentTextNode) { // if previous node was also text
adjacentTextNode.appendData(inode.data); // merge the data in adjacent text nodes
__appendChild__(nodesToRemove, inode); // add this node to the list of nodes to be removed
}else {
adjacentTextNode = inode; // remember this node for next cycle
}
}
} else {
adjacentTextNode = null; // (soon to be) previous node is not a text node
inode.normalize(); // normalise non Text childNodes
}
}
// 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 determin if this feature is supported
return __ownerDocument__(this).implementation.hasFeature(feature, version);
},
getElementsByTagName : function(tagname) {
// delegate to _getElementsByTagNameRecursive
// recurse childNodes
var nodelist = new DOMNodeList(__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 DOMNodeList(__ownerDocument__(this)));
},
importNode : function(importedNode, deep) {
var importNode;
//$debug("importing node " + importedNode.nodeName + "(?deep = "+deep+")");
//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)._performingImportNodeOperation = true;
if (importedNode.nodeType == DOMNode.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 == DOMNode.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 == DOMNode.DOCUMENT_FRAGMENT) {
// create a local DocumentFragment
importNode = __ownerDocument__(this).createDocumentFragment();
} else if (importedNode.nodeType == DOMNode.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 == DOMNode.TEXT_NODE) {
// create a local TextNode (with the same data as the importedNode)
importNode = __ownerDocument__(this).createTextNode(importedNode.data);
} else if (importedNode.nodeType == DOMNode.CDATA_SECTION_NODE) {
// create a local CDATANode (with the same data as the importedNode)
importNode = __ownerDocument__(this).createCDATASection(importedNode.data);
} else if (importedNode.nodeType == DOMNode.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 == DOMNode.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 _performingImportNodeOperation
__ownerDocument__(this)._performingImportNodeOperation = false;
return importNode;
},
contains : function(node){
while(node && node != this ){
node = node.parentNode;
}
return !!node;
},
compareDocumentPosition : function(b){
var a = this;
var number = (a != b && a.contains(b) && 16) + (a != b && b.contains(a) && 8);
//find position of both
var all = document.getElementsByTagName("*");
var my_location = 0, node_location = 0;
for(var i=0; i < all.length; i++){
if(all[i] == a) my_location = i;
if(all[i] == b) node_location = i;
if(my_location && node_location) break;
}
number += (my_location < node_location && 4)
number += (my_location > node_location && 2)
return number;
}
});
/**
* @method DOMNode._getElementsByTagNameRecursive - implements getElementsByTagName()
* @param elem : DOMElement - 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 : DOMNodeList - The accumulating list of matching nodes
*
* @return : DOMNodeList
*/
var __getElementsByTagNameRecursive__ = function (elem, tagname, nodeList) {
if (elem.nodeType == DOMNode.ELEMENT_NODE || elem.nodeType == DOMNode.DOCUMENT_NODE) {
if(elem.nodeType !== DOMNode.DOCUMENT_NODE &&
((elem.nodeName.toUpperCase() == tagname.toUpperCase()) ||
(tagname == "*")) ){
__appendChild__(nodeList, elem); // add matching node to nodeList
}
// recurse childNodes
for(var i = 0; i < elem.childNodes.length; i++) {
nodeList = __getElementsByTagNameRecursive__(elem.childNodes.item(i), tagname, nodeList);
}
}
return nodeList;
};
/**
* @method DOMNode._getElementsByTagNameNSRecursive - implements getElementsByTagName()
*
* @param elem : DOMElement - 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 : DOMNodeList - The accumulating list of matching nodes
*
* @return : DOMNodeList
*/
var __getElementsByTagNameNSRecursive__ = function(elem, namespaceURI, localName, nodeList) {
if (elem.nodeType == DOMNode.ELEMENT_NODE || elem.nodeType == DOMNode.DOCUMENT_NODE) {
if (((elem.namespaceURI == namespaceURI) || (namespaceURI == "*")) && ((elem.localName == localName) || (localName == "*"))) {
__appendChild__(nodeList, elem); // add matching node to nodeList
}
// recurse childNodes
for(var i = 0; i < elem.childNodes.length; i++) {
nodeList = __getElementsByTagNameNSRecursive__(elem.childNodes.item(i), namespaceURI, localName, nodeList);
}
}
return nodeList;
};
/**
* @method DOMNode._isAncestor - returns true if node is ancestor of target
* @param target : DOMNode - The node we are using as context
* @param node : DOMNode - 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 == DOMNode.DOCUMENT_NODE)?node:node.ownerDocument;
};
$w.Node = DOMNode;
/**
* @class DOMNamespace - The Namespace interface represents an namespace in an Element object
*
* @extends DOMNode
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMNamespace = function(ownerDocument) {
this.DOMNode = DOMNode;
this.DOMNode(ownerDocument);
this.name = ""; // the name of this attribute
// 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;
};
DOMNamespace.prototype = new DOMNode;
__extend__(DOMNamespace.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 DOMNode.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 "Namespace #" + this.id;
}
});
$debug("Defining CharacterData");
/*
* CharacterData - DOM Level 2
*/
/**
* @class DOMCharacterData - parent abstract class for DOMText and DOMComment
* @extends DOMNode
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMCharacterData = function(ownerDocument) {
this.DOMNode = DOMNode;
this.DOMNode(ownerDocument);
};
DOMCharacterData.prototype = new DOMNode;
__extend__(DOMCharacterData.prototype,{
get data(){
return this.nodeValue;
},
set data(data){
this.nodeValue = data;
},
get length(){return this.nodeValue.length;},
appendData: function(arg){
// throw Exception if DOMCharacterData 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 DOMCharacterData 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 DOMCharacterData 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 DOMCharacterData 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;
}
});
$w.CharacterData = DOMCharacterData;$debug("Defining Text");
/*
* Text - DOM Level 2
*/
/**
* @class DOMText - 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 DOMCharacterData
* @author Jon van Noort (jon@webarcana.com.au) and David Joham (djoham@yahoo.com)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMText = function(ownerDocument) {
this.DOMCharacterData = DOMCharacterData;
this.DOMCharacterData(ownerDocument);
this.nodeName = "#text";
};
DOMText.prototype = new DOMCharacterData;
__extend__(DOMText.prototype,{
//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 DOMNode.TEXT_NODE;
},
get xml(){
return __escapeXML__(""+ this.nodeValue);
},
toString: function(){
return "Text #" + this._id;
}
});
$w.Text = DOMText;$debug("Defining CDATASection");
/*
* CDATASection - DOM Level 2
*/
/**
* @class DOMCDATASection - 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 DOMCharacterData
* @author Jon van Noort (jon@webarcana.com.au) and David Joham (djoham@yahoo.com)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMCDATASection = function(ownerDocument) {
this.DOMText = DOMText;
this.DOMText(ownerDocument);
this.nodeName = "#cdata-section";
};
DOMCDATASection.prototype = new DOMText;
__extend__(DOMCDATASection.prototype,{
get nodeType(){
return DOMNode.CDATA_SECTION_NODE;
},
get xml(){
return "<![CDATA[" + this.nodeValue + "]]>";
},
toString : function(){
return "CDATA #"+this._id;
}
});
$w.CDATASection = DOMCDATASection;$debug("Defining Comment");
/*
* Comment - DOM Level 2
*/
/**
* @class DOMComment - This represents the content of a comment, i.e., all the characters between the starting '<!--' and ending '-->'
* @extends DOMCharacterData
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMComment = function(ownerDocument) {
this.DOMCharacterData = DOMCharacterData;
this.DOMCharacterData(ownerDocument);
this.nodeName = "#comment";
};
DOMComment.prototype = new DOMCharacterData;
__extend__(DOMComment.prototype, {
get nodeType(){
return DOMNode.COMMENT_NODE;
},
get xml(){
return "<!--" + this.nodeValue + "-->";
},
toString : function(){
return "Comment #"+this._id;
}
});
$w.Comment = DOMComment;
$debug("Defining DocumentType");
;/*
* DocumentType - DOM Level 2
*/
var DOMDocumentType = function() {
$error("DOMDocumentType.constructor(): Not Implemented" );
};
$w.DocumentType = DOMDocumentType;
$debug("Defining Attr");
/*
* Attr - DOM Level 2
*/
/**
* @class DOMAttr - The Attr interface represents an attribute in an Element object
* @extends DOMNode
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMAttr = function(ownerDocument) {
this.DOMNode = DOMNode;
this.DOMNode(ownerDocument);
this.ownerElement = null; // set when Attr is added to NamedNodeMap
};
DOMAttr.prototype = new DOMNode;
__extend__(DOMAttr.prototype, {
// the name of this attribute
get name(){
return this.nodeName;
},
set name(name){
this.nodeName = name;
},
// 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 specified(){
return (this.value.length > 0);
},
get nodeType(){
return DOMNode.ATTRIBUTE_NODE;
},
get xml(){
return this.nodeName + '="' + __escapeXML__(this.nodeValue) + '" ';
},
toString : function(){
return "Attr #" + this._id + " " + this.name;
}
});
$w.Attr = DOMAttr;
$debug("Defining Element");
/**
* @class DOMElement - By far the vast majority of objects (apart from text) that authors encounter
* when traversing a document are Element nodes.
* @extends DOMNode
* @author Jon van Noort (jon@webarcana.com.au) and David Joham (djoham@yahoo.com)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMElement = function(ownerDocument) {
this.DOMNode = DOMNode;
this.DOMNode(ownerDocument);
this.id = ""; // the ID of the element
};
DOMElement.prototype = new DOMNode;
__extend__(DOMElement.prototype, {
// The name of the element.
get tagName(){
return this.nodeName;
},
set tagName(name){
this.nodeName = name;
},
addEventListener : function(){ window.addEventListener.apply(this, arguments) },
removeEventListener : function(){ window.removeEventListener.apply(this, arguments) },
dispatchEvent : function(){ window.dispatchEvent.apply(this, arguments) },
getAttribute: function(name) {
var ret = null;
// if attribute exists, use it
var attr = this.attributes.getNamedItem(name);
if (attr) {
ret = attr.value;
}
return ret; // if Attribute exists, return its value, otherwise, return ""
},
setAttribute : function (name, value) {
// if attribute exists, use it
var attr = this.attributes.getNamedItem(name);
var value = value+'';
//I had to add this check becuase 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) {
attr = __ownerDocument__(this).createAttribute(name); // otherwise create it
}
// 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));
}
}
if (__isIdDeclaration__(name)) {
// this.id = value; // cache ID for getElementById()
}
// assign values to properties (and aliases)
attr.value = value;
// add/replace Attribute in NamedNodeMap
this.attributes.setNamedItem(attr);
}
},
removeAttribute : function removeAttribute(name) {
// delegate to DOMNamedNodeMap.removeNamedItem
return this.attributes.removeNamedItem(name);
},
getAttributeNode : function getAttributeNode(name) {
// delegate to DOMNamedNodeMap.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 DOMNamedNodeMap.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 DOMNAmedNodeMap.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 DOMNamedNodeMap.getNamedItem
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__(namespaceURI, qualifiedName)) {
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; // cache ID for getElementById()
}
// assign values to properties (and aliases)
attr.value = value;
attr.nodeValue = value;
// delegate to DOMNamedNodeMap.setNamedItem
this.attributes.setNamedItemNS(attr);
},
removeAttributeNS : function(namespaceURI, localName) {
// delegate to DOMNamedNodeMap.removeNamedItemNS
return this.attributes.removeNamedItemNS(namespaceURI, localName);
},
getAttributeNodeNS : function(namespaceURI, localName) {
// delegate to DOMNamedNodeMap.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 DOMNamedNodeMap.setNamedItemNS
return this.attributes.setNamedItemNS(newAttr);
},
hasAttribute : function(name) {
// delegate to DOMNamedNodeMap._hasAttribute
return __hasAttribute__(this.attributes,name);
},
hasAttributeNS : function(namespaceURI, localName) {
// delegate to DOMNamedNodeMap._hasAttributeNS
return __hasAttributeNS__(this.attributes, namespaceURI, localName);
},
get nodeType(){
return DOMNode.ELEMENT_NODE;
},
get xml() {
var ret = "";
// serialize namespace declarations
var ns = this._namespaces.xml;
if (ns.length > 0) ns = " "+ ns;
// serialize Attribute declarations
var attrs = this.attributes.xml;
if (attrs.length > 0) attrs = " "+ attrs;
// serialize this Element
ret += "<" + this.nodeName.toLowerCase() + ns + attrs +">";
ret += this.childNodes.xml;
ret += "</" + this.nodeName.toLowerCase()+">";
return ret;
},
toString : function(){
return "Element #"+this._id + " "+ this.tagName + (this.id?" => "+this.id:'');
}
});
$w.Element = DOMElement;
/**
* @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)
*/
var 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;
$debug("Defining DocumentFragment");
/*
* DocumentFragment - DOM Level 2
*/
/**
* @class DOMDocumentFragment - DocumentFragment is a "lightweight" or "minimal" Document object.
* @extends DOMNode
* @author Jon van Noort (jon@webarcana.com.au) and David Joham (djoham@yahoo.com)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMDocumentFragment = function(ownerDocument) {
this.DOMNode = DOMNode;
this.DOMNode(ownerDocument);
this.nodeName = "#document-fragment";
};
DOMDocumentFragment.prototype = new DOMNode;
__extend__(DOMDocumentFragment.prototype,{
get nodeType(){
return DOMNode.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 "DocumentFragment #"+this._id;
}
});
$w.DocumentFragment = DOMDocumentFragment;
$debug("Defining ProcessingInstruction");
/*
* ProcessingInstruction - DOM Level 2
*/
/**
* @class DOMProcessingInstruction - 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 DOMNode
* @author Jon van Noort (jon@webarcana.com.au)
* @param ownerDocument : DOMDocument - The Document object associated with this node.
*/
var DOMProcessingInstruction = function(ownerDocument) {
this.DOMNode = DOMNode;
this.DOMNode(ownerDocument);
};
DOMProcessingInstruction.prototype = new DOMNode;
__extend__(DOMProcessingInstruction.prototype, {
get data(){
return this.nodeValue;
},
set data(data){
// throw Exception if DOMNode is readonly
if (__ownerDocument__(this).errorChecking && this._readonly) {
throw(new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR));
}
this.nodeValue = data;
},
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;
},
get nodeType(){
return DOMNode.PROCESSING_INSTRUCTION_NODE;
},
get xml(){
return "<?" + this.nodeName +" "+ this.nodeValue + " ?>";
},
toString : function(){
return "ProcessingInstruction #"+this._id;
}
});
$w.ProcessesingInstruction = DOMProcessingInstruction;
$debug("Defining DOMParser");
/*
* DOMParser
*/
var DOMParser = function(){};
__extend__(DOMParser.prototype,{
parseFromString: function(xmlString){
//$log("Parsing XML String: " +xmlString);
return document.implementation.createDocument().loadXML(xmlString);
}
});
$debug("Initializing Internal DOMParser.");
//keep one around for internal use
$domparser = new DOMParser();
$w.DOMParser = DOMParser;
// =========================================================================
//
// xmlsax.js - an XML SAX parser in JavaScript.
//
// version 3.1
//
// =========================================================================
//
// Copyright (C) 2001 - 2002 David Joham (djoham@yahoo.com) and Scott Severtson
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// Visit the XML for <SCRIPT> home page at http://xmljs.sourceforge.net
//
// CONSTANTS
var whitespace = "\n\r\t ";
/**
* function: this is the constructor to the XMLP Object
* Author: Scott Severtson
* Description:XMLP is a pull-based parser. The calling application passes in a XML string
* to the constructor, then repeatedly calls .next() to parse the next segment.
* .next() returns a flag indicating what type of segment was found, and stores
* data temporarily in couple member variables (name, content, array of
* attributes), which can be accessed by several .get____() methods.
*
* Basically, XMLP is the lowest common denominator parser - an very simple
* API which other wrappers can be built against.
**/
var XMLP = function(strXML) {
// Normalize line breaks
strXML = SAXStrings.replace(strXML, null, null, "\r\n", "\n");
strXML = SAXStrings.replace(strXML, null, null, "\r", "\n");
this.m_xml = strXML;
this.m_iP = 0;
this.m_iState = XMLP._STATE_PROLOG;
this.m_stack = new Stack();
this._clearAttributes();
this.replaceEntities = true;
};
// CONSTANTS (these must be below the constructor)
XMLP._NONE = 0;
XMLP._ELM_B = 1;
XMLP._ELM_E = 2;
XMLP._ELM_EMP = 3;
XMLP._ATT = 4;
XMLP._TEXT = 5;
XMLP._ENTITY = 6;
XMLP._PI = 7;
XMLP._CDATA = 8;
XMLP._COMMENT = 9;
XMLP._DTD = 10;
XMLP._ERROR = 11;
XMLP._CONT_XML = 0;
XMLP._CONT_ALT = 1;
XMLP._ATT_NAME = 0;
XMLP._ATT_VAL = 1;
XMLP._STATE_PROLOG = 1;
XMLP._STATE_DOCUMENT = 2;
XMLP._STATE_MISC = 3;
XMLP._errs = new Array();
XMLP._errs[XMLP.ERR_CLOSE_PI = 0 ] = "PI: missing closing sequence";
XMLP._errs[XMLP.ERR_CLOSE_DTD = 1 ] = "DTD: missing closing sequence";
XMLP._errs[XMLP.ERR_CLOSE_COMMENT = 2 ] = "Comment: missing closing sequence";
XMLP._errs[XMLP.ERR_CLOSE_CDATA = 3 ] = "CDATA: missing closing sequence";
XMLP._errs[XMLP.ERR_CLOSE_ELM = 4 ] = "Element: missing closing sequence";
XMLP._errs[XMLP.ERR_CLOSE_ENTITY = 5 ] = "Entity: missing closing sequence";
XMLP._errs[XMLP.ERR_PI_TARGET = 6 ] = "PI: target is required";
XMLP._errs[XMLP.ERR_ELM_EMPTY = 7 ] = "Element: cannot be both empty and closing";
XMLP._errs[XMLP.ERR_ELM_NAME = 8 ] = "Element: name must immediatly follow \"<\"";
XMLP._errs[XMLP.ERR_ELM_LT_NAME = 9 ] = "Element: \"<\" not allowed in element names";
XMLP._errs[XMLP.ERR_ATT_VALUES = 10] = "Attribute: values are required and must be in quotes";
XMLP._errs[XMLP.ERR_ATT_LT_NAME = 11] = "Element: \"<\" not allowed in attribute names";
XMLP._errs[XMLP.ERR_ATT_LT_VALUE = 12] = "Attribute: \"<\" not allowed in attribute values";
XMLP._errs[XMLP.ERR_ATT_DUP = 13] = "Attribute: duplicate attributes not allowed";
XMLP._errs[XMLP.ERR_ENTITY_UNKNOWN = 14] = "Entity: unknown entity";
XMLP._errs[XMLP.ERR_INFINITELOOP = 15] = "Infininte loop";
XMLP._errs[XMLP.ERR_DOC_STRUCTURE = 16] = "Document: only comments, processing instructions, or whitespace allowed outside of document element";
XMLP._errs[XMLP.ERR_ELM_NESTING = 17] = "Element: must be nested correctly";
XMLP.prototype._addAttribute = function(name, value) {
this.m_atts[this.m_atts.length] = new Array(name, value);
}
XMLP.prototype._checkStructure = function(iEvent) {
if(XMLP._STATE_PROLOG == this.m_iState) {
if((XMLP._TEXT == iEvent) || (XMLP._ENTITY == iEvent)) {
if(SAXStrings.indexOfNonWhitespace(this.getContent(), this.getContentBegin(), this.getContentEnd()) != -1) {
return this._setErr(XMLP.ERR_DOC_STRUCTURE);
}
}
if((XMLP._ELM_B == iEvent) || (XMLP._ELM_EMP == iEvent)) {
this.m_iState = XMLP._STATE_DOCUMENT;
// Don't return - fall through to next state
}
}
if(XMLP._STATE_DOCUMENT == this.m_iState) {
if((XMLP._ELM_B == iEvent) || (XMLP._ELM_EMP == iEvent)) {
this.m_stack.push(this.getName());
}
if((XMLP._ELM_E == iEvent) || (XMLP._ELM_EMP == iEvent)) {
var strTop = this.m_stack.pop();
if((strTop == null) || (strTop != this.getName())) {
return this._setErr(XMLP.ERR_ELM_NESTING);
}
}
if(this.m_stack.count() == 0) {
this.m_iState = XMLP._STATE_MISC;
return iEvent;
}
}
if(XMLP._STATE_MISC == this.m_iState) {
if((XMLP._ELM_B == iEvent) || (XMLP._ELM_E == iEvent) || (XMLP._ELM_EMP == iEvent) || (XMLP.EVT_DTD == iEvent)) {
return this._setErr(XMLP.ERR_DOC_STRUCTURE);
}
if((XMLP._TEXT == iEvent) || (XMLP._ENTITY == iEvent)) {
if(SAXStrings.indexOfNonWhitespace(this.getContent(), this.getContentBegin(), this.getContentEnd()) != -1) {
return this._setErr(XMLP.ERR_DOC_STRUCTURE);
}
}
}
return iEvent;
}
XMLP.prototype._clearAttributes = function() {
this.m_atts = new Array();
}
XMLP.prototype._findAttributeIndex = function(name) {
for(var i = 0; i < this.m_atts.length; i++) {
if(this.m_atts[i][XMLP._ATT_NAME] == name) {
return i;
}
}
return -1;
}
XMLP.prototype.getAttributeCount = function() {
return this.m_atts ? this.m_atts.length : 0;
}
XMLP.prototype.getAttributeName = function(index) {
return ((index < 0) || (index >= this.m_atts.length)) ? null : this.m_atts[index][XMLP._ATT_NAME];
}
XMLP.prototype.getAttributeValue = function(index) {
return ((index < 0) || (index >= this.m_atts.length)) ? null : __unescapeXML__(this.m_atts[index][XMLP._ATT_VAL]);
}
XMLP.prototype.getAttributeValueByName = function(name) {
return this.getAttributeValue(this._findAttributeIndex(name));
}
XMLP.prototype.getColumnNumber = function() {
return SAXStrings.getColumnNumber(this.m_xml, this.m_iP);
}
XMLP.prototype.getContent = function() {
return (this.m_cSrc == XMLP._CONT_XML) ? this.m_xml : this.m_cAlt;
}
XMLP.prototype.getContentBegin = function() {
return this.m_cB;
}
XMLP.prototype.getContentEnd = function() {
return this.m_cE;
}
XMLP.prototype.getLineNumber = function() {
return SAXStrings.getLineNumber(this.m_xml, this.m_iP);
}
XMLP.prototype.getName = function() {
return this.m_name;
}
XMLP.prototype.next = function() {
return this._checkStructure(this._parse());
}
XMLP.prototype.appendFragment = function(xmlfragment) {
var start = this.m_xml.slice(0,this.m_iP);
var end = this.m_xml.slice(this.m_iP);
this.m_xml = start+xmlfragment+end;
}
XMLP.prototype._parse = function() {
if(this.m_iP == this.m_xml.length) {
return XMLP._NONE;
}
if(this.m_iP == this.m_xml.indexOf("<", this.m_iP)){
if(this.m_xml.charAt(this.m_iP+1) == "?") {
return this._parsePI(this.m_iP + 2);
}
else if(this.m_xml.charAt(this.m_iP+1) == "!") {
if(this.m_xml.charAt(this.m_iP+2) == "D") {
return this._parseDTD(this.m_iP + 9);
}
else if(this.m_xml.charAt(this.m_iP+2) == "-") {
return this._parseComment(this.m_iP + 4);
}
else if(this.m_xml.charAt(this.m_iP+2) == "[") {
return this._parseCDATA(this.m_iP + 9);
}
}
else{
return this._parseElement(this.m_iP + 1);
}
}
else if(this.m_iP == this.m_xml.indexOf("&", this.m_iP)) {
return this._parseEntity(this.m_iP + 1);
}
else{
return this._parseText(this.m_iP);
}
}
XMLP.prototype._parseAttribute = function(iB, iE) {
var iNB, iNE, iEq, iVB, iVE;
var cQuote, strN, strV;
this.m_cAlt = ""; //resets the value so we don't use an old one by accident (see testAttribute7 in the test suite)
iNB = SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iE);
if((iNB == -1) ||(iNB >= iE)) {
return iNB;
}
iEq = this.m_xml.indexOf("=", iNB);
if((iEq == -1) || (iEq > iE)) {
return this._setErr(XMLP.ERR_ATT_VALUES);
}
iNE = SAXStrings.lastIndexOfNonWhitespace(this.m_xml, iNB, iEq);
iVB = SAXStrings.indexOfNonWhitespace(this.m_xml, iEq + 1, iE);
if((iVB == -1) ||(iVB > iE)) {
return this._setErr(XMLP.ERR_ATT_VALUES);
}
cQuote = this.m_xml.charAt(iVB);
if(_SAXStrings.QUOTES.indexOf(cQuote) == -1) {
return this._setErr(XMLP.ERR_ATT_VALUES);
}
iVE = this.m_xml.indexOf(cQuote, iVB + 1);
if((iVE == -1) ||(iVE > iE)) {
return this._setErr(XMLP.ERR_ATT_VALUES);
}
strN = this.m_xml.substring(iNB, iNE + 1);
strV = this.m_xml.substring(iVB + 1, iVE);
if(strN.indexOf("<") != -1) {
return this._setErr(XMLP.ERR_ATT_LT_NAME);
}
if(strV.indexOf("<") != -1) {
return this._setErr(XMLP.ERR_ATT_LT_VALUE);
}
strV = SAXStrings.replace(strV, null, null, "\n", " ");
strV = SAXStrings.replace(strV, null, null, "\t", " ");
iRet = this._replaceEntities(strV);
if(iRet == XMLP._ERROR) {
return iRet;
}
strV = this.m_cAlt;
if(this._findAttributeIndex(strN) == -1) {
this._addAttribute(strN, strV);
}else {
return this._setErr(XMLP.ERR_ATT_DUP);
}
this.m_iP = iVE + 2;
return XMLP._ATT;
}
XMLP.prototype._parseCDATA = function(iB) {
var iE = this.m_xml.indexOf("]]>", iB);
if (iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_CDATA);
}
this._setContent(XMLP._CONT_XML, iB, iE);
this.m_iP = iE + 3;
return XMLP._CDATA;
}
XMLP.prototype._parseComment = function(iB) {
var iE = this.m_xml.indexOf("-" + "->", iB);
if (iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_COMMENT);
}
this._setContent(XMLP._CONT_XML, iB, iE);
this.m_iP = iE + 3;
return XMLP._COMMENT;
}
XMLP.prototype._parseDTD = function(iB) {
// Eat DTD
var iE, strClose, iInt, iLast;
iE = this.m_xml.indexOf(">", iB);
if(iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_DTD);
}
iInt = this.m_xml.indexOf("[", iB);
strClose = ((iInt != -1) && (iInt < iE)) ? "]>" : ">";
while(true) {
// DEBUG: Remove
/*if(iE == iLast) {
return this._setErr(XMLP.ERR_INFINITELOOP);
}
iLast = iE;*/
// DEBUG: Remove End
iE = this.m_xml.indexOf(strClose, iB);
if(iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_DTD);
}
// Make sure it is not the end of a CDATA section
if (this.m_xml.substring(iE - 1, iE + 2) != "]]>") {
break;
}
}
this.m_iP = iE + strClose.length;
return XMLP._DTD;
}
XMLP.prototype._parseElement = function(iB) {
var iE, iDE, iNE, iRet;
var iType, strN, iLast;
iDE = iE = this.m_xml.indexOf(">", iB);
if(iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_ELM);
}
if(this.m_xml.charAt(iB) == "/") {
iType = XMLP._ELM_E;
iB++;
} else {
iType = XMLP._ELM_B;
}
if(this.m_xml.charAt(iE - 1) == "/") {
if(iType == XMLP._ELM_E) {
return this._setErr(XMLP.ERR_ELM_EMPTY);
}
iType = XMLP._ELM_EMP;
iDE--;
}
iDE = SAXStrings.lastIndexOfNonWhitespace(this.m_xml, iB, iDE);
//djohack
//hack to allow for elements with single character names to be recognized
/*if (iE - iB != 1 ) {
if(SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iDE) != iB) {
return this._setErr(XMLP.ERR_ELM_NAME);
}
}*/
// end hack -- original code below
/*
if(SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iDE) != iB)
return this._setErr(XMLP.ERR_ELM_NAME);
*/
this._clearAttributes();
iNE = SAXStrings.indexOfWhitespace(this.m_xml, iB, iDE);
if(iNE == -1) {
iNE = iDE + 1;
}
else {
this.m_iP = iNE;
while(this.m_iP < iDE) {
// DEBUG: Remove
//if(this.m_iP == iLast) return this._setErr(XMLP.ERR_INFINITELOOP);
//iLast = this.m_iP;
// DEBUG: Remove End
iRet = this._parseAttribute(this.m_iP, iDE);
if(iRet == XMLP._ERROR) return iRet;
}
}
strN = this.m_xml.substring(iB, iNE);
/*if(strN.indexOf("<") != -1) {
return this._setErr(XMLP.ERR_ELM_LT_NAME);
}*/
this.m_name = strN;
this.m_iP = iE + 1;
return iType;
}
XMLP.prototype._parseEntity = function(iB) {
var iE = this.m_xml.indexOf(";", iB);
if(iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_ENTITY);
}
this.m_iP = iE + 1;
return this._replaceEntity(this.m_xml, iB, iE);
}
XMLP.prototype._parsePI = function(iB) {
var iE, iTB, iTE, iCB, iCE;
iE = this.m_xml.indexOf("?>", iB);
if(iE == -1) {
return this._setErr(XMLP.ERR_CLOSE_PI);
}
iTB = SAXStrings.indexOfNonWhitespace(this.m_xml, iB, iE);
if(iTB == -1) {
return this._setErr(XMLP.ERR_PI_TARGET);
}
iTE = SAXStrings.indexOfWhitespace(this.m_xml, iTB, iE);
if(iTE == -1) {
iTE = iE;
}
iCB = SAXStrings.indexOfNonWhitespace(this.m_xml, iTE, iE);
if(iCB == -1) {
iCB = iE;
}
iCE = SAXStrings.lastIndexOfNonWhitespace(this.m_xml, iCB, iE);
if(iCE == -1) {
iCE = iE - 1;
}
this.m_name = this.m_xml.substring(iTB, iTE);
this._setContent(XMLP._CONT_XML, iCB, iCE + 1);
this.m_iP = iE + 2;
return XMLP._PI;
}
XMLP.prototype._parseText = function(iB) {
var iE, iEE;
iE = this.m_xml.indexOf("<", iB);
if(iE == -1) {
iE = this.m_xml.length;
}
if(this.replaceEntities) {
iEE = this.m_xml.indexOf("&", iB);
if((iEE != -1) && (iEE <= iE)) {
iE = iEE;
}
}
this._setContent(XMLP._CONT_XML, iB, iE);
this.m_iP = iE;
return XMLP._TEXT;
}
XMLP.prototype._replaceEntities = function(strD, iB, iE) {
if(SAXStrings.isEmpty(strD)) return "";
iB = iB || 0;
iE = iE || strD.length;
var iEB, iEE, strRet = "";
iEB = strD.indexOf("&", iB);
iEE = iB;
while((iEB > 0) && (iEB < iE)) {
strRet += strD.substring(iEE, iEB);
iEE = strD.indexOf(";", iEB) + 1;
if((iEE == 0) || (iEE > iE)) {
return this._setErr(XMLP.ERR_CLOSE_ENTITY);
}
iRet = this._replaceEntity(strD, iEB + 1, iEE - 1);
if(iRet == XMLP._ERROR) {
return iRet;
}
strRet += this.m_cAlt;
iEB = strD.indexOf("&", iEE);
}
if(iEE != iE) {
strRet += strD.substring(iEE, iE);
}
this._setContent(XMLP._CONT_ALT, strRet);
return XMLP._ENTITY;
}
XMLP.prototype._replaceEntity = function(strD, iB, iE) {
if(SAXStrings.isEmpty(strD)) return -1;
iB = iB || 0;
iE = iE || strD.length;
ent = strD.substring(iB, iE);
strEnt = $w.$entityDefinitions[ent];
if (!strEnt) // special case for entity name==JS reserved keyword
strEnt = $w.$entityDefinitions[ent+"XX"];
if (!strEnt) {
if(strD.charAt(iB) == "#")
strEnt = String.fromCharCode(
parseInt(strD.substring(iB + 1, iE)))+'';
else
return this._setErr(XMLP.ERR_ENTITY_UNKNOWN);
}
this._setContent(XMLP._CONT_ALT, strEnt);
return XMLP._ENTITY;
}
XMLP.prototype._setContent = function(iSrc) {
var args = arguments;
if(XMLP._CONT_XML == iSrc) {
this.m_cAlt = null;
this.m_cB = args[1];
this.m_cE = args[2];
} else {
this.m_cAlt = args[1];
this.m_cB = 0;
this.m_cE = args[1].length;
}
this.m_cSrc = iSrc;
}
XMLP.prototype._setErr = function(iErr) {
var strErr = XMLP._errs[iErr];
this.m_cAlt = strErr;
this.m_cB = 0;
this.m_cE = strErr.length;
this.m_cSrc = XMLP._CONT_ALT;
return XMLP._ERROR;
}
/**
* function: SAXDriver
* Author: Scott Severtson
* Description:
* SAXDriver is an object that basically wraps an XMLP instance, and provides an
* event-based interface for parsing. This is the object users interact with when coding
* with XML for <SCRIPT>
**/
var SAXDriver = function() {
this.m_hndDoc = null;
this.m_hndErr = null;
this.m_hndLex = null;
}
// CONSTANTS
SAXDriver.DOC_B = 1;
SAXDriver.DOC_E = 2;
SAXDriver.ELM_B = 3;
SAXDriver.ELM_E = 4;
SAXDriver.CHARS = 5;
SAXDriver.PI = 6;
SAXDriver.CD_B = 7;
SAXDriver.CD_E = 8;
SAXDriver.CMNT = 9;
SAXDriver.DTD_B = 10;
SAXDriver.DTD_E = 11;
SAXDriver.prototype.parse = function(strD) {
var parser = new XMLP(strD);
if(this.m_hndDoc && this.m_hndDoc.setDocumentLocator) {
this.m_hndDoc.setDocumentLocator(this);
}
this.m_parser = parser;
this.m_bErr = false;
if(!this.m_bErr) {
this._fireEvent(SAXDriver.DOC_B);
}
this._parseLoop();
if(!this.m_bErr) {
this._fireEvent(SAXDriver.DOC_E);
}
this.m_xml = null;
this.m_iP = 0;
}
SAXDriver.prototype.setDocumentHandler = function(hnd) {
this.m_hndDoc = hnd;
}
SAXDriver.prototype.setErrorHandler = function(hnd) {
this.m_hndErr = hnd;
}
SAXDriver.prototype.setLexicalHandler = function(hnd) {
this.m_hndLex = hnd;
}
/**
* LOCATOR/PARSE EXCEPTION INTERFACE
***/
SAXDriver.prototype.getColumnNumber = function() {
return this.m_parser.getColumnNumber();
}
SAXDriver.prototype.getLineNumber = function() {
return this.m_parser.getLineNumber();
}
SAXDriver.prototype.getMessage = function() {
return this.m_strErrMsg;
}
SAXDriver.prototype.getPublicId = function() {
return null;
}
SAXDriver.prototype.getSystemId = function() {
return null;
}
/***
* Attribute List Interface
**/
SAXDriver.prototype.getLength = function() {
return this.m_parser.getAttributeCount();
}
SAXDriver.prototype.getName = function(index) {
return this.m_parser.getAttributeName(index);
}
SAXDriver.prototype.getValue = function(index) {
return this.m_parser.getAttributeValue(index);
}
SAXDriver.prototype.getValueByName = function(name) {
return this.m_parser.getAttributeValueByName(name);
}
/***
* Private functions
**/
SAXDriver.prototype._fireError = function(strMsg) {
this.m_strErrMsg = strMsg;
this.m_bErr = true;
if(this.m_hndErr && this.m_hndErr.fatalError) {
this.m_hndErr.fatalError(this);
}
} // end function _fireError
SAXDriver.prototype._fireEvent = function(iEvt) {
var hnd, func, args = arguments, iLen = args.length - 1;
if(this.m_bErr) return;
if(SAXDriver.DOC_B == iEvt) {
func = "startDocument"; hnd = this.m_hndDoc;
}
else if (SAXDriver.DOC_E == iEvt) {
func = "endDocument"; hnd = this.m_hndDoc;
}
else if (SAXDriver.ELM_B == iEvt) {
func = "startElement"; hnd = this.m_hndDoc;
}
else if (SAXDriver.ELM_E == iEvt) {
func = "endElement"; hnd = this.m_hndDoc;
}
else if (SAXDriver.CHARS == iEvt) {
func = "characters"; hnd = this.m_hndDoc;
}
else if (SAXDriver.PI == iEvt) {
func = "processingInstruction"; hnd = this.m_hndDoc;
}
else if (SAXDriver.CD_B == iEvt) {
func = "startCDATA"; hnd = this.m_hndLex;
}
else if (SAXDriver.CD_E == iEvt) {
func = "endCDATA"; hnd = this.m_hndLex;
}
else if (SAXDriver.CMNT == iEvt) {
func = "comment"; hnd = this.m_hndLex;
}
if(hnd && hnd[func]) {
if(0 == iLen) {
hnd[func]();
}
else if (1 == iLen) {
hnd[func](args[1]);
}
else if (2 == iLen) {
hnd[func](args[1], args[2]);
}
else if (3 == iLen) {
hnd[func](args[1], args[2], args[3]);
}
}
} // end function _fireEvent
SAXDriver.prototype._parseLoop = function(parser) {
var iEvent, parser;
parser = this.m_parser;
while(!this.m_bErr) {
iEvent = parser.next();
if(iEvent == XMLP._ELM_B) {
this._fireEvent(SAXDriver.ELM_B, parser.getName(), this);
}
else if(iEvent == XMLP._ELM_E) {
this._fireEvent(SAXDriver.ELM_E, parser.getName());
}
else if(iEvent == XMLP._ELM_EMP) {
this._fireEvent(SAXDriver.ELM_B, parser.getName(), this);
this._fireEvent(SAXDriver.ELM_E, parser.getName());
}
else if(iEvent == XMLP._TEXT) {
this._fireEvent(SAXDriver.CHARS, parser.getContent(), parser.getContentBegin(), parser.getContentEnd() - parser.getContentBegin());
}
else if(iEvent == XMLP._ENTITY) {
this._fireEvent(SAXDriver.CHARS, parser.getContent(), parser.getContentBegin(), parser.getContentEnd() - parser.getContentBegin());
}
else if(iEvent == XMLP._PI) {
this._fireEvent(SAXDriver.PI, parser.getName(), parser.getContent().substring(parser.getContentBegin(), parser.getContentEnd()));
}
else if(iEvent == XMLP._CDATA) {
this._fireEvent(SAXDriver.CD_B);
this._fireEvent(SAXDriver.CHARS, parser.getContent(), parser.getContentBegin(), parser.getContentEnd() - parser.getContentBegin());
this._fireEvent(SAXDriver.CD_E);
}
else if(iEvent == XMLP._COMMENT) {
this._fireEvent(SAXDriver.CMNT, parser.getContent(), parser.getContentBegin(), parser.getContentEnd() - parser.getContentBegin());
}
else if(iEvent == XMLP._DTD) {
}
else if(iEvent == XMLP._ERROR) {
this._fireError(parser.getContent());
}
else if(iEvent == XMLP._NONE) {
return;
}
}
} // end function _parseLoop
/**
* function: SAXStrings
* Author: Scott Severtson
* Description: a useful object containing string manipulation functions
**/
var _SAXStrings = function() {};
_SAXStrings.WHITESPACE = " \t\n\r";
_SAXStrings.NONWHITESPACE = /\S/;
_SAXStrings.QUOTES = "\"'";
_SAXStrings.prototype.getColumnNumber = function(strD, iP) {
if((strD === null) || (strD.length === 0)) {
return -1;
}
iP = iP || strD.length;
var arrD = strD.substring(0, iP).split("\n");
var strLine = arrD[arrD.length - 1];
arrD.length--;
var iLinePos = arrD.join("\n").length;
return iP - iLinePos;
} // end function getColumnNumber
_SAXStrings.prototype.getLineNumber = function(strD, iP) {
if((strD === null) || (strD.length === 0)) {
return -1;
}
iP = iP || strD.length;
return strD.substring(0, iP).split("\n").length
} // end function getLineNumber
_SAXStrings.prototype.indexOfNonWhitespace = function(strD, iB, iE) {
if((strD === null) || (strD.length === 0)) {
return -1;
}
iB = iB || 0;
iE = iE || strD.length;
//var i = strD.substring(iB, iE).search(_SAXStrings.NONWHITESPACE);
//return i < 0 ? i : iB + i;
while( strD.charCodeAt(iB++) < 33 );
return (iB > iE)?-1:iB-1;
/*for(var i = iB; i < iE; i++){
if(_SAXStrings.WHITESPACE.indexOf(strD.charAt(i)) == -1) {
return i;
}
}
return -1;*/
} // end function indexOfNonWhitespace
_SAXStrings.prototype.indexOfWhitespace = function(strD, iB, iE) {
if((strD === null) || (strD.length === 0)) {
return -1;
}
iB = iB || 0;
iE = iE || strD.length;
while( strD.charCodeAt(iB++) >= 33 );
return (iB > iE)?-1:iB-1;
/*for(var i = iB; i < iE; i++) {
if(_SAXStrings.WHITESPACE.indexOf(strD.charAt(i)) != -1) {
return i;
}
}
return -1;*/
} // end function indexOfWhitespace
_SAXStrings.prototype.isEmpty = function(strD) {
return (strD == null) || (strD.length == 0);
}
_SAXStrings.prototype.lastIndexOfNonWhitespace = function(strD, iB, iE) {
if((strD === null) || (strD.length === 0)) {
return -1;
}
iB = iB || 0;
iE = iE || strD.length;
while( (iE >= iB) && strD.charCodeAt(--iE) < 33 );
return (iE < iB)?-1:iE;
/*for(var i = iE - 1; i >= iB; i--){
if(_SAXStrings.WHITESPACE.indexOf(strD.charAt(i)) == -1){
return i;
}
}
return -1;*/
}
_SAXStrings.prototype.replace = function(strD, iB, iE, strF, strR) {
if((strD == null) || (strD.length == 0)) {
return "";
}
iB = iB || 0;
iE = iE || strD.length;
return strD.substring(iB, iE).split(strF).join(strR);
};
var SAXStrings = new _SAXStrings();
/***************************************************************************************************************
Stack: A simple stack class, used for verifying document structure.
Author: Scott Severtson
*****************************************************************************************************************/
var Stack = function() {
this.m_arr = new Array();
};
__extend__(Stack.prototype, {
clear : function() {
this.m_arr = new Array();
},
count : function() {
return this.m_arr.length;
},
destroy : function() {
this.m_arr = null;
},
peek : function() {
if(this.m_arr.length == 0) {
return null;
}
return this.m_arr[this.m_arr.length - 1];
},
pop : function() {
if(this.m_arr.length == 0) {
return null;
}
var o = this.m_arr[this.m_arr.length - 1];
this.m_arr.length--;
return o;
},
push : function(o) {
this.m_arr[this.m_arr.length] = o;
}
});
/**
* function: isEmpty
* Author: mike@idle.org
* Description: convenience function to identify an empty string
**/
function isEmpty(str) {
return (str==null) || (str.length==0);
};
/**
* function __escapeXML__
* author: David Joham djoham@yahoo.com
* @param str : string - The string to be escaped
* @return : string - The escaped string
*/
var escAmpRegEx = /&/g;
var escLtRegEx = /</g;
var escGtRegEx = />/g;
var quotRegEx = /"/g;
var aposRegEx = /'/g;
function __escapeXML__(str) {
str = str.replace(escAmpRegEx, "&amp;").
replace(escLtRegEx, "&lt;").
replace(escGtRegEx, "&gt;").
replace(quotRegEx, "&quot;").
replace(aposRegEx, "&apos;");
return str;
};
/**
* function __unescapeXML__
* author: David Joham djoham@yahoo.com
* @param str : string - The string to be unescaped
* @return : string - The unescaped string
*/
var unescAmpRegEx = /&amp;/g;
var unescLtRegEx = /&lt;/g;
var unescGtRegEx = /&gt;/g;
var unquotRegEx = /&quot;/g;
var unaposRegEx = /&apos;/g;
function __unescapeXML__(str) {
str = str.replace(unescAmpRegEx, "&").
replace(unescLtRegEx, "<").
replace(unescGtRegEx, ">").
replace(unquotRegEx, "\"").
replace(unaposRegEx, "'");
return str;
};
/**
* @author Glen Ivey (gleneivey@wontology.org)
*/
$debug("Instantiating list of HTML4 standard entities");
/*
* $w.$entityDefinitions
*/
var $entityDefinitions = {
// 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: "'"
};
$w.$entityDefinitions = $entityDefinitions;
//DOMImplementation
$debug("Defining DOMImplementation");
/**
* @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)
*/
var 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"));
}
return ret;
},
createDocumentType : function(qname, publicid, systemid){
return new DOMDocumentType();
},
createDocument : function(nsuri, qname, doctype){
//TODO - this currently returns an empty doc
//but needs to handle the args
return new HTMLDocument($implementation);
},
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;
}
});
/**
* Defined 'globally' to this scope. Remember everything is wrapped in a closure so this doesnt show up
* in the outer most global scope.
*/
/**
* process SAX events
*
* @author Jon van Noort (jon@webarcana.com.au), David Joham (djoham@yahoo.com) and Scott Severtson
*
* @param impl : DOMImplementation
* @param doc : DOMDocument - the Document to contain the parsed XML string
* @param p : XMLP - the SAX Parser
*
* @return : DOMDocument
*/
function __parseLoop__(impl, doc, p) {
var iEvt, iNode, iAttr, strName;
var iNodeParent = doc;
var el_close_count = 0;
var entitiesList = new Array();
var textNodesList = new Array();
// if namespaceAware, add default namespace
if (impl.namespaceAware) {
var iNS = doc.createNamespace(""); // add the default-default namespace
iNS.value = "http://www.w3.org/2000/xmlns/";
doc._namespaces.setNamedItem(iNS);
}
// loop until SAX parser stops emitting events
while(true) {
// get next event
iEvt = p.next();
if (iEvt == XMLP._ELM_B) { // Begin-Element Event
var pName = p.getName(); // get the Element name
pName = trim(pName, true, true); // strip spaces from Element name
if(pName.toLowerCase() == 'script')
p.replaceEntities = false;
if (!impl.namespaceAware) {
iNode = doc.createElement(p.getName()); // create the Element
// add attributes to Element
for(var i = 0; i < p.getAttributeCount(); i++) {
strName = p.getAttributeName(i); // get Attribute name
iAttr = iNode.getAttributeNode(strName); // if Attribute exists, use it
if(!iAttr) {
iAttr = doc.createAttribute(strName); // otherwise create it
}
iAttr.value = p.getAttributeValue(i); // set Attribute value
iNode.setAttributeNode(iAttr); // attach Attribute to Element
}
}
else { // Namespace Aware
// create element (with empty namespaceURI,
// resolve after namespace 'attributes' have been parsed)
iNode = doc.createElementNS("", p.getName());
// duplicate ParentNode's Namespace definitions
iNode._namespaces = __cloneNamedNodes__(iNodeParent._namespaces, iNode);
// add attributes to Element
for(var i = 0; i < p.getAttributeCount(); i++) {
strName = p.getAttributeName(i); // get Attribute name
// if attribute is a namespace declaration
if (__isNamespaceDeclaration__(strName)) {
// parse Namespace Declaration
var namespaceDec = __parseNSName__(strName);
if (strName != "xmlns") {
iNS = doc.createNamespace(strName); // define namespace
}
else {
iNS = doc.createNamespace(""); // redefine default namespace
}
iNS.value = p.getAttributeValue(i); // set value = namespaceURI
iNode._namespaces.setNamedItem(iNS); // attach namespace to namespace collection
}
else { // otherwise, it is a normal attribute
iAttr = iNode.getAttributeNode(strName); // if Attribute exists, use it
if(!iAttr) {
iAttr = doc.createAttributeNS("", strName); // otherwise create it
}
iAttr.value = p.getAttributeValue(i); // set Attribute value
iNode.setAttributeNodeNS(iAttr); // attach Attribute to Element
if (__isIdDeclaration__(strName)) {
iNode.id = p.getAttributeValue(i); // cache ID for getElementById()
}
}
}
// resolve namespaceURIs for this Element
if (iNode._namespaces.getNamedItem(iNode.prefix)) {
iNode.namespaceURI = iNode._namespaces.getNamedItem(iNode.prefix).value;
}
// for this Element's attributes
for (var i = 0; i < iNode.attributes.length; i++) {
if (iNode.attributes.item(i).prefix != "") { // attributes do not have a default namespace
if (iNode._namespaces.getNamedItem(iNode.attributes.item(i).prefix)) {
iNode.attributes.item(i).namespaceURI = iNode._namespaces.getNamedItem(iNode.attributes.item(i).prefix).value;
}
}
}
}
// if this is the Root Element
if (iNodeParent.nodeType == DOMNode.DOCUMENT_NODE) {
iNodeParent.documentElement = iNode; // register this Element as the Document.documentElement
}
iNodeParent.appendChild(iNode); // attach Element to parentNode
iNodeParent = iNode; // descend one level of the DOM Tree
}
else if(iEvt == XMLP._ELM_E) { // End-Element Event
//handle script tag
if(iNodeParent.nodeName.toLowerCase() == 'script'){
p.replaceEntities = true;
$env.loadLocalScript(iNodeParent, p);
}
iNodeParent = iNodeParent.parentNode; // ascend one level of the DOM Tree
}
else if(iEvt == XMLP._ELM_EMP) { // Empty Element Event
pName = p.getName(); // get the Element name
pName = trim(pName, true, true); // strip spaces from Element name
if (!impl.namespaceAware) {
iNode = doc.createElement(pName); // create the Element
// add attributes to Element
for(var i = 0; i < p.getAttributeCount(); i++) {
strName = p.getAttributeName(i); // get Attribute name
iAttr = iNode.getAttributeNode(strName); // if Attribute exists, use it
if(!iAttr) {
iAttr = doc.createAttribute(strName); // otherwise create it
}
iAttr.value = p.getAttributeValue(i); // set Attribute value
iNode.setAttributeNode(iAttr); // attach Attribute to Element
}
}
else { // Namespace Aware
// create element (with empty namespaceURI,
// resolve after namespace 'attributes' have been parsed)
iNode = doc.createElementNS("", p.getName());
// duplicate ParentNode's Namespace definitions
iNode._namespaces = __cloneNamedNodes__(iNodeParent._namespaces, iNode);
// add attributes to Element
for(var i = 0; i < p.getAttributeCount(); i++) {
strName = p.getAttributeName(i); // get Attribute name
// if attribute is a namespace declaration
if (__isNamespaceDeclaration__(strName)) {
// parse Namespace Declaration
var namespaceDec = __parseNSName__(strName);
if (strName != "xmlns") {
iNS = doc.createNamespace(strName); // define namespace
}
else {
iNS = doc.createNamespace(""); // redefine default namespace
}
iNS.value = p.getAttributeValue(i); // set value = namespaceURI
iNode._namespaces.setNamedItem(iNS); // attach namespace to namespace collection
}
else { // otherwise, it is a normal attribute
iAttr = iNode.getAttributeNode(strName); // if Attribute exists, use it
if(!iAttr) {
iAttr = doc.createAttributeNS("", strName); // otherwise create it
}
iAttr.value = p.getAttributeValue(i); // set Attribute value
iNode.setAttributeNodeNS(iAttr); // attach Attribute to Element
if (__isIdDeclaration__(strName)) {
iNode.id = p.getAttributeValue(i); // cache ID for getElementById()
}
}
}
// resolve namespaceURIs for this Element
if (iNode._namespaces.getNamedItem(iNode.prefix)) {
iNode.namespaceURI = iNode._namespaces.getNamedItem(iNode.prefix).value;
}
// for this Element's attributes
for (var i = 0; i < iNode.attributes.length; i++) {
if (iNode.attributes.item(i).prefix != "") { // attributes do not have a default namespace
if (iNode._namespaces.getNamedItem(iNode.attributes.item(i).prefix)) {
iNode.attributes.item(i).namespaceURI = iNode._namespaces.getNamedItem(iNode.attributes.item(i).prefix).value;
}
}
}
}
// if this is the Root Element
if (iNodeParent.nodeType == DOMNode.DOCUMENT_NODE) {
iNodeParent.documentElement = iNode; // register this Element as the Document.documentElement
}
iNodeParent.appendChild(iNode); // attach Element to parentNode
}
else if(iEvt == XMLP._TEXT || iEvt == XMLP._ENTITY) { // TextNode and entity Events
// get Text content
var pContent = p.getContent().substring(p.getContentBegin(), p.getContentEnd());
if (!impl.preserveWhiteSpace ) {
if (trim(pContent, true, true) == "") {
pContent = ""; //this will cause us not to create the text node below
}
}
if (pContent.length > 0) { // ignore empty TextNodes
var textNode = doc.createTextNode(pContent);
iNodeParent.appendChild(textNode); // attach TextNode to parentNode
//the sax parser breaks up text nodes when it finds an entity. For
//example hello&lt;there will fire a text, an entity and another text
//this sucks for the dom parser because it looks to us in this logic
//as three text nodes. I fix this by keeping track of the entity nodes
//and when we're done parsing, calling normalize on their parent to
//turn the multiple text nodes into one, which is what DOM users expect
//the code to do this is at the bottom of this function
if (iEvt == XMLP._ENTITY) {
entitiesList[entitiesList.length] = textNode;
}
else {
//I can't properly decide how to handle preserve whitespace
//until the siblings of the text node are built due to
//the entitiy handling described above. I don't know that this
//will be all of the text node or not, so trimming is not appropriate
//at this time. Keep a list of all the text nodes for now
//and we'll process the preserve whitespace stuff at a later time.
textNodesList[textNodesList.length] = textNode;
}
}
}
else if(iEvt == XMLP._PI) { // ProcessingInstruction Event
// attach ProcessingInstruction to parentNode
iNodeParent.appendChild(doc.createProcessingInstruction(p.getName(), p.getContent().substring(p.getContentBegin(), p.getContentEnd())));
}
else if(iEvt == XMLP._CDATA) { // CDATA Event
// get CDATA data
pContent = p.getContent().substring(p.getContentBegin(), p.getContentEnd());
if (!impl.preserveWhiteSpace) {
pContent = trim(pContent, true, true); // trim whitespace
pContent.replace(/ +/g, ' '); // collapse multiple spaces to 1 space
}
if (pContent.length > 0) { // ignore empty CDATANodes
iNodeParent.appendChild(doc.createCDATASection(pContent)); // attach CDATA to parentNode
}
}
else if(iEvt == XMLP._COMMENT) { // Comment Event
// get COMMENT data
var pContent = p.getContent().substring(p.getContentBegin(), p.getContentEnd());
if (!impl.preserveWhiteSpace) {
pContent = trim(pContent, true, true); // trim whitespace
pContent.replace(/ +/g, ' '); // collapse multiple spaces to 1 space
}
if (pContent.length > 0) { // ignore empty CommentNodes
iNodeParent.appendChild(doc.createComment(pContent)); // attach Comment to parentNode
}
}
else if(iEvt == XMLP._DTD) { // ignore DTD events
}
else if(iEvt == XMLP._ERROR) {
$error("Fatal Error: " + p.getContent() +
"\nLine: " + p.getLineNumber() +
"\nColumn: " + p.getColumnNumber() + "\n");
throw(new DOMException(DOMException.SYNTAX_ERR));
}
else if(iEvt == XMLP._NONE) { // no more events
//steven woods notes that unclosed tags are rejected elsewhere and this check
//breaks a table patching routine
/*if (iNodeParent == doc) { // confirm that we have recursed back up to root
break;
}
else {
throw(new DOMException(DOMException.SYNTAX_ERR)); // one or more Tags were not closed properly
}*/
break;
}
}
//normalize any entities in the DOM to a single textNode
for (var i = 0; i < entitiesList.length; i++) {
var entity = entitiesList[i];
//its possible (if for example two entities were in the
//same domnode, that the normalize on the first entitiy
//will remove the parent for the second. Only do normalize
//if I can find a parent node
var parentNode = entity.parentNode;
if (parentNode) {
parentNode.normalize();
//now do whitespace (if necessary)
//it was not done for text nodes that have entities
if(!impl.preserveWhiteSpace) {
var children = parentNode.childNodes;
for ( var j = 0; j < children.length; j++) {
var child = children.item(j);
if (child.nodeType == DOMNode.TEXT_NODE) {
var childData = child.data;
childData.replace(/\s/g, ' ');
child.data = childData;
}
}
}
}
}
//do the preserve whitespace processing on the rest of the text nodes
//It's possible (due to the processing above) that the node will have been
//removed from the tree. Only do whitespace checking if parentNode is not null.
//This may duplicate the whitespace processing for some nodes that had entities in them
//but there's no way around that
if (!impl.preserveWhiteSpace) {
for (var i = 0; i < textNodesList.length; i++) {
var node = textNodesList[i];
if (node.parentNode != null) {
var nodeData = node.data;
nodeData.replace(/\s/g, ' ');
node.data = nodeData;
}
}
}
};
/**
* @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.toLowerCase() == 'id');
};
/**
* @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 = new Object();
resultNSName.prefix = qualifiedName; // unless the qname has a namespaceName, the prefix is the entire String
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 = new Object();
resultQName.localName = qualifiedName; // unless the qname has a prefix, the local name is the entire String
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;
};
$debug("Initializing document.implementation");
var $implementation = new DOMImplementation();
$implementation.namespaceAware = false;
$implementation.errorChecking = false;$debug("Defining Document");
/**
* @class DOMDocument - 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 DOMNode
* @author Jon van Noort (jon@webarcana.com.au)
* @param implementation : DOMImplementation - the creator Implementation
*/
var DOMDocument = function(implementation) {
//$log("\tcreating dom document");
this.DOMNode = DOMNode;
this.DOMNode(this);
this.doctype = null; // The Document Type Declaration (see DocumentType) associated with this document
this.implementation = implementation; // The DOMImplementation object that handles this document.
this.documentElement = null; // This is a convenience attribute that allows direct access to the child node that is the root element of the document
this.nodeName = "#document";
this._id = 0;
this._lastId = 0;
this._parseComplete = false; // initially false, set to true by parser
this._url = "";
this.ownerDocument = null;
this._performingImportNodeOperation = false;
//$log("\tfinished creating dom document " + this);
};
DOMDocument.prototype = new DOMNode;
__extend__(DOMDocument.prototype, {
addEventListener : function(){ window.addEventListener.apply(this, arguments); },
removeEventListener : function(){ window.removeEventListener.apply(this, arguments); },
attachEvent : function(){ window.addEventListener.apply(this, arguments); },
detachEvent : function(){ window.removeEventListener.apply(this, arguments); },
dispatchEvent : function(){ window.dispatchEvent.apply(this, arguments); },
get styleSheets(){
return [];/*TODO*/
},
get all(){
return this.getElementsByTagName("*");
},
loadXML : function(xmlStr) {
// create SAX Parser
var parser = new XMLP(xmlStr+'');
// create DOM Document
if(this === $document){
$debug("Setting internal window.document");
$document = this;
}
// populate Document with Parsed Nodes
try {
__parseLoop__(this.implementation, this, parser);
//doc = html2dom(xmlStr+"", doc);
//$log("\nhtml2xml\n" + doc.xml);
} catch (e) {
//$error(this.implementation.translateErrCode(e.code))
$error(e);
}
// set parseComplete flag, (Some validation Rules are relaxed if this is false)
this._parseComplete = true;
return this;
},
load: function(url){
$debug("Loading url into DOM Document: "+ url + " - (Asynch? "+$w.document.async+")");
var scripts, _this = this;
var xhr = new XMLHttpRequest();
xhr.open("GET", url, $w.document.async);
xhr.onreadystatechange = function(){
try{
_this.loadXML(xhr.responseText);
}catch(e){
$error("Error Parsing XML - ",e);
_this.loadXML(
"<html><head></head><body>"+
"<h1>Parse Error</h1>"+
"<p>"+e.toString()+"</p>"+
"</body></html>");
}
_this._url = url;
$info("Sucessfully loaded document at "+url);
var event = document.createEvent();
event.initEvent("load");
$w.dispatchEvent( event );
};
xhr.send();
},
createEvent : function(eventType){
var event;
if(eventType === "UIEvents"){ event = new UIEvent();}
else if(eventType === "MouseEvents"){ event = new MouseEvent();}
else{ event = new Event(); }
return event;
},
createExpression : function(xpath, nsuriMap){
return new XPathExpression(xpath, nsuriMap);
},
createElement : function(tagName) {
//$debug("DOMDocument.createElement( "+tagName+" )");
// throw Exception if the tagName string contains an illegal character
if (__ownerDocument__(this).implementation.errorChecking
&& (!__isValidName__(tagName))) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
// create DOMElement specifying 'this' as ownerDocument
var node = new DOMElement(this);
// assign values to properties (and aliases)
node.tagName = tagName;
return node;
},
createDocumentFragment : function() {
// create DOMDocumentFragment specifying 'this' as ownerDocument
var node = new DOMDocumentFragment(this);
return node;
},
createTextNode: function(data) {
// create DOMText specifying 'this' as ownerDocument
var node = new DOMText(this);
// assign values to properties (and aliases)
node.data = data;
return node;
},
createComment : function(data) {
// create DOMComment specifying 'this' as ownerDocument
var node = new DOMComment(this);
// assign values to properties (and aliases)
node.data = data;
return node;
},
createCDATASection : function(data) {
// create DOMCDATASection specifying 'this' as ownerDocument
var node = new DOMCDATASection(this);
// assign values to properties (and aliases)
node.data = data;
return node;
},
createProcessingInstruction : function(target, data) {
// throw Exception if the target string contains an illegal character
//$log("DOMDocument.createProcessingInstruction( "+target+" )");
if (__ownerDocument__(this).implementation.errorChecking
&& (!__isValidName__(target))) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
// create DOMProcessingInstruction specifying 'this' as ownerDocument
var node = new DOMProcessingInstruction(this);
// assign values to properties (and aliases)
node.target = target;
node.data = data;
return node;
},
createAttribute : function(name) {
// throw Exception if the name string contains an illegal character
//$log("DOMDocument.createAttribute( "+target+" )");
if (__ownerDocument__(this).implementation.errorChecking
&& (!__isValidName__(name))) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
// create DOMAttr specifying 'this' as ownerDocument
var node = new DOMAttr(this);
// assign values to properties (and aliases)
node.name = name;
return node;
},
createElementNS : function(namespaceURI, qualifiedName) {
//$log("DOMDocument.createElement( "+namespaceURI+", "+qualifiedName+" )");
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if the Namespace is invalid
if (!__isValidNamespace__(this, namespaceURI, qualifiedName)) {
throw(new DOMException(DOMException.NAMESPACE_ERR));
}
// throw Exception if the qualifiedName string contains an illegal character
if (!__isValidName__(qualifiedName)) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
}
// create DOMElement specifying 'this' as ownerDocument
var node = new DOMElement(this);
var qname = __parseQName__(qualifiedName);
// assign values to properties (and aliases)
node.namespaceURI = namespaceURI;
node.prefix = qname.prefix;
node.localName = qname.localName;
node.tagName = qualifiedName;
return node;
},
createAttributeNS : function(namespaceURI, qualifiedName) {
// test for exceptions
if (__ownerDocument__(this).implementation.errorChecking) {
// throw Exception if the Namespace is invalid
if (!__isValidNamespace__(this, namespaceURI, qualifiedName, true)) {
throw(new DOMException(DOMException.NAMESPACE_ERR));
}
// throw Exception if the qualifiedName string contains an illegal character
if (!__isValidName__(qualifiedName)) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
}
// create DOMAttr specifying 'this' as ownerDocument
var node = new DOMAttr(this);
var qname = __parseQName__(qualifiedName);
// assign values to properties (and aliases)
node.namespaceURI = namespaceURI;
node.prefix = qname.prefix;
node.localName = qname.localName;
node.name = qualifiedName;
node.nodeValue = "";
return node;
},
createNamespace : function(qualifiedName) {
// create DOMNamespace specifying 'this' as ownerDocument
var node = new DOMNamespace(this);
var qname = __parseQName__(qualifiedName);
// assign values to properties (and aliases)
node.prefix = qname.prefix;
node.localName = qname.localName;
node.name = qualifiedName;
node.nodeValue = "";
return node;
},
/** from David Flanagan's JavaScript - The Definitive Guide
*
* @param {String} xpathText
* The string representing the XPath expression to evaluate.
* @param {Node} contextNode
* The node in this document against which the expression is to
* be evaluated.
* @param {Function} nsuriMapper
* A function that will map from namespace prefix to to a full
* namespace URL or null if no such mapping is required.
* @param {Number} resultType
* Specifies the type of object expected as a result, using
* XPath conversions to coerce the result. Possible values for
* type are the constrainsts defined by the XPathResult object.
* (null if not required)
* @param {XPathResult} result
* An XPathResult object to be reused or null
* if you want a new XPathResult object to be created.
* @returns {XPathResult} result
* A XPathResult object representing the evaluation of the
* expression against the given context node.
* @throws {Exception} e
* This method may throw an exception if the xpathText contains
* a syntax error, if the expression cannot be converted to the
* desired resultType, if the expression contains namespaces
* that nsuriMapper cannot resolve, or if contextNode is of the
* wrong type or is not assosciated with this document.
* @seealso
* Document.evaluate
*/
/*evaluate: function(xpathText, contextNode, nsuriMapper, resultType, result){
return new XPathExpression().evaluate();
},*/
getElementById : function(elementId) {
var retNode = null,
node;
// loop through all Elements in the 'all' collection
var all = this.all;
for (var i=0; i < all.length; i++) {
node = all[i];
// if id matches & node is alive (ie, connected (in)directly to the documentElement)
if (node.id == elementId) {
if((__ownerDocument__(node).documentElement._id == this.documentElement._id)){
retNode = node;
//$log("Found node with id = " + node.id);
break;
}
}
}
//if(retNode == null){$log("Couldn't find id " + elementId);}
return retNode;
},
normalizeDocument: function(){
this.documentElement.normalize();
},
get nodeType(){
return DOMNode.DOCUMENT_NODE;
},
get xml(){
//$log("Serializing " + this);
return this.documentElement.xml;
},
toString: function(){
return "Document" + (typeof this._url == "string" ? ": " + this._url : "");
},
get defaultView(){ //TODO: why isnt this just 'return $w;'?
return { getComputedStyle: function(elem){
return { getPropertyValue: function(prop){
prop = prop.replace(/\-(\w)/g,function(m,c){ return c.toUpperCase(); });
var val = elem.style[prop];
if ( prop == "opacity" && val == "" ){ val = "1"; }return val;
}};
}};
},
_genId : function() {
this._lastId += 1; // increment lastId (to generate unique id)
return this._lastId;
}
});
var __isValidNamespace__ = function(doc, namespaceURI, qualifiedName, isAttribute) {
if (doc._performingImportNodeOperation == true) {
//we're doing an importNode operation (or a cloneNode) - in both cases, there
//is no need to perform any namespace checking since the nodes have to have been valid
//to have gotten into the DOM in the first place
return true;
}
var valid = true;
// parse QName
var qName = __parseQName__(qualifiedName);
//only check for namespaces if we're finished parsing
if (this._parseComplete == true) {
// if the qualifiedName is malformed
if (qName.localName.indexOf(":") > -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;
};
$w.Document = DOMDocument;
/*
* parser.js
*/
/*
* HTML Parser By John Resig (ejohn.org)
* Original code by Erik Arvidsson, Mozilla Public License
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
*
* // Use like so:
* HTMLParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
* // or to get an XML string:
* HTMLtoXML(htmlString);
*
* // or to get an XML DOM Document
* HTMLtoDOM(htmlString);
*
* // or to inject into an existing document/DOM node
* HTMLtoDOM(htmlString, document);
* HTMLtoDOM(htmlString, document.body);
*
*/
var html2dom, html2xml;
(function(){
// Regular Expressions for parsing tags and attributes
var startTag = /^<([\w\:\-]+)((?:\s+[\w\:\-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
endTag = /^<\/([\w\:\-]+)[^>]*>/,
attr = /([\w\:\-]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
// Empty Elements - HTML 4.01
var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed");
// Block Elements - HTML 4.01
var block = makeMap("address,applet,blockquote,button,center,dd,del,dir,div,dl,dt,fieldset,form,frameset,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul");
// Inline Elements - HTML 4.01
var inline = makeMap("a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
// Elements that you can, intentionally, leave open
// (and which close themselves)
var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
// Attributes that have their values filled in disabled="disabled"
var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
// Special Elements (can contain anything)
var special = makeMap("script,style");
var HTMLParser = function( html, handler ) {
var index, chars, match, stack = [], last = html;
stack.last = function(){
return this[ this.length - 1 ];
};
while ( html ) {
//$log("HTMLParser: chunking... ");
chars = true;
// Make sure we're not in a script or style element
if ( !stack.last() || !special[ stack.last() ] ) {
//$log("HTMLParser: ... ");
// Comment
if ( html.indexOf("<!--") === 0 ) {
//$log("HTMLParser: comment ");
index = html.indexOf("-->");
if ( index >= 0 ) {
if ( handler.comment )
handler.comment( html.substring( 4, index ) );
html = html.substring( index + 3 );
chars = false;
}
// end tag
} else if ( html.indexOf("</") === 0 ) {
//$log("HTMLParser: endtag ");
match = html.match( endTag );
if ( match ) {
//$log("HTMLParser: endtag match : "+match[0]);
html = html.substring( match[0].length );
match[0].replace( endTag, parseEndTag );
chars = false;
}
// start tag
} else if ( html.indexOf("<") === 0 ) {
//$log("HTMLParser: starttag ");
match = html.match( startTag );
if ( match ) {
//$log("HTMLParser: starttag match : "+match[0]);
html = html.substring( match[0].length );
match[0].replace( startTag, parseStartTag );
chars = false;
}
}
if ( chars ) {
//$log("HTMLParser: other ");
index = html.indexOf("<");
var text = index < 0 ? html : html.substring( 0, index );
html = index < 0 ? "" : html.substring( index );
if ( handler.chars ){
//$log("HTMLParser: chars " + text);
handler.chars( text );
}
}
} else {
//$log("HTMLParser: special ");
html = html.replace(new RegExp("(.*)<\/" + stack.last() + "[^>]*>"), function(all, text){
text = text.replace(/<!--(.*?)-->/g, "$1").
replace(/<!\[CDATA\[(.*?)]]>/g, "$1");
if ( handler.chars ){
//$log("HTMLParser: special chars " + text);
handler.chars( text );
}
return "";
});
parseEndTag( "", stack.last() );
}
if ( html == last ){throw "Parse Error: " + html;}
last = html;
}
// Clean up any remaining tags
parseEndTag();
function parseStartTag( tag, tagName, rest, unary ) {
if ( block[ tagName ] ) {
while ( stack.last() && inline[ stack.last() ] ) {
parseEndTag( "", stack.last() );
}
}
if ( closeSelf[ tagName ] && stack.last() == tagName ) {
parseEndTag( "", tagName );
}
unary = empty[ tagName ] || !!unary;
if ( !unary )
stack.push( tagName );
if ( handler.start ) {
var attrs = [];
rest.replace(attr, function(match, name) {
var value = arguments[2] ? arguments[2] :
arguments[3] ? arguments[3] :
arguments[4] ? arguments[4] :
fillAttrs[name] ? name : "";
attrs.push({
name: name,
value: value,
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
});
});
if ( handler.start ){
//$log("unary ? : "+unary);
handler.start( tagName, attrs, unary );
}
}
}
function parseEndTag( tag, tagName ) {
var pos;
// If no tag name is provided, clean shop
if ( !tagName ){
pos = 0;
}else{
// Find the closest opened tag of the same type
for ( pos = stack.length - 1; pos >= 0; pos-- ){
//$log("parseEndTag : "+stack[ pos ] );
if ( stack[ pos ] == tagName ){
break;
}
}
}
if ( pos >= 0 ) {
// Close all the open elements, up the stack
for ( var i = stack.length - 1; i >= pos; i-- ){
if ( handler.end ){
//$log("end : "+stack[ i ] );
handler.end( stack[ i ] );
}
}
// Remove the open elements from the stack
//$log("setting stack length : " + stack.length + " -> " +pos );
stack.length = pos;
}
}
};
html2xml = function( html ) {
var results = "";
HTMLParser(html, {
start: function( tag, attrs, unary ) {
results += "<" + tag;
for ( var i = 0; i < attrs.length; i++ )
results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';
results += (unary ? "/" : "") + ">";
},
end: function( tag ) {
results += "</" + tag + ">";
},
chars: function( text ) {
results += text;
},
comment: function( text ) {
results += "<!--" + text + "-->";
}
});
return results;
};
html2dom = function( html, doc ) {
// There can be only one of these elements
var one = makeMap("html,head,body,title");
// Enforce a structure for the document
/*var structure = {
link: "head",
base: "head"
};*/
if ( !doc ) {
if ( typeof DOMDocument != "undefined" ){
doc = new DOMDocument();
}else if ( typeof document != "undefined" && document.implementation && document.implementation.createDocument ){
doc = document.implementation.createDocument("", "", null);
}else if ( typeof ActiveX != "undefined" ){
doc = new ActiveXObject("Msxml.DOMDocument");
}
} else {
doc = doc.ownerDocument ||
doc.getOwnerDocument && doc.getOwnerDocument() ||
doc;
}
var elems = [],
documentElement = doc.documentElement ||
doc.getDocumentElement && doc.getDocumentElement();
// If we're dealing with an empty document then we
// need to pre-populate it with the HTML document structure
/*if ( !documentElement && doc.createElement ) (function(){
//$log("HTMLtoDOM: adding structure... ");
var html = doc.createElement("html");
var head = doc.createElement("head");
head.appendChild( doc.createElement("title") );
html.appendChild( head );
html.appendChild( doc.createElement("body") );
doc.appendChild( html );
doc.documentElement = html;
})();*/
// Find all the unique elements
/*if ( doc.getElementsByTagName ){
for ( var i in one ){
one[ i ] = doc.getElementsByTagName( i )[0];
}
}*/
// If we're working with a document, inject contents into
// the body element
var curParentNode;// = one.body;
//$log("HTMLtoDOM: Parsing... ");
HTMLParser( html, {
start: function( tagName, attrs, unary ) {
var elem;
//$log("HTMLtoDOM: createElement... " + tagName);
elem = doc.createElement( tagName );
for ( var attr in attrs ){
//$log("HTMLtoDOM: setAttribute... " + attrs[ attr ].name);
elem.setAttribute( attrs[ attr ].name, attrs[ attr ].value );
}
if ( !doc.documentElement ){
//$log("HTMLtoDOM: documentElement... " + elem.nodeName);
doc.documentElement = elem;
doc.appendChild( elem );
}
else if ( curParentNode && curParentNode.appendChild ){
//$log("HTMLtoDOM: curParentNode.appendChild... " + curParentNode.nodeName + " -> " +elem.nodeName);
curParentNode.appendChild( elem );
}
if ( !unary ) {
//$log("start : push into elems[] " + tagName);
elems.push( elem );
curParentNode = elem;
}
},
end: function( tag ) {
//$log(tag + " : elems.lengths : "+elems.length);
elems.length -= 1;
// Init the new parentNode
curParentNode = elems[ elems.length - 1 ];
},
chars: function( text ) {
curParentNode.appendChild( doc.createTextNode( text ) );
},
comment: function( text ) {
curParentNode.appendChild( doc.createComment( text ) );
}
});
//$log("HTMLtoDOM: doc... " + doc);
return doc;
};
function makeMap(str){
var obj = {}, items = str.split(",");
for ( var i = 0; i < items.length; i++ )
obj[ items[i] ] = true;
return obj;
};
})( );
$debug("Defining HTMLDocument");
/*
* HTMLDocument - DOM Level 2
*/
/**
* @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 DOMDocument
*/
var HTMLDocument = function(implementation) {
this.DOMDocument = DOMDocument;
this.DOMDocument(implementation);
this._refferer = "";
this._domain;
this._open = false;
};
HTMLDocument.prototype = new DOMDocument;
__extend__(HTMLDocument.prototype, {
createElement: function(tagName){
// throw Exception if the tagName string contains an illegal character
if (__ownerDocument__(this).implementation.errorChecking &&
(!__isValidName__(tagName))) {
throw(new DOMException(DOMException.INVALID_CHARACTER_ERR));
}
tagName = tagName.toUpperCase();
// create DOMElement specifying 'this' as ownerDocument
//This is an html document so we need to use explicit interfaces per the
if( tagName.match(/^A$/)) {node = new HTMLAnchorElement(this);}
else if(tagName.match(/AREA/)) {node = new HTMLAreaElement(this);}
else if(tagName.match(/BASE/)) {node = new HTMLBaseElement(this);}
else if(tagName.match(/BLOCKQUOTE|Q/)) {node = new HTMLQuoteElement(this);}
else if(tagName.match(/BODY/)) {node = new HTMLElement(this);}
else if(tagName.match(/BR/)) {node = new HTMLElement(this);}
else if(tagName.match(/BUTTON/)) {node = new HTMLButtonElement(this);}
else if(tagName.match(/CAPTION/)) {node = new HTMLElement(this);}
else if(tagName.match(/COL|COLGROUP/)) {node = new HTMLTableColElement(this);}
else if(tagName.match(/DEL|INS/)) {node = new HTMLModElement(this);}
else if(tagName.match(/DIV/)) {node = new HTMLElement(this);}
else if(tagName.match(/DL/)) {node = new HTMLElement(this);}
else if(tagName.match(/FIELDSET/)) {node = new HTMLFieldSetElement(this);}
else if(tagName.match(/FORM/)) {node = new HTMLFormElement(this);}
else if(tagName.match(/^FRAME$/)) {node = new HTMLFrameElement(this);}
else if(tagName.match(/FRAMESET/)) {node = new HTMLFrameSetElement(this);}
else if(tagName.match(/H1|H2|H3|H4|H5|H6/)) {node = new HTMLElement(this);}
else if(tagName.match(/HEAD/)) {node = new HTMLHeadElement(this);}
else if(tagName.match(/HR/)) {node = new HTMLElement(this);}
else if(tagName.match(/HTML/)) {node = new HTMLElement(this);}
else if(tagName.match(/IFRAME/)) {node = new HTMLIFrameElement(this);}
else if(tagName.match(/IMG/)) {node = new HTMLImageElement(this);}
else if(tagName.match(/INPUT/)) {node = new HTMLInputElement(this);}
else if(tagName.match(/LABEL/)) {node = new HTMLLabelElement(this);}
else if(tagName.match(/LEGEND/)) {node = new HTMLLegendElement(this);}
else if(tagName.match(/^LI$/)) {node = new HTMLElement(this);}
else if(tagName.match(/LINK/)) {node = new HTMLLinkElement(this);}
else if(tagName.match(/MAP/)) {node = new HTMLMapElement(this);}
else if(tagName.match(/META/)) {node = new HTMLMetaElement(this);}
else if(tagName.match(/OBJECT/)) {node = new HTMLObjectElement(this);}
else if(tagName.match(/OL/)) {node = new HTMLElement(this);}
else if(tagName.match(/OPTGROUP/)) {node = new HTMLOptGroupElement(this);}
else if(tagName.match(/OPTION/)) {node = new HTMLOptionElement(this);;}
else if(tagName.match(/^P$/)) {node = new HTMLElement(this);}
else if(tagName.match(/PARAM/)) {node = new HTMLParamElement(this);}
else if(tagName.match(/PRE/)) {node = new HTMLElement(this);}
else if(tagName.match(/SCRIPT/)) {node = new HTMLScriptElement(this);}
else if(tagName.match(/SELECT/)) {node = new HTMLSelectElement(this);}
else if(tagName.match(/STYLE/)) {node = new HTMLStyleElement(this);}
else if(tagName.match(/TABLE/)) {node = new HTMLTableElement(this);}
else if(tagName.match(/TBODY|TFOOT|THEAD/)) {node = new HTMLSectionElement(this);}
else if(tagName.match(/TD|TH/)) {node = new HTMLTableCellElement(this);}
else if(tagName.match(/TEXTAREA/)) {node = new HTMLElement(this);}
else if(tagName.match(/TITLE/)) {node = new HTMLTitleElement(this);}
else if(tagName.match(/TR/)) {node = new HTMLTableRowElement(this);}
else if(tagName.match(/UL/)) {node = new HTMLElement(this);}
else{
node = new HTMLElement(this);
}
// assign values to properties (and aliases)
node.tagName = tagName;
return node;
},
get anchors(){
return new HTMLCollection(this.getElementsByTagName('a'), 'Anchor');
},
get applets(){
return new HTMLCollection(this.getElementsByTagName('applet'), 'Applet');
},
get body(){
var nodelist = this.getElementsByTagName('body');
return nodelist.item(0);
},
set body(html){
return this.replaceNode(this.body,html);
},
get title(){
var titleArray = this.getElementsByTagName('title');
if (titleArray.length < 1)
return "";
return titleArray[0].text;
},
set title(titleStr){
titleArray = this.getElementsByTagName('title');
if (titleArray.length < 1){
// need to make a new element and add it to "head"
var titleElem = new HTMLTitleElement(this);
titleElem.text = titleStr;
var headArray = this.getElementsByTagName('head');
if (headArray.length < 1)
return; // ill-formed, just give up.....
headArray[0].appendChild(titleElem);
}
else {
titleArray[0].text = titleStr;
}
},
//set/get cookie see cookie.js
get domain(){
return this._domain||window.location.domain;
},
set domain(){
/* TODO - requires a bit of thought to enforce domain restrictions */
return;
},
get forms(){
return new HTMLCollection(this.getElementsByTagName('form'), 'Form');
},
get images(){
return new HTMLCollection(this.getElementsByTagName('img'), 'Image');
},
get lastModified(){
/* TODO */
return this._lastModified;
},
get links(){
return new HTMLCollection(this.getElementsByTagName('a'), 'Link');
},
get location(){
return $w.location
},
get referrer(){
/* TODO */
return this._refferer;
},
get URL(){
/* TODO*/
return this._url;
},
close : function(){
/* TODO */
this._open = false;
},
getElementsByName : function(name){
//returns a real Array + the DOMNodeList
var retNodes = __extend__([],new DOMNodeList(this, this.documentElement)),
node;
// loop through all Elements in the 'all' collection
var all = this.all;
for (var i=0; i < all.length; i++) {
node = all[i];
if (node.nodeType == DOMNode.ELEMENT_NODE && node.getAttribute('name') == name) {
retNodes.push(node);
}
}
return retNodes;
},
open : function(){
/* TODO */
this._open = true;
},
write: function(htmlstring){
/* TODO */
return;
},
writeln: function(htmlstring){
this.write(htmlstring+'\n');
},
toString: function(){
return "Document" + (typeof this._url == "string" ? ": " + this._url : "");
},
get innerHTML(){
return this.documentElement.outerHTML;
},
get __html__(){
return true;
}
});
$w.HTMLDocument = HTMLDocument;
$debug("Defining HTMLElement");
/*
* HTMLElement - DOM Level 2
*/
var HTMLElement = function(ownerDocument) {
this.DOMElement = DOMElement;
this.DOMElement(ownerDocument);
this.$css2props = null;
};
HTMLElement.prototype = new DOMElement;
__extend__(HTMLElement.prototype, {
get className() {
return this.getAttribute("class")||"";
},
set className(val) {
return this.setAttribute("class",trim(val));
},
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(){
return this.childNodes.xml;
},
set innerHTML(html){
//$debug("htmlElement.innerHTML("+html+")");
//Should be replaced with HTMLPARSER usage
var doc = new DOMParser().
parseFromString('<div>'+html+'</div>');
var parent = doc.documentElement;
while(this.firstChild != null){
this.removeChild( this.firstChild );
}
var importedNode;
while(parent.firstChild != null){
importedNode = this.importNode(
parent.removeChild( parent.firstChild ), true);
this.appendChild( importedNode );
}
//Mark for garbage collection
doc = null;
},
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(){
if(this.$css2props === null){
this.updateCss2Props();
}
return this.$css2props
},
updateCss2Props: function() {
this.$css2props = new CSS2Properties({
onSet: (function(that) {
return function() { that.__setAttribute("style", this.cssText); }
})(this),
cssText:this.getAttribute("style")
});
},
__setAttribute: HTMLElement.prototype.setAttribute,
setAttribute: function (name, value) {
this.__setAttribute(name, value);
if (name === "style") {
this.updateCss2Props();
}
},
get title() {
return this.getAttribute("title")||"";
},
set title(val) {
return this.setAttribute("title",val);
},
//Not in the specs but I'll leave it here for now.
get outerHTML(){
return this.xml;
},
scrollIntoView: function(){
/*TODO*/
return;
},
onclick: function(event){
__eval__(this.getAttribute('onclick')||'')
},
ondblclick: function(event){
__eval__(this.getAttribute('ondblclick')||'');
},
onkeydown: function(event){
__eval__(this.getAttribute('onkeydown')||'');
},
onkeypress: function(event){
__eval__(this.getAttribute('onkeypress')||'');
},
onkeyup: function(event){
__eval__(this.getAttribute('onkeyup')||'');
},
onmousedown: function(event){
__eval__(this.getAttribute('onmousedown')||'');
},
onmousemove: function(event){
__eval__(this.getAttribute('onmousemove')||'');
},
onmouseout: function(event){
__eval__(this.getAttribute('onmouseout')||'');
},
onmouseover: function(event){
__eval__(this.getAttribute('onmouseover')||'');
},
onmouseup: function(event){
__eval__(this.getAttribute('onmouseup')||'');
}
});
var __eval__ = function(script){
try{
eval(script);
}catch(e){
$error(e);
}
};
var __registerEventAttrs__ = function(elm){
if(elm.hasAttribute('onclick')){
elm.addEventListener('click', elm.onclick );
}
if(elm.hasAttribute('ondblclick')){
elm.addEventListener('dblclick', elm.onclick );
}
if(elm.hasAttribute('onkeydown')){
elm.addEventListener('keydown', elm.onclick );
}
if(elm.hasAttribute('onkeypress')){
elm.addEventListener('keypress', elm.onclick );
}
if(elm.hasAttribute('onkeyup')){
elm.addEventListener('keyup', elm.onclick );
}
if(elm.hasAttribute('onmousedown')){
elm.addEventListener('mousedown', elm.onclick );
}
if(elm.hasAttribute('onmousemove')){
elm.addEventListener('mousemove', elm.onclick );
}
if(elm.hasAttribute('onmouseout')){
elm.addEventListener('mouseout', elm.onclick );
}
if(elm.hasAttribute('onmouseover')){
elm.addEventListener('mouseover', elm.onclick );
}
if(elm.hasAttribute('onmouseup')){
elm.addEventListener('mouseup', elm.onclick );
}
return elm;
};
var __click__ = function(element){
var event = new Event({
target:element,
currentTarget:element
});
event.initEvent("click");
element.dispatchEvent(event);
};
var __submit__ = function(element){
var event = new Event({
target:element,
currentTarget:element
});
event.initEvent("submit");
element.dispatchEvent(event);
};
var __focus__ = function(element){
var event = new Event({
target:element,
currentTarget:element
});
event.initEvent("focus");
element.dispatchEvent(event);
};
var __blur__ = function(element){
var event = new Event({
target:element,
currentTarget:element
});
event.initEvent("blur");
element.dispatchEvent(event);
};
$w.HTMLElement = HTMLElement;
$debug("Defining HTMLCollection");
/*
* HTMLCollection - DOM Level 2
* Implementation Provided by Steven Wood
*/
var HTMLCollection = function(nodelist, type){
__setArray__(this, []);
for (var i=0; i<nodelist.length; i++) {
this[i] = nodelist[i];
}
this.length = nodelist.length;
}
HTMLCollection.prototype = {
item : function (idx) {
var ret = null;
if ((idx >= 0) && (idx < this.length)) {
ret = this[idx];
}
return ret;
},
namedItem : function (name) {
}
};
$w.HTMLCollection = HTMLCollection;
/*var HTMLCollection = function(nodelist, type){
var $items = [],
$item, i;
if(type === "Anchor" ){
for(i=0;i<nodelist.length;i++){
//The name property is required to be add to the collection
if(nodelist.item(i).name){
item = new nodelist.item(i);
$items.push(item);
this[nodelist.item(i).name] = item;
}
}
}else if(type === "Link"){
for(i=0;i<nodelist.length;i++){
//The name property is required to be add to the collection
if(nodelist.item(i).href){
item = new nodelist.item(i);
$items.push(item);
this[nodelist.item(i).name] = item;
}
}
}else if(type === "Form"){
for(i=0;i<nodelist.length;i++){
//The name property is required to be add to the collection
if(nodelist.item(i).href){
item = new nodelist.item(i);
$items.push(item);
this[nodelist.item(i).name] = item;
}
}
}
setArray(this, $items);
return __extend__(this, {
item : function(i){return this[i];},
namedItem : function(name){return this[name];}
});
};*/
$debug("Defining HTMLAnchorElement");
/*
* HTMLAnchorElement - DOM Level 2
*/
var HTMLAnchorElement = function(ownerDocument) {
//$log("creating anchor element");
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLAnchorElement.prototype = new HTMLElement;
__extend__(HTMLAnchorElement.prototype, {
get accessKey() {
return this.getAttribute("accesskey") || "";
},
set accessKey(val) {
return this.setAttribute("accesskey",val);
},
get charset() {
return this.getAttribute("charset") || "";
},
set charset(val) {
return this.setAttribute("charset",val);
},
get coords() {
return this.getAttribute("coords") || "";
},
set coords(val) {
return this.setAttribute("coords",val);
},
get href() {
return this.getAttribute("href") || "";
},
set href(val) {
return this.setAttribute("href",val);
},
get hreflang() {
return this.getAttribute("hreflang") || "";
},
set hreflang(val) {
return this.setAttribute("hreflang",val);
},
get name() {
return this.getAttribute("name") || "";
},
set name(val) {
return this.setAttribute("name",val);
},
get rel() {
return this.getAttribute("rel") || "";
},
set rel(val) {
return this.setAttribute("rel",val);
},
get rev() {
return this.getAttribute("rev") || "";
},
set rev(val) {
return this.setAttribute("rev",val);
},
get shape() {
return this.getAttribute("shape") || "";
},
set shape(val) {
return this.setAttribute("shape",val);
},
get tabIndex() {
return this.getAttribute("tabindex") || "";
},
set tabIndex(val) {
return this.setAttribute("tabindex",val);
},
get target() {
return this.getAttribute("target") || "";
},
set target(val) {
return this.setAttribute("target",val);
},
get type() {
return this.getAttribute("type") || "";
},
set type(val) {
return this.setAttribute("type",val);
},
blur:function(){
__blur__(this);
},
focus:function(){
__focus__(this);
}
});
$w.HTMLAnchorElement = HTMLAnchorElement;$debug("Defining Anchor");
/*
* Anchor - DOM Level 2
*/
var Anchor = function(ownerDocument) {
this.HTMLAnchorElement = HTMLAnchorElement;
this.HTMLAnchorElement(ownerDocument);
};
(function(){
//static regular expressions
var hash = new RegExp('(\\#.*)'),
hostname = new RegExp('\/\/([^\:\/]+)'),
pathname = new RegExp('(\/[^\\?\\#]*)'),
port = new RegExp('\:(\\d+)\/'),
protocol = new RegExp('(^\\w*\:)'),
search = new RegExp('(\\?[^\\#]*)');
__extend__(Anchor.prototype, {
get hash(){
var m = hash.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set hash(_hash){
//setting the hash is the only property of the location object
//that doesn't cause the window to reload
_hash = _hash.indexOf('#')===0?_hash:"#"+_hash;
this.href = this.protocol + this.host + this.pathname + this.search + _hash;
},
get host(){
return this.hostname + (this.port !== "")?":"+this.port:"";
},
set host(_host){
this.href = this.protocol + _host + this.pathname + this.search + this.hash;
},
get hostname(){
var m = hostname.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set hostname(_hostname){
this.href = this.protocol + _hostname + ((this.port=="")?"":(":"+this.port)) +
this.pathname + this.search + this.hash;
},
get pathname(){
var m = this.href;
m = pathname.exec(m.substring(m.indexOf(this.hostname)));
return m&&m.length>1?m[1]:"/";
},
set pathname(_pathname){
this.href = this.protocol + this.host + _pathname +
this.search + this.hash;
},
get port(){
var m = port.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set port(_port){
this.href = this.protocol + this.hostname + ":"+_port + this.pathname +
this.search + this.hash;
},
get protocol(){
return protocol.exec(this.href)[0];
},
set protocol(_protocol){
this.href = _protocol + this.host + this.pathname +
this.search + this.hash;
},
get search(){
var m = search.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set search(_search){
this.href = this.protocol + this.host + this.pathname +
_search + this.hash;
}
});
})();
$w.Anchor = Anchor;
$debug("Defining HTMLAreaElement");
/*
* HTMLAreaElement - DOM Level 2
*/
var HTMLAreaElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLAreaElement.prototype = new HTMLElement;
__extend__(HTMLAreaElement.prototype, {
get accessKey(){
return this.getAttribute('accesskey');
},
set accessKey(value){
this.setAttribute('accesskey',value);
},
get alt(){
return this.getAttribute('alt');
},
set alt(value){
this.setAttribute('alt',value);
},
get coords(){
return this.getAttribute('coords');
},
set coords(value){
this.setAttribute('coords',value);
},
get href(){
return this.getAttribute('href');
},
set href(value){
this.setAttribute('href',value);
},
get noHref(){
return this.hasAttribute('href');
},
get shape(){
//TODO
return 0;
},
get tabIndex(){
return this.getAttribute('tabindex');
},
set tabIndex(value){
this.setAttribute('tabindex',value);
},
get target(){
return this.getAttribute('target');
},
set target(value){
this.setAttribute('target',value);
}
});
$w.HTMLAreaElement = HTMLAreaElement;
$debug("Defining HTMLBaseElement");
/*
* HTMLBaseElement - DOM Level 2
*/
var HTMLBaseElement = function(ownerDocument) {
//$log("creating anchor element");
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLBaseElement.prototype = new HTMLElement;
__extend__(HTMLBaseElement.prototype, {
get href(){
return this.getAttribute('href');
},
set href(value){
this.setAttribute('href',value);
},
get target(){
return this.getAttribute('target');
},
set target(value){
this.setAttribute('target',value);
}
});
$w.HTMLBaseElement = HTMLBaseElement; $debug("Defining HTMLQuoteElement");
/*
* HTMLQuoteElement - DOM Level 2
*/
var HTMLQuoteElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLQuoteElement.prototype = new HTMLElement;
__extend__(HTMLQuoteElement.prototype, {
get cite(){
return this.getAttribute('cite');
},
set cite(value){
this.setAttribute('cite',value);
}
});
$w.HTMLQuoteElement = HTMLQuoteElement; $debug("Defining HTMLButtonElement");
/*
* HTMLButtonElement - DOM Level 2
*/
var HTMLButtonElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLButtonElement.prototype = new HTMLElement;
__extend__(HTMLButtonElement.prototype, {
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
},
get accessKey(){
return this.getAttribute('accesskey');
},
set accessKey(value){
this.setAttribute('accesskey',value);
},
get tabIndex(){
return Number(this.getAttribute('tabindex'));
},
set tabIndex(value){
this.setAttribute('tabindex',Number(value));
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
},
get value(){
return this.getAttribute('value');
},
set value(value){
this.setAttribute('value',value);
}
});
$w.HTMLButtonElement = HTMLButtonElement; $debug("Defining HTMLTableColElement");
/*
* HTMLTableColElement - DOM Level 2
*/
var HTMLTableColElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLTableColElement.prototype = new HTMLElement;
__extend__(HTMLTableColElement.prototype, {
get align(){
return this.getAttribute('align');
},
set align(value){
this.setAttribute('align', value);
},
get ch(){
return this.getAttribute('ch');
},
set ch(value){
this.setAttribute('ch', value);
},
get chOff(){
return this.getAttribute('ch');
},
set chOff(value){
this.setAttribute('ch', value);
},
get span(){
return this.getAttribute('span');
},
set span(value){
this.setAttribute('span', value);
},
get vAlign(){
return this.getAttribute('valign');
},
set vAlign(value){
this.setAttribute('valign', value);
},
get width(){
return this.getAttribute('width');
},
set width(value){
this.setAttribute('width', value);
}
});
$w.HTMLTableColElement = HTMLTableColElement;
$debug("Defining HTMLModElement");
/*
* HTMLModElement - DOM Level 2
*/
var HTMLModElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLModElement.prototype = new HTMLElement;
__extend__(HTMLModElement.prototype, {
get cite(){
return this.getAttribute('cite');
},
set cite(value){
this.setAttribute('cite', value);
},
get dateTime(){
return this.getAttribute('datetime');
},
set dateTime(value){
this.setAttribute('datetime', value);
}
});
$w.HTMLModElement = HTMLModElement; $debug("Defining HTMLFieldSetElement");
/*
* HTMLFieldSetElement - DOM Level 2
*/
var HTMLFieldSetElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLFieldSetElement.prototype = new HTMLElement;
__extend__(HTMLFieldSetElement.prototype, {
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
}
});
$w.HTMLFieldSetElement = HTMLFieldSetElement; $debug("Defining HTMLFormElement");
/*
* HTMLFormElement - DOM Level 2
*/
var HTMLFormElement = function(ownerDocument){
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLFormElement.prototype = new HTMLElement;
__extend__(HTMLFormElement.prototype,{
get acceptCharset(){
return this.getAttribute('accept-charset');
},
set acceptCharset(acceptCharset){
this.setAttribute('accept-charset', acceptCharset);
},
get action(){
return this.getAttribute('action');
},
set action(action){
this.setAttribute('action', action);
},
get elements() {
return this.getElementsByTagName("*");
},
get enctype(){
return this.getAttribute('enctype');
},
set enctype(enctype){
this.setAttribute('enctype', enctype);
},
get length() {
return this.elements.length;
},
get method(){
return this.getAttribute('method');
},
set method(action){
this.setAttribute('method', method);
},
get name() {
return this.getAttribute("name") || "";
},
set name(val) {
return this.setAttribute("name",val);
},
get target() {
return this.getAttribute("target") || "";
},
set target(val) {
return this.setAttribute("target",val);
},
submit:function(){
__submit__(this);
},
reset:function(){
__reset__(this);
}
});
$w.HTMLFormElement = HTMLFormElement;$debug("Defining HTMLFrameElement");
/*
* HTMLFrameElement - DOM Level 2
*/
var HTMLFrameElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLFrameElement.prototype = new HTMLElement;
__extend__(HTMLFrameElement.prototype, {
get frameBorder(){
return this.getAttribute('border')||"";
},
set frameBorder(value){
this.setAttribute('border', value);
},
get longDesc(){
return this.getAttribute('longdesc')||"";
},
set longDesc(value){
this.setAttribute('longdesc', value);
},
get marginHeight(){
return this.getAttribute('marginheight')||"";
},
set marginHeight(value){
this.setAttribute('marginheight', value);
},
get marginWidth(){
return this.getAttribute('marginwidth')||"";
},
set marginWidth(value){
this.setAttribute('marginwidth', value);
},
get name(){
return this.getAttribute('name')||"";
},
set name(value){
this.setAttribute('name', value);
},
get noResize(){
return this.getAttribute('noresize')||"";
},
set noResize(value){
this.setAttribute('noresize', value);
},
get scrolling(){
return this.getAttribute('scrolling')||"";
},
set scrolling(value){
this.setAttribute('scrolling', value);
},
get src(){
return this.getAttribute('src')||"";
},
set src(value){
this.setAttribute('src', value);
},
get contentDocument(){
$debug("getting content document for (i)frame");
if(!this._content){
this._content = new HTMLDocument($implementation);
if(this.src.length > 0){
$info("Loading frame content from " + this.src);
try{
this._content.load(this.src);
}catch(e){
$error("failed to load frame content: from " + this.src, e);
}
}
}
return this._content;
}
});
$w.HTMLFrameElement = HTMLFrameElement;
$debug("Defining HTMLFrameSetElement");
/*
* HTMLFrameSetElement - DOM Level 2
*/
var HTMLFrameSetElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLFrameSetElement.prototype = new HTMLElement;
__extend__(HTMLFrameSetElement.prototype, {
get cols(){
return this.getAttribute('cols');
},
set cols(value){
this.setAttribute('cols', value);
},
get rows(){
return this.getAttribute('rows');
},
set rows(value){
this.setAttribute('rows', value);
}
});
$w.HTMLFrameSetElement = HTMLFrameSetElement; $debug("Defining HTMLHeadElement");
/*
* HTMLHeadElement - DOM Level 2
*/
var HTMLHeadElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLHeadElement.prototype = new HTMLElement;
__extend__(HTMLHeadElement.prototype, {
get profile(){
return this.getAttribute('profile');
},
set profile(value){
this.setAttribute('profile', value);
},
//we override this so we can apply browser behavior specific to head children
//like loading scripts
appendChild : function(newChild) {
var newChild = HTMLElement.prototype.appendChild.apply(this,[newChild]);
//__evalScript__(newChild);
return newChild;
},
insertBefore : function(newChild, refChild) {
var newChild = HTMLElement.prototype.insertBefore.apply(this,[newChild]);
//__evalScript__(newChild);
return newChild;
}
});
var __evalScript__ = function(newChild){
//check to see if this is a script element and apply a script loading strategy
//the check against the ownerDocument isnt really enough to support frames in
// the long run, but for now it's ok
if(newChild.nodeType == DOMNode.ELEMENT_NODE &&
newChild.ownerDocument == window.document ){
if(newChild.nodeName.toUpperCase() == "SCRIPT"){
$debug("loading script via policy. ");
$policy.loadScript(newChild);
}
}
};
$w.HTMLHeadElement = HTMLHeadElement;
$debug("Defining HTMLIFrameElement");
/*
* HTMLIFrameElement - DOM Level 2
*/
var HTMLIFrameElement = function(ownerDocument) {
this.HTMLFrameElement = HTMLFrameElement;
this.HTMLFrameElement(ownerDocument);
};
HTMLIFrameElement.prototype = new HTMLFrameElement;
__extend__(HTMLIFrameElement.prototype, {
get height() {
return this.getAttribute("height") || "";
},
set height(val) {
return this.setAttribute("height",val);
},
get width() {
return this.getAttribute("width") || "";
},
set width(val) {
return this.setAttribute("width",val);
}
});
$w.HTMLIFrameElement = HTMLIFrameElement;
$debug("Defining HTMLImageElement");
/*
* HTMLImageElement - DOM Level 2
*/
var HTMLImageElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLImageElement.prototype = new HTMLElement;
__extend__(HTMLImageElement.prototype, {
get alt(){
return this.getAttribute('alt');
},
set alt(value){
this.setAttribute('alt', value);
},
get height(){
return this.getAttribute('height');
},
set height(value){
this.setAttribute('height', value);
},
get isMap(){
return this.hasAttribute('map');
},
set useMap(value){
this.setAttribute('map', value);
},
get longDesc(){
return this.getAttribute('longdesc');
},
set longDesc(value){
this.setAttribute('longdesc', value);
},
get name(){
return this.getAttribute('name');
},
set name(value){
this.setAttribute('name', value);
},
get src(){
return this.getAttribute('src');
},
set src(value){
this.setAttribute('src', value);
},
get width(){
return this.getAttribute('width');
},
set width(value){
this.setAttribute('width', value);
}
});
$w.HTMLImageElement = HTMLImageElement;$debug("Defining HTMLInputElement");
/*
* HTMLInputElement - DOM Level 2
*/
var HTMLInputElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLInputElement.prototype = new HTMLElement;
__extend__(HTMLInputElement.prototype, {
get defaultValue(){
return this.getAttribute('defaultValue');
},
set defaultValue(value){
this.setAttribute('defaultValue', value);
},
get defaultChecked(){
return this.getAttribute('defaultChecked');
},
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
},
get accessKey(){
return this.getAttribute('accesskey');
},
set accessKey(value){
this.setAttribute('accesskey',value);
},
get access(){
return this.getAttribute('access');
},
set access(value){
this.setAttribute('access', value);
},
get alt(){
return this.getAttribute('alt');
},
set alt(value){
this.setAttribute('alt', value);
},
get checked(){
return (this.getAttribute('checked')=='checked');
},
set checked(value){
this.setAttribute('checked', (value ? 'checked' :''));
},
get disabled(){
return (this.getAttribute('disabled')=='disabled');
},
set disabled(value){
this.setAttribute('disabled', (value ? 'disabled' :''));
},
get maxLength(){
return Number(this.getAttribute('maxlength')||'0');
},
set maxLength(value){
this.setAttribute('maxlength', value);
},
get name(){
return this.getAttribute('name')||'';
},
set name(value){
this.setAttribute('name', value);
},
get readOnly(){
return (this.getAttribute('readonly')=='readonly');
},
set readOnly(value){
this.setAttribute('readonly', (value ? 'readonly' :''));
},
get size(){
return this.getAttribute('size');
},
set size(value){
this.setAttribute('size', value);
},
get src(){
return this.getAttribute('src');
},
set src(value){
this.setAttribute('src', value);
},
get tabIndex(){
return Number(this.getAttribute('tabindex'));
},
set tabIndex(value){
this.setAttribute('tabindex',Number(value));
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
},
get useMap(){
return this.getAttribute('map');
},
get value(){
return this.getAttribute('value');
},
set value(value){
this.setAttribute('value',value);
},
blur:function(){
__blur__(this);
},
focus:function(){
__focus__(this);
},
select:function(){
__select__(this);
},
click:function(){
__click__(this);
}
});
$w.HTMLInputElement = HTMLInputElement;$debug("Defining HTMLLabelElement");
/*
* HTMLLabelElement - DOM Level 2
*/
var HTMLLabelElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLLabelElement.prototype = new HTMLElement;
__extend__(HTMLLabelElement.prototype, {
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
},
get accessKey(){
return this.getAttribute('accesskey');
},
set accessKey(value){
this.setAttribute('accesskey',value);
},
get htmlFor(){
return this.getAttribute('for');
},
set htmlFor(value){
this.setAttribute('for',value);
}
});
$w.HTMLLabelElement = HTMLLabelElement; $debug("Defining HTMLLegendElement");
/*
* HTMLLegendElement - DOM Level 2
*/
var HTMLLegendElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLLegendElement.prototype = new HTMLElement;
__extend__(HTMLLegendElement.prototype, {
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
},
get accessKey(){
return this.getAttribute('accesskey');
},
set accessKey(value){
this.setAttribute('accesskey',value);
}
});
$w.HTMLLegendElement = HTMLLegendElement; /**
* Link - HTMLElement
*/
$w.__defineGetter__("Link", function(){
return function(){
throw new Error("Object cannot be created in this context");
};
});
$debug("Defining HTMLLinkElement");
/*
* HTMLLinkElement - DOM Level 2
*/
var HTMLLinkElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLLinkElement.prototype = new HTMLElement;
__extend__(HTMLLinkElement.prototype, {
get disabled(){
return this.getAttribute('disabled');
},
set disabled(value){
this.setAttribute('disabled',value);
},
get charset(){
return this.getAttribute('charset');
},
set charset(value){
this.setAttribute('charset',value);
},
get href(){
return this.getAttribute('href');
},
set href(value){
this.setAttribute('href',value);
},
get hreflang(){
return this.getAttribute('hreflang');
},
set hreflang(value){
this.setAttribute('hreflang',value);
},
get media(){
return this.getAttribute('media');
},
set media(value){
this.setAttribute('media',value);
},
get rel(){
return this.getAttribute('rel');
},
set rel(value){
this.setAttribute('rel',value);
},
get rev(){
return this.getAttribute('rev');
},
set rev(value){
this.setAttribute('rev',value);
},
get target(){
return this.getAttribute('target');
},
set target(value){
this.setAttribute('target',value);
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
}
});
$w.HTMLLinkElement = HTMLLinkElement;
$debug("Defining HTMLMapElement");
/*
* HTMLMapElement - DOM Level 2
*/
var HTMLMapElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLMapElement.prototype = new HTMLElement;
__extend__(HTMLMapElement.prototype, {
get areas(){
return this.getElementsByTagName('area');
},
get name(){
return this.getAttribute('name');
},
set name(value){
this.setAttribute('name',value);
}
});
$w.HTMLMapElement = HTMLMapElement;$debug("Defining HTMLMetaElement");
/*
* HTMLMetaElement - DOM Level 2
*/
var HTMLMetaElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLMetaElement.prototype = new HTMLElement;
__extend__(HTMLMetaElement.prototype, {
get content(){
return this.getAttribute('content');
},
set content(value){
this.setAttribute('content',value);
},
get httpEquiv(){
return this.getAttribute('http-equiv');
},
set httpEquiv(value){
this.setAttribute('http-equiv',value);
},
get name(){
return this.getAttribute('name');
},
set name(value){
this.setAttribute('name',value);
},
get scheme(){
return this.getAttribute('scheme');
},
set scheme(value){
this.setAttribute('scheme',value);
}
});
$w.HTMLMetaElement = HTMLMetaElement;
$debug("Defining HTMLObjectElement");
/*
* HTMLObjectElement - DOM Level 2
*/
var HTMLObjectElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLObjectElement.prototype = new HTMLElement;
__extend__(HTMLObjectElement.prototype, {
get code(){
return this.getAttribute('code');
},
set code(value){
this.setAttribute('code',value);
},
get archive(){
return this.getAttribute('archive');
},
set archive(value){
this.setAttribute('archive',value);
},
get codeBase(){
return this.getAttribute('codebase');
},
set codeBase(value){
this.setAttribute('codebase',value);
},
get codeType(){
return this.getAttribute('codetype');
},
set codeType(value){
this.setAttribute('codetype',value);
},
get data(){
return this.getAttribute('data');
},
set data(value){
this.setAttribute('data',value);
},
get declare(){
return this.getAttribute('declare');
},
set declare(value){
this.setAttribute('declare',value);
},
get height(){
return this.getAttribute('height');
},
set height(value){
this.setAttribute('height',value);
},
get standby(){
return this.getAttribute('standby');
},
set standby(value){
this.setAttribute('standby',value);
},
get tabIndex(){
return this.getAttribute('tabindex');
},
set tabIndex(value){
this.setAttribute('tabindex',value);
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
},
get useMap(){
return this.getAttribute('usemap');
},
set useMap(value){
this.setAttribute('usemap',value);
},
get width(){
return this.getAttribute('width');
},
set width(value){
this.setAttribute('width',value);
},
get contentDocument(){
return this.ownerDocument;
}
});
$w.HTMLObjectElement = HTMLObjectElement;
$debug("Defining HTMLOptGroupElement");
/*
* HTMLOptGroupElement - DOM Level 2
*/
var HTMLOptGroupElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLOptGroupElement.prototype = new HTMLElement;
__extend__(HTMLOptGroupElement.prototype, {
get disabled(){
return this.getAttribute('disabled');
},
set disabled(value){
this.setAttribute('disabled',value);
},
get label(){
return this.getAttribute('label');
},
set label(value){
this.setAttribute('label',value);
},
});
$w.HTMLOptGroupElement = HTMLOptGroupElement; $debug("Defining HTMLOptionElement");
/*
* HTMLOptionElement - DOM Level 2
*/
var HTMLOptionElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLOptionElement.prototype = new HTMLElement;
__extend__(HTMLOptionElement.prototype, {
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
},
get defaultSelected(){
return this.getAttribute('defaultSelected');
},
set defaultSelected(value){
this.setAttribute('defaultSelected',value);
},
get text(){
return ((this.nodeValue === null) || (this.nodeValue ===undefined)) ?
this.innerHTML :
this.nodeValue;
},
get index(){
var options = this.parent.childNodes;
for(var i; i<options.length;i++){
if(this == options[i])
return i;
}
return -1;
},
get disabled(){
return this.getAttribute('disabled');
},
set disabled(value){
this.setAttribute('disabled',value);
},
get label(){
return this.getAttribute('label');
},
set label(value){
this.setAttribute('label',value);
},
get selected(){
return (this.getAttribute('selected')=='selected');
},
set selected(value){
this.setAttribute('selected', (value ? 'selected' :''));
},
get value(){
return ((this.getAttribute('value') === undefined) || (this.getAttribute('value') === null)) ?
this.text :
this.getAttribute('value');
},
set value(value){
this.setAttribute('value',value);
}
});
$w.HTMLOptionElement = HTMLOptionElement;
$debug("Defining HTMLParamElement");
/*
* HTMLParamElement - DOM Level 2
*/
var HTMLParamElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLParamElement.prototype = new HTMLElement;
__extend__(HTMLParamElement.prototype, {
get name(){
return this.getAttribute('name');
},
set name(value){
this.setAttribute('name',value);
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
},
get value(){
return this.getAttribute('value');
},
set value(value){
this.setAttribute('value',value);
},
get valueType(){
return this.getAttribute('valuetype');
},
set valueType(value){
this.setAttribute('valuetype',value);
},
});
$w.HTMLParamElement = HTMLParamElement;
$debug("Defining HTMLScriptElement");
/*
* HTMLScriptElement - DOM Level 2
*/
var HTMLScriptElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLScriptElement.prototype = new HTMLElement;
__extend__(HTMLScriptElement.prototype, {
get text(){
// text of script is in a child node of the element
// scripts with < operator must be in a CDATA node
for (var i=0; i<this.childNodes.length; i++) {
if (this.childNodes[i].nodeType == DOMNode.CDATA_SECTION_NODE) {
return this.childNodes[i].nodeValue;
}
}
// otherwise there will be a text node containing the script
if (this.childNodes[0] && this.childNodes[0].nodeType == DOMNode.TEXT_NODE) {
return this.childNodes[0].nodeValue;
}
return this.nodeValue;
},
get htmlFor(){
return this.getAttribute('for');
},
set htmlFor(value){
this.setAttribute('for',value);
},
get event(){
return this.getAttribute('event');
},
set event(value){
this.setAttribute('event',value);
},
get charset(){
return this.getAttribute('charset');
},
set charset(value){
this.setAttribute('charset',value);
},
get defer(){
return this.getAttribute('defer');
},
set defer(value){
this.setAttribute('defer',value);
},
get src(){
return this.getAttribute('src');
},
set src(value){
this.setAttribute('src',value);
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
}
});
$w.HTMLScriptElement = HTMLScriptElement;$debug("Defining HTMLSelectElement");
/*
* HTMLSelectElement - DOM Level 2
*/
var HTMLSelectElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLSelectElement.prototype = new HTMLElement;
__extend__(HTMLSelectElement.prototype, {
get type(){
return this.getAttribute('type');
},
get selectedIndex(){
var options = this.options;
for(var i=0;i<options.length;i++){
if(options[i].selected){
return i;
}
};
return -1;
},
set selectedIndex(value){
if (this.selectedIndex != -1) {
this.options[this.selectedIndex].selected = '';
}
var option = this.options[Number(value)];
if (option) {
option.selected = 'selected';
}
},
get value(){
return this.getAttribute('value')||'';
},
set value(value) {
var options = this.options,
i, index;
for (i=0; i<options.length; i++) {
if (options[i].value == value) {
index = i;
break;
}
}
if (index !== undefined) {
this.setAttribute('value', value);
this.selectedIndex = index;
}
},
get length(){
return this.options.length;
},
get form(){
var parent = this.parent;
while(parent.nodeName.toLowerCase() != 'form'){
parent = parent.parent;
}
return parent;
},
get options(){
return this.getElementsByTagName('option');
},
get disabled(){
return (this.getAttribute('disabled')=='disabled');
},
set disabled(value){
this.setAttribute('disabled', (value ? 'disabled' :''));
},
get multiple(){
return this.getAttribute('multiple');
},
set multiple(value){
this.setAttribute('multiple',value);
},
get name(){
return this.getAttribute('name')||'';
},
set name(value){
this.setAttribute('name',value);
},
get size(){
return Number(this.getAttribute('size'));
},
set size(value){
this.setAttribute('size',value);
},
get tabIndex(){
return Number(this.getAttribute('tabindex'));
},
set tabIndex(value){
this.setAttribute('tabindex',value);
},
add : function(){
__add__(this);
},
remove : function(){
__remove__(this);
},
blur: function(){
__blur__(this);
},
focus: function(){
__focus__(this);
}
});
$w.HTMLSelectElement = HTMLSelectElement;$debug("Defining HTMLStyleElement");
/*
* HTMLStyleElement - DOM Level 2
*/
var HTMLStyleElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLStyleElement.prototype = new HTMLElement;
__extend__(HTMLStyleElement.prototype, {
get disabled(){
return this.getAttribute('disabled');
},
set disabled(value){
this.setAttribute('disabled',value);
},
get media(){
return this.getAttribute('media');
},
set media(value){
this.setAttribute('media',value);
},
get type(){
return this.getAttribute('type');
},
set type(value){
this.setAttribute('type',value);
}
});
$w.HTMLStyleElement = HTMLStyleElement;$debug("Defining HTMLTableElement");
/*
* HTMLTableElement - DOM Level 2
* Implementation Provided by Steven Wood
*/
var HTMLTableElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLTableElement.prototype = new HTMLElement;
__extend__(HTMLTableElement.prototype, {
get tFoot() {
//tFoot returns the table footer.
return this.getElementsByTagName("tfoot")[0];
},
createTFoot : function () {
var tFoot = this.tFoot;
if (!tFoot) {
tFoot = document.createElement("tfoot");
this.appendChild(tFoot);
}
return tFoot;
},
deleteTFoot : function () {
var foot = this.tFoot;
if (foot) {
foot.parentNode.removeChild(foot);
}
},
get tHead() {
//tHead returns the table head.
return this.getElementsByTagName("thead")[0];
},
createTHead : function () {
var tHead = this.tHead;
if (!tHead) {
tHead = document.createElement("thead");
this.insertBefore(tHead, this.firstChild);
}
return tHead;
},
deleteTHead : function () {
var head = this.tHead;
if (head) {
head.parentNode.removeChild(head);
}
},
appendChild : function (child) {
var tagName = child.tagName.toLowerCase();
if (tagName === "tr") {
// need an implcit <tbody> to contain this...
if (!this.currentBody) {
this.currentBody = document.createElement("tbody");
DOMNode.prototype.appendChild.apply(this, [this.currentBody]);
}
return this.currentBody.appendChild(child);
} else if (tagName === "tbody" || tagName === "tfoot" && this.currentBody) {
this.currentBody = child;
return DOMNode.prototype.appendChild.apply(this, arguments);
} else {
return DOMNode.prototype.appendChild.apply(this, arguments);
}
},
get tBodies() {
return new HTMLCollection(this.getElementsByTagName("tbody"));
},
get rows() {
return new HTMLCollection(this.getElementsByTagName("tr"));
},
insertRow : function (idx) {
if (idx === undefined) {
throw new Error("Index omitted in call to HTMLTableElement.insertRow ");
}
var rows = this.rows,
numRows = rows.length,
node,
inserted,
lastRow;
if (idx > numRows) {
throw new Error("Index > rows.length in call to HTMLTableElement.insertRow");
}
var inserted = document.createElement("tr");
// If index is -1 or equal to the number of rows,
// the row is appended as the last row. If index is omitted
// or greater than the number of rows, an error will result
if (idx === -1 || idx === numRows) {
lastRow = rows[rows.length-1];
lastRow.parentNode.appendChild(inserted);
} else {
rows[idx].parentNode.insertBefore(inserted, rows[idx]);
}
return inserted;
},
deleteRow : function (idx) {
var elem = this.rows[idx];
elem.parentNode.removeChild(elem);
},
get summary() {
return this.getAttribute("summary");
},
set summary(summary) {
this.setAttribute("summary", summary);
},
get align() {
return this.getAttribute("align");
},
set align(align) {
this.setAttribute("align", align);
},
get bgColor() {
return this.getAttribute("bgColor");
},
set bgColor(bgColor) {
return this.setAttribute("bgColor", bgColor);
},
get cellPadding() {
return this.getAttribute("cellPadding");
},
set cellPadding(cellPadding) {
return this.setAttribute("cellPadding", cellPadding);
},
get cellSpacing() {
return this.getAttribute("cellSpacing");
},
set cellSpacing(cellSpacing) {
this.setAttribute("cellSpacing", cellSpacing);
},
get frame() {
return this.getAttribute("frame");
},
set frame(frame) {
this.setAttribute("frame", frame);
},
get rules() {
return this.getAttribute("rules");
},
set rules(rules) {
this.setAttribute("rules", rules);
},
get width() {
return this.getAttribute("width");
},
set width(width) {
this.setAttribute("width", width);
}
});
$w.HTMLTableElement = HTMLTableElement; $debug("Defining HTMLTableSectionElement");
/*
* HTMLxElement - DOM Level 2
* - Contributed by Steven Wood
*/
var HTMLTableSectionElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLTableSectionElement.prototype = new HTMLElement;
__extend__(HTMLTableSectionElement.prototype, {
appendChild : function (child) {
// disallow nesting of these elements.
if (child.tagName.match(/TBODY|TFOOT|THEAD/)) {
return this.parentNode.appendChild(child);
} else {
return DOMNode.prototype.appendChild.apply(this, arguments);
}
},
get align() {
return this.getAttribute("align");
},
get ch() {
return this.getAttribute("ch");
},
set ch(ch) {
this.setAttribute("ch", ch);
},
// ch gets or sets the alignment character for cells in a column.
set chOff(chOff) {
this.setAttribute("chOff", chOff);
},
get chOff(chOff) {
return this.getAttribute("chOff");
},
get vAlign () {
return this.getAttribute("vAlign");
},
get rows() {
return new HTMLCollection(this.getElementsByTagName("tr"));
},
insertRow : function (idx) {
if (idx === undefined) {
throw new Error("Index omitted in call to HTMLTableSectionElement.insertRow ");
}
var numRows = this.rows.length,
node = null;
if (idx > numRows) {
throw new Error("Index > rows.length in call to HTMLTableSectionElement.insertRow");
}
var row = document.createElement("tr");
// If index is -1 or equal to the number of rows,
// the row is appended as the last row. If index is omitted
// or greater than the number of rows, an error will result
if (idx === -1 || idx === numRows) {
this.appendChild(row);
} else {
node = this.firstChild;
for (var i=0; i<idx; i++) {
node = node.nextSibling;
}
}
this.insertBefore(row, node);
return row;
},
deleteRow : function (idx) {
var elem = this.rows[idx];
this.removeChild(elem);
}
});
$w.HTMLTableSectionElement = HTMLTableSectionElement;
$debug("Defining HTMLTableCellElement");
/*
* HTMLTableCellElement - DOM Level 2
* Implementation Provided by Steven Wood
*/
var HTMLTableCellElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLTableCellElement.prototype = new HTMLElement;
__extend__(HTMLTableCellElement.prototype, {
// TODO :
});
$w.HTMLTableCellElement = HTMLTableCellElement;$debug("Defining HTMLTitleElement");
/*
* HTMLTitleElement - DOM Level 2
*/
var HTMLTitleElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLTitleElement.prototype = new HTMLElement;
__extend__(HTMLTitleElement.prototype, {
$recursivelyGatherTextFromNodeTree: function(aNode) {
var accumulateText = "";
var idx; var n;
for (idx=0;idx < aNode.childNodes.length;idx++){
n = aNode.childNodes.item(idx);
if (n.nodeType == DOMNode.TEXT_NODE)
accumulateText += n.data;
else
accumulateText += this.$recursivelyGatherTextFromNodeTree(n);
}
return accumulateText;
},
get text() {
return this.$recursivelyGatherTextFromNodeTree(this);
},
set text(titleStr) {
this.innerHTML = titleStr; // if paranoid, would error on embedded HTML
}
});
$w.HTMLTitleElement = HTMLTitleElement;
$debug("Defining HTMLTableRowElement");
/*
* HTMLRowElement - DOM Level 2
* Implementation Provided by Steven Wood
*/
var HTMLTableRowElement = function(ownerDocument) {
this.HTMLElement = HTMLElement;
this.HTMLElement(ownerDocument);
};
HTMLTableRowElement.prototype = new HTMLElement;
__extend__(HTMLTableRowElement.prototype, {
// align gets or sets the horizontal alignment of data within cells of the row.
get align() {
return this.getAttribute("align");
},
get bgColor() {
return this.getAttribute("bgcolor");
},
get cells() {
var nl = this.getElementsByTagName("td");
return new HTMLCollection(nl);
},
get ch() {
return this.getAttribute("ch");
},
set ch(ch) {
this.setAttribute("ch", ch);
},
// ch gets or sets the alignment character for cells in a column.
set chOff(chOff) {
this.setAttribute("chOff", chOff);
},
get chOff(chOff) {
return this.getAttribute("chOff");
},
get rowIndex() {
var nl = this.parentNode.childNodes;
for (var i=0; i<nl.length; i++) {
if (nl[i] === this) {
return i;
}
}
},
get sectionRowIndex() {
var nl = this.parentNode.getElementsByTagName(this.tagName);
for (var i=0; i<nl.length; i++) {
if (nl[i] === this) {
return i;
}
}
},
get vAlign () {
return this.getAttribute("vAlign");
},
insertCell : function (idx) {
if (idx === undefined) {
throw new Error("Index omitted in call to HTMLTableRow.insertCell");
}
var numCells = this.cells.length,
node = null;
if (idx > numCells) {
throw new Error("Index > rows.length in call to HTMLTableRow.insertCell");
}
var cell = document.createElement("td");
if (idx === -1 || idx === numCells) {
this.appendChild(cell);
} else {
node = this.firstChild;
for (var i=0; i<idx; i++) {
node = node.nextSibling;
}
}
this.insertBefore(cell, node);
return cell;
},
deleteCell : function (idx) {
var elem = this.cells[idx];
this.removeChild(elem);
}
});
$w.HTMLTableRowElement = HTMLTableRowElement;
/**
* @author thatcher
*/
$debug("Defining XMLSerializer");
/*
* XMLSerializer
*/
$w.__defineGetter__("XMLSerializer", function(){
return new XMLSerializer(arguments);
});
var XMLSerializer = function() {
};
__extend__(XMLSerializer.prototype, {
serializeToString: function(node){
return node.xml;
}
});/**
* @author thatcher
*/
$debug("Defining XPathExpression");
/*
* XPathExpression
*/
$w.__defineGetter__("XPathExpression", function(){
return XPathExpression;
});
var XPathExpression = function() {};
__extend__(XPathExpression.prototype, {
evaluate: function(){
//TODO for now just return an empty XPathResult
return new XPathResult();
}
});/**
* @author thatcher
*/
$debug("Defining XPathResult");
/*
* XPathResult
*/
$w.__defineGetter__("XPathResult", function(){
return XPathResult;
});
var XPathResult = function() {
this.snapshotLength = 0;
this.stringValue = '';
};
__extend__( XPathResult, {
ANY_TYPE: 0,
NUMBER_TYPE: 1,
STRING_TYPE: 2,
BOOLEAN_TYPE: 3,
UNORDERED_NODE_ITERATOR_TYPE: 4,
ORDERED_NODEITERATOR_TYPE: 5,
UNORDERED_NODE_SNAPSHOT_TYPE: 6,
ORDERED_NODE_SNAPSHOT_TYPE: 7,
ANY_ORDERED_NODE_TYPE: 8,
FIRST_ORDERED_NODE_TYPE: 9
});
__extend__(XPathResult.prototype, {
get booleanValue(){
//TODO
},
get invalidIteration(){
//TODO
},
get numberValue(){
//TODO
},
get resultType(){
//TODO
},
get singleNodeValue(){
//TODO
},
iterateNext: function(){
//TODO
},
snapshotItem: function(index){
//TODO
}
});
/**
* @author thatcher
*/
$w.__defineGetter__("XSLTProcessor", function(){
return new XSLTProcessor(arguments);
});
var XSLTProcessor = function() {
this.__stylesheet__ = null;
};
__extend__(XSLTProcessor.prototype, {
clearParameters: function(){
//TODO
},
getParameter: function(nsuri, name){
//TODO
},
importStyleSheet: function(stylesheet){
this.__stylesheet__ = stylesheet;
},
removeParameter: function(nsuri, name){
//TODO
},
reset: function(){
//TODO
},
setParameter: function(nsuri, name, value){
//TODO
},
transformToDocument: function(sourceNode){
return xsltProcess(sourceNode, this.__stylesheet__);
},
transformToFragment: function(sourceNode, ownerDocument){
return xsltProcess(sourceNode, this.__stylesheet__).childNodes;
}
});$debug("Defining Event");
/*
* event.js
*/
var Event = function(options){
if(options === undefined){
options={target:window,currentTarget:window};
}
__extend__(this,{
CAPTURING_PHASE : 1,
AT_TARGET : 2,
BUBBLING_PHASE : 3
});
$debug("Creating new Event");
var $bubbles = options.bubbles?options.bubbles:true,
$cancelable = options.cancelable?options.cancelable:true,
$currentTarget = options.currentTarget?options.currentTarget:null,
$eventPhase = options.eventPhase?options.eventPhase:Event.CAPTURING_PHASE,
$target = options.eventPhase?options.eventPhase:document,
$timestamp = options.timestamp?options.timestamp:new Date().getTime().toString(),
$type = options.type?options.type:"";
return __extend__(this,{
get bubbles(){return $bubbles;},
get cancelable(){return $cancelable;},
get currentTarget(){return $currentTarget;},
get eventPhase(){return $eventPhase;},
get target(){return $target;},
get timestamp(){return $timestamp;},
get type(){return $type;},
initEvent: function(type,bubbles,cancelable){
$type=type?type:$type;
$bubbles=bubbles?bubbles:$bubbles;
$cancelable=cancelable?cancelable:$cancelable;
},
preventDefault: function(){return;/* TODO */},
stopPropagation: function(){return;/* TODO */}
});
};
$w.Event = Event;
$debug("Defining MouseEvent");
/*
* mouseevent.js
*/
$debug("Defining MouseEvent");
/*
* uievent.js
*/
var $onblur,
$onfocus,
$onresize;/*
* CSS2Properties - DOM Level 2 CSS
*/
var CSS2Properties = function(options){
__extend__(this, __supportedStyles__);
this.onSetCallback = options.onSet?options.onSet:(function(){});
this.styleIndices = {};
__cssTextToStyles__(this, options.cssText?options.cssText:"");
};
__extend__(CSS2Properties.prototype, {
get cssText(){
return Array.prototype.join.apply(this,[';\n']);
},
set cssText(cssText){
__cssTextToStyles__(this, cssText);
},
getPropertyCSSValue : function(){
},
getPropertyPriority : function(){
},
getPropertyValue : function(name){
var camelCase = name.replace(/\-(\w)/g, function(all, letter){
return letter.toUpperCase();
});
var i, value = this[camelCase];
if(value === undefined){
for(i=0;i<this.length;i++){
if(this[i]===name){
return this[i];
}
}
}
return value;
},
item : function(index){
return this[index];
},
removeProperty: function(){
},
setProperty: function(){
},
toString:function(){
if (this.length >0){
return "{\n\t"+Array.prototype.join.apply(this,[';\n\t'])+"}\n";
}else{
return '';
}
},
onSet:function(camelCaseName, value){
var dashedName = camelCaseName.replace(/[A-Z]/g, function(all) {
return "-" + all.toLowerCase();
});
var definition = dashedName + ": " + value;
if (this.styleIndices[camelCaseName] !== undefined)
this[this.styleIndices[camelCaseName]] = definition;
else {
Array.prototype.push.apply(this, [definition]);
this.styleIndices[camelCaseName] = this.length - 1;
}
this.onSetCallback();
},
});
var __cssTextToStyles__ = function(css2props, cssText){
var styleArray=[];
var style, name, value, camelCaseName, w3cName, styles = cssText.split(';');
this.styleIndices = {};
for ( var i = 0; i < styles.length; i++ ) {
//$log("Adding style property " + styles[i]);
style = styles[i].split(':');
if ( style.length == 2 ){
//keep a reference to the original name of the style which was set
//this is the w3c style setting method.
var idx = styleArray.length;
styleArray[idx] = w3cName = styles[i];
//camel case for dash case
value = trim(style[1]);
camelCaseName = trim(style[0].replace(/\-(\w)/g, function(all, letter){
return letter.toUpperCase();
}));
this.styleIndices[camelCaseName] = idx;
$debug('CSS Style Name: ' + camelCaseName);
if(css2props["_" + camelCaseName]!==undefined){
//set the value internally with camelcase name
$debug('Setting css ' + camelCaseName + ' to ' + value);
css2props["_" + camelCaseName] = value;
};
}
}
__setArray__(css2props, styleArray);
};
//Obviously these arent all supported but by commenting out various sections
//this provides a single location to configure what is exposed as supported.
//These getters/setters will need to get fine-tuned in the future to deal with
//the variation on input formulations
var __supportedStyles__ = (function(){
return{
_azimuth: "",
get azimuth() {
return this._azimuth;
},
set azimuth(val) {
this._azimuth = val;
this.onSet("azimuth", val);
},
_background: "",
get background() {
return this._background;
},
set background(val) {
this._background = val;
this.onSet("background", val);
},
_backgroundAttachment: "",
get backgroundAttachment() {
return this._backgroundAttachment;
},
set backgroundAttachment(val) {
this._backgroundAttachment = val;
this.onSet("backgroundAttachment", val);
},
_backgroundColor: "",
get backgroundColor() {
return this._backgroundColor;
},
set backgroundColor(val) {
this._backgroundColor = val;
this.onSet("backgroundColor", val);
},
_backgroundImage: "",
get backgroundImage() {
return this._backgroundImage;
},
set backgroundImage(val) {
this._backgroundImage = val;
this.onSet("backgroundImage", val);
},
_backgroundPosition: "",
get backgroundPosition() {
return this._backgroundPosition;
},
set backgroundPosition(val) {
this._backgroundPosition = val;
this.onSet("backgroundPosition", val);
},
_backgroundRepeat: "",
get backgroundRepeat() {
return this._backgroundRepeat;
},
set backgroundRepeat(val) {
this._backgroundRepeat = val;
this.onSet("backgroundRepeat", val);
},
_border: "",
get border() {
return this._border;
},
set border(val) {
this._border = val;
this.onSet("border", val);
},
_borderBottom: "",
get borderBottom() {
return this._borderBottom;
},
set borderBottom(val) {
this._borderBottom = val;
this.onSet("borderBottom", val);
},
_borderBottomColor: "",
get borderBottomColor() {
return this._borderBottomColor;
},
set borderBottomColor(val) {
this._borderBottomColor = val;
this.onSet("borderBottomColor", val);
},
_borderBottomStyle: "",
get borderBottomStyle() {
return this._borderBottomStyle;
},
set borderBottomStyle(val) {
this._borderBottomStyle = val;
this.onSet("borderBottomStyle", val);
},
_borderBottomWidth: "",
get borderBottomWidth() {
return this._borderBottomWidth;
},
set borderBottomWidth(val) {
this._borderBottomWidth = val;
this.onSet("borderBottomWidth", val);
},
_borderCollapse: "",
get borderCollapse() {
return this._borderCollapse;
},
set borderCollapse(val) {
this._borderCollapse = val;
this.onSet("borderCollapse", val);
},
_borderColor: "",
get borderColor() {
return this._borderColor;
},
set borderColor(val) {
this._borderColor = val;
this.onSet("borderColor", val);
},
_borderLeft: "",
get borderLeft() {
return this._borderLeft;
},
set borderLeft(val) {
this._borderLeft = val;
this.onSet("borderLeft", val);
},
_borderLeftColor: "",
get borderLeftColor() {
return this._borderLeftColor;
},
set borderLeftColor(val) {
this._borderLeftColor = val;
this.onSet("borderLeftColor", val);
},
_borderLeftStyle: "",
get borderLeftStyle() {
return this._borderLeftStyle;
},
set borderLeftStyle(val) {
this._borderLeftStyle = val;
this.onSet("borderLeftStyle", val);
},
_borderLeftWidth: "",
get borderLeftWidth() {
return this._borderLeftWidth;
},
set borderLeftWidth(val) {
this._borderLeftWidth = val;
this.onSet("borderLeftWidth", val);
},
_borderRight: "",
get borderRight() {
return this._borderRight;
},
set borderRight(val) {
this._borderRight = val;
this.onSet("borderRight", val);
},
_borderRightColor: "",
get borderRightColor() {
return this._borderRightColor;
},
set borderRightColor(val) {
this._borderRightColor = val;
this.onSet("borderRightColor", val);
},
_borderRightStyle: "",
get borderRightStyle() {
return this._borderRightStyle;
},
set borderRightStyle(val) {
this._borderRightStyle = val;
this.onSet("borderRightStyle", val);
},
_borderRightWidth: "",
get borderRightWidth() {
return this._borderRightWidth;
},
set borderRightWidth(val) {
this._borderRightWidth = val;
this.onSet("borderRightWidth", val);
},
_borderSpacing: "",
get borderSpacing() {
return this._borderSpacing;
},
set borderSpacing(val) {
this._borderSpacing = val;
this.onSet("borderSpacing", val);
},
_borderStyle: "",
get borderStyle() {
return this._borderStyle;
},
set borderStyle(val) {
this._borderStyle = val;
this.onSet("borderStyle", val);
},
_borderTop: "",
get borderTop() {
return this._borderTop;
},
set borderTop(val) {
this._borderTop = val;
this.onSet("borderTop", val);
},
_borderTopColor: "",
get borderTopColor() {
return this._borderTopColor;
},
set borderTopColor(val) {
this._borderTopColor = val;
this.onSet("borderTopColor", val);
},
_borderTopStyle: "",
get borderTopStyle() {
return this._borderTopStyle;
},
set borderTopStyle(val) {
this._borderTopStyle = val;
this.onSet("borderTopStyle", val);
},
_borderTopWidth: "",
get borderTopWidth() {
return this._borderTopWidth;
},
set borderTopWidth(val) {
this._borderTopWidth = val;
this.onSet("borderTopWidth", val);
},
_borderWidth: "",
get borderWidth() {
return this._borderWidth;
},
set borderWidth(val) {
this._borderWidth = val;
this.onSet("borderWidth", val);
},
_bottom: "",
get bottom() {
return this._bottom;
},
set bottom(val) {
this._bottom = val;
this.onSet("bottom", val);
},
_captionSide: "",
get captionSide() {
return this._captionSide;
},
set captionSide(val) {
this._captionSide = val;
this.onSet("captionSide", val);
},
_clear: "",
get clear() {
return this._clear;
},
set clear(val) {
this._clear = val;
this.onSet("clear", val);
},
_clip: "",
get clip() {
return this._clip;
},
set clip(val) {
this._clip = val;
this.onSet("clip", val);
},
_color: "",
get color() {
return this._color;
},
set color(val) {
this._color = val;
this.onSet("color", val);
},
_content: "",
get content() {
return this._content;
},
set content(val) {
this._content = val;
this.onSet("content", val);
},
_counterIncrement: "",
get counterIncrement() {
return this._counterIncrement;
},
set counterIncrement(val) {
this._counterIncrement = val;
this.onSet("counterIncrement", val);
},
_counterReset: "",
get counterReset() {
return this._counterReset;
},
set counterReset(val) {
this._counterReset = val;
this.onSet("counterReset", val);
},
_cssFloat: "",
get cssFloat() {
return this._cssFloat;
},
set cssFloat(val) {
this._cssFloat = val;
this.onSet("cssFloat", val);
},
_cue: "",
get cue() {
return this._cue;
},
set cue(val) {
this._cue = val;
this.onSet("cue", val);
},
_cueAfter: "",
get cueAfter() {
return this._cueAfter;
},
set cueAfter(val) {
this._cueAfter = val;
this.onSet("cueAfter", val);
},
_cueBefore: "",
get cueBefore() {
return this._cueBefore;
},
set cueBefore(val) {
this._cueBefore = val;
this.onSet("cueBefore", val);
},
_cursor: "",
get cursor() {
return this._cursor;
},
set cursor(val) {
this._cursor = val;
this.onSet("cursor", val);
},
_direction: "",
get direction() {
return this._direction;
},
set direction(val) {
this._direction = val;
this.onSet("direction", val);
},
_display: "",
get display() {
return this._display;
},
set display(val) {
this._display = val;
this.onSet("display", val);
},
_elevation: "",
get elevation() {
return this._elevation;
},
set elevation(val) {
this._elevation = val;
this.onSet("elevation", val);
},
_emptyCells: "",
get emptyCells() {
return this._emptyCells;
},
set emptyCells(val) {
this._emptyCells = val;
this.onSet("emptyCells", val);
},
_font: "",
get font() {
return this._font;
},
set font(val) {
this._font = val;
this.onSet("font", val);
},
_fontFamily: "",
get fontFamily() {
return this._fontFamily;
},
set fontFamily(val) {
this._fontFamily = val;
this.onSet("fontFamily", val);
},
_fontSize: "",
get fontSize() {
return this._fontSize;
},
set fontSize(val) {
this._fontSize = val;
this.onSet("fontSize", val);
},
_fontSizeAdjust: "",
get fontSizeAdjust() {
return this._fontSizeAdjust;
},
set fontSizeAdjust(val) {
this._fontSizeAdjust = val;
this.onSet("fontSizeAdjust", val);
},
_fontStretch: "",
get fontStretch() {
return this._fontStretch;
},
set fontStretch(val) {
this._fontStretch = val;
this.onSet("fontStretch", val);
},
_fontStyle: "",
get fontStyle() {
return this._fontStyle;
},
set fontStyle(val) {
this._fontStyle = val;
this.onSet("fontStyle", val);
},
_fontVariant: "",
get fontVariant() {
return this._fontVariant;
},
set fontVariant(val) {
this._fontVariant = val;
this.onSet("fontVariant", val);
},
_fontWeight: "",
get fontWeight() {
return this._fontWeight;
},
set fontWeight(val) {
this._fontWeight = val;
this.onSet("fontWeight", val);
},
_height: "",
get height() {
return this._height;
},
set height(val) {
this._height = val;
this.onSet("height", val);
},
_left: "",
get left() {
return this._left;
},
set left(val) {
this._left = val;
this.onSet("left", val);
},
_letterSpacing: "",
get letterSpacing() {
return this._letterSpacing;
},
set letterSpacing(val) {
this._letterSpacing = val;
this.onSet("letterSpacing", val);
},
_lineHeight: "",
get lineHeight() {
return this._lineHeight;
},
set lineHeight(val) {
this._lineHeight = val;
this.onSet("lineHeight", val);
},
_listStyle: "",
get listStyle() {
return this._listStyle;
},
set listStyle(val) {
this._listStyle = val;
this.onSet("listStyle", val);
},
_listStyleImage: "",
get listStyleImage() {
return this._listStyleImage;
},
set listStyleImage(val) {
this._listStyleImage = val;
this.onSet("listStyleImage", val);
},
_listStylePosition: "",
get listStylePosition() {
return this._listStylePosition;
},
set listStylePosition(val) {
this._listStylePosition = val;
this.onSet("listStylePosition", val);
},
_listStyleType: "",
get listStyleType() {
return this._listStyleType;
},
set listStyleType(val) {
this._listStyleType = val;
this.onSet("listStyleType", val);
},
_margin: "",
get margin() {
return this._margin;
},
set margin(val) {
this._margin = val;
this.onSet("margin", val);
},
_marginBottom: "",
get marginBottom() {
return this._marginBottom;
},
set marginBottom(val) {
this._marginBottom = val;
this.onSet("marginBottom", val);
},
_marginLeft: "",
get marginLeft() {
return this._marginLeft;
},
set marginLeft(val) {
this._marginLeft = val;
this.onSet("marginLeft", val);
},
_marginRight: "",
get marginRight() {
return this._marginRight;
},
set marginRight(val) {
this._marginRight = val;
this.onSet("marginRight", val);
},
_marginTop: "",
get marginTop() {
return this._marginTop;
},
set marginTop(val) {
this._marginTop = val;
this.onSet("marginTop", val);
},
_markerOffset: "",
get markerOffset() {
return this._markerOffset;
},
set markerOffset(val) {
this._markerOffset = val;
this.onSet("markerOffset", val);
},
_marks: "",
get marks() {
return this._marks;
},
set marks(val) {
this._marks = val;
this.onSet("marks", val);
},
_maxHeight: "",
get maxHeight() {
return this._maxHeight;
},
set maxHeight(val) {
this._maxHeight = val;
this.onSet("maxHeight", val);
},
_maxWidth: "",
get maxWidth() {
return this._maxWidth;
},
set maxWidth(val) {
this._maxWidth = val;
this.onSet("maxWidth", val);
},
_minHeight: "",
get minHeight() {
return this._minHeight;
},
set minHeight(val) {
this._minHeight = val;
this.onSet("minHeight", val);
},
_minWidth: "",
get minWidth() {
return this._minWidth;
},
set minWidth(val) {
this._minWidth = val;
this.onSet("minWidth", val);
},
_opacity: 1,
get opacity() {
return this._opacity;
},
set opacity(val) {
this._opacity = val;
this.onSet("opacity", val);
},
_orphans: "",
get orphans() {
return this._orphans;
},
set orphans(val) {
this._orphans = val;
this.onSet("orphans", val);
},
_outline: "",
get outline() {
return this._outline;
},
set outline(val) {
this._outline = val;
this.onSet("outline", val);
},
_outlineColor: "",
get outlineColor() {
return this._outlineColor;
},
set outlineColor(val) {
this._outlineColor = val;
this.onSet("outlineColor", val);
},
_outlineOffset: "",
get outlineOffset() {
return this._outlineOffset;
},
set outlineOffset(val) {
this._outlineOffset = val;
this.onSet("outlineOffset", val);
},
_outlineStyle: "",
get outlineStyle() {
return this._outlineStyle;
},
set outlineStyle(val) {
this._outlineStyle = val;
this.onSet("outlineStyle", val);
},
_outlineWidth: "",
get outlineWidth() {
return this._outlineWidth;
},
set outlineWidth(val) {
this._outlineWidth = val;
this.onSet("outlineWidth", val);
},
_overflow: "",
get overflow() {
return this._overflow;
},
set overflow(val) {
this._overflow = val;
this.onSet("overflow", val);
},
_overflowX: "",
get overflowX() {
return this._overflowX;
},
set overflowX(val) {
this._overflowX = val;
this.onSet("overflowX", val);
},
_overflowY: "",
get overflowY() {
return this._overflowY;
},
set overflowY(val) {
this._overflowY = val;
this.onSet("overflowY", val);
},
_padding: "",
get padding() {
return this._padding;
},
set padding(val) {
this._padding = val;
this.onSet("padding", val);
},
_paddingBottom: "",
get paddingBottom() {
return this._paddingBottom;
},
set paddingBottom(val) {
this._paddingBottom = val;
this.onSet("paddingBottom", val);
},
_paddingLeft: "",
get paddingLeft() {
return this._paddingLeft;
},
set paddingLeft(val) {
this._paddingLeft = val;
this.onSet("paddingLeft", val);
},
_paddingRight: "",
get paddingRight() {
return this._paddingRight;
},
set paddingRight(val) {
this._paddingRight = val;
this.onSet("paddingRight", val);
},
_paddingTop: "",
get paddingTop() {
return this._paddingTop;
},
set paddingTop(val) {
this._paddingTop = val;
this.onSet("paddingTop", val);
},
_page: "",
get page() {
return this._page;
},
set page(val) {
this._page = val;
this.onSet("page", val);
},
_pageBreakAfter: "",
get pageBreakAfter() {
return this._pageBreakAfter;
},
set pageBreakAfter(val) {
this._pageBreakAfter = val;
this.onSet("pageBreakAfter", val);
},
_pageBreakBefore: "",
get pageBreakBefore() {
return this._pageBreakBefore;
},
set pageBreakBefore(val) {
this._pageBreakBefore = val;
this.onSet("pageBreakBefore", val);
},
_pageBreakInside: "",
get pageBreakInside() {
return this._pageBreakInside;
},
set pageBreakInside(val) {
this._pageBreakInside = val;
this.onSet("pageBreakInside", val);
},
_pause: "",
get pause() {
return this._pause;
},
set pause(val) {
this._pause = val;
this.onSet("pause", val);
},
_pauseAfter: "",
get pauseAfter() {
return this._pauseAfter;
},
set pauseAfter(val) {
this._pauseAfter = val;
this.onSet("pauseAfter", val);
},
_pauseBefore: "",
get pauseBefore() {
return this._pauseBefore;
},
set pauseBefore(val) {
this._pauseBefore = val;
this.onSet("pauseBefore", val);
},
_pitch: "",
get pitch() {
return this._pitch;
},
set pitch(val) {
this._pitch = val;
this.onSet("pitch", val);
},
_pitchRange: "",
get pitchRange() {
return this._pitchRange;
},
set pitchRange(val) {
this._pitchRange = val;
this.onSet("pitchRange", val);
},
_position: "",
get position() {
return this._position;
},
set position(val) {
this._position = val;
this.onSet("position", val);
},
_quotes: "",
get quotes() {
return this._quotes;
},
set quotes(val) {
this._quotes = val;
this.onSet("quotes", val);
},
_richness: "",
get richness() {
return this._richness;
},
set richness(val) {
this._richness = val;
this.onSet("richness", val);
},
_right: "",
get right() {
return this._right;
},
set right(val) {
this._right = val;
this.onSet("right", val);
},
_size: "",
get size() {
return this._size;
},
set size(val) {
this._size = val;
this.onSet("size", val);
},
_speak: "",
get speak() {
return this._speak;
},
set speak(val) {
this._speak = val;
this.onSet("speak", val);
},
_speakHeader: "",
get speakHeader() {
return this._speakHeader;
},
set speakHeader(val) {
this._speakHeader = val;
this.onSet("speakHeader", val);
},
_speakNumeral: "",
get speakNumeral() {
return this._speakNumeral;
},
set speakNumeral(val) {
this._speakNumeral = val;
this.onSet("speakNumeral", val);
},
_speakPunctuation: "",
get speakPunctuation() {
return this._speakPunctuation;
},
set speakPunctuation(val) {
this._speakPunctuation = val;
this.onSet("speakPunctuation", val);
},
_speechRate: "",
get speechRate() {
return this._speechRate;
},
set speechRate(val) {
this._speechRate = val;
this.onSet("speechRate", val);
},
_stress: "",
get stress() {
return this._stress;
},
set stress(val) {
this._stress = val;
this.onSet("stress", val);
},
_tableLayout: "",
get tableLayout() {
return this._tableLayout;
},
set tableLayout(val) {
this._tableLayout = val;
this.onSet("tableLayout", val);
},
_textAlign: "",
get textAlign() {
return this._textAlign;
},
set textAlign(val) {
this._textAlign = val;
this.onSet("textAlign", val);
},
_textDecoration: "",
get textDecoration() {
return this._textDecoration;
},
set textDecoration(val) {
this._textDecoration = val;
this.onSet("textDecoration", val);
},
_textIndent: "",
get textIndent() {
return this._textIndent;
},
set textIndent(val) {
this._textIndent = val;
this.onSet("textIndent", val);
},
_textShadow: "",
get textShadow() {
return this._textShadow;
},
set textShadow(val) {
this._textShadow = val;
this.onSet("textShadow", val);
},
_textTransform: "",
get textTransform() {
return this._textTransform;
},
set textTransform(val) {
this._textTransform = val;
this.onSet("textTransform", val);
},
_top: "",
get top() {
return this._top;
},
set top(val) {
this._top = val;
this.onSet("top", val);
},
_unicodeBidi: "",
get unicodeBidi() {
return this._unicodeBidi;
},
set unicodeBidi(val) {
this._unicodeBidi = val;
this.onSet("unicodeBidi", val);
},
_verticalAlign: "",
get verticalAlign() {
return this._verticalAlign;
},
set verticalAlign(val) {
this._verticalAlign = val;
this.onSet("verticalAlign", val);
},
_visibility: "",
get visibility() {
return this._visibility;
},
set visibility(val) {
this._visibility = val;
this.onSet("visibility", val);
},
_voiceFamily: "",
get voiceFamily() {
return this._voiceFamily;
},
set voiceFamily(val) {
this._voiceFamily = val;
this.onSet("voiceFamily", val);
},
_volume: "",
get volume() {
return this._volume;
},
set volume(val) {
this._volume = val;
this.onSet("volume", val);
},
_whiteSpace: "",
get whiteSpace() {
return this._whiteSpace;
},
set whiteSpace(val) {
this._whiteSpace = val;
this.onSet("whiteSpace", val);
},
_widows: "",
get widows() {
return this._widows;
},
set widows(val) {
this._widows = val;
this.onSet("widows", val);
},
_width: "",
get width() {
return this._width;
},
set width(val) {
this._width = val;
this.onSet("width", val);
},
_wordSpacing: "",
get wordSpacing() {
return this._wordSpacing;
},
set wordSpacing(val) {
this._wordSpacing = val;
this.onSet("wordSpacing", val);
},
_zIndex: "",
get zIndex() {
return this._zIndex;
},
set zIndex(val) {
this._zIndex = val;
this.onSet("zIndex", val);
}
};
})()
$w.CSS2Properties = CSS2Properties;/*
* CSSRule - DOM Level 2
*/
var CSSRule = function(options){
var $style,
$selectorText = options.selectorText?options.selectorText:"";
$style = new CSS2Properties({
cssText:options.cssText?options.cssText:null
});
return __extend__(this, {
get style(){
return $style;
},
get selectorText(){
return $selectorText;
},
set selectorText(selectorText){
$selectorText = selectorText;
}
});
};
$w.CSSRule = CSSRule;
/*
* CSSStyleSheet - DOM Level 2
*/
var CSSStyleSheet = function(options){
var $cssRules,
$disabled = options.disabled?options.disabled:false,
$href = options.href?options.href:null,
$parentStyleSheet = options.parentStyleSheet?options.parentStyleSheet:null,
$title = options.title?options.title:"",
$type = "text/css";
function parseStyleSheet(text){
$debug("parsing css");
//this is pretty ugly, but text is the entire text of a stylesheet
var cssRules = [];
if (!text) text = "";
text = trim(text.replace(/\/\*(\r|\n|.)*\*\//g,""));
// TODO: @import ?
var blocks = text.split("}");
blocks.pop();
var i, len = blocks.length;
var definition_block, properties, selectors;
for (i=0; i<len; i++){
definition_block = blocks[i].split("{");
if(definition_block.length === 2){
selectors = definition_block[0].split(",");
for(var j=0;j<selectors.length;j++){
cssRules.push(new CSSRule({
selectorText:selectors[j],
cssText:definition_block[1]
}));
}
__setArray__($cssRules, cssRules);
}
}
};
parseStyleSheet(options.text);
return __extend__(this, {
get cssRules(){return $cssRules;},
get rule(){return $cssRules;},//IE - may be deprecated
get href(){return $href;},
get parentStyleSheet(){return $parentStyleSheet;},
get title(){return $title;},
get type(){return $type;},
addRule: function(selector, style, index){/*TODO*/},
deleteRule: function(index){/*TODO*/},
insertRule: function(rule, index){/*TODO*/},
removeRule: function(index){this.deleteRule(index);}//IE - may be deprecated
});
};
$w.CSSStyleSheet = CSSStyleSheet;
/*
* location.js
* - requires env
*/
$debug("Initializing Window Location.");
//the current location
var $location = '';
$w.__defineSetter__("location", function(url){
//$w.onunload();
$location = $env.location(url);
setHistory($location);
$w.document.load($location);
});
$w.__defineGetter__("location", function(url){
var hash = new RegExp('(\\#.*)'),
hostname = new RegExp('\/\/([^\:\/]+)'),
pathname = new RegExp('(\/[^\\?\\#]*)'),
port = new RegExp('\:(\\d+)\/'),
protocol = new RegExp('(^\\w*\:)'),
search = new RegExp('(\\?[^\\#]*)');
return {
get hash(){
var m = hash.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set hash(_hash){
//setting the hash is the only property of the location object
//that doesn't cause the window to reload
_hash = _hash.indexOf('#')===0?_hash:"#"+_hash;
$location = this.protocol + this.host + this.pathname +
this.search + _hash;
setHistory(_hash, "hash");
},
get host(){
return this.hostname + (this.port !== "")?":"+this.port:"";
},
set host(_host){
$w.location = this.protocol + _host + this.pathname +
this.search + this.hash;
},
get hostname(){
var m = hostname.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set hostname(_hostname){
$w.location = this.protocol + _hostname + ((this.port==="")?"":(":"+this.port)) +
this.pathname + this.search + this.hash;
},
get href(){
//This is the only env specific function
return $location;
},
set href(url){
$w.location = url;
},
get pathname(){
var m = this.href;
m = pathname.exec(m.substring(m.indexOf(this.hostname)));
return m&&m.length>1?m[1]:"/";
},
set pathname(_pathname){
$w.location = this.protocol + this.host + _pathname +
this.search + this.hash;
},
get port(){
var m = port.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set port(_port){
$w.location = this.protocol + this.hostname + ":"+_port + this.pathname +
this.search + this.hash;
},
get protocol(){
return protocol.exec(this.href)[0];
},
set protocol(_protocol){
$w.location = _protocol + this.host + this.pathname +
this.search + this.hash;
},
get search(){
var m = search.exec(this.href);
return m&&m.length>1?m[1]:"";
},
set search(_search){
$w.location = this.protocol + this.host + this.pathname +
_search + this.hash;
},
toString: function(){
return this.href;
},
reload: function(force){
//TODO
},
replace: function(url){
//TODO
}
};
});
/*
* history.js
*/
$info("Initializing Window History.");
$currentHistoryIndex = 0;
$history = [];
// Browser History
$w.__defineGetter__("history", function(){
return {
get length(){ return $history.length; },
back : function(count){
if(count){
go(-count);
}else{go(-1);}
},
forward : function(count){
if(count){
go(count);
}else{go(1);}
},
go : function(target){
if(typeof target == "number"){
target = $currentHistoryIndex+target;
if(target > -1 && target < $history.length){
if($history[target].location == "hash"){
$w.location.hash = $history[target].value;
}else{
$w.location = $history[target].value;
}
$currentHistoryIndex = target;
//remove the last item added to the history
//since we are moving inside the history
$history.pop();
}
}else{
//TODO: walk throu the history and find the 'best match'
}
}
};
});
//Here locationPart is the particutlar method/attribute
// of the location object that was modified. This allows us
// to modify the correct portion of the location object
// when we navigate the history
var setHistory = function( value, locationPart){
$info("adding value to history: " +value);
$currentHistoryIndex++;
$history.push({
location: locationPart||"href",
value: value
});
};
/*
* navigator.js
* - requires env
*/
$debug("Initializing Window Navigator.");
var $appCodeName = $env.appCodeName;//eg "Mozilla"
var $appName = $env.appName;//eg "Gecko/20070309 Firefox/2.0.0.3"
// Browser Navigator
$w.__defineGetter__("navigator", function(){
return {
get appCodeName(){
return $appCodeName;
},
get appName(){
return $appName;
},
get appVersion(){
return $version +" ("+
$w.navigator.platform +"; "+
"U; "+//?
$env.os_name+" "+$env.os_arch+" "+$env.os_version+"; "+
$env.lang+"; "+
"rv:"+$revision+
")";
},
get cookieEnabled(){
return true;
},
get mimeTypes(){
return [];
},
get platform(){
return $env.platform;
},
get plugins(){
return [];
},
get userAgent(){
return $w.navigator.appCodeName + "/" + $w.navigator.appVersion + " " + $w.navigator.appName;
},
javaEnabled : function(){
return $env.javaEnabled;
}
};
});
/*
* timer.js
*/
$debug("Initializing Window Timer.");
//private
var $timers = [];
window.setTimeout = function(fn, time){
var num = $timers.length+1;
var tfn;
if (typeof fn == 'string') {
tfn = function() {
eval(fn);
window.clearInterval(num);
};
} else {
tfn = function() {
fn();
window.clearInterval(num);
}
}
$debug("Creating timer number "+num);
$timers[num] = new $env.timer(tfn, time);
$timers[num].start();
return num;
};
window.setInterval = function(fn, time){
var num = $timers.length+1;
if (typeof fn == 'string') {
var fnstr = fn;
fn = function() {
eval(fnstr);
};
}
if(time===0){
fn();
}else{
$debug("Creating timer number "+num);
$timers[num] = new $env.timer(fn, time);
$timers[num].start();
}
return num;
};
window.clearInterval = window.clearTimeout = function(num){
if ( $timers[num] ) {
$debug("Deleting timer number "+num);
$timers[num].stop();
delete $timers[num];
}
};
window.$wait = function(wait){ $env.wait(wait); }/*
* event.js
*/
// Window Events
$debug("Initializing Window Event.");
var $events = [],
$onerror,
$onload,
$onunload;
$w.addEventListener = function(type, fn){
//$log("adding event listener " + type);
if ( !this.uuid ) {
this.uuid = $events.length;
$events[this.uuid] = {};
}
if ( !$events[this.uuid][type] ){
$events[this.uuid][type] = [];
}
if ( $events[this.uuid][type].indexOf( fn ) < 0 ){
$events[this.uuid][type].push( fn );
}
};
$w.removeEventListener = function(type, fn){
if ( !this.uuid ) {
this.uuid = $events.length;
$events[this.uuid] = {};
}
if ( !$events[this.uuid][type] ){
$events[this.uuid][type] = [];
}
$events[this.uuid][type] =
$events[this.uuid][type].filter(function(f){
return f != fn;
});
};
$w.dispatchEvent = function(event){
$debug("dispatching event " + event.type);
//the window scope defines the $event object, for IE(^^^) compatibility;
$event = event;
if (!event.target) {
event.target = this;
}
$debug("event target: " + event.target);
if ( event.type ) {
if ( this.uuid && $events[this.uuid][event.type] ) {
var _this = this;
$events[this.uuid][event.type].forEach(function(fn){
$debug('calling event handler '+fn+' on target '+_this);
fn.call( _this, event );
});
}
if (this["on" + event.type]) {
$debug('calling event handler '+event.type+' on target '+this);
this["on" + event.type].call(_this, event);
}
}
if(this.parentNode){
this.parentNode.dispatchEvent.call(this.parentNode,event);
}
};
$w.__defineGetter__('onerror', function(){
return function(){
//$w.dispatchEvent('error');
};
});
$w.__defineSetter__('onerror', function(fn){
//$w.addEventListener('error', fn);
});
/*$w.__defineGetter__('onload', function(){
return function(){
//var event = document.createEvent();
//event.initEvent("load");
//$w.dispatchEvent(event);
};
});
$w.__defineSetter__('onload', function(fn){
//$w.addEventListener('load', fn);
});
$w.__defineGetter__('onunload', function(){
return function(){
//$w.dispatchEvent('unload');
};
});
$w.__defineSetter__('onunload', function(fn){
//$w.addEventListener('unload', fn);
});*//*
* xhr.js
*/
$debug("Initializing Window XMLHttpRequest.");
// XMLHttpRequest
// Originally implemented by Yehuda Katz
$w.XMLHttpRequest = function(){
this.headers = {};
this.responseHeaders = {};
$debug("creating xhr");
};
XMLHttpRequest.prototype = {
open: function(method, url, async, user, password){
this.readyState = 1;
if (async === false ){
this.async = false;
}else{ this.async = true; }
this.method = method || "GET";
this.url = $env.location(url);
this.onreadystatechange();
},
setRequestHeader: function(header, value){
this.headers[header] = value;
},
getResponseHeader: function(header){ },
send: function(data){
var _this = this;
function makeRequest(){
$env.connection(_this, function(){
var responseXML = null;
_this.__defineGetter__("responseXML", function(){
if ( _this.responseText.match(/^\s*</) ) {
if(responseXML){
return responseXML;
}else{
try {
$debug("parsing response text into xml document");
responseXML = $domparser.parseFromString(_this.responseText+"");
return responseXML;
} catch(e) { return null;/*TODO: need to flag an error here*/}
}
}else{return null;}
});
}, data);
_this.onreadystatechange();
}
if (this.async){
$debug("XHR sending asynch;");
$env.runAsync(makeRequest);
}else{
$debug("XHR sending synch;");
makeRequest();
}
},
abort: function(){
//TODO
},
onreadystatechange: function(){
//TODO
},
getResponseHeader: function(header){
var rHeader, returnedHeaders;
if (this.readyState < 3){
throw new Error("INVALID_STATE_ERR");
} else {
returnedHeaders = [];
for (rHeader in this.responseHeaders) {
if (rHeader.match(new RegExp(header, "i")))
returnedHeaders.push(this.responseHeaders[rHeader]);
}
if (returnedHeaders.length){ return returnedHeaders.join(", "); }
}return null;
},
getAllResponseHeaders: function(){
var header, returnedHeaders = [];
if (this.readyState < 3){
throw new Error("INVALID_STATE_ERR");
} else {
for (header in this.responseHeaders){
returnedHeaders.push( header + ": " + this.responseHeaders[header] );
}
}return returnedHeaders.join("\r\n");
},
async: true,
readyState: 0,
responseText: "",
status: 0
};/*
* css.js
*/
$debug("Initializing Window CSS");
// returns a CSS2Properties object that represents the style
// attributes and values used to render the specified element in this
// window. Any length values are always expressed in pixel, or
// absolute values.
$w.getComputedStyle = function(elt, pseudo_elt){
//TODO
//this is a naive implementation
$debug("Getting computed style");
return elt?elt.style:new CSS2Properties({cssText:""});
};/*
* screen.js
*/
$debug("Initializing Window Screen.");
var $availHeight = 600,
$availWidth = 800,
$colorDepth = 16,
$height = 600,
$width = 800;
$w.__defineGetter__("screen", function(){
return {
get availHeight(){return $availHeight;},
get availWidth(){return $availWidth;},
get colorDepth(){return $colorDepth;},
get height(){return $height;},
get width(){return $width;}
};
});
$w.moveBy = function(dx,dy){
//TODO
};
$w.moveTo = function(x,y) {
//TODO
};
/*$w.print = function(){
//TODO
};*/
$w.resizeBy = function(dw, dh){
$w.resizeTo($width+dw,$height+dh);
};
$w.resizeTo = function(width, height){
$width = (width <= $availWidth) ? width : $availWidth;
$height = (height <= $availHeight) ? height : $availHeight;
};
$w.scroll = function(x,y){
//TODO
};
$w.scrollBy = function(dx, dy){
//TODO
};
$w.scrollTo = function(x,y){
//TODO
};/*
* dialog.js
*/
$debug("Initializing Window Dialogs.");
$w.alert = function(message){
$env.warn(message);
};
$w.confirm = function(question){
//TODO
};
$w.prompt = function(message, defaultMsg){
//TODO
};/**
* 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
*/
window.$profiler;
(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];
};
window.$profiler =
{
/**
* 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<Function>
*
* @example jQuery.aop.after( {target: String, method: 'indexOf'}, function(index) { alert('Result found at: ' + index + ' on:' + this); } );
* @result Array<Function>
*
* @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<Function>
* @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<Function>
*
* @example jQuery.aop.before( {target: String, method: 'indexOf'}, function(index) { alert('About to execute String.indexOf on: ' + this); } );
* @result Array<Function>
*
* @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<Function>
* @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<Function>
*
* @example jQuery.aop.around( {target: String, method: 'indexOf'}, function(invocation) {
* alert('Searching: ' + invocation.arguments[0] + ' on: ' + this);
* return invocation.proceed();
* } );
* @result Array<Function>
*
* @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<Function>
*
*
* @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<Function>
* @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<Function>
*
* @example jQuery.aop.introduction( {target: String, method: 'log'}, function() { alert('Console: ' + this); } );
* @result Array<Function>
*
* @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<Function>
* @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;
}
};
})();
var $profile = window.$profile = {};
var __profile__ = function(id, invocation){
var start = new Date().getTime();
var retval = invocation.proceed();
var finish = new Date().getTime();
$profile[id] = $profile[id] ? $profile[id] : {};
$profile[id].callCount = $profile[id].callCount !== undefined ?
$profile[id].callCount+1 : 0;
$profile[id].times = $profile[id].times ? $profile[id].times : [];
$profile[id].times[$profile[id].callCount++] = (finish-start);
return retval;
};
window.$profiler.stats = function(raw){
var max = 0,
avg = -1,
min = 10000000,
own = 0;
for(var i = 0;i<raw.length;i++){
if(raw[i] > 0){
own += raw[i];
};
if(raw[i] > max){
max = raw[i];
}
if(raw[i] < min){
min = raw[i];
}
}
avg = Math.floor(own/raw.length);
return {
min: min,
max: max,
avg: avg,
own: own
};
};
if(Envjs.profile){
/**
* CSS2Properties
*/
window.$profiler.around({ target: CSS2Properties, method:"getPropertyCSSValue"}, function(invocation) {
return __profile__("CSS2Properties.getPropertyCSSValue", invocation);
});
window.$profiler.around({ target: CSS2Properties, method:"getPropertyPriority"}, function(invocation) {
return __profile__("CSS2Properties.getPropertyPriority", invocation);
});
window.$profiler.around({ target: CSS2Properties, method:"getPropertyValue"}, function(invocation) {
return __profile__("CSS2Properties.getPropertyValue", invocation);
});
window.$profiler.around({ target: CSS2Properties, method:"item"}, function(invocation) {
return __profile__("CSS2Properties.item", invocation);
});
window.$profiler.around({ target: CSS2Properties, method:"removeProperty"}, function(invocation) {
return __profile__("CSS2Properties.removeProperty", invocation);
});
window.$profiler.around({ target: CSS2Properties, method:"setProperty"}, function(invocation) {
return __profile__("CSS2Properties.setProperty", invocation);
});
window.$profiler.around({ target: CSS2Properties, method:"toString"}, function(invocation) {
return __profile__("CSS2Properties.toString", invocation);
});
/**
* DOMNode
*/
window.$profiler.around({ target: DOMNode, method:"hasAttributes"}, function(invocation) {
return __profile__("DOMNode.hasAttributes", invocation);
});
window.$profiler.around({ target: DOMNode, method:"insertBefore"}, function(invocation) {
return __profile__("DOMNode.insertBefore", invocation);
});
window.$profiler.around({ target: DOMNode, method:"replaceChild"}, function(invocation) {
return __profile__("DOMNode.replaceChild", invocation);
});
window.$profiler.around({ target: DOMNode, method:"removeChild"}, function(invocation) {
return __profile__("DOMNode.removeChild", invocation);
});
window.$profiler.around({ target: DOMNode, method:"replaceChild"}, function(invocation) {
return __profile__("DOMNode.replaceChild", invocation);
});
window.$profiler.around({ target: DOMNode, method:"appendChild"}, function(invocation) {
return __profile__("DOMNode.appendChild", invocation);
});
window.$profiler.around({ target: DOMNode, method:"hasChildNodes"}, function(invocation) {
return __profile__("DOMNode.hasChildNodes", invocation);
});
window.$profiler.around({ target: DOMNode, method:"cloneNode"}, function(invocation) {
return __profile__("DOMNode.cloneNode", invocation);
});
window.$profiler.around({ target: DOMNode, method:"normalize"}, function(invocation) {
return __profile__("DOMNode.normalize", invocation);
});
window.$profiler.around({ target: DOMNode, method:"isSupported"}, function(invocation) {
return __profile__("DOMNode.isSupported", invocation);
});
window.$profiler.around({ target: DOMNode, method:"getElementsByTagName"}, function(invocation) {
return __profile__("DOMNode.getElementsByTagName", invocation);
});
window.$profiler.around({ target: DOMNode, method:"getElementsByTagNameNS"}, function(invocation) {
return __profile__("DOMNode.getElementsByTagNameNS", invocation);
});
window.$profiler.around({ target: DOMNode, method:"importNode"}, function(invocation) {
return __profile__("DOMNode.importNode", invocation);
});
window.$profiler.around({ target: DOMNode, method:"contains"}, function(invocation) {
return __profile__("DOMNode.contains", invocation);
});
window.$profiler.around({ target: DOMNode, method:"compareDocumentPosition"}, function(invocation) {
return __profile__("DOMNode.compareDocumentPosition", invocation);
});
/**
* DOMDocument
*/
window.$profiler.around({ target: DOMDocument, method:"addEventListener"}, function(invocation) {
return __profile__("DOMDocument.addEventListener", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"removeEventListener"}, function(invocation) {
return __profile__("DOMDocument.removeEventListener", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"attachEvent"}, function(invocation) {
return __profile__("DOMDocument.attachEvent", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"detachEvent"}, function(invocation) {
return __profile__("DOMDocument.detachEvent", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"dispatchEvent"}, function(invocation) {
return __profile__("DOMDocument.dispatchEvent", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"loadXML"}, function(invocation) {
return __profile__("DOMDocument.loadXML", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"load"}, function(invocation) {
return __profile__("DOMDocument.load", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createEvent"}, function(invocation) {
return __profile__("DOMDocument.createEvent", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createExpression"}, function(invocation) {
return __profile__("DOMDocument.createExpression", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createElement"}, function(invocation) {
return __profile__("DOMDocument.createElement", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createDocumentFragment"}, function(invocation) {
return __profile__("DOMDocument.createDocumentFragment", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createTextNode"}, function(invocation) {
return __profile__("DOMDocument.createTextNode", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createComment"}, function(invocation) {
return __profile__("DOMDocument.createComment", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createCDATASection"}, function(invocation) {
return __profile__("DOMDocument.createCDATASection", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createProcessingInstruction"}, function(invocation) {
return __profile__("DOMDocument.createProcessingInstruction", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createAttribute"}, function(invocation) {
return __profile__("DOMDocument.createAttribute", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createElementNS"}, function(invocation) {
return __profile__("DOMDocument.createElementNS", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createAttributeNS"}, function(invocation) {
return __profile__("DOMDocument.createAttributeNS", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"createNamespace"}, function(invocation) {
return __profile__("DOMDocument.createNamespace", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"getElementById"}, function(invocation) {
return __profile__("DOMDocument.getElementById", invocation);
});
window.$profiler.around({ target: DOMDocument, method:"normalizeDocument"}, function(invocation) {
return __profile__("DOMDocument.normalizeDocument", invocation);
});
/**
* HTMLDocument
*/
window.$profiler.around({ target: HTMLDocument, method:"createElement"}, function(invocation) {
return __profile__("HTMLDocument.createElement", invocation);
});
/**
* DOMParser
*/
window.$profiler.around({ target: DOMParser, method:"parseFromString"}, function(invocation) {
return __profile__("DOMParser.parseFromString", invocation);
});
/**
* DOMNodeList
*/
window.$profiler.around({ target: DOMNodeList, method:"item"}, function(invocation) {
return __profile__("DOMNode.item", invocation);
});
window.$profiler.around({ target: DOMNodeList, method:"toString"}, function(invocation) {
return __profile__("DOMNode.toString", invocation);
});
/**
* XMLP
*/
window.$profiler.around({ target: XMLP, method:"_addAttribute"}, function(invocation) {
return __profile__("XMLP._addAttribute", invocation);
});
window.$profiler.around({ target: XMLP, method:"_checkStructure"}, function(invocation) {
return __profile__("XMLP._checkStructure", invocation);
});
window.$profiler.around({ target: XMLP, method:"_clearAttributes"}, function(invocation) {
return __profile__("XMLP._clearAttributes", invocation);
});
window.$profiler.around({ target: XMLP, method:"_findAttributeIndex"}, function(invocation) {
return __profile__("XMLP._findAttributeIndex", invocation);
});
window.$profiler.around({ target: XMLP, method:"getAttributeCount"}, function(invocation) {
return __profile__("XMLP.getAttributeCount", invocation);
});
window.$profiler.around({ target: XMLP, method:"getAttributeName"}, function(invocation) {
return __profile__("XMLP.getAttributeName", invocation);
});
window.$profiler.around({ target: XMLP, method:"getAttributeValue"}, function(invocation) {
return __profile__("XMLP.getAttributeValue", invocation);
});
window.$profiler.around({ target: XMLP, method:"getAttributeValueByName"}, function(invocation) {
return __profile__("XMLP.getAttributeValueByName", invocation);
});
window.$profiler.around({ target: XMLP, method:"getColumnNumber"}, function(invocation) {
return __profile__("XMLP.getColumnNumber", invocation);
});
window.$profiler.around({ target: XMLP, method:"getContentBegin"}, function(invocation) {
return __profile__("XMLP.getContentBegin", invocation);
});
window.$profiler.around({ target: XMLP, method:"getContentEnd"}, function(invocation) {
return __profile__("XMLP.getContentEnd", invocation);
});
window.$profiler.around({ target: XMLP, method:"getLineNumber"}, function(invocation) {
return __profile__("XMLP.getLineNumber", invocation);
});
window.$profiler.around({ target: XMLP, method:"getName"}, function(invocation) {
return __profile__("XMLP.getName", invocation);
});
window.$profiler.around({ target: XMLP, method:"next"}, function(invocation) {
return __profile__("XMLP.next", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parse"}, function(invocation) {
return __profile__("XMLP._parse", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parse"}, function(invocation) {
return __profile__("XMLP._parse", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseAttribute"}, function(invocation) {
return __profile__("XMLP._parseAttribute", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseCDATA"}, function(invocation) {
return __profile__("XMLP._parseCDATA", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseComment"}, function(invocation) {
return __profile__("XMLP._parseComment", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseDTD"}, function(invocation) {
return __profile__("XMLP._parseDTD", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseElement"}, function(invocation) {
return __profile__("XMLP._parseElement", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseEntity"}, function(invocation) {
return __profile__("XMLP._parseEntity", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parsePI"}, function(invocation) {
return __profile__("XMLP._parsePI", invocation);
});
window.$profiler.around({ target: XMLP, method:"_parseText"}, function(invocation) {
return __profile__("XMLP._parseText", invocation);
});
window.$profiler.around({ target: XMLP, method:"_replaceEntities"}, function(invocation) {
return __profile__("XMLP._replaceEntities", invocation);
});
window.$profiler.around({ target: XMLP, method:"_replaceEntity"}, function(invocation) {
return __profile__("XMLP._replaceEntity", invocation);
});
window.$profiler.around({ target: XMLP, method:"_setContent"}, function(invocation) {
return __profile__("XMLP._setContent", invocation);
});
window.$profiler.around({ target: XMLP, method:"_setErr"}, function(invocation) {
return __profile__("XMLP._setErr", invocation);
});
/**
* SAXDriver
*/
window.$profiler.around({ target: SAXDriver, method:"parse"}, function(invocation) {
return __profile__("SAXDriver.parse", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"setDocumentHandler"}, function(invocation) {
return __profile__("SAXDriver.setDocumentHandler", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"setErrorHandler"}, function(invocation) {
return __profile__("SAXDriver.setErrorHandler", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"setLexicalHandler"}, function(invocation) {
return __profile__("SAXDriver.setLexicalHandler", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getColumnNumber"}, function(invocation) {
return __profile__("SAXDriver.getColumnNumber", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getLineNumber"}, function(invocation) {
return __profile__("SAXDriver.getLineNumber", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getMessage"}, function(invocation) {
return __profile__("SAXDriver.getMessage", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getPublicId"}, function(invocation) {
return __profile__("SAXDriver.getPublicId", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getSystemId"}, function(invocation) {
return __profile__("SAXDriver.getSystemId", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getLength"}, function(invocation) {
return __profile__("SAXDriver.getLength", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getName"}, function(invocation) {
return __profile__("SAXDriver.getName", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getValue"}, function(invocation) {
return __profile__("SAXDriver.getValue", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"getValueByName"}, function(invocation) {
return __profile__("SAXDriver.getValueByName", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"_fireError"}, function(invocation) {
return __profile__("SAXDriver._fireError", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"_fireEvent"}, function(invocation) {
return __profile__("SAXDriver._fireEvent", invocation);
});
window.$profiler.around({ target: SAXDriver, method:"_parseLoop"}, function(invocation) {
return __profile__("SAXDriver._parseLoop", invocation);
});
/**
* SAXStrings
*/
window.$profiler.around({ target: SAXStrings, method:"getColumnNumber"}, function(invocation) {
return __profile__("SAXStrings.getColumnNumber", invocation);
});
window.$profiler.around({ target: SAXStrings, method:"getLineNumber"}, function(invocation) {
return __profile__("SAXStrings.getLineNumber", invocation);
});
window.$profiler.around({ target: SAXStrings, method:"indexOfNonWhitespace"}, function(invocation) {
return __profile__("SAXStrings.indexOfNonWhitespace", invocation);
});
window.$profiler.around({ target: SAXStrings, method:"indexOfWhitespace"}, function(invocation) {
return __profile__("SAXStrings.indexOfWhitespace", invocation);
});
window.$profiler.around({ target: SAXStrings, method:"isEmpty"}, function(invocation) {
return __profile__("SAXStrings.isEmpty", invocation);
});
window.$profiler.around({ target: SAXStrings, method:"lastIndexOfNonWhitespace"}, function(invocation) {
return __profile__("SAXStrings.lastIndexOfNonWhitespace", invocation);
});
window.$profiler.around({ target: SAXStrings, method:"replace"}, function(invocation) {
return __profile__("SAXStrings.replace", invocation);
});
/**
* Stack - SAX Utility
window.$profiler.around({ target: Stack, method:"clear"}, function(invocation) {
return __profile__("Stack.clear", invocation);
});
window.$profiler.around({ target: Stack, method:"count"}, function(invocation) {
return __profile__("Stack.count", invocation);
});
window.$profiler.around({ target: Stack, method:"destroy"}, function(invocation) {
return __profile__("Stack.destroy", invocation);
});
window.$profiler.around({ target: Stack, method:"peek"}, function(invocation) {
return __profile__("Stack.peek", invocation);
});
window.$profiler.around({ target: Stack, method:"pop"}, function(invocation) {
return __profile__("Stack.pop", invocation);
});
window.$profiler.around({ target: Stack, method:"push"}, function(invocation) {
return __profile__("Stack.push", invocation);
});
*/
}
/*
* document.js
*
* DOM Level 2 /DOM level 3 (partial)
*
* This file adds the document object to the window and allows you
* you to set the window.document using an html string or dom object.
*
*/
// read only reference to the Document object
$debug("Initializing window.document.");
var $async = false;
__extend__(HTMLDocument.prototype, {
get async(){ return $async;},
set async(async){ $async = async; },
get baseURI(){ return $env.location('./'); },
get URL(){ return $w.location.href; }
});
var $document = new HTMLDocument($implementation);
$w.__defineGetter__("document", function(){
return $document;
});
$debug("Defining document.cookie");
/*
* cookie.js
* - requires env
*/
var $cookies = {
persistent:{
//domain - key on domain name {
//path - key on path {
//name - key on name {
//value : cookie value
//other cookie properties
//}
//}
//}
//expire - provides a timestamp for expiring the cookie
//cookie - the cookie!
},
temporary:{//transient is a reserved word :(
//like above
}
};
//HTMLDocument cookie
document.__defineSetter__("cookie", function(cookie){
var i,name,value,properties = {},attr,attrs = cookie.split(";");
//for now the strategy is to simply create a json object
//and post it to a file in the .cookies.js file. I hate parsing
//dates so I decided not to implement support for 'expires'
//(which is deprecated) and instead focus on the easier 'max-age'
//(which succeeds 'expires')
cookie = {};//keyword properties of the cookie
for(i=0;i<attrs.length;i++){
attr = attrs[i].split("=");
if(attr.length > 0){
name = trim(attr[0]);
value = trim(attr[1]);
if(name=='max-age'){
//we'll have to set a timer to check these
//and garbage collect expired cookies
cookie[name] = parseInt(value, 10);
} else if(name=='domain'){
if(domainValid(value)){
cookie['domain']=value;
}else{
cookie['domain']=$w.location.domain;
}
} else if(name=='path'){
//not sure of any special logic for path
cookie['path'] = value;
} else {
//its not a cookie keyword so store it in our array of properties
//and we'll serialize individually in a moment
properties[name] = value;
}
}else{
if(attr[0] == 'secure'){
cookie[attr[0]] = true;
}
}
}
if(!cookie['max-age']){
//it's a transient cookie so it only lasts as long as
//the window.location remains the same
mergeCookie($cookies.temporary, cookie, properties);
}else if(cookie['max-age']===0){
//delete the cookies
//TODO
}else{
//the cookie is persistent
mergeCookie($cookies.persistent, cookie, properties);
persistCookies();
}
});
document.__defineGetter__("cookie", function(c){
//The cookies that are returned must belong to the same domain
//and be at or below the current window.location.path. Also
//we must check to see if the cookie was set to 'secure' in which
//case we must check our current location.protocol to make sure it's
//https:
var allcookies = [], i;
//TODO
});
var domainValid = function(domain){
//make sure the domain
//TODO
};
var mergeCookie = function(target, cookie, properties){
var name, now;
if(!target[cookie.domain]){
target[cookie.domain] = {};
}
if(!target[cookie.domain][cookie.path]){
target[cookie.domain][cookie.path] = {};
}
for(name in properties){
now = new Date().getTime();
target[cookie.domain][cookie.path][name] = {
value:properties[name],
"@env:secure":cookie.secure,
"@env:max-age":cookie['max-age'],
"@env:date-created":now,
"@env:expiration":now + cookie['max-age']
};
}
};
var persistCookies = function(){
//TODO
//I think it should be done via $env so it can be customized
};
var loadCookies = function(){
//TODO
//should also be configurable via $env
};
//We simply use the default ajax get to load the .cookies.js file
//if it doesn't exist we create it with a post. Cookies are maintained
//in memory, but serialized with each set.
$info("Loading Cookies");
try{
//TODO - load cookies
loadCookies();
}catch(e){
//TODO - fail gracefully
}
/*
* outro.js
*/
})(window, Envjs);
}catch(e){
Envjs.error("ERROR LOADING ENV : " + e + "\nLINE SOURCE:\n" + Envjs.lineSource(e));
}