author | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
commit | 541bb378ddece2eab135a8066a16994e94436dea (patch) (unidiff) | |
tree | ff160ea3e26f7fe07fcfd401387c5a0232ca715e /frontend/beta/js/YUI-extensions/DomHelper.js | |
parent | 1bf431fd3d45cbdf4afa3e12afefe5d24f4d3bc7 (diff) | |
parent | ecad5e895831337216544e81f1a467e0c68c4a6a (diff) | |
download | clipperz-541bb378ddece2eab135a8066a16994e94436dea.zip clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.gz clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.bz2 |
Merge pull request #1 from gcsolaroli/master
First version of the restructured repository
Diffstat (limited to 'frontend/beta/js/YUI-extensions/DomHelper.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/YUI-extensions/DomHelper.js | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/DomHelper.js b/frontend/beta/js/YUI-extensions/DomHelper.js new file mode 100644 index 0000000..d9e7484 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/DomHelper.js | |||
@@ -0,0 +1,416 @@ | |||
1 | /** | ||
2 | * @class YAHOO.ext.DomHelper | ||
3 | * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM. | ||
4 | * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>. | ||
5 | * @singleton | ||
6 | */ | ||
7 | YAHOO.ext.DomHelper = new function(){ | ||
8 | /**@private*/ | ||
9 | var d = document; | ||
10 | var tempTableEl = null; | ||
11 | /** True to force the use of DOM instead of html fragments @type Boolean */ | ||
12 | this.useDom = false; | ||
13 | var emptyTags = /^(?:base|basefont|br|frame|hr|img|input|isindex|link|meta|nextid|range|spacer|wbr|audioscope|area|param|keygen|col|limittext|spot|tab|over|right|left|choose|atop|of)$/i; | ||
14 | /** | ||
15 | * Applies a style specification to an element | ||
16 | * @param {String/HTMLElement} el The element to apply styles to | ||
17 | * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or | ||
18 | * a function which returns such a specification. | ||
19 | */ | ||
20 | this.applyStyles = function(el, styles){ | ||
21 | if(styles){ | ||
22 | var D = YAHOO.util.Dom; | ||
23 | if (typeof styles == "string"){ | ||
24 | var re = /\s?([a-z\-]*)\:([^;]*);?/gi; | ||
25 | var matches; | ||
26 | while ((matches = re.exec(styles)) != null){ | ||
27 | D.setStyle(el, matches[1], matches[2]); | ||
28 | } | ||
29 | }else if (typeof styles == "object"){ | ||
30 | for (var style in styles){ | ||
31 | D.setStyle(el, style, styles[style]); | ||
32 | } | ||
33 | }else if (typeof styles == "function"){ | ||
34 | YAHOO.ext.DomHelper.applyStyles(el, styles.call()); | ||
35 | } | ||
36 | } | ||
37 | }; | ||
38 | |||
39 | // build as innerHTML where available | ||
40 | /** @ignore */ | ||
41 | var createHtml = function(o){ | ||
42 | var b = ''; | ||
43 | b += '<' + o.tag; | ||
44 | for(var attr in o){ | ||
45 | if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue; | ||
46 | if(attr == 'style'){ | ||
47 | var s = o['style']; | ||
48 | if(typeof s == 'function'){ | ||
49 | s = s.call(); | ||
50 | } | ||
51 | if(typeof s == 'string'){ | ||
52 | b += ' style="' + s + '"'; | ||
53 | }else if(typeof s == 'object'){ | ||
54 | b += ' style="'; | ||
55 | for(var key in s){ | ||
56 | if(typeof s[key] != 'function'){ | ||
57 | b += key + ':' + s[key] + ';'; | ||
58 | } | ||
59 | } | ||
60 | b += '"'; | ||
61 | } | ||
62 | }else{ | ||
63 | if(attr == 'cls'){ | ||
64 | b += ' class="' + o['cls'] + '"'; | ||
65 | }else if(attr == 'htmlFor'){ | ||
66 | b += ' for="' + o['htmlFor'] + '"'; | ||
67 | }else{ | ||
68 | b += ' ' + attr + '="' + o[attr] + '"'; | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | if(emptyTags.test(o.tag)){ | ||
73 | b += ' />'; | ||
74 | }else{ | ||
75 | b += '>'; | ||
76 | if(o.children){ | ||
77 | for(var i = 0, len = o.children.length; i < len; i++) { | ||
78 | b += createHtml(o.children[i], b); | ||
79 | } | ||
80 | } | ||
81 | if(o.html){ | ||
82 | b += o.html; | ||
83 | } | ||
84 | b += '</' + o.tag + '>'; | ||
85 | } | ||
86 | return b; | ||
87 | } | ||
88 | |||
89 | // build as dom | ||
90 | /** @ignore */ | ||
91 | var createDom = function(o, parentNode){ | ||
92 | var el = d.createElement(o.tag); | ||
93 | var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute | ||
94 | for(var attr in o){ | ||
95 | if(attr == 'tag' || attr == 'children' || attr == 'html' || attr == 'style' || typeof o[attr] == 'function') continue; | ||
96 | if(attr=='cls'){ | ||
97 | el.className = o['cls']; | ||
98 | }else{ | ||
99 | if(useSet) el.setAttribute(attr, o[attr]); | ||
100 | else el[attr] = o[attr]; | ||
101 | } | ||
102 | } | ||
103 | YAHOO.ext.DomHelper.applyStyles(el, o.style); | ||
104 | if(o.children){ | ||
105 | for(var i = 0, len = o.children.length; i < len; i++) { | ||
106 | createDom(o.children[i], el); | ||
107 | } | ||
108 | } | ||
109 | if(o.html){ | ||
110 | el.innerHTML = o.html; | ||
111 | } | ||
112 | if(parentNode){ | ||
113 | parentNode.appendChild(el); | ||
114 | } | ||
115 | return el; | ||
116 | }; | ||
117 | |||
118 | /** | ||
119 | * @ignore | ||
120 | * Nasty code for IE's broken table implementation | ||
121 | */ | ||
122 | var insertIntoTable = function(tag, where, el, html){ | ||
123 | if(!tempTableEl){ | ||
124 | tempTableEl = document.createElement('div'); | ||
125 | } | ||
126 | var node; | ||
127 | if(tag == 'table' || tag == 'tbody'){ | ||
128 | tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>'; | ||
129 | node = tempTableEl.firstChild.firstChild.firstChild; | ||
130 | }else{ | ||
131 | tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>'; | ||
132 | node = tempTableEl.firstChild.firstChild.firstChild.firstChild; | ||
133 | } | ||
134 | if(where == 'beforebegin'){ | ||
135 | el.parentNode.insertBefore(node, el); | ||
136 | return node; | ||
137 | }else if(where == 'afterbegin'){ | ||
138 | el.insertBefore(node, el.firstChild); | ||
139 | return node; | ||
140 | }else if(where == 'beforeend'){ | ||
141 | el.appendChild(node); | ||
142 | return node; | ||
143 | }else if(where == 'afterend'){ | ||
144 | el.parentNode.insertBefore(node, el.nextSibling); | ||
145 | return node; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * Inserts an HTML fragment into the Dom | ||
151 | * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd. | ||
152 | * @param {HTMLElement} el The context element | ||
153 | * @param {String} html The HTML fragmenet | ||
154 | * @return {HTMLElement} The new node | ||
155 | */ | ||
156 | this.insertHtml = function(where, el, html){ | ||
157 | where = where.toLowerCase(); | ||
158 | if(el.insertAdjacentHTML){ | ||
159 | var tag = el.tagName.toLowerCase(); | ||
160 | if(tag == 'table' || tag == 'tbody' || tag == 'tr'){ | ||
161 | return insertIntoTable(tag, where, el, html); | ||
162 | } | ||
163 | switch(where){ | ||
164 | case 'beforebegin': | ||
165 | el.insertAdjacentHTML(where, html); | ||
166 | return el.previousSibling; | ||
167 | case 'afterbegin': | ||
168 | el.insertAdjacentHTML(where, html); | ||
169 | return el.firstChild; | ||
170 | case 'beforeend': | ||
171 | el.insertAdjacentHTML(where, html); | ||
172 | return el.lastChild; | ||
173 | case 'afterend': | ||
174 | el.insertAdjacentHTML(where, html); | ||
175 | return el.nextSibling; | ||
176 | } | ||
177 | throw 'Illegal insertion point -> "' + where + '"'; | ||
178 | } | ||
179 | var range = el.ownerDocument.createRange(); | ||
180 | var frag; | ||
181 | switch(where){ | ||
182 | case 'beforebegin': | ||
183 | range.setStartBefore(el); | ||
184 | frag = range.createContextualFragment(html); | ||
185 | el.parentNode.insertBefore(frag, el); | ||
186 | return el.previousSibling; | ||
187 | case 'afterbegin': | ||
188 | if(el.firstChild){ // faster | ||
189 | range.setStartBefore(el.firstChild); | ||
190 | }else{ | ||
191 | range.selectNodeContents(el); | ||
192 | range.collapse(true); | ||
193 | } | ||
194 | frag = range.createContextualFragment(html); | ||
195 | el.insertBefore(frag, el.firstChild); | ||
196 | return el.firstChild; | ||
197 | case 'beforeend': | ||
198 | if(el.lastChild){ | ||
199 | range.setStartAfter(el.lastChild); // faster | ||
200 | }else{ | ||
201 | range.selectNodeContents(el); | ||
202 | range.collapse(false); | ||
203 | } | ||
204 | frag = range.createContextualFragment(html); | ||
205 | el.appendChild(frag); | ||
206 | return el.lastChild; | ||
207 | case 'afterend': | ||
208 | range.setStartAfter(el); | ||
209 | frag = range.createContextualFragment(html); | ||
210 | el.parentNode.insertBefore(frag, el.nextSibling); | ||
211 | return el.nextSibling; | ||
212 | } | ||
213 | throw 'Illegal insertion point -> "' + where + '"'; | ||
214 | }; | ||
215 | |||
216 | /** | ||
217 | * Creates new Dom element(s) and inserts them before el | ||
218 | * @param {String/HTMLElement/Element} el The context element | ||
219 | * @param {Object} o The Dom object spec (and children) | ||
220 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
221 | * @return {HTMLElement} The new node | ||
222 | */ | ||
223 | this.insertBefore = function(el, o, returnElement){ | ||
224 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
225 | var newNode; | ||
226 | if(this.useDom){ | ||
227 | newNode = createDom(o, null); | ||
228 | el.parentNode.insertBefore(newNode, el); | ||
229 | }else{ | ||
230 | var html = createHtml(o); | ||
231 | newNode = this.insertHtml('beforeBegin', el, html); | ||
232 | } | ||
233 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
234 | }; | ||
235 | |||
236 | /** | ||
237 | * Creates new Dom element(s) and inserts them after el | ||
238 | * @param {String/HTMLElement/Element} el The context element | ||
239 | * @param {Object} o The Dom object spec (and children) | ||
240 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
241 | * @return {HTMLElement} The new node | ||
242 | */ | ||
243 | this.insertAfter = function(el, o, returnElement){ | ||
244 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
245 | var newNode; | ||
246 | if(this.useDom){ | ||
247 | newNode = createDom(o, null); | ||
248 | el.parentNode.insertBefore(newNode, el.nextSibling); | ||
249 | }else{ | ||
250 | var html = createHtml(o); | ||
251 | newNode = this.insertHtml('afterEnd', el, html); | ||
252 | } | ||
253 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
254 | }; | ||
255 | |||
256 | /** | ||
257 | * Creates new Dom element(s) and appends them to el | ||
258 | * @param {String/HTMLElement/Element} el The context element | ||
259 | * @param {Object} o The Dom object spec (and children) | ||
260 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
261 | * @return {HTMLElement} The new node | ||
262 | */ | ||
263 | this.append = function(el, o, returnElement){ | ||
264 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
265 | var newNode; | ||
266 | if(this.useDom){ | ||
267 | newNode = createDom(o, null); | ||
268 | el.appendChild(newNode); | ||
269 | }else{ | ||
270 | var html = createHtml(o); | ||
271 | newNode = this.insertHtml('beforeEnd', el, html); | ||
272 | } | ||
273 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
274 | }; | ||
275 | |||
276 | /** | ||
277 | * Creates new Dom element(s) and overwrites the contents of el with them | ||
278 | * @param {String/HTMLElement/Element} el The context element | ||
279 | * @param {Object} o The Dom object spec (and children) | ||
280 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
281 | * @return {HTMLElement} The new node | ||
282 | */ | ||
283 | this.overwrite = function(el, o, returnElement){ | ||
284 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
285 | el.innerHTML = createHtml(o); | ||
286 | return returnElement ? YAHOO.ext.Element.get(el.firstChild, true) : el.firstChild; | ||
287 | }; | ||
288 | |||
289 | /** | ||
290 | * Creates a new YAHOO.ext.DomHelper.Template from the Dom object spec | ||
291 | * @param {Object} o The Dom object spec (and children) | ||
292 | * @return {YAHOO.ext.DomHelper.Template} The new template | ||
293 | */ | ||
294 | this.createTemplate = function(o){ | ||
295 | var html = createHtml(o); | ||
296 | return new YAHOO.ext.DomHelper.Template(html); | ||
297 | }; | ||
298 | }(); | ||
299 | |||
300 | /** | ||
301 | * @class YAHOO.ext.DomHelper.Template | ||
302 | * Represents an HTML fragment template. | ||
303 | * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>. | ||
304 | * <br> | ||
305 | * <b>This class is also available as YAHOO.ext.Template</b>. | ||
306 | * @constructor | ||
307 | * @param {String/Array} html The HTML fragment or an array of fragments to join('') or multiple arguments to join('') | ||
308 | */ | ||
309 | YAHOO.ext.DomHelper.Template = function(html){ | ||
310 | if(html instanceof Array){ | ||
311 | html = html.join(''); | ||
312 | }else if(arguments.length > 1){ | ||
313 | html = Array.prototype.join.call(arguments, ''); | ||
314 | } | ||
315 | /**@private*/ | ||
316 | this.html = html; | ||
317 | }; | ||
318 | YAHOO.ext.DomHelper.Template.prototype = { | ||
319 | /** | ||
320 | * Returns an HTML fragment of this template with the specified values applied | ||
321 | * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'}) | ||
322 | * @return {String} | ||
323 | */ | ||
324 | applyTemplate : function(values){ | ||
325 | if(this.compiled){ | ||
326 | return this.compiled(values); | ||
327 | } | ||
328 | var empty = ''; | ||
329 | var fn = function(match, index){ | ||
330 | if(typeof values[index] != 'undefined'){ | ||
331 | return values[index]; | ||
332 | }else{ | ||
333 | return empty; | ||
334 | } | ||
335 | } | ||
336 | return this.html.replace(this.re, fn); | ||
337 | }, | ||
338 | |||
339 | /** | ||
340 | * The regular expression used to match template variables | ||
341 | * @type RegExp | ||
342 | * @property | ||
343 | */ | ||
344 | re : /\{([\w|-]+)\}/g, | ||
345 | |||
346 | /** | ||
347 | * Compiles the template into an internal function, eliminating the RegEx overhead | ||
348 | */ | ||
349 | compile : function(){ | ||
350 | var body = ["this.compiled = function(values){ return ['"]; | ||
351 | body.push(this.html.replace(this.re, "', values['$1'], '")); | ||
352 | body.push("'].join('');};"); | ||
353 | eval(body.join('')); | ||
354 | return this; | ||
355 | }, | ||
356 | |||
357 | /** | ||
358 | * Applies the supplied values to the template and inserts the new node(s) before el | ||
359 | * @param {String/HTMLElement/Element} el The context element | ||
360 | * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'}) | ||
361 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
362 | * @return {HTMLElement} The new node | ||
363 | */ | ||
364 | insertBefore: function(el, values, returnElement){ | ||
365 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
366 | var newNode = YAHOO.ext.DomHelper.insertHtml('beforeBegin', el, this.applyTemplate(values)); | ||
367 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
368 | }, | ||
369 | |||
370 | /** | ||
371 | * Applies the supplied values to the template and inserts the new node(s) after el | ||
372 | * @param {String/HTMLElement/Element} el The context element | ||
373 | * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'}) | ||
374 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
375 | * @return {HTMLElement} The new node | ||
376 | */ | ||
377 | insertAfter : function(el, values, returnElement){ | ||
378 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
379 | var newNode = YAHOO.ext.DomHelper.insertHtml('afterEnd', el, this.applyTemplate(values)); | ||
380 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
381 | }, | ||
382 | |||
383 | /** | ||
384 | * Applies the supplied values to the template and append the new node(s) to el | ||
385 | * @param {String/HTMLElement/Element} el The context element | ||
386 | * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'}) | ||
387 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
388 | * @return {HTMLElement} The new node | ||
389 | */ | ||
390 | append : function(el, values, returnElement){ | ||
391 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
392 | var newNode = YAHOO.ext.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values)); | ||
393 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
394 | }, | ||
395 | |||
396 | /** | ||
397 | * Applies the supplied values to the template and overwrites the content of el with the new node(s) | ||
398 | * @param {String/HTMLElement/Element} el The context element | ||
399 | * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'}) | ||
400 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
401 | * @return {HTMLElement} The new node | ||
402 | */ | ||
403 | overwrite : function(el, values, returnElement){ | ||
404 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
405 | el.innerHTML = ''; | ||
406 | var newNode = YAHOO.ext.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values)); | ||
407 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
408 | } | ||
409 | }; | ||
410 | /** | ||
411 | * Alias for applyTemplate | ||
412 | * @method | ||
413 | */ | ||
414 | YAHOO.ext.DomHelper.Template.prototype.apply = YAHOO.ext.DomHelper.Template.prototype.applyTemplate; | ||
415 | |||
416 | YAHOO.ext.Template = YAHOO.ext.DomHelper.Template; | ||