/** * @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, { add: function(name){ this[this.length] = name; }, 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.toLowerCase()] = arg; } } else { // add new NamedNode Array.prototype.push.apply(this, [arg]); this[arg.name.toLowerCase()] = 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 this[arg.name.toLowerCase()] = arg; } }else { // add new NamedNode Array.prototype.push.apply(this, [arg]); this[arg.name.toLowerCase()] = 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 * @return : int */ var __findNamedItemIndex__ = function(namednodemap, name) { var ret = -1; // loop through all nodes for (var i=0; i -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) { var cloneNamedNodeMap = namednodemap.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, []); this.isnsmap = true; }; 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; } }); // Local Variables: // espresso-indent-level:4 // c-basic-offset:4 // tab-width:4 // End: