]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/dom-construct.js.uncompressed.js
make precache_headlines_idle() start slower
[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 });