1// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 2 3// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4// 5// script.aculo.us is freely distributable under the terms of an MIT-style license. 6// For details, see the script.aculo.us web site: http://script.aculo.us/ 7 8var Builder = { 9 NODEMAP: { 10 AREA: 'map', 11 CAPTION: 'table', 12 COL: 'table', 13 COLGROUP: 'table', 14 LEGEND: 'fieldset', 15 OPTGROUP: 'select', 16 OPTION: 'select', 17 PARAM: 'object', 18 TBODY: 'table', 19 TD: 'table', 20 TFOOT: 'table', 21 TH: 'table', 22 THEAD: 'table', 23 TR: 'table' 24 }, 25 // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, 26 // due to a Firefox bug 27 node: function(elementName) { 28 elementName = elementName.toUpperCase(); 29 30 // try innerHTML approach 31 var parentTag = this.NODEMAP[elementName] || 'div'; 32 var parentElement = document.createElement(parentTag); 33 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 34 parentElement.innerHTML = "<" + elementName + "></" + elementName + ">"; 35 } catch(e) {} 36 var element = parentElement.firstChild || null; 37 38 // see if browser added wrapping tags 39 if(element && (element.tagName.toUpperCase() != elementName)) 40 element = element.getElementsByTagName(elementName)[0]; 41 42 // fallback to createElement approach 43 if(!element) element = document.createElement(elementName); 44 45 // abort if nothing could be created 46 if(!element) return; 47 48 // attributes (or text) 49 if(arguments[1]) 50 if(this._isStringOrNumber(arguments[1]) || 51 (arguments[1] instanceof Array)) { 52 this._children(element, arguments[1]); 53 } else { 54 var attrs = this._attributes(arguments[1]); 55 if(attrs.length) { 56 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 57 parentElement.innerHTML = "<" +elementName + " " + 58 attrs + "></" + elementName + ">"; 59 } catch(e) {} 60 element = parentElement.firstChild || null; 61 // workaround firefox 1.0.X bug 62 if(!element) { 63 element = document.createElement(elementName); 64 for(attr in arguments[1]) 65 element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; 66 } 67 if(element.tagName.toUpperCase() != elementName) 68 element = parentElement.getElementsByTagName(elementName)[0]; 69 } 70 } 71 72 // text, or array of children 73 if(arguments[2]) 74 this._children(element, arguments[2]); 75 76 return element; 77 }, 78 _text: function(text) { 79 return document.createTextNode(text); 80 }, 81 82 ATTR_MAP: { 83 'className': 'class', 84 'htmlFor': 'for' 85 }, 86 87 _attributes: function(attributes) { 88 var attrs = []; 89 for(attribute in attributes) 90 attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + 91 '="' + attributes[attribute].toString().escapeHTML() + '"'); 92 return attrs.join(" "); 93 }, 94 _children: function(element, children) { 95 if(typeof children=='object') { // array can hold nodes and text 96 children.flatten().each( function(e) { 97 if(typeof e=='object') 98 element.appendChild(e) 99 else 100 if(Builder._isStringOrNumber(e)) 101 element.appendChild(Builder._text(e)); 102 }); 103 } else 104 if(Builder._isStringOrNumber(children)) 105 element.appendChild(Builder._text(children)); 106 }, 107 _isStringOrNumber: function(param) { 108 return(typeof param=='string' || typeof param=='number'); 109 }, 110 build: function(html) { 111 var element = this.node('div'); 112 $(element).update(html.strip()); 113 return element.down(); 114 }, 115 dump: function(scope) { 116 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 117 118 var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + 119 "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + 120 "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ 121 "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ 122 "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ 123 "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); 124 125 tags.each( function(tag){ 126 scope[tag] = function() { 127 return Builder.node.apply(Builder, [tag].concat($A(arguments))); 128 } 129 }); 130 } 131} 132