diff options
Diffstat (limited to 'lib/dojo/dom-construct.js.uncompressed.js')
-rw-r--r-- | lib/dojo/dom-construct.js.uncompressed.js | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/lib/dojo/dom-construct.js.uncompressed.js b/lib/dojo/dom-construct.js.uncompressed.js new file mode 100644 index 000000000..6abef71aa --- /dev/null +++ b/lib/dojo/dom-construct.js.uncompressed.js @@ -0,0 +1,329 @@ +define("dojo/dom-construct", ["exports", "./_base/kernel", "./sniff", "./_base/window", "./dom", "./dom-attr", "./on"], + function(exports, dojo, has, win, dom, attr, on){ + // module: + // dojo/dom-construct + // summary: + // This module defines the core dojo DOM construction API. + + // TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42 + + // support stuff for toDom() + var tagWrap = { + option: ["select"], + tbody: ["table"], + thead: ["table"], + tfoot: ["table"], + tr: ["table", "tbody"], + td: ["table", "tbody", "tr"], + th: ["table", "thead", "tr"], + legend: ["fieldset"], + caption: ["table"], + colgroup: ["table"], + col: ["table", "colgroup"], + li: ["ul"] + }, + reTag = /<\s*([\w\:]+)/, + masterNode = {}, masterNum = 0, + masterName = "__" + dojo._scopeName + "ToDomId"; + + // generate start/end tag strings to use + // for the injection for each special tag wrap case. + for(var param in tagWrap){ + if(tagWrap.hasOwnProperty(param)){ + var tw = tagWrap[param]; + tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">"; + tw.post = "</" + tw.reverse().join("></") + ">"; + // the last line is destructive: it reverses the array, + // but we don't care at this point + } + } + + function _insertBefore(/*DomNode*/ node, /*DomNode*/ ref){ + var parent = ref.parentNode; + if(parent){ + parent.insertBefore(node, ref); + } + } + + function _insertAfter(/*DomNode*/ node, /*DomNode*/ ref){ + // summary: + // Try to insert node after ref + var parent = ref.parentNode; + if(parent){ + if(parent.lastChild == ref){ + parent.appendChild(node); + }else{ + parent.insertBefore(node, ref.nextSibling); + } + } + } + + exports.toDom = function toDom(frag, doc){ + // summary: + // instantiates an HTML fragment returning the corresponding DOM. + // frag: String + // the HTML fragment + // doc: DocumentNode? + // optional document to use when creating DOM nodes, defaults to + // dojo.doc if not specified. + // returns: + // Document fragment, unless it's a single node in which case it returns the node itself + // example: + // Create a table row: + // | var tr = dojo.toDom("<tr><td>First!</td></tr>"); + + doc = doc || win.doc; + var masterId = doc[masterName]; + if(!masterId){ + doc[masterName] = masterId = ++masterNum + ""; + masterNode[masterId] = doc.createElement("div"); + } + + // make sure the frag is a string. + frag += ""; + + // find the starting tag, and get node wrapper + var match = frag.match(reTag), + tag = match ? match[1].toLowerCase() : "", + master = masterNode[masterId], + wrap, i, fc, df; + if(match && tagWrap[tag]){ + wrap = tagWrap[tag]; + master.innerHTML = wrap.pre + frag + wrap.post; + for(i = wrap.length; i; --i){ + master = master.firstChild; + } + }else{ + master.innerHTML = frag; + } + + // one node shortcut => return the node itself + if(master.childNodes.length == 1){ + return master.removeChild(master.firstChild); // DOMNode + } + + // return multiple nodes as a document fragment + df = doc.createDocumentFragment(); + while((fc = master.firstChild)){ // intentional assignment + df.appendChild(fc); + } + return df; // DocumentFragment + }; + + exports.place = function place(/*DOMNode|String*/ node, /*DOMNode|String*/ refNode, /*String|Number?*/ position){ + // summary: + // Attempt to insert node into the DOM, choosing from various positioning options. + // Returns the first argument resolved to a DOM node. + // node: DOMNode|String + // id or node reference, or HTML fragment starting with "<" to place relative to refNode + // refNode: DOMNode|String + // id or node reference to use as basis for placement + // position: String|Number? + // string noting the position of node relative to refNode or a + // number indicating the location in the childNodes collection of refNode. + // Accepted string values are: + // + // - before + // - after + // - replace + // - only + // - first + // - last + // + // "first" and "last" indicate positions as children of refNode, "replace" replaces refNode, + // "only" replaces all children. position defaults to "last" if not specified + // returns: DOMNode + // Returned values is the first argument resolved to a DOM node. + // + // .place() is also a method of `dojo/NodeList`, allowing `dojo.query` node lookups. + // example: + // Place a node by string id as the last child of another node by string id: + // | dojo.place("someNode", "anotherNode"); + // example: + // Place a node by string id before another node by string id + // | dojo.place("someNode", "anotherNode", "before"); + // example: + // Create a Node, and place it in the body element (last child): + // | dojo.place("<div></div>", dojo.body()); + // example: + // Put a new LI as the first child of a list by id: + // | dojo.place("<li></li>", "someUl", "first"); + + refNode = dom.byId(refNode); + if(typeof node == "string"){ // inline'd type check + node = /^\s*</.test(node) ? exports.toDom(node, refNode.ownerDocument) : dom.byId(node); + } + if(typeof position == "number"){ // inline'd type check + var cn = refNode.childNodes; + if(!cn.length || cn.length <= position){ + refNode.appendChild(node); + }else{ + _insertBefore(node, cn[position < 0 ? 0 : position]); + } + }else{ + switch(position){ + case "before": + _insertBefore(node, refNode); + break; + case "after": + _insertAfter(node, refNode); + break; + case "replace": + refNode.parentNode.replaceChild(node, refNode); + break; + case "only": + exports.empty(refNode); + refNode.appendChild(node); + break; + case "first": + if(refNode.firstChild){ + _insertBefore(node, refNode.firstChild); + break; + } + // else fallthrough... + default: // aka: last + refNode.appendChild(node); + } + } + return node; // DomNode + }; + + exports.create = function create(/*DOMNode|String*/ tag, /*Object*/ attrs, /*DOMNode|String?*/ refNode, /*String?*/ pos){ + // summary: + // Create an element, allowing for optional attribute decoration + // and placement. + // description: + // A DOM Element creation function. A shorthand method for creating a node or + // a fragment, and allowing for a convenient optional attribute setting step, + // as well as an optional DOM placement reference. + // + // Attributes are set by passing the optional object through `dojo.setAttr`. + // See `dojo.setAttr` for noted caveats and nuances, and API if applicable. + // + // Placement is done via `dojo.place`, assuming the new node to be the action + // node, passing along the optional reference node and position. + // tag: DOMNode|String + // A string of the element to create (eg: "div", "a", "p", "li", "script", "br"), + // or an existing DOM node to process. + // attrs: Object + // An object-hash of attributes to set on the newly created node. + // Can be null, if you don't want to set any attributes/styles. + // See: `dojo.setAttr` for a description of available attributes. + // refNode: DOMNode|String? + // Optional reference node. Used by `dojo.place` to place the newly created + // node somewhere in the dom relative to refNode. Can be a DomNode reference + // or String ID of a node. + // pos: String? + // Optional positional reference. Defaults to "last" by way of `dojo.place`, + // though can be set to "first","after","before","last", "replace" or "only" + // to further control the placement of the new node relative to the refNode. + // 'refNode' is required if a 'pos' is specified. + // example: + // Create a DIV: + // | var n = dojo.create("div"); + // + // example: + // Create a DIV with content: + // | var n = dojo.create("div", { innerHTML:"<p>hi</p>" }); + // + // example: + // Place a new DIV in the BODY, with no attributes set + // | var n = dojo.create("div", null, dojo.body()); + // + // example: + // Create an UL, and populate it with LI's. Place the list as the first-child of a + // node with id="someId": + // | var ul = dojo.create("ul", null, "someId", "first"); + // | var items = ["one", "two", "three", "four"]; + // | dojo.forEach(items, function(data){ + // | dojo.create("li", { innerHTML: data }, ul); + // | }); + // + // example: + // Create an anchor, with an href. Place in BODY: + // | dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body()); + // + // example: + // Create a `dojo/NodeList()` from a new element (for syntactic sugar): + // | dojo.query(dojo.create('div')) + // | .addClass("newDiv") + // | .onclick(function(e){ console.log('clicked', e.target) }) + // | .place("#someNode"); // redundant, but cleaner. + + var doc = win.doc; + if(refNode){ + refNode = dom.byId(refNode); + doc = refNode.ownerDocument; + } + if(typeof tag == "string"){ // inline'd type check + tag = doc.createElement(tag); + } + if(attrs){ attr.set(tag, attrs); } + if(refNode){ exports.place(tag, refNode, pos); } + return tag; // DomNode + }; + + var _empty = has("ie") ? + function(/*DomNode*/ node){ + try{ + node.innerHTML = ""; // really fast when it works + }catch(e){ // IE can generate Unknown Error + for(var c; c = node.lastChild;){ // intentional assignment + _destroy(c, node); // destroy is better than removeChild so TABLE elements are removed in proper order + } + } + } : + function(/*DomNode*/ node){ + node.innerHTML = ""; + }; + + exports.empty = function empty(/*DOMNode|String*/ node){ + // summary: + // safely removes all children of the node. + // node: DOMNode|String + // a reference to a DOM node or an id. + // example: + // Destroy node's children byId: + // | dojo.empty("someId"); + // + // example: + // Destroy all nodes' children in a list by reference: + // | dojo.query(".someNode").forEach(dojo.empty); + + _empty(dom.byId(node)); + }; + + + function _destroy(/*DomNode*/ node, /*DomNode*/ parent){ + if(node.firstChild){ + _empty(node); + } + if(parent){ + parent.removeChild(node); + } + } + exports.destroy = function destroy(/*DOMNode|String*/ node){ + // summary: + // Removes a node from its parent, clobbering it and all of its + // children. + // + // description: + // Removes a node from its parent, clobbering it and all of its + // children. Function only works with DomNodes, and returns nothing. + // + // node: DOMNode|String + // A String ID or DomNode reference of the element to be destroyed + // + // example: + // Destroy a node byId: + // | dojo.destroy("someId"); + // + // example: + // Destroy all nodes in a list by reference: + // | dojo.query(".someNode").forEach(dojo.destroy); + + node = dom.byId(node); + if(!node){ return; } + _destroy(node, node.parentNode); + }; +}); |