]> git.wh0rd.org Git - tt-rss.git/blob - lib/dojo/dom-construct.js.uncompressed.js
update dojo to 1.7.3
[tt-rss.git] / lib / dojo / dom-construct.js.uncompressed.js
1 define("dojo/dom-construct", ["exports", "./_base/kernel", "./_base/sniff", "./_base/window", "./dom", "./dom-attr", "./on"],
2                 function(exports, dojo, has, win, dom, attr, on){
3         // module:
4         //              dojo/dom-construct
5         // summary:
6         //              This module defines the core dojo DOM construction API.
7
8         /*=====
9         dojo.toDom = function(frag, doc){
10                 // summary:
11                 //              instantiates an HTML fragment returning the corresponding DOM.
12                 // frag: String
13                 //              the HTML fragment
14                 // doc: DocumentNode?
15                 //              optional document to use when creating DOM nodes, defaults to
16                 //              dojo.doc if not specified.
17                 // returns: DocumentFragment
18                 //
19                 // example:
20                 //              Create a table row:
21                 //      |       var tr = dojo.toDom("<tr><td>First!</td></tr>");
22         };
23         =====*/
24
25         /*=====
26         dojo._toDom = function(frag, doc){
27                 // summary:
28                 //              Existing alias for `dojo.toDom`. Deprecated, will be removed in 2.0.
29         };
30         =====*/
31
32         /*=====
33         dojo.place = function(node, refNode, position){
34                 // summary:
35                 //              Attempt to insert node into the DOM, choosing from various positioning options.
36                 //              Returns the first argument resolved to a DOM node.
37                 //
38                 // node: DOMNode|String
39                 //              id or node reference, or HTML fragment starting with "<" to place relative to refNode
40                 //
41                 // refNode: DOMNode|String
42                 //              id or node reference to use as basis for placement
43                 //
44                 // position: String|Number?
45                 //              string noting the position of node relative to refNode or a
46                 //              number indicating the location in the childNodes collection of refNode.
47                 //              Accepted string values are:
48                 //      |       * before
49                 //      |       * after
50                 //      |       * replace
51                 //      |       * only
52                 //      |       * first
53                 //      |       * last
54                 //              "first" and "last" indicate positions as children of refNode, "replace" replaces refNode,
55                 //              "only" replaces all children.  position defaults to "last" if not specified
56                 //
57                 // returns: DOMNode
58                 //              Returned values is the first argument resolved to a DOM node.
59                 //
60                 //              .place() is also a method of `dojo.NodeList`, allowing `dojo.query` node lookups.
61                 //
62                 // example:
63                 //              Place a node by string id as the last child of another node by string id:
64                 //      |       dojo.place("someNode", "anotherNode");
65                 //
66                 // example:
67                 //              Place a node by string id before another node by string id
68                 //      |       dojo.place("someNode", "anotherNode", "before");
69                 //
70                 // example:
71                 //              Create a Node, and place it in the body element (last child):
72                 //      |       dojo.place("<div></div>", dojo.body());
73                 //
74                 // example:
75                 //              Put a new LI as the first child of a list by id:
76                 //      |       dojo.place("<li></li>", "someUl", "first");
77         };
78         =====*/
79
80         /*=====
81         dojo.create = function(tag, attrs, refNode, pos){
82                 // summary:
83                 //              Create an element, allowing for optional attribute decoration
84                 //              and placement.
85                 //
86                 // description:
87                 //              A DOM Element creation function. A shorthand method for creating a node or
88                 //              a fragment, and allowing for a convenient optional attribute setting step,
89                 //              as well as an optional DOM placement reference.
90                 //|
91                 //              Attributes are set by passing the optional object through `dojo.setAttr`.
92                 //              See `dojo.setAttr` for noted caveats and nuances, and API if applicable.
93                 //|
94                 //              Placement is done via `dojo.place`, assuming the new node to be the action
95                 //              node, passing along the optional reference node and position.
96                 //
97                 // tag: DOMNode|String
98                 //              A string of the element to create (eg: "div", "a", "p", "li", "script", "br"),
99                 //              or an existing DOM node to process.
100                 //
101                 // attrs: Object
102                 //              An object-hash of attributes to set on the newly created node.
103                 //              Can be null, if you don't want to set any attributes/styles.
104                 //              See: `dojo.setAttr` for a description of available attributes.
105                 //
106                 // refNode: DOMNode?|String?
107                 //              Optional reference node. Used by `dojo.place` to place the newly created
108                 //              node somewhere in the dom relative to refNode. Can be a DomNode reference
109                 //              or String ID of a node.
110                 //
111                 // pos: String?
112                 //              Optional positional reference. Defaults to "last" by way of `dojo.place`,
113                 //              though can be set to "first","after","before","last", "replace" or "only"
114                 //              to further control the placement of the new node relative to the refNode.
115                 //              'refNode' is required if a 'pos' is specified.
116                 //
117                 // returns: DOMNode
118                 //
119                 // example:
120                 //              Create a DIV:
121                 //      |       var n = dojo.create("div");
122                 //
123                 // example:
124                 //              Create a DIV with content:
125                 //      |       var n = dojo.create("div", { innerHTML:"<p>hi</p>" });
126                 //
127                 // example:
128                 //              Place a new DIV in the BODY, with no attributes set
129                 //      |       var n = dojo.create("div", null, dojo.body());
130                 //
131                 // example:
132                 //              Create an UL, and populate it with LI's. Place the list as the first-child of a
133                 //              node with id="someId":
134                 //      |       var ul = dojo.create("ul", null, "someId", "first");
135                 //      |       var items = ["one", "two", "three", "four"];
136                 //      |       dojo.forEach(items, function(data){
137                 //      |               dojo.create("li", { innerHTML: data }, ul);
138                 //      |       });
139                 //
140                 // example:
141                 //              Create an anchor, with an href. Place in BODY:
142                 //      |       dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body());
143                 //
144                 // example:
145                 //              Create a `dojo.NodeList()` from a new element (for syntatic sugar):
146                 //      |       dojo.query(dojo.create('div'))
147                 //      |               .addClass("newDiv")
148                 //      |               .onclick(function(e){ console.log('clicked', e.target) })
149                 //      |               .place("#someNode"); // redundant, but cleaner.
150         };
151         =====*/
152
153         /*=====
154         dojo.empty = function(node){
155                         // summary:
156                         //              safely removes all children of the node.
157                         // node: DOMNode|String
158                         //              a reference to a DOM node or an id.
159                         // example:
160                         //              Destroy node's children byId:
161                         //      |       dojo.empty("someId");
162                         //
163                         // example:
164                         //              Destroy all nodes' children in a list by reference:
165                         //      |       dojo.query(".someNode").forEach(dojo.empty);
166         }
167         =====*/
168
169         /*=====
170         dojo.destroy = function(node){
171                 // summary:
172                 //              Removes a node from its parent, clobbering it and all of its
173                 //              children.
174                 //
175                 // description:
176                 //              Removes a node from its parent, clobbering it and all of its
177                 //              children. Function only works with DomNodes, and returns nothing.
178                 //
179                 // node: DOMNode|String
180                 //              A String ID or DomNode reference of the element to be destroyed
181                 //
182                 // example:
183                 //              Destroy a node byId:
184                 //      |       dojo.destroy("someId");
185                 //
186                 // example:
187                 //              Destroy all nodes in a list by reference:
188                 //      |       dojo.query(".someNode").forEach(dojo.destroy);
189         };
190         =====*/
191
192         /*=====
193         dojo._destroyElement = function(node){
194                 // summary:
195                 //              Existing alias for `dojo.destroy`. Deprecated, will be removed in 2.0.
196         };
197         =====*/
198
199         // support stuff for dojo.toDom
200         var tagWrap = {
201                         option: ["select"],
202                         tbody: ["table"],
203                         thead: ["table"],
204                         tfoot: ["table"],
205                         tr: ["table", "tbody"],
206                         td: ["table", "tbody", "tr"],
207                         th: ["table", "thead", "tr"],
208                         legend: ["fieldset"],
209                         caption: ["table"],
210                         colgroup: ["table"],
211                         col: ["table", "colgroup"],
212                         li: ["ul"]
213                 },
214                 reTag = /<\s*([\w\:]+)/,
215                 masterNode = {}, masterNum = 0,
216                 masterName = "__" + dojo._scopeName + "ToDomId";
217
218         // generate start/end tag strings to use
219         // for the injection for each special tag wrap case.
220         for(var param in tagWrap){
221                 if(tagWrap.hasOwnProperty(param)){
222                         var tw = tagWrap[param];
223                         tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
224                         tw.post = "</" + tw.reverse().join("></") + ">";
225                         // the last line is destructive: it reverses the array,
226                         // but we don't care at this point
227                 }
228         }
229
230         function _insertBefore(/*DomNode*/node, /*DomNode*/ref){
231                 var parent = ref.parentNode;
232                 if(parent){
233                         parent.insertBefore(node, ref);
234                 }
235         }
236
237         function _insertAfter(/*DomNode*/node, /*DomNode*/ref){
238                 // summary:
239                 //              Try to insert node after ref
240                 var parent = ref.parentNode;
241                 if(parent){
242                         if(parent.lastChild == ref){
243                                 parent.appendChild(node);
244                         }else{
245                                 parent.insertBefore(node, ref.nextSibling);
246                         }
247                 }
248         }
249
250         var _destroyContainer = null,
251                 _destroyDoc;
252                 on(window, "unload", function(){
253                 _destroyContainer = null; //prevent IE leak
254         });
255         
256         exports.toDom = function toDom(frag, doc){
257                 doc = doc || win.doc;
258                 var masterId = doc[masterName];
259                 if(!masterId){
260                         doc[masterName] = masterId = ++masterNum + "";
261                         masterNode[masterId] = doc.createElement("div");
262                 }
263
264                 // make sure the frag is a string.
265                 frag += "";
266
267                 // find the starting tag, and get node wrapper
268                 var match = frag.match(reTag),
269                         tag = match ? match[1].toLowerCase() : "",
270                         master = masterNode[masterId],
271                         wrap, i, fc, df;
272                 if(match && tagWrap[tag]){
273                         wrap = tagWrap[tag];
274                         master.innerHTML = wrap.pre + frag + wrap.post;
275                         for(i = wrap.length; i; --i){
276                                 master = master.firstChild;
277                         }
278                 }else{
279                         master.innerHTML = frag;
280                 }
281
282                 // one node shortcut => return the node itself
283                 if(master.childNodes.length == 1){
284                         return master.removeChild(master.firstChild); // DOMNode
285                 }
286
287                 // return multiple nodes as a document fragment
288                 df = doc.createDocumentFragment();
289                 while(fc = master.firstChild){ // intentional assignment
290                         df.appendChild(fc);
291                 }
292                 return df; // DOMNode
293         };
294
295         exports.place = function place(/*DOMNode|String*/node, /*DOMNode|String*/refNode, /*String|Number?*/position){
296                 refNode = dom.byId(refNode);
297                 if(typeof node == "string"){ // inline'd type check
298                         node = /^\s*</.test(node) ? exports.toDom(node, refNode.ownerDocument) : dom.byId(node);
299                 }
300                 if(typeof position == "number"){ // inline'd type check
301                         var cn = refNode.childNodes;
302                         if(!cn.length || cn.length <= position){
303                                 refNode.appendChild(node);
304                         }else{
305                                 _insertBefore(node, cn[position < 0 ? 0 : position]);
306                         }
307                 }else{
308                         switch(position){
309                                 case "before":
310                                         _insertBefore(node, refNode);
311                                         break;
312                                 case "after":
313                                         _insertAfter(node, refNode);
314                                         break;
315                                 case "replace":
316                                         refNode.parentNode.replaceChild(node, refNode);
317                                         break;
318                                 case "only":
319                                         exports.empty(refNode);
320                                         refNode.appendChild(node);
321                                         break;
322                                 case "first":
323                                         if(refNode.firstChild){
324                                                 _insertBefore(node, refNode.firstChild);
325                                                 break;
326                                         }
327                                         // else fallthrough...
328                                 default: // aka: last
329                                         refNode.appendChild(node);
330                         }
331                 }
332                 return node; // DomNode
333         };
334
335         exports.create = function create(/*DOMNode|String*/tag, /*Object*/attrs, /*DOMNode?|String?*/refNode, /*String?*/pos){
336                 var doc = win.doc;
337                 if(refNode){
338                         refNode = dom.byId(refNode);
339                         doc = refNode.ownerDocument;
340                 }
341                 if(typeof tag == "string"){ // inline'd type check
342                         tag = doc.createElement(tag);
343                 }
344                 if(attrs){ attr.set(tag, attrs); }
345                 if(refNode){ exports.place(tag, refNode, pos); }
346                 return tag; // DomNode
347         };
348
349         exports.empty =
350                                 has("ie") ? function(node){
351                         node = dom.byId(node);
352                         for(var c; c = node.lastChild;){ // intentional assignment
353                                 exports.destroy(c);
354                         }
355                 } :
356                                 function(node){
357                         dom.byId(node).innerHTML = "";
358                 };
359
360         exports.destroy = function destroy(/*DOMNode|String*/node){
361                 node = dom.byId(node);
362                 try{
363                         var doc = node.ownerDocument;
364                         // cannot use _destroyContainer.ownerDocument since this can throw an exception on IE
365                         if(!_destroyContainer || _destroyDoc != doc){
366                                 _destroyContainer = doc.createElement("div");
367                                 _destroyDoc = doc;
368                         }
369                         _destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node);
370                         // NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature
371                         _destroyContainer.innerHTML = "";
372                 }catch(e){
373                         /* squelch */
374                 }
375         };
376 });