1// script.aculo.us builder.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 2 3// Copyright (c) 2005-2009 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 arguments[1].tagName) { 53 this._children(element, arguments[1]); 54 } else { 55 var attrs = this._attributes(arguments[1]); 56 if(attrs.length) { 57 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 58 parentElement.innerHTML = "<" +elementName + " " + 59 attrs + "></" + elementName + ">"; 60 } catch(e) {} 61 element = parentElement.firstChild || null; 62 // workaround firefox 1.0.X bug 63 if(!element) { 64 element = document.createElement(elementName); 65 for(attr in arguments[1]) 66 element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; 67 } 68 if(element.tagName.toUpperCase() != elementName) 69 element = parentElement.getElementsByTagName(elementName)[0]; 70 } 71 } 72 73 // text, or array of children 74 if(arguments[2]) 75 this._children(element, arguments[2]); 76 77 return $(element); 78 }, 79 _text: function(text) { 80 return document.createTextNode(text); 81 }, 82 83 ATTR_MAP: { 84 'className': 'class', 85 'htmlFor': 'for' 86 }, 87 88 _attributes: function(attributes) { 89 var attrs = []; 90 for(attribute in attributes) 91 attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + 92 '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); 93 return attrs.join(" "); 94 }, 95 _children: function(element, children) { 96 if(children.tagName) { 97 element.appendChild(children); 98 return; 99 } 100 if(typeof children=='object') { // array can hold nodes and text 101 children.flatten().each( function(e) { 102 if(typeof e=='object') 103 element.appendChild(e); 104 else 105 if(Builder._isStringOrNumber(e)) 106 element.appendChild(Builder._text(e)); 107 }); 108 } else 109 if(Builder._isStringOrNumber(children)) 110 element.appendChild(Builder._text(children)); 111 }, 112 _isStringOrNumber: function(param) { 113 return(typeof param=='string' || typeof param=='number'); 114 }, 115 build: function(html) { 116 var element = this.node('div'); 117 $(element).update(html.strip()); 118 return element.down(); 119 }, 120 dump: function(scope) { 121 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 122 123 var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + 124 "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + 125 "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ 126 "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ 127 "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ 128 "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); 129 130 tags.each( function(tag){ 131 scope[tag] = function() { 132 return Builder.node.apply(Builder, [tag].concat($A(arguments))); 133 }; 134 }); 135 } 136};