summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/DomHelper.js
Unidiff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/DomHelper.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/YUI-extensions/DomHelper.js416
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 */
7YAHOO.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*/
309YAHOO.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};
318YAHOO.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 */
414YAHOO.ext.DomHelper.Template.prototype.apply = YAHOO.ext.DomHelper.Template.prototype.applyTemplate;
415
416YAHOO.ext.Template = YAHOO.ext.DomHelper.Template;