You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by jm...@apache.org on 2007/03/02 23:47:35 UTC
svn commit: r514021 - in /incubator/xap/trunk/codebase/src/xap/xml/dom:
Document.js XapElement.js
Author: jmargaris
Date: Fri Mar 2 15:47:34 2007
New Revision: 514021
URL: http://svn.apache.org/viewvc?view=rev&rev=514021
Log:
patched in changes from Michael M
Modified:
incubator/xap/trunk/codebase/src/xap/xml/dom/Document.js
incubator/xap/trunk/codebase/src/xap/xml/dom/XapElement.js
Modified: incubator/xap/trunk/codebase/src/xap/xml/dom/Document.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/dom/Document.js?view=diff&rev=514021&r1=514020&r2=514021
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/dom/Document.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/dom/Document.js Fri Mar 2 15:47:34 2007
@@ -32,21 +32,16 @@
* Conceptually, it is the root of the document tree, and provides the
* primary access to the document's data.
*
- * @author ikaplansky
- * @author jmargaris
- *
* @see xap.xml.dom.XapElement
*/
/**
* Creates a xap.xml.dom.Document instance.
* @extends google.XDocument
- * @class The xap.xml.dom.Document object represents an entire XML document. Conceptually, it
- * is the root of the document tree, and provides the primary access to the
+ * @class The xap.xml.dom.Document object represents an entire XML document.
+ * Conceptually, it is the root of the document tree, and provides the primary access to the
* document's data.
*
- * <br><br>
- *
* Listeners may be registered at the xap.xml.dom.Document level to hear changes
* in the entire document.
*
@@ -64,7 +59,8 @@
* @param rootElement The root Element for the newly created document.
*/
xap.xml.dom.Document = function( rootElement ) {
- google.XDocument.call(this);
+
+ google.XDocument.call(this);
this._rootElement = rootElement;
this._structureChangeListeners = [];
@@ -72,21 +68,16 @@
this._idToElementMap = {};
this._prefixToNamespaceMap = {};
-}
+};
-xap.xml.dom.Document.prototype = new google.XDocument();
+xap.xml.dom.Document.prototype = new google.XDocument();
-//-----------------------------------------------------------------------
-// Constants.
-//-----------------------------------------------------------------------
/** @private */
xap.xml.dom.Document.XML_DECL_WITHOUT_ENC = "<?xml version=\"1.0\"?>";
-//-----------------------------------------------------------------------
-// xap.xml.dom.Document Interface.
-//-----------------------------------------------------------------------
+
/**
* Creates a new xap.xml.dom.XapElement with the specified name, prefix and namespace.
*
@@ -98,7 +89,7 @@
if( !localName ) {
throw new xap.xml.InvalidXmlException(
xap.xml.InvalidXmlException.NULL_LOCALNAME_MSGID,
- new Array( "xap.xml.dom.Document.createElement" ));
+ [ "xap.xml.dom.Document.createElement" ] );
}
//note we are passing in NO owner doc here! only is set when node actually
@@ -110,14 +101,16 @@
e._setNamespaceUri( ns ? ns : "" );
e._setPrefix( prefix );
return e;
-}
+};
+
/**
+ *
* @return The root xap.xml.dom.XapElement of this xap.xml.dom.Document
*/
xap.xml.dom.Document.prototype.getRootElement = function() {
return this._rootElement;
-}
+};
/**
@@ -126,7 +119,8 @@
*/
xap.xml.dom.Document.prototype.addAttributeChangeListener = function( listener ) {
this._attributeChangeListeners.push( listener );
-}
+};
+
/**
* Removes the specified xap.xml.dom.events.AttributeChangeListener
@@ -134,7 +128,8 @@
*/
xap.xml.dom.Document.prototype.removeAttributeChangeListener = function( listener ) {
return xap.util.ArrayHelper.removeElement(this._attributeChangeListeners, listener);
-}
+};
+
/**
* Adds a xap.xml.dom.events.StructureChangeListener to this xap.xml.dom.Document
@@ -142,7 +137,8 @@
*/
xap.xml.dom.Document.prototype.addStructureChangeListener = function( listener ) {
this._structureChangeListeners.push( listener );
-}
+};
+
/**
* Removes the specified xap.xml.dom.events.StructureChangeListener from this xap.xml.dom.Document.
@@ -150,7 +146,8 @@
*/
xap.xml.dom.Document.prototype.removeStructureChangeListener = function( listener ) {
return xap.util.ArrayHelper.removeElement(this._structureChangeListeners, listener);
-}
+};
+
/**
* Returns the xap.xml.dom.XapElement with the specified id attribute value. The xap.xml.dom.Document
@@ -160,7 +157,8 @@
*/
xap.xml.dom.Document.prototype.getElementById = function( id ) {
return this._idToElementMap[id];
-}
+};
+
/**
* Sets the root xap.xml.dom.XapElement on this xap.xml.dom.Document
@@ -184,12 +182,9 @@
if ( root) {
var event = new xap.xml.dom.events.StructureChangeEvent( null, root );
-
- this._notifyListenersOfStructureChange
- ( this._structureChangeListeners, event, 'beforeChildAdded' );
+ this._notifyListenersOfStructureChange( this._structureChangeListeners, event, 'beforeChildAdded' );
-
// Take the element from the event because they have the
// opportunity to change the element in the event. It is safe to
// cast here because the event itself guarantees that root element
@@ -198,8 +193,7 @@
this._rootElement = event.getChange();
if ( this._rootElement.getParent() ) {
- // remove the to-be root from its current parent and owner
- // document.
+ // remove the to-be root from its current parent and owner document.
this._rootElement.getParent().removeChild( this._rootElement );
}
@@ -216,14 +210,13 @@
this._addDocumentFragmentToIdMapAndCheckForPrefixCollisions( this._rootElement );
- this._notifyListenersOfStructureChange(
- this._structureChangeListeners, event, 'onChildAdded');
-
+ this._notifyListenersOfStructureChange(this._structureChangeListeners, event, 'onChildAdded');
- } else {
+ } else {
this._rootElement = null;
}
-}
+};
+
/**
* Returns an XML string representation of this xap.xml.dom.Document.
@@ -233,7 +226,8 @@
*/
xap.xml.dom.Document.prototype.toXml = function( prettyPrint ) {
return this._toStringHelper( prettyPrint, true );
-}
+};
+
/**
* Returns an XML string representation of this xap.xml.dom.Document omitting all auto
@@ -244,134 +238,158 @@
*/
xap.xml.dom.Document.prototype.toXmlWithoutAutoAssignedIds = function( prettyPrint ) {
return this._toStringHelper( prettyPrint, false );
-}
+};
+
/**
* @return The string representation of this xap.xml.dom.Document object.
*/
xap.xml.dom.Document.prototype.toString = function() {
return this._toStringHelper( true, false );
-}
+};
-
-//-----------------------------------------------------------------------
-// Private Methods
-//-----------------------------------------------------------------------
/**
+ * Update fragment after adding to this Document
* @private
+ * @param {XapElement} e Element to be added to this document
*/
xap.xml.dom.Document.prototype._addDocumentFragmentToIdMapAndCheckForPrefixCollisions = function( e ) {
+
e.ownerDocument = this;
this._addIdToElementMapping( e.getAttribute( "id" ), e );
this._checkPrefixForCollisionAndRegister( e );
e._notifyListenersOnAddedToDocument( this );
- for( var i=0; i < e.childNodes.length; i++ ) {
+
+ // update all children recursively
+ for( var i = 0; i < e.childNodes.length; i++ ) {
var o = e.childNodes[i];
if (o.nodeType==google.DOM_ELEMENT_NODE){
this._addDocumentFragmentToIdMapAndCheckForPrefixCollisions( o );
}
}
-}
+};
+
/**
+ * Update fragment after removing from this Document
+ *
* @private
+ * @param {XapElement} e Element to be removed from this document
*/
xap.xml.dom.Document.prototype._removeDocumentFragmentFromIdMap = function( e ) {
delete e.ownerDocument;
delete (this._idToElementMap[e.getAttribute( "id" )]);
e._notifyListenersOnRemovedFromDocument( this );
- for( var i=0; i < e.childNodes.length; i++ ) {
+
+ // update all children recursively
+ for( var i = 0; i < e.childNodes.length; i++ ) {
var o = e.childNodes[i];
if (o.nodeType==google.DOM_ELEMENT_NODE){
this._removeDocumentFragmentFromIdMap( o );
}
}
-}
+};
/**
+ * Remove root Element (if any) fron this Document
+ *
* @private
*/
xap.xml.dom.Document.prototype._removeExistingRoot = function() {
if ( this._rootElement ) {
var event = new xap.xml.dom.events.StructureChangeEvent( null, this._rootElement );
- this._notifyListenersOfStructureChange
- ( this._structureChangeListeners, 'beforeChildRemoved' );
+ this._notifyListenersOfStructureChange( this._structureChangeListeners, 'beforeChildRemoved' );
this.removeChild(this._rootElement);
+
this._removeDocumentFragmentFromIdMap( this._rootElement );
- this._notifyListenersOfStructureChange
- ( this._structureChangeListeners, event, 'onChildRemoved' );
-
+ this._notifyListenersOfStructureChange( this._structureChangeListeners, event, 'onChildRemoved' );
}
-}
+};
+
/**
+ * Notifies all registered Listeners
+ *
* @private
+ * @param listeners An array of registered listeneres
+ * @param event Change event object
+ * @param {String} method An onXXX event name
*/
-xap.xml.dom.Document.prototype._notifyListenersOfStructureChange = function( v, e, method ) {
- if ( v ) {
- for ( var i = 0; i < v.length; i ++ ) {
- var listener = v[i];
+xap.xml.dom.Document.prototype._notifyListenersOfStructureChange = function( listeners, event, method ) {
+ if ( listeners ) {
+ for ( var i = 0; i < listeners.length; i ++ ) {
+ var listener = listeners[i];
//if the listener has that callback method, call it.
if (listener[method]){
- listener[method].call(listener,e);
+ listener[method].call(listener, event);
// Handle the case where the event causes the
// listener to remove itself.
- if ( v[i] != listener ) {
- i = i - 1;
- }
+ if ( listeners[i] != listener ) { i = i - 1; }
}
-
- }
+ } // end for()
}
-}
+};
+
/**
+ * Adds an element to the id-element map
+ *
* @private
+ * @param {String} id An Element's Id
+ * @param e An element object
*/
-xap.xml.dom.Document.prototype._addIdToElementMapping = function( id, e ) {
+xap.xml.dom.Document.prototype._addIdToElementMapping = function( id, element ) {
if( this._idToElementMap[id] ) {
throw new xap.xml.InvalidXmlException(
xap.xml.InvalidXmlException.ID_CONFLICT_MSGID,
- [id, e.toXml(), this._idToElementMap[id].toXml()]);
+ [id, element.toXml(), this._idToElementMap[id].toXml()]);
}
- this._idToElementMap[id] = e;
-}
+ this._idToElementMap[id] = element;
+};
+
/**
+ * Registers a new NS prefix
+ *
* @private
+ * @param element An element to check
+ * @throw xap.xml.InvalidXmlException
*/
-xap.xml.dom.Document.prototype._checkPrefixForCollisionAndRegister = function( e ) {
- if( !e.getPrefix()) {
- return;
- }
- if( this._prefixToNamespaceMap[e.getPrefix()]) {
- var currentNs = this._prefixToNamespaceMap[e.getPrefix()];
- var newNs = e.getNamespaceUri();
+xap.xml.dom.Document.prototype._checkPrefixForCollisionAndRegister = function( element ) {
+
+ if( !element.getPrefix()) { return; }
+
+ if( this._prefixToNamespaceMap[element.getPrefix()]) {
+ var currentNs = this._prefixToNamespaceMap[element.getPrefix()];
+ var newNs = element.getNamespaceUri();
if( currentNs != newNs ) {
throw new xap.xml.InvalidXmlException(
xap.xml.InvalidXmlException.PREFIX_CONFLICT_MSGID,
- new Array( e.getPrefix(),
- currentNs,
- e.getPrefix(),
- newNs ));
+ [ element.getPrefix(), currentNs, element.getPrefix(), newNs ]);
}
} else {
- this._prefixToNamespaceMap[e.getPrefix()] = e.getNamespaceUri();
+ this._prefixToNamespaceMap[element.getPrefix()] = element.getNamespaceUri();
}
-}
+};
+
/**
+ *
+ * Converts an XML fragmment to string
+ *
* @private
+ * @param prettyPrint If we need to add new lines to the output
+ * @param withInternalIds If we need to output internal ids as well
*/
xap.xml.dom.Document.prototype._toStringHelper = function( prettyPrint, withInternalIds ) {
- var elementOutput = "";
+ var elementOutput = '';
if( this._rootElement ) {
if( withInternalIds ) {
elementOutput = this._rootElement.toXml( prettyPrint );
@@ -381,11 +399,12 @@
}
}
var sbuf = xap.xml.dom.Document.XML_DECL_WITHOUT_ENC;
- if( prettyPrint ) {
- sbuf += "\n";
- }
+
+ if( prettyPrint ) { sbuf += '\n'; }
+
// append the toXml of the root element.s
sbuf += elementOutput;
+
return sbuf;
-}
+};
Modified: incubator/xap/trunk/codebase/src/xap/xml/dom/XapElement.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/dom/XapElement.js?view=diff&rev=514021&r1=514020&r2=514021
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/dom/XapElement.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/dom/XapElement.js Fri Mar 2 15:47:34 2007
@@ -32,9 +32,6 @@
* @fileoverview An DOM element node implementation that supports
* notification of changes.
*
- * @author ikaplansky
- * @author jmargaris
- *
*/
@@ -56,9 +53,10 @@
* @param id The id attribute to use for the new xap.xml.dom.XapElement
*
*/
-xap.xml.dom.XapElement = function(elementName, ownerDoc, parentEl, id ){
+xap.xml.dom.XapElement = function( elementName, ownerDoc, parentEl, id ) {
- google.XNode.call(this, google.DOM_ELEMENT_NODE, elementName, null, ownerDoc)
+ // params: nodeType, nodeName, nodeValue, ownerDocument
+ google.XNode.call(this, google.DOM_ELEMENT_NODE, elementName, null, ownerDoc);
this._namespaceUri = null;
this._prefix = null;
@@ -74,9 +72,9 @@
this.setAttribute( "id", id );
}
else{
- this.setAttribute( "id",xap.util.UidProvider.createId() );
+ this.setAttribute( "id", xap.util.UidProvider.createId() );
}
-}
+};
xap.xml.dom.XapElement.prototype = new google.XNode();
@@ -84,11 +82,6 @@
xap.xml.dom.XapElement.prototype.constructor = xap.xml.dom.XapElement ;
-
-//-----------------------------------------------------------------------
-// Private Constants.
-//-----------------------------------------------------------------------
-
/** @private */
xap.xml.dom.XapElement.CANNOT_SET_ID_ATTRIBUTE_WHEN_PART_OF_DOCUMENT = "cannotSetIdAttributeWhenPartOfOwnerDocument";
@@ -104,9 +97,6 @@
/** @private */
xap.xml.dom.XapElement.s_log = xap.log.Logger.getLogger( "xap.xml.dom.DocumentObjectModel" );
-//-----------------------------------------------------------------------
-// Public Class Methods.
-//-----------------------------------------------------------------------
/**
* Returns true if the ID was a system generated one rather than
@@ -114,36 +104,27 @@
*/
xap.xml.dom.XapElement.isGeneratedId = function( id ) {
return ( id && id.indexOf( xap.util.UidProvider.XAP_ID_PREFIX, 0 ) != -1 );
-}
-
-
-
-//-----------------------------------------------------------------------
-// Private Class Methods.
-//-----------------------------------------------------------------------
+};
/** Appends this class' indentation string to a prexisting string:
- * @param{int} indent The indentation level.
- * @param{Swtring}sbuf The string to which to append the indentation.
+ * @param {int} indent The indentation level.
+ * @param {String} sbuf The string to which to append the indentation.
* @see xap.xml.dom.XapElement.INDENT
- * @private
+ * @private
**/
xap.xml.dom.XapElement._writeIndent = function ( sbuf, indent ) {
for ( var i = 0; i < indent; i++ ) {
sbuf += xap.xml.dom.XapElement.INDENT;
}
-}
-
+};
-//-----------------------------------------------------------------------
-// Public Methods.
-//-----------------------------------------------------------------------
-
/**
* Returns the attribute interpreted as a url. That url will be properly
* qualified based on information stored within this element and attribute.
+ * @param name {String} Attribute name
+ * @return //TODO why do we need it?
*/
xap.xml.dom.XapElement.prototype.getAttributeAsUrl = function( name ) {
var att = null;
@@ -154,26 +135,25 @@
}
}
- if (att==null){
+ if (att === null){
return null;
}
var attValue = att.nodeValue;
-
var baseUrl = att.baseUrl;
- baseUrl = baseUrl || this.baseUrl;
- baseUrl = baseUrl || "";
+ baseUrl = baseUrl || this.baseUrl || "";
return (baseUrl + attValue);
-}
+};
/**
* Sets an attribute with the given name to the given value.
* @param{String} name The name of the attribute to set
* @param{String} value The value of the attribute to set
+ * @param{String} baseUrl The base URL of the attribute to set
*/
-xap.xml.dom.XapElement.prototype.setAttribute = function(name, value, baseUrl){
+xap.xml.dom.XapElement.prototype.setAttribute = function(name, value, baseUrl) {
//NOTE this is tricky because NULL values are not ok but "" is ok...
//TODO clean this up and check for NULL/UNDEF better
@@ -183,70 +163,76 @@
//flag that indicates if we are setting the id att
if( "id" == name ) {
if ( doc ) {
- throw new xap.util.Exception
- ( xap.util.ResourceDictionary.getMessage
- ( xap.xml.dom.XapElement.CANNOT_SET_ID_ATTRIBUTE_WHEN_PART_OF_DOCUMENT,
+ throw new xap.util.Exception( xap.util.ResourceDictionary.getMessage(
+ xap.xml.dom.XapElement.CANNOT_SET_ID_ATTRIBUTE_WHEN_PART_OF_DOCUMENT,
xap.xml.dom.XapElement.CLASSNAME ) );
}
}
- var event = null;
- var attributeChangeListenersExist =
- this._doAnyAttributeChangeListenersExist( doc );
- if ( attributeChangeListenersExist ) {
- event = new xap.xml.dom.events.AttributeChangeEvent( this, name, value );
+ if ( this._doAnyAttributeChangeListenersExist( doc ) ) {
+
+ var event = new xap.xml.dom.events.AttributeChangeEvent( this, name, value );
this._fireAttributeChangeEvent( doc, event, 'beforeAttributeSet');
+
// Listeners have the opportunity to modify the value.
// Make sure we get the latest value out of the event.
value = event.getNewValue();
- if ( value == null ) {
- throw new xap.xml.dom.events.ChangeRejectedException
- ( xap.xml.dom.events.ChangeRejectedException.CHANGE_ATTRIBUTE_TO_NULL_MSGID,
- null, null, event );
+
+ if ( value === null ) {
+ throw new xap.xml.dom.events.ChangeRejectedException(
+ xap.xml.dom.events.ChangeRejectedException.CHANGE_ATTRIBUTE_TO_NULL_MSGID, null, null, event );
}
- }
-
- if ( attributeChangeListenersExist ) {
- event.setNewValue( value );
- }
-
- google.XNode.prototype.setAttribute.call(this, name, value, baseUrl);
-
- if ( attributeChangeListenersExist ) {
+
+ event.setNewValue( value );
+
+ google.XNode.prototype.setAttribute.call(this, name, value, baseUrl);
+
this._fireAttributeChangeEvent( doc, event, 'onAttributeSet');
- }
-}
+
+ } else {
+
+ // just set the new value
+ google.XNode.prototype.setAttribute.call(this, name, value, baseUrl);
+
+ }// end if ( attributeChangeListenersExist )
+
+
+}; // end xap.xml.dom.XapElement.prototype.setAttribute
+
/**
* Removes the attribute with the given name.
* @param {String} name The name of the attribute to remove.
*/
xap.xml.dom.XapElement.prototype.removeAttribute = function(name) {
+
var doc = this.ownerDocument;
- if (doc && name=="id"){
- throw "Can't change ID of element already in document";
+
+ if (doc && (name == "id") ){
+ throw new xap.util.Exception( xap.util.ResourceDictionary.getMessage(
+ xap.xml.dom.XapElement.CANNOT_SET_ID_ATTRIBUTE_WHEN_PART_OF_DOCUMENT,
+ xap.xml.dom.XapElement.CLASSNAME ) );
}
var event = new xap.xml.dom.events.AttributeChangeEvent(this, name, null);
this._fireAttributeChangeEvent( doc, event, 'beforeAttributeRemoved');
+
// Actually perform the removal:
google.XNode.prototype.removeAttribute.call(this, name);
this._fireAttributeChangeEvent( doc, event, 'onAttributeRemoved');
-
+
+ //IMPORTANT auto-assigning IDs should depend on the document type?
+ //for example data sources should have auto-assigned IDs?
// We never allow elements not to have IDs - if the id attribute tries
// to be removed - remove it then reset it with one of our IDs
-
- //IMPORTANT does this really make sense? shouldn't this be conditional on
- //the document type or something like that? Maybe when we add to a doc
- //that expects IDs we should assign them then instead of here?
- if ( "id" == name ) {
+ if ( name == "id" ) {
setAttribute( "id", xap.util.UidProvider.createId());
}
-
- return name;
-}
+
+}; // end xap.xml.dom.XapElement.prototype.removeAttribute
+
//TODO override replace child?
@@ -257,45 +243,50 @@
*/
xap.xml.dom.XapElement.prototype.insertBefore = function(newNode, oldNode) {
return this._insertBefore( newNode, oldNode );
-}
+};
+
+
/**
* Appends the given child to this element.
*
- * @param {google.XNode} child The child text or element node to append.
+ * @param {google.XNode} newNode The new child text or element node to append.
*/
-xap.xml.dom.XapElement.prototype.appendChild = function(child){
- return this._insertBefore( child );
-}
+xap.xml.dom.XapElement.prototype.appendChild = function(newNode){
+ return this._insertBefore( newNode, null );
+};
+
/**
* Inserts the new child newNode at the given index.
* @param {google.XNode} newChild The new child to insert.
* @param {int} index The index at which to insert the new child
+ * @return {google.XNode} newChild
*/
xap.xml.dom.XapElement.prototype.insertChildAt = function(index, newChild) {
- var nChildren = this.childNodes.length ;
+
+ var nChildren = this.childNodes.length;
+
if(index > nChildren){
var event = new xap.xml.dom.events.StructureChangeEvent(this, newChild, index);
throw new xap.xml.dom.events.ChangeRejectedException(
xap.xml.dom.events.ChangeRejectedException.REJECTED_WITH_REASON_MSGID,
- ["Attempted to insert at invalid index: "+index+"; last child is at nChildren"],
- null,
- event
- );
- }
+ ["Attempted to insert at invalid index: " + index + ", last child is at " + nChildren],
+ null, event);
+ }// end if()
+
// reduce to known cases:
- var result = null ;
+ var result = null;
+
if( index == nChildren){
// At the end:
result = this.appendChild(newChild) ;
} else {
- // This is a bit backwards, but at this
- // point I'd rather not (e.g.) just copy
- // most of the code from _insertBefore
result = this.insertBefore( newChild, this.childNodes[index] );
}
- return result ;
-}
+
+ return result;
+
+}; // end xap.xml.dom.XapElement.prototype.insertChildAt
@@ -303,22 +294,13 @@
* Removes the given child from this element.
*
* @param {google.XNode} child The child text or element node to remove.
+ * @return {google.XNode} removed child node or null
*/
-xap.xml.dom.XapElement.prototype.removeChild = function(child){
- var index = 0; //TODO fill in correctly
+xap.xml.dom.XapElement.prototype.removeChild = function(child) {
+
+ var index = xap.util.ArrayHelper.indexOf(this.childNodes, child);
- //TODO what if o is not a child?
- if(!child){
-// throw new xap.util.Exception
-// ( xap.util.ResourceDictionary.getMessage
-// ( CANNOT_REMOVE_NULL_CHILD, ElementImpl.class ) );
-// }
-//
-// int i = _children.indexOf(o);
-// if ( i == -1 ) {
-// return null;
- return null;
- }
+ if( (!child) || (index == -1) ) { return null; }
var doc = this.ownerDocument;
var structureChangeListenerExists = this._doAnyStructureChangeListenersExist( doc );
@@ -332,7 +314,7 @@
}
//make the actual change
- google.XNode.prototype.removeChild.call(this,child);
+ google.XNode.prototype.removeChild.call(this, child);
//if we are removing an element node we have to remove it from
//our ID map and clean up owner doc stuff
@@ -347,9 +329,11 @@
this._fireStructureChangeEvent( doc, event, 'onChildRemoved');
}
- //TODO child here could be changed by the before event?
return child;
-}
+
+};
+
+
/**
*
* For compatibility with existing code we don't consider
@@ -357,50 +341,49 @@
* We need to clean this up at some point
*/
xap.xml.dom.XapElement.prototype.getParent = function() {
- if (!this.parentNode) return null;
- if (this.parentNode.nodeType!=google.DOM_ELEMENT_NODE) return null;
+ if (!this.parentNode || (this.parentNode.nodeType != google.DOM_ELEMENT_NODE) ) {
+ return null;
+ }
+
return this.parentNode;
-}
+};
+
/**
* Returns the element namespace prefix
*/
xap.xml.dom.XapElement.prototype.getPrefix = function() {
return this._prefix;
-}
+};
+
/**
* Returns the namespace uri for the element.
*/
xap.xml.dom.XapElement.prototype.getNamespaceUri = function() {
return this._namespaceUri;
-}
+};
+
/**
- * TODO should we differentiate between local name
- * and nodeName? Technically we should but then xpath
- * needs to use localName instead of nodeName or
- * something like that?
+ * Returns node name for the element
*/
xap.xml.dom.XapElement.prototype.getLocalName = function() {
return this.nodeName;
-}
+};
+
/**
- * Returns an XML string representing this element
- * and all children.
+ * Returns an XML string representing this element and all children.
*
* @param prettyPrint If true print this in human-readable form with spacing.
*/
xap.xml.dom.XapElement.prototype.toXml = function ( prettyPrint ) {
var sbuf = "";
- sbuf = this._toStringHelper( this,
- sbuf,
- 0,
- prettyPrint,
- true );
+ this._toStringHelper( this, sbuf, 0, prettyPrint, true );
return sbuf;
-}
+};
+
/**
* Returns an XML string representing this element
@@ -410,13 +393,9 @@
*/
xap.xml.dom.XapElement.prototype.toXmlWithoutAutoAssignedIds = function( prettyPrint ) {
var sbuf = "";
- sbuf = this._toStringHelper( this,
- sbuf,
- 0,
- prettyPrint,
- false );
+ this._toStringHelper( this, sbuf, 0, prettyPrint, false );
return sbuf;
-}
+};
/**
@@ -429,7 +408,8 @@
*/
xap.xml.dom.XapElement.prototype.addAttributeChangeListener = function ( listener ) {
this._getAttributeChangeListeners().push( listener );
-}
+};
+
/**
* Removes an xap.xml.dom.events.AttributeChangeListener from the element.
@@ -440,7 +420,8 @@
*/
xap.xml.dom.XapElement.prototype.removeAttributeChangeListener = function( listener ) {
xap.util.ArrayHelper.removeElement( this._getAttributeChangeListeners(), listener );
-}
+};
+
/**
* Adds a xap.xml.dom.events.StructureChangeListener to the element. This listener
@@ -452,7 +433,8 @@
*/
xap.xml.dom.XapElement.prototype.addStructureChangeListener = function ( listener ) {
this._getStructureChangeListeners().push( listener );
-}
+};
+
/**
* Removes a xap.xml.dom.events.StructureChangeListener from the element.
@@ -463,7 +445,8 @@
*/
xap.xml.dom.XapElement.prototype.removeStructureChangeListener = function( listener ) {
xap.util.ArrayHelper.removeElement( this._getStructureChangeListeners(), listener );
-}
+};
+
/**
* Adds a xap.xml.dom.DocumentOwnershipListener to the element. This listener
@@ -475,7 +458,8 @@
*/
xap.xml.dom.XapElement.prototype.addDocumentOwnershipListener = function( listener ) {
this._getDocumentOwnershipListeners().push( listener );
-}
+};
+
/**
* Removes a xap.xml.dom.DocumentOwnershipListener from the element.
@@ -484,9 +468,9 @@
* xap.xml.dom.DocumentOwnershipListener or implements the same methods.
*
*/
-xap.xml.dom.XapElement.prototype.removeDocumentOwnershipListener = function( listener) {
+xap.xml.dom.XapElement.prototype.removeDocumentOwnershipListener = function( listener ) {
xap.util.ArrayHelper.removeElement( this._getDocumentOwnershipListeners(), listener );
-}
+};
/**
@@ -495,7 +479,8 @@
*/
xap.xml.dom.XapElement.prototype.clone = function ( ) {
return this._cloneHelper( false );
-}
+};
+
/**
* Creates a deep clone of the element. This will not copy generated IDs.
@@ -503,11 +488,7 @@
*/
xap.xml.dom.XapElement.prototype.deepClone = function( ) {
return this._cloneHelper( true );
-}
-
-//-----------------------------------------------------------------------
-// Private methods
-//-----------------------------------------------------------------------
+};
/**
@@ -520,15 +501,17 @@
*/
xap.xml.dom.XapElement.prototype._insertBefore = function(newNode, oldNode) {
- //TODO check newNode for null?
-
var index = this.childNodes.length;
- if (oldNode){
+
+ if (oldNode) {
//TODO this is somewhat inneficient as the superclass
//insertBefore does this same lookup
index = xap.util.ArrayHelper.indexOf(this.childNodes, oldNode);
- if (index==-1){
- return null; //TODO exception?
+ if (index == -1){
+ throw new xap.xml.dom.events.ChangeRejectedException(
+ xap.xml.dom.events.ChangeRejectedException.REJECTED_WITH_REASON_MSGID,
+ ["Attempted to insert before at invalid node"],
+ null, null);
}
}
@@ -545,8 +528,8 @@
// event, not the element passed to this method.
newNode = event.getChange();
if ( !newNode ) {
- throw new xap.xml.dom.events.ChangeRejectedException
- ( xap.xml.dom.events.ChangeRejectedException.CHANGE_CHILD_TO_NULL_MSGID,
+ throw new xap.xml.dom.events.ChangeRejectedException(
+ xap.xml.dom.events.ChangeRejectedException.CHANGE_CHILD_TO_NULL_MSGID,
null, null, event );
}
}
@@ -579,20 +562,21 @@
}
//if there was an old node we are doing an insert before
- if (oldNode){
+ if (oldNode) {
google.XNode.prototype.insertBefore.call(this,newNode, oldNode);
}
-
//otherwise we are doing an append
- else{
- google.XNode.prototype.appendChild.call(this,newNode);
+ else {
+ google.XNode.prototype.appendChild.call(this, newNode);
}
+ // send notification
if ( structureChangeListenersExist ) {
this._fireStructureChangeEvent( doc, event, 'onChildAdded');
}
+
return newNode;
-}
+};
/**
@@ -604,7 +588,8 @@
*/
xap.xml.dom.XapElement.prototype._setNamespaceUri = function( ns ) {
this._namespaceUri = ns;
-}
+};
+
/**
* A simple accessor for the prefix.
@@ -615,9 +600,14 @@
*/
xap.xml.dom.XapElement.prototype._setPrefix = function( prefix ) {
this._prefix = prefix;
-}
+};
-/** @private */
+
+/**
+ * Sends 'onRemovedFromDocument' message to all Document Ownership Listeners
+ *
+ * @private
+ */
xap.xml.dom.XapElement.prototype._notifyListenersOnRemovedFromDocument = function( doc ) {
var listeners = this._getDocumentOwnershipListeners();
@@ -631,15 +621,19 @@
i = i - 1;
}
} catch ( t ) {
- xap.xml.dom.XapElement.s_log.error
- ( xap.util.ResourceDictionary.getMessage
- ( xap.xml.dom.XapElement.DOC_OWNERSHIP_FAILURE,
- xap.xml.dom.XapElement.CLASSNAME ), t );
+ xap.xml.dom.XapElement.s_log.error( xap.util.ResourceDictionary.getMessage(
+ xap.xml.dom.XapElement.DOC_OWNERSHIP_FAILURE,
+ xap.xml.dom.XapElement.CLASSNAME ), t );
}
}
-}
+};
-/** @private */
+
+/**
+ * Sends 'onAddedToDocument' message to all Document Ownership Listeners
+ *
+ * @private
+ */
xap.xml.dom.XapElement.prototype._notifyListenersOnAddedToDocument = function( doc ) {
var listeners = this._getDocumentOwnershipListeners();
for ( var i = 0; i < listeners.length; i++ ) {
@@ -651,33 +645,31 @@
if ( listeners[i] != listener ) {
i = i - 1;
}
- } catch ( t ) {
- xap.xml.dom.XapElement.s_log.error
- ( xap.util.ResourceDictionary.getMessage
- ( xap.xml.dom.XapElement.DOC_OWNERSHIP_FAILURE,
- xap.xml.dom.XapElement.CLASSNAME ), t );
+ } catch ( e ) {
+ xap.xml.dom.XapElement.s_log.error( xap.util.ResourceDictionary.getMessage(
+ xap.xml.dom.XapElement.DOC_OWNERSHIP_FAILURE,
+ xap.xml.dom.XapElement.CLASSNAME ), e );
}
}
-}
+};
-//-----------------------------------------------------------------------
-// Private Methods.
-//-----------------------------------------------------------------------
/** @private */
xap.xml.dom.XapElement.prototype._getAttributeChangeListeners = function() {
return this._attributeChangeListeners;
-}
+};
+
/** @private */
xap.xml.dom.XapElement.prototype._getStructureChangeListeners = function() {
return this._structureChangeListeners;
-}
+};
+
/** @private */
xap.xml.dom.XapElement.prototype._getDocumentOwnershipListeners = function() {
return this._documentOwnershipListeners;
-}
+};
/**
@@ -688,13 +680,10 @@
* @param node the current node.
* @param sbuf the resulting content
* @param indent the indentation for this step
- * @param prettyPrint if true the resulting StringBuffer will contain
- * pretty-printed XML
- * @param attributeEncodingChoice is one of the private constants on this
- * class.
+ * @param prettyPrint if true the resulting StringBuffer will contain pretty-printed XML
+ * @param attributeEncodingChoice is one of the private constants on this class.
*/
-xap.xml.dom.XapElement.prototype._toStringHelper = function( node, sbuf, indent, prettyPrint,
- withInternalIds) {
+xap.xml.dom.XapElement.prototype._toStringHelper = function( node, sbuf, indent, prettyPrint, withInternalIds) {
if( node.nodeType == google.DOM_TEXT_NODE ) {
// if its a string, simply print it XML-encoded
sbuf += xap.util.XmlUtils.encode( node.nodeValue );
@@ -707,8 +696,8 @@
// any of the protocol handlers.
} else {
//var child = node.getParent().getChildAt(index-1);
- if ( index == 0 ||
- ( node.getParent().childNodes[index-1].nodeType==google.DOM_ELEMENT_NODE)) {
+ if ( index === 0 ||
+ ( node.getParent().childNodes[index - 1].nodeType == google.DOM_ELEMENT_NODE)) {
sbuf += '\n';
xap.xml.dom.XapElement._writeIndent( sbuf, indent );
}
@@ -726,19 +715,13 @@
// on this element. This is to handle the case where the namespace
// is inherited, it should not be printed on every child element
var printNamespaceAtt = false;
- if( node.getNamespaceUri() != null ) { //"" namespace URI is ok!
+ if( node.getNamespaceUri() !== null ) { //"" namespace URI is ok!
if( node.getParent() ) {
var myNS = node.getNamespaceUri();
var parentNS = node.getParent().getNamespaceUri();
-
// if this is the first element where this namespace
// appears then print it
- if( parentNS == null ) {
- printNamespaceAtt = true;
- }
- else if( myNS != parentNS ) {
- printNamespaceAtt = true;
- }
+ if( parentNS === null || myNS != parentNS) { printNamespaceAtt = true; }
} else {
printNamespaceAtt = true;
}
@@ -747,19 +730,18 @@
//TODO what if this has a namespace URI and ALSO
//has an xmlns attribute? Will print twice
- if( printNamespaceAtt == true ){
+ if( printNamespaceAtt === true ){
sbuf += " ";
// determine correct namespace attribute to use
if( node.getPrefix() ) {
sbuf += "xmlns:" + node.getPrefix();
-
} else {
sbuf += "xmlns";
}
sbuf += "=\"" + xap.util.XmlUtils.encode(node.getNamespaceUri()) + "\"";
}
- for( var i=0; i<node.attributes.length; i++ ) {
+ for( var i = 0; i < node.attributes.length; i++ ) {
var key = node.attributes[i].nodeName;
var value = node.attributes[i].nodeValue;
@@ -776,14 +758,13 @@
}
//add children if there are any
- if ( node.childNodes.length == 0 ) {
+ if ( node.childNodes.length === 0 ) {
sbuf += "/>";
- }
- else {
+ } else {
sbuf += '>';
var elementHasTextNode = false;
- for ( var i = 0; i < node.childNodes.length; i++ ) {
- var child = node.childNodes[i];
+ for ( var j = 0; j < node.childNodes.length; j++ ) {
+ var child = node.childNodes[j];
if( child.nodeType == google.DOM_TEXT_NODE ) {
elementHasTextNode = true;
}
@@ -794,7 +775,7 @@
withInternalIds);
}
- if( prettyPrint && elementHasTextNode == false ) {
+ if( prettyPrint && (elementHasTextNode === false) ) {
// if this element had a text node it is not valid to
// write whitespace
sbuf += '\n';
@@ -809,33 +790,41 @@
}
}
return sbuf;
-}
+};
/**
+ * Notifies document's listenters (if there is one) and then its own listeners
+ *
* @private
+ * @param doc Containing document. Can be null.
+ * @param event Modification event
+ * @param methodName { String } onXXX handler name
*/
xap.xml.dom.XapElement.prototype._fireStructureChangeEvent = function( doc, event, methodName){
if (doc){
- this._notifyListeners(doc._structureChangeListeners,
- event, methodName);
+ this._notifyListeners(doc._structureChangeListeners, event, methodName);
}
this._notifyListeners(this._getStructureChangeListeners(), event, methodName);
-}
+};
/**
- * @private
+ * Notifies document's listenters (if there is one) and then its own listeners
+ *
+ * @private
+ * @param doc Containing document. Can be null.
+ * @param event Modification event
+ * @param methodName { String } onXXX handler name
*/
-xap.xml.dom.XapElement.prototype._fireAttributeChangeEvent = function( doc, event, methodName){
+xap.xml.dom.XapElement.prototype._fireAttributeChangeEvent = function( doc, event, methodName ) {
if (doc){
- this._notifyListeners(doc._attributeChangeListeners,
- event, methodName);
+ this._notifyListeners(doc._attributeChangeListeners, event, methodName);
}
this._notifyListeners(this._getAttributeChangeListeners(), event, methodName);
-}
+};
@@ -848,110 +837,116 @@
* @throws xap.xml.dom.events.ChangeRejectedException
*/
xap.xml.dom.XapElement.prototype._notifyListeners = function( listeners, event, methodName){
- if (!listeners) return;
- for (var i =0; i<listeners.length; i++){
+ if (!listeners) { return; }
+
+ for (var i = 0; i < listeners.length; i++){
var listener = listeners[i];
-
if(listener[methodName]){
listener[methodName].call(listener, event);
-
if ( listeners[i] != listener ) {
- i = i - 1;
+ i = i - 1;
}
}
}
-}
-
+};
-/**
+/**
+ *
+ *
* @private
*/
xap.xml.dom.XapElement.prototype._doAnyAttributeChangeListenersExist = function( doc ) {
return ( (doc && doc._attributeChangeListeners.length>0) ||
(this._getAttributeChangeListeners().length > 0 ));
-}
+};
-/** @private */
+
+/**
+ *
+ *
+ * @private
+ */
xap.xml.dom.XapElement.prototype._doAnyStructureChangeListenersExist = function( doc ) {
return ( (doc && doc._structureChangeListeners.length>0) ||
(this._getStructureChangeListeners().length > 0 ));
-}
+};
/**
- * Needed for data.controller classes---Binding and ElementLocation
+ * Needed for data.controller classes---Binding and ElementLocation
+ *
+ * @param child A child node to search for in this.childNodes
* @return {int}
*/
-xap.xml.dom.XapElement.prototype.indexOfChild = function(aChild) {
- return xap.util.ArrayHelper.indexOf(this.childNodes, aChild);
-}
+xap.xml.dom.XapElement.prototype.indexOfChild = function(child) {
+ return xap.util.ArrayHelper.indexOf(this.childNodes, child);
+};
+
+
/**
* Needed for Iterator
* @return {int}
*/
xap.xml.dom.XapElement.prototype.getChildCount = function() {
- return this.childNodes.length ;
-}
-
-
+ return this.childNodes.length;
+};
/**
* Needed for Iterator
- * @return {int}
+ * @return Child node or null
*/
xap.xml.dom.XapElement.prototype.getChildAt = function(anInt) {
- return this.childNodes[anInt] ;
-}
+ if(anInt < this.childNodes.length) {
+ return this.childNodes[anInt] ;
+ }
+ return null;
+};
/**
* This will return the first text node of this element. If this element
* has multiple text nodes ONLY the first text node is returned.
*
- * @param node{XNode}
+ * @param {XNode} node
* @return {String} The first text node of the element.
*/
xap.xml.dom.XapElement.getFirstTextChild = function(node) {
- var result=null ;
- var children = node.childNodes ;
- for(var i=0; node.childNodes && i< children.length ; i++) {
+
+ var children = node.childNodes;
+
+ if(!children) { return null; }
+
+ for(var i = 0; children.length ; i++) {
if(children[i].nodeType == google.DOM_TEXT_NODE ) {
- result = children[i] ;
- break ;
+ return (children[i]);
}
}
- return result ;
-}
-
-
-
-
+ return null;
+};
-//-----------------------------------------------------------------------
-// Array Helpers.
-//-----------------------------------------------------------------------
-
-/**
- * @private
+/**
+ * Makes a deep clone of this node
+ *
+ * @private
+ * @return {xap.xml.dom.XapElement} New node
*/
xap.xml.dom.XapElement.prototype._cloneHelper = function( deep ) {
+
var e = new xap.xml.dom.XapElement( this.nodeName );
e._setNamespaceUri( this._namespaceUri );
e._setPrefix( this._prefix );
for (var i = 0; i<this.attributes.length; i++){
- e.setAttribute(this.attributes[i].nodeName, this.attributes[i].nodeValue,this.attributes[i].baseUrl);
+ e.setAttribute(this.attributes[i].nodeName, this.attributes[i].nodeValue, this.attributes[i].baseUrl);
}
- if (this.baseUrl){
- e.baseUrl = this.baseUrl;
- }
+ if (this.baseUrl) { e.baseUrl = this.baseUrl; }
var id = e.getAttribute( "id" );
@@ -959,51 +954,21 @@
if ( xap.xml.dom.XapElement.isGeneratedId( id ) ) {
e.setAttribute( "id", xap.util.UidProvider.createId());
}
-
- if ( deep == false ) {
- return e;
- }
+ if ( deep === false ) { return e; }
- for ( var i = 0; i < this.childNodes.length; i++ ) {
- var o = this.childNodes[i];
- if (o.nodeType==google.DOM_ELEMENT_NODE){
- var childCopy = o._cloneHelper( deep );
- e.appendChild( childCopy );
+ for ( var j = 0; j < this.childNodes.length; j++ ) {
+ var o = this.childNodes[j];
+ if (o.nodeType == google.DOM_ELEMENT_NODE){
+ e.appendChild( o._cloneHelper( deep ) );
}
- else if (o.nodeType==google.DOM_TEXT_NODE){
+ else if (o.nodeType == google.DOM_TEXT_NODE){
//TODO we should really use document.createTextNode here
//but do we always have a document to reference?
- var childCopy = google.XNode.create(google.DOM_TEXT_NODE,null,o.nodeValue,null);
+ var childCopy = google.XNode.create(google.DOM_TEXT_NODE, null, o.nodeValue, null);
e.appendChild( childCopy );
}
}
return e;
-}
-
+};
-/**
- * @private
- */
-xap.xml.dom.XapElement.prototype._encodeEverythingButSingleTicks = function( s ) {
- if ( !s ) { return ""; }
- var buffer = new Array( s.length );
- var c;
- for ( var i = 0; i < s.length; i++ ) {
- c = s.charAt(i);
- if (c == '&') {
- buffer[i] = "&";
- } else if (c == '<') {
- buffer[i] = "<";
- } else if (c == '>') {
- buffer[i] = ">";
- } else if (c == '\'') {
- buffer[i] = "'";
- } else if (c == '\"') {
- buffer[i] = """;
- } else {
- buffer[i] = c;
- }
- }
- return buffer.join();
-}