author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
commit | ef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (unidiff) | |
tree | c403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/beta/js/Clipperz/YUI/DomHelper.js | |
parent | 597ecfbc0249d83e1b856cbd558340c01237a360 (diff) | |
download | clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2 |
First version of the newly restructured repository
Diffstat (limited to 'frontend/beta/js/Clipperz/YUI/DomHelper.js') (more/less context) (show whitespace changes)
-rw-r--r-- | frontend/beta/js/Clipperz/YUI/DomHelper.js | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/frontend/beta/js/Clipperz/YUI/DomHelper.js b/frontend/beta/js/Clipperz/YUI/DomHelper.js new file mode 100644 index 0000000..4f8acde --- a/dev/null +++ b/frontend/beta/js/Clipperz/YUI/DomHelper.js | |||
@@ -0,0 +1,465 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz's Javascript Crypto Library. | ||
6 | Javascript Crypto Library provides web developers with an extensive | ||
7 | and efficient set of cryptographic functions. The library aims to | ||
8 | obtain maximum execution speed while preserving modularity and | ||
9 | reusability. | ||
10 | For further information about its features and functionalities please | ||
11 | refer to http://www.clipperz.com | ||
12 | |||
13 | * Javascript Crypto Library is free software: you can redistribute | ||
14 | it and/or modify it under the terms of the GNU Affero General Public | ||
15 | License as published by the Free Software Foundation, either version | ||
16 | 3 of the License, or (at your option) any later version. | ||
17 | |||
18 | * Javascript Crypto Library is distributed in the hope that it will | ||
19 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
20 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
21 | See the GNU Affero General Public License for more details. | ||
22 | |||
23 | * You should have received a copy of the GNU Affero General Public | ||
24 | License along with Javascript Crypto Library. If not, see | ||
25 | <http://www.gnu.org/licenses/>. | ||
26 | |||
27 | */ | ||
28 | |||
29 | if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||
30 | if (typeof(Clipperz.ext) == 'undefined') { Clipperz.ext = {}; } | ||
31 | |||
32 | /** | ||
33 | * @class Clipperz.YUI.DomHelper | ||
34 | * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM. | ||
35 | * 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>. | ||
36 | * @singleton | ||
37 | */ | ||
38 | Clipperz.YUI.DomHelper = new function(){ | ||
39 | /**@private*/ | ||
40 | var d = document; | ||
41 | var tempTableEl = null; | ||
42 | /** True to force the use of DOM instead of html fragments @type Boolean */ | ||
43 | this.useDom = false; | ||
44 | 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; | ||
45 | /** | ||
46 | * Applies a style specification to an element | ||
47 | * @param {String/HTMLElement} el The element to apply styles to | ||
48 | * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or | ||
49 | * a function which returns such a specification. | ||
50 | */ | ||
51 | this.applyStyles = function(el, styles){ | ||
52 | if(styles){ | ||
53 | var D = YAHOO.util.Dom; | ||
54 | if (typeof styles == "string"){ | ||
55 | var re = /\s?([a-z\-]*)\:([^;]*);?/gi; | ||
56 | var matches; | ||
57 | while ((matches = re.exec(styles)) != null){ | ||
58 | D.setStyle(el, matches[1], matches[2]); | ||
59 | } | ||
60 | }else if (typeof styles == "object"){ | ||
61 | for (var style in styles){ | ||
62 | D.setStyle(el, style, styles[style]); | ||
63 | } | ||
64 | }else if (typeof styles == "function"){ | ||
65 | Clipperz.YUI.DomHelper.applyStyles(el, styles.call()); | ||
66 | } | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | // build as innerHTML where available | ||
71 | /** @ignore */ | ||
72 | var createHtml = function(o){ | ||
73 | var b = ''; | ||
74 | |||
75 | if(typeof(o['html']) != 'undefined') { | ||
76 | o['html'] = Clipperz.Base.sanitizeString(o['html']); | ||
77 | } else if (typeof(o['htmlString']) != 'undefined') { | ||
78 | o['html'] = o['htmlString']; | ||
79 | delete o.htmlString; | ||
80 | } | ||
81 | |||
82 | b += '<' + o.tag; | ||
83 | for(var attr in o){ | ||
84 | if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue; | ||
85 | if(attr == 'style'){ | ||
86 | var s = o['style']; | ||
87 | if(typeof s == 'function'){ | ||
88 | s = s.call(); | ||
89 | } | ||
90 | if(typeof s == 'string'){ | ||
91 | b += ' style="' + s + '"'; | ||
92 | }else if(typeof s == 'object'){ | ||
93 | b += ' style="'; | ||
94 | for(var key in s){ | ||
95 | if(typeof s[key] != 'function'){ | ||
96 | b += key + ':' + s[key] + ';'; | ||
97 | } | ||
98 | } | ||
99 | b += '"'; | ||
100 | } | ||
101 | }else{ | ||
102 | if(attr == 'cls'){ | ||
103 | b += ' class="' + o['cls'] + '"'; | ||
104 | }else if(attr == 'htmlFor'){ | ||
105 | b += ' for="' + o['htmlFor'] + '"'; | ||
106 | }else{ | ||
107 | b += ' ' + attr + '="' + o[attr] + '"'; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | if(emptyTags.test(o.tag)){ | ||
112 | b += ' />'; | ||
113 | }else{ | ||
114 | b += '>'; | ||
115 | if(o.children){ | ||
116 | for(var i = 0, len = o.children.length; i < len; i++) { | ||
117 | b += createHtml(o.children[i], b); | ||
118 | } | ||
119 | } | ||
120 | if(o.html){ | ||
121 | b += o.html; | ||
122 | } | ||
123 | b += '</' + o.tag + '>'; | ||
124 | } | ||
125 | return b; | ||
126 | } | ||
127 | |||
128 | // build as dom | ||
129 | /** @ignore */ | ||
130 | var createDom = function(o, parentNode){ | ||
131 | var el = d.createElement(o.tag); | ||
132 | var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute | ||
133 | for(var attr in o){ | ||
134 | if(attr == 'tag' || attr == 'children' || attr == 'html' || attr == 'style' || typeof o[attr] == 'function') continue; | ||
135 | if(attr=='cls'){ | ||
136 | el.className = o['cls']; | ||
137 | }else{ | ||
138 | if(useSet) el.setAttribute(attr, o[attr]); | ||
139 | else el[attr] = o[attr]; | ||
140 | } | ||
141 | } | ||
142 | Clipperz.YUI.DomHelper.applyStyles(el, o.style); | ||
143 | if(o.children){ | ||
144 | for(var i = 0, len = o.children.length; i < len; i++) { | ||
145 | createDom(o.children[i], el); | ||
146 | } | ||
147 | } | ||
148 | if(o.html){ | ||
149 | el.innerHTML = o.html; | ||
150 | } | ||
151 | if(parentNode){ | ||
152 | parentNode.appendChild(el); | ||
153 | } | ||
154 | return el; | ||
155 | }; | ||
156 | |||
157 | /** | ||
158 | * @ignore | ||
159 | * Nasty code for IE's broken table implementation | ||
160 | */ | ||
161 | var insertIntoTable = function(tag, where, el, html){ | ||
162 | if(!tempTableEl){ | ||
163 | tempTableEl = document.createElement('div'); | ||
164 | } | ||
165 | var node; | ||
166 | if(tag == 'table' || tag == 'tbody'){ | ||
167 | tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>'; | ||
168 | node = tempTableEl.firstChild.firstChild.firstChild; | ||
169 | }else{ | ||
170 | tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>'; | ||
171 | node = tempTableEl.firstChild.firstChild.firstChild.firstChild; | ||
172 | } | ||
173 | if(where == 'beforebegin'){ | ||
174 | el.parentNode.insertBefore(node, el); | ||
175 | return node; | ||
176 | }else if(where == 'afterbegin'){ | ||
177 | el.insertBefore(node, el.firstChild); | ||
178 | return node; | ||
179 | }else if(where == 'beforeend'){ | ||
180 | el.appendChild(node); | ||
181 | return node; | ||
182 | }else if(where == 'afterend'){ | ||
183 | el.parentNode.insertBefore(node, el.nextSibling); | ||
184 | return node; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Inserts an HTML fragment into the Dom | ||
190 | * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd. | ||
191 | * @param {HTMLElement} el The context element | ||
192 | * @param {String} html The HTML fragmenet | ||
193 | * @return {HTMLElement} The new node | ||
194 | */ | ||
195 | this.insertHtml = function(where, el, html){ | ||
196 | where = where.toLowerCase(); | ||
197 | if(el.insertAdjacentHTML){ | ||
198 | var tag = el.tagName.toLowerCase(); | ||
199 | if(tag == 'table' || tag == 'tbody' || tag == 'tr'){ | ||
200 | return insertIntoTable(tag, where, el, html); | ||
201 | } | ||
202 | switch(where){ | ||
203 | case 'beforebegin': | ||
204 | el.insertAdjacentHTML(where, html); | ||
205 | return el.previousSibling; | ||
206 | case 'afterbegin': | ||
207 | el.insertAdjacentHTML(where, html); | ||
208 | return el.firstChild; | ||
209 | case 'beforeend': | ||
210 | el.insertAdjacentHTML(where, html); | ||
211 | return el.lastChild; | ||
212 | case 'afterend': | ||
213 | el.insertAdjacentHTML(where, html); | ||
214 | return el.nextSibling; | ||
215 | } | ||
216 | throw 'Illegal insertion point -> "' + where + '"'; | ||
217 | } | ||
218 | var range = el.ownerDocument.createRange(); | ||
219 | var frag; | ||
220 | switch(where){ | ||
221 | case 'beforebegin': | ||
222 | range.setStartBefore(el); | ||
223 | frag = range.createContextualFragment(html); | ||
224 | el.parentNode.insertBefore(frag, el); | ||
225 | return el.previousSibling; | ||
226 | case 'afterbegin': | ||
227 | if(el.firstChild){ // faster | ||
228 | range.setStartBefore(el.firstChild); | ||
229 | }else{ | ||
230 | range.selectNodeContents(el); | ||
231 | range.collapse(true); | ||
232 | } | ||
233 | frag = range.createContextualFragment(html); | ||
234 | el.insertBefore(frag, el.firstChild); | ||
235 | return el.firstChild; | ||
236 | case 'beforeend': | ||
237 | if(el.lastChild){ | ||
238 | range.setStartAfter(el.lastChild); // faster | ||
239 | }else{ | ||
240 | range.selectNodeContents(el); | ||
241 | range.collapse(false); | ||
242 | } | ||
243 | frag = range.createContextualFragment(html); | ||
244 | el.appendChild(frag); | ||
245 | return el.lastChild; | ||
246 | case 'afterend': | ||
247 | range.setStartAfter(el); | ||
248 | frag = range.createContextualFragment(html); | ||
249 | el.parentNode.insertBefore(frag, el.nextSibling); | ||
250 | return el.nextSibling; | ||
251 | } | ||
252 | throw 'Illegal insertion point -> "' + where + '"'; | ||
253 | }; | ||
254 | |||
255 | /** | ||
256 | * Creates new Dom element(s) and inserts them before el | ||
257 | * @param {String/HTMLElement/Element} el The context element | ||
258 | * @param {Object} o The Dom object spec (and children) | ||
259 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
260 | * @return {HTMLElement} The new node | ||
261 | */ | ||
262 | this.insertBefore = function(el, o, returnElement){ | ||
263 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
264 | var newNode; | ||
265 | if(this.useDom){ | ||
266 | newNode = createDom(o, null); | ||
267 | el.parentNode.insertBefore(newNode, el); | ||
268 | }else{ | ||
269 | var html = createHtml(o); | ||
270 | newNode = this.insertHtml('beforeBegin', el, html); | ||
271 | } | ||
272 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
273 | }; | ||
274 | |||
275 | /** | ||
276 | * Creates new Dom element(s) and inserts them after el | ||
277 | * @param {String/HTMLElement/Element} el The context element | ||
278 | * @param {Object} o The Dom object spec (and children) | ||
279 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
280 | * @return {HTMLElement} The new node | ||
281 | */ | ||
282 | this.insertAfter = function(el, o, returnElement){ | ||
283 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
284 | var newNode; | ||
285 | if(this.useDom){ | ||
286 | newNode = createDom(o, null); | ||
287 | el.parentNode.insertBefore(newNode, el.nextSibling); | ||
288 | }else{ | ||
289 | var html = createHtml(o); | ||
290 | newNode = this.insertHtml('afterEnd', el, html); | ||
291 | } | ||
292 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
293 | }; | ||
294 | |||
295 | /** | ||
296 | * Creates new Dom element(s) and appends them to el | ||
297 | * @param {String/HTMLElement/Element} el The context element | ||
298 | * @param {Object} o The Dom object spec (and children) | ||
299 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
300 | * @return {HTMLElement} The new node | ||
301 | */ | ||
302 | this.append = function(el, o, returnElement){ | ||
303 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
304 | var newNode; | ||
305 | if(this.useDom){ | ||
306 | newNode = createDom(o, null); | ||
307 | el.appendChild(newNode); | ||
308 | }else{ | ||
309 | var html = createHtml(o); | ||
310 | newNode = this.insertHtml('beforeEnd', el, html); | ||
311 | } | ||
312 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
313 | }; | ||
314 | |||
315 | /** | ||
316 | * Creates new Dom element(s) and overwrites the contents of el with them | ||
317 | * @param {String/HTMLElement/Element} el The context element | ||
318 | * @param {Object} o The Dom object spec (and children) | ||
319 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
320 | * @return {HTMLElement} The new node | ||
321 | */ | ||
322 | this.overwrite = function(el, o, returnElement){ | ||
323 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
324 | el.innerHTML = createHtml(o); | ||
325 | return returnElement ? YAHOO.ext.Element.get(el.firstChild, true) : el.firstChild; | ||
326 | }; | ||
327 | |||
328 | /** | ||
329 | * Creates a new Clipperz.YUI.DomHelper.Template from the Dom object spec | ||
330 | * @param {Object} o The Dom object spec (and children) | ||
331 | * @return {Clipperz.YUI.DomHelper.Template} The new template | ||
332 | */ | ||
333 | this.createTemplate = function(o){ | ||
334 | var html = createHtml(o); | ||
335 | return new Clipperz.YUI.DomHelper.Template(html); | ||
336 | }; | ||
337 | }(); | ||
338 | |||
339 | /** | ||
340 | * @class Clipperz.YUI.DomHelper.Template | ||
341 | * Represents an HTML fragment template. | ||
342 | * 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>. | ||
343 | * <br> | ||
344 | * <b>This class is also available as YAHOO.ext.Template</b>. | ||
345 | * @constructor | ||
346 | * @param {String/Array} html The HTML fragment or an array of fragments to join('') or multiple arguments to join('') | ||
347 | */ | ||
348 | Clipperz.YUI.DomHelper.Template = function(html){ | ||
349 | if(html instanceof Array){ | ||
350 | html = html.join(''); | ||
351 | }else if(arguments.length > 1){ | ||
352 | html = Array.prototype.join.call(arguments, ''); | ||
353 | } | ||
354 | /**@private*/ | ||
355 | this.html = html; | ||
356 | }; | ||
357 | Clipperz.YUI.DomHelper.Template.prototype = { | ||
358 | /** | ||
359 | * Returns an HTML fragment of this template with the specified values applied | ||
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 | * @return {String} | ||
362 | */ | ||
363 | applyTemplate : function(values){ | ||
364 | if(this.compiled){ | ||
365 | return this.compiled(values); | ||
366 | } | ||
367 | var empty = ''; | ||
368 | var fn = function(match, index){ | ||
369 | if(typeof values[index] != 'undefined'){ | ||
370 | return values[index]; | ||
371 | }else{ | ||
372 | return empty; | ||
373 | } | ||
374 | } | ||
375 | return this.html.replace(this.re, fn); | ||
376 | }, | ||
377 | |||
378 | /** | ||
379 | * The regular expression used to match template variables | ||
380 | * @type RegExp | ||
381 | * @property | ||
382 | */ | ||
383 | re : /\{([\w|-]+)\}/g, | ||
384 | |||
385 | /** | ||
386 | * Compiles the template into an internal function, eliminating the RegEx overhead | ||
387 | */ | ||
388 | compile : function(){ | ||
389 | var body = ["this.compiled = function(values){ return ['"]; | ||
390 | body.push(this.html.replace(this.re, "', values['$1'], '")); | ||
391 | body.push("'].join('');};"); | ||
392 | eval(body.join('')); | ||
393 | return this; | ||
394 | }, | ||
395 | |||
396 | /** | ||
397 | * Applies the supplied values to the template and inserts the new node(s) before el | ||
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 | insertBefore: function(el, values, returnElement){ | ||
404 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
405 | var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeBegin', el, this.applyTemplate(values)); | ||
406 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
407 | }, | ||
408 | |||
409 | /** | ||
410 | * Applies the supplied values to the template and inserts the new node(s) after el | ||
411 | * @param {String/HTMLElement/Element} el The context element | ||
412 | * @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'}) | ||
413 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
414 | * @return {HTMLElement} The new node | ||
415 | */ | ||
416 | insertAfter : function(el, values, returnElement){ | ||
417 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
418 | var newNode = Clipperz.YUI.DomHelper.insertHtml('afterEnd', el, this.applyTemplate(values)); | ||
419 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
420 | }, | ||
421 | |||
422 | /** | ||
423 | * Applies the supplied values to the template and append the new node(s) to el | ||
424 | * @param {String/HTMLElement/Element} el The context element | ||
425 | * @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'}) | ||
426 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
427 | * @return {HTMLElement} The new node | ||
428 | */ | ||
429 | append : function(el, values, returnElement){ | ||
430 | var sanitizedValues; | ||
431 | var key; | ||
432 | |||
433 | // sanitizedValues = MochiKit.Base.map(sanitizedValues) | ||
434 | //console.log("values", values); | ||
435 | sanitizedValues = {}; | ||
436 | for (key in values) { | ||
437 | sanitizedValues[key] = Clipperz.Base.sanitizeString(values[key]); | ||
438 | } | ||
439 | //console.log("sanitizedValues", sanitizedValues); | ||
440 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
441 | var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(sanitizedValues)); | ||
442 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
443 | }, | ||
444 | |||
445 | /** | ||
446 | * Applies the supplied values to the template and overwrites the content of el with the new node(s) | ||
447 | * @param {String/HTMLElement/Element} el The context element | ||
448 | * @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'}) | ||
449 | * @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.ext.Element | ||
450 | * @return {HTMLElement} The new node | ||
451 | */ | ||
452 | overwrite : function(el, values, returnElement){ | ||
453 | el = el.dom ? el.dom : YAHOO.util.Dom.get(el); | ||
454 | el.innerHTML = ''; | ||
455 | var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values)); | ||
456 | return returnElement ? YAHOO.ext.Element.get(newNode, true) : newNode; | ||
457 | } | ||
458 | }; | ||
459 | /** | ||
460 | * Alias for applyTemplate | ||
461 | * @method | ||
462 | */ | ||
463 | Clipperz.YUI.DomHelper.Template.prototype.apply = Clipperz.YUI.DomHelper.Template.prototype.applyTemplate; | ||
464 | |||
465 | YAHOO.ext.Template = Clipperz.YUI.DomHelper.Template; | ||