/*______________ | ______ | U I Z E J A V A S C R I P T F R A M E W O R K | / / | --------------------------------------------------- | / O / | MODULE : Uize.Web.xDom Object Extension | / / / | | / / / /| | ONLINE : http://uize.com | /____/ /__/_| | COPYRIGHT : (c)2009-2014 UIZE | /___ | LICENSE : Available under MIT License or GNU General Public License |_______________| http://uize.com/license.html */ /* Module Meta Data type: Extension importance: 5 codeCompleteness: 10 docCompleteness: 50 */ /*? Introduction The =Uize.Web.xDom= module extends the =Uize.Web= object by adding functionality for manipulating the DOM. *DEVELOPERS:* `Ben Ilegbodu`, original code contributed by `Zazzle Inc.` The =Uize.Web.xDom= module is an extension module that extends the =Uize.Web= class. Pages that want to leverage the syntax-friendly nature of =Uize.Web= may not need to leverage any DOM manipulation. Therefore, the DOM manipulation functionality is not implemented in the =Uize.Web= class in order to reduce the need for loading the extra code. Instead, in order to include the DOM manipulation functionality, one needs to require the =Uize.Web.xDom= extension module. Key Features The =Uize.Web.xDom= extension module provides the following features... Insertion Methods document... Removal Methods document... */ Uize.module ({ name:'Uize.Web.xDom', required:'Uize.Dom.Basics', builder:function (_object) { 'use strict'; var /*** Variables for Scruncher Optimization ***/ _true = true, _Uize = Uize, _Uize_Dom_Basics = _Uize.Dom.Basics, _objectPrototype = _object.prototype ; /*** Utility Functions ***/ var _emptyNode = function(_rootNode, _unwireChildNodes, _removeRoot) { var _removeAndUnwireChildNodes = function(_node) { var _childNodes = _node.childNodes, _childNodeNo = _childNodes.length - 1, _parentNode = _node.parentNode ; // pre-order recursion so the children are removed/unwired first // remove/unwire child nodes in reverse, so that the change in length doesn't // affect our indexing for (; _childNodeNo > 0; _childNodeNo--) _removeAndUnwireChildNodes(_childNodes[_childNodeNo]) ; // don't remove the root node since we're emptying if (_removeRoot || _node != _rootNode) { // if the node is an element than unwire it (no point unwiring text nodes) _node.nodeType == 1 && _Uize_Dom_Basics.unwire(_node); // if the node is a child of the root node, remove it (an optimization since // we don't actually need to remove deep descendent nodes because removing their // parent will remove them too) (_parentNode == _rootNode || (_removeRoot && (_node == _rootNode))) && _Uize_Dom_Basics.remove(_node); } } ; _unwireChildNodes && _removeAndUnwireChildNodes(_rootNode); _rootNode.innerHTML = ''; // ensure completely empty }, _isMatch = _object.isMatch ; /*** Public Instance Methods ***/ /** Insertion **/ var _makeInjectHtmlMethodFrom = function(_fromMethodName, _toMethodName) { // "from" the set of matched nodes _objectPrototype[_fromMethodName] = function(_target) { // NOTE: Essentially what this does is wrap the target in a Uize.Web object and then call the peer toMethod // (i.e "appendTo" would call "append") and then pass 'this' as the content to inject return _object(_target)[_toMethodName](this); }; }, _makeInjectHtmlMethodTo = function(_methodName, _injectMode) { // "to" the set of matched nodes _objectPrototype[_methodName] = function() { var m = this, _length = m.length ; _Uize.forEach( arguments, function(_arg) { m.handleSetAction( _arg, function(_node, _content) { _Uize.forEach( _Uize.isList(_content) ? _content : [_content], function(_contentToAdd) { // If there's only one node in the matched set (i.e. one location we want to inject into), // then we'll detach it, so that injecting will be a move instead of a clone. // But if there is more than one target node, injectHtml will clone since the nodes will have // parents _length == 1 && _Uize_Dom_Basics.isNode(_contentToAdd) && _Uize_Dom_Basics.remove(_contentToAdd) ; _Uize_Dom_Basics.injectHtml(_node, _contentToAdd, _injectMode); } ); } ); } ); return m; }; } ; _makeInjectHtmlMethodTo('after', 'outer bottom'); /*? Instance Methods after Inserts HTML string, DOM node, array of DOM nodes or =Uize.Web= object after each node in the set of matched DOM nodes. SYNTAX ........................................................ myWeb = myWeb.after(contentBLOB); ........................................................ VARIATION 1 ........................................................ myWeb = myWeb.after(contentFUNC); ........................................................ VARIATION 2 ........................................................ myWeb = myWeb.after(content1BLOB, content2BLOB, ...); ........................................................ VARIATION 3 ........................................................ myWeb = myWeb.after(content1FUNC, content2FUNC, ...); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being added after a single DOM node (i.e. there is only one DOM node in the set of matched DOM nodes), that DOM node will be moved and not cloned. - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being added after multiple DOM nodes (i.e. there is more than one DOM node in the set of matched DOM nodes), that DOM node will be cloned before being inserted. */ _makeInjectHtmlMethodTo('append'); /*? Instance Methods append Inserts HTML string, DOM node, array of DOM nodes or =Uize.Web= object to the end of each node in the set of matched DOM nodes. SYNTAX ........................................................ myWeb = myWeb.append(contentBLOB); ........................................................ VARIATION 1 ........................................................ myWeb = myWeb.append(contentFUNC); ........................................................ VARIATION 2 ........................................................ myWeb = myWeb.append(content1BLOB, content2BLOB, ...); ........................................................ VARIATION 3 ........................................................ myWeb = myWeb.append(content1FUNC, content2FUNC, ...); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being appended to a single DOM node (i.e. there is only one DOM node in the set of matched DOM nodes), that DOM node will be moved and not cloned. - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being appended to multiple DOM nodes (i.e. there is more than one DOM node in the set of matched DOM nodes), that DOM node will be cloned before being inserted. */ _makeInjectHtmlMethodFrom('appendTo', 'append'); /*? Instance Methods appendTo Inserts every DOM node in the set of matched DOM nodes to the end of each node in the target. SYNTAX ........................................................ newWeb = myWeb.appendTo(targetBLOB); ........................................................ NOTES - Returns a reference to the target wrapped in a new =Uize.Web= object - If =targetBLOB= is a single DOM node, the DOM nodes in the matched set of DOM nodes will be moved to the target (not cloned) - If =targetBLOB= is multiple DOM nodes, the DOM nodes in the matched set of DOM nodes will be cloned for each target after the first. */ _makeInjectHtmlMethodTo('before', 'outer top'); /*? Instance Methods before Inserts HTML string, DOM node, array of DOM nodes or =Uize.Web= object before each node in the set of matched DOM nodes. SYNTAX ........................................................ myWeb = myWeb.before(contentSTR); ........................................................ VARIATION 1 ........................................................ myWeb = myWeb.before(contentFUNC); ........................................................ VARIATION 2 ........................................................ myWeb = myWeb.before(content1STR, content2STR, ...); ........................................................ VARIATION 3 ........................................................ myWeb = myWeb.before(content1FUNC, content2FUNC, ...); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being added before a single DOM node (i.e. there is only one DOM node in the set of matched DOM nodes), that DOM node will be moved and not cloned. - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being added before multiple DOM nodes (i.e. there is more than one DOM node in the set of matched DOM nodes), that DOM node will be cloned before being inserted. */ _makeInjectHtmlMethodFrom('insertAfter', 'after'); /*? Instance Methods insertAfter Inserts every DOM node in the set of matched DOM nodes after each node in the target. SYNTAX ........................................................ newWeb = myWeb.insertAfter(targetBLOB); ........................................................ NOTES - Returns a reference to the target wrapped in a new =Uize.Web= object - If =targetBLOB= is a single DOM node, the DOM nodes in the matched set of DOM nodes will be moved to the target (not cloned) - If =targetBLOB= is multiple DOM nodes, the DOM nodes in the matched set of DOM nodes will be cloned for each target after the first. */ _makeInjectHtmlMethodFrom('insertBefore', 'before'); /*? Instance Methods insertBefore Inserts every DOM node in the set of matched DOM nodes before each node in the target. SYNTAX ........................................................ newWeb = myWeb.insertBefore(targetBLOB); ........................................................ NOTES - Returns a reference to the target wrapped in a new =Uize.Web= object - If =targetBLOB= is a single DOM node, the DOM nodes in the matched set of DOM nodes will be moved to the target (not cloned) - If =targetBLOB= is multiple DOM nodes, the DOM nodes in the matched set of DOM nodes will be cloned for each target after the first. */ _makeInjectHtmlMethodTo('prepend', 'inner top'); /*? Instance Methods prepend Inserts HTML string, DOM node, array of DOM nodes or =Uize.Web= object to the beginning of each node in the set of matched DOM nodes. SYNTAX ........................................................ myWeb = myWeb.prepend(contentSTR); ........................................................ VARIATION 1 ........................................................ myWeb = myWeb.prepend(contentFUNC); ........................................................ VARIATION 2 ........................................................ myWeb = myWeb.prepend(content1STR, content2STR, ...); ........................................................ VARIATION 3 ........................................................ myWeb = myWeb.prepend(content1FUNC, content2FUNC, ...); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being prepended to a single DOM node (i.e. there is only one DOM node in the set of matched DOM nodes), that DOM node will be moved and not cloned. - If a DOM node (or an array of DOM nodes) is specified as an argument, but is being prepended to multiple DOM nodes (i.e. there is more than one DOM node in the set of matched DOM nodes), that DOM node will be cloned before being inserted. */ _makeInjectHtmlMethodFrom('prependTo', 'prepend'); /*? Instance Methods prependTo Inserts every DOM node in the set of matched DOM nodes to the beginning of each node in the target. SYNTAX ........................................................ newWeb = myWeb.prependTo(targetBLOB); ........................................................ NOTES - Returns a reference to the target wrapped in a new =Uize.Web= object - If =targetBLOB= is a single DOM node, the DOM nodes in the matched set of DOM nodes will be moved to the target (not cloned) - If =targetBLOB= is multiple DOM nodes, the DOM nodes in the matched set of DOM nodes will be cloned for each target after the first. */ _makeInjectHtmlMethodFrom('replaceAll', 'replaceWith'); /*? Instance Methods replaceAll Replaces every DOM node in the set of matched DOM nodes with each node in the target. SYNTAX ........................................................ newWeb = myWeb.replaceAll(targetBLOB); ........................................................ NOTES - Returns a reference to the target wrapped in a new =Uize.Web= object - If =targetBLOB= is a single DOM node, the DOM nodes in the matched set of DOM nodes will be moved to replace the target (not cloned) - If =targetBLOB= is multiple DOM nodes, the DOM nodes in the matched set of DOM nodes will be cloned for each target after the first. */ _makeInjectHtmlMethodTo('replaceWith', 'outer replace'); /*? Instance Methods replaceWith Replaces each node in the set of matched DOM nodes with the specified HTML string, DOM node, or =Uize.Web= object. SYNTAX ........................................................ myWeb = myWeb.replaceWith(contentSTR); ........................................................ VARIATION 1 ........................................................ myWeb = myWeb.replaceWith(contentFUNC); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - If a DOM node (or an array of DOM nodes) is specified as an argument, but is replacing a single DOM node (i.e. there is only one DOM node in the set of matched DOM nodes), that DOM node will be moved and not cloned. - If a DOM node (or an array of DOM nodes) is specified as an argument, but is replacing multiple DOM nodes (i.e. there is more than one DOM node in the set of matched DOM nodes), that DOM node will be cloned before replacing. */ /** Removal **/ _objectPrototype.detach = function(_selector) { return this.each(function() { _isMatch(this, _selector) && _Uize_Dom_Basics.remove(this) }); // NOTE: "this" in each is a reference to the node /*? Instance Methods detach Removes the set of matched DOM nodes that match a (optional) selector, keeping all of the wired events. SYNTAX ........................................................ myWeb = myWeb.detach(); ........................................................ VARIATION 1 ........................................................ myWeb = myWeb.detach(selectorSTR); ........................................................ VARIATION 2 ........................................................ myWeb = myWeb.detach(node); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - All events wired on the detached DOM nodes are retained, which is useful when the detached DOM nodes are to be reinserted into the DOM at a later time - See related =remove= and =empty= methods */ }; _objectPrototype.empty = function() { return this.each(function() { _emptyNode(this, _true) }); /*? Instance Methods empty Iterates over the set of matched DOM nodes, removing all of the child DOM nodes (i.e. "emptying") of each one. SYNTAX ........................................................ myWeb = myWeb.empty(); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - All wired events are also removed from the child DOM nodes before removing the DOM nodes themselves - See also related =detatch= and =remove= methods */ }; _objectPrototype.remove = function(_selector) { return this.each(function() { _isMatch(this, _selector) && _emptyNode(this, _true, _true) }); /*? Instance Methods remove Iterates over the set of matched DOM nodes, removing each from the DOM. SYNTAX ........................................................ myWeb = myWeb.remove(); ........................................................ VARIATION ........................................................ myWeb = myWeb.remove(selector); ........................................................ NOTES - Returns a reference to the same =Uize.Web= object - All wired events are also removed from the DOM nodes before removing the DOM nodes themselves - See also related =detatch= and =empty= methods */ }; } });