| [21] | 1 | // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
|---|
| 2 | // |
|---|
| 3 | // See scriptaculous.js for full license. |
|---|
| 4 | |
|---|
| 5 | var Builder = { |
|---|
| 6 | NODEMAP: { |
|---|
| 7 | AREA: 'map', |
|---|
| 8 | CAPTION: 'table', |
|---|
| 9 | COL: 'table', |
|---|
| 10 | COLGROUP: 'table', |
|---|
| 11 | LEGEND: 'fieldset', |
|---|
| 12 | OPTGROUP: 'select', |
|---|
| 13 | OPTION: 'select', |
|---|
| 14 | PARAM: 'object', |
|---|
| 15 | TBODY: 'table', |
|---|
| 16 | TD: 'table', |
|---|
| 17 | TFOOT: 'table', |
|---|
| 18 | TH: 'table', |
|---|
| 19 | THEAD: 'table', |
|---|
| 20 | TR: 'table' |
|---|
| 21 | }, |
|---|
| 22 | // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, |
|---|
| 23 | // due to a Firefox bug |
|---|
| 24 | node: function(elementName) { |
|---|
| 25 | elementName = elementName.toUpperCase(); |
|---|
| 26 | |
|---|
| 27 | // try innerHTML approach |
|---|
| 28 | var parentTag = this.NODEMAP[elementName] || 'div'; |
|---|
| 29 | var parentElement = document.createElement(parentTag); |
|---|
| 30 | try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 |
|---|
| 31 | parentElement.innerHTML = "<" + elementName + "></" + elementName + ">"; |
|---|
| 32 | } catch(e) {} |
|---|
| 33 | var element = parentElement.firstChild || null; |
|---|
| 34 | |
|---|
| 35 | // see if browser added wrapping tags |
|---|
| 36 | if(element && (element.tagName != elementName)) |
|---|
| 37 | element = element.getElementsByTagName(elementName)[0]; |
|---|
| 38 | |
|---|
| 39 | // fallback to createElement approach |
|---|
| 40 | if(!element) element = document.createElement(elementName); |
|---|
| 41 | |
|---|
| 42 | // abort if nothing could be created |
|---|
| 43 | if(!element) return; |
|---|
| 44 | |
|---|
| 45 | // attributes (or text) |
|---|
| 46 | if(arguments[1]) |
|---|
| 47 | if(this._isStringOrNumber(arguments[1]) || |
|---|
| 48 | (arguments[1] instanceof Array)) { |
|---|
| 49 | this._children(element, arguments[1]); |
|---|
| 50 | } else { |
|---|
| 51 | var attrs = this._attributes(arguments[1]); |
|---|
| 52 | if(attrs.length) { |
|---|
| 53 | try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 |
|---|
| 54 | parentElement.innerHTML = "<" +elementName + " " + |
|---|
| 55 | attrs + "></" + elementName + ">"; |
|---|
| 56 | } catch(e) {} |
|---|
| 57 | element = parentElement.firstChild || null; |
|---|
| 58 | // workaround firefox 1.0.X bug |
|---|
| 59 | if(!element) { |
|---|
| 60 | element = document.createElement(elementName); |
|---|
| 61 | for(attr in arguments[1]) |
|---|
| 62 | element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; |
|---|
| 63 | } |
|---|
| 64 | if(element.tagName != elementName) |
|---|
| 65 | element = parentElement.getElementsByTagName(elementName)[0]; |
|---|
| 66 | } |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | // text, or array of children |
|---|
| 70 | if(arguments[2]) |
|---|
| 71 | this._children(element, arguments[2]); |
|---|
| 72 | |
|---|
| 73 | return element; |
|---|
| 74 | }, |
|---|
| 75 | _text: function(text) { |
|---|
| 76 | return document.createTextNode(text); |
|---|
| 77 | }, |
|---|
| 78 | _attributes: function(attributes) { |
|---|
| 79 | var attrs = []; |
|---|
| 80 | for(attribute in attributes) |
|---|
| 81 | attrs.push((attribute=='className' ? 'class' : attribute) + |
|---|
| 82 | '="' + attributes[attribute].toString().escapeHTML() + '"'); |
|---|
| 83 | return attrs.join(" "); |
|---|
| 84 | }, |
|---|
| 85 | _children: function(element, children) { |
|---|
| 86 | if(typeof children=='object') { // array can hold nodes and text |
|---|
| 87 | children.flatten().each( function(e) { |
|---|
| 88 | if(typeof e=='object') |
|---|
| 89 | element.appendChild(e) |
|---|
| 90 | else |
|---|
| 91 | if(Builder._isStringOrNumber(e)) |
|---|
| 92 | element.appendChild(Builder._text(e)); |
|---|
| 93 | }); |
|---|
| 94 | } else |
|---|
| 95 | if(Builder._isStringOrNumber(children)) |
|---|
| 96 | element.appendChild(Builder._text(children)); |
|---|
| 97 | }, |
|---|
| 98 | _isStringOrNumber: function(param) { |
|---|
| 99 | return(typeof param=='string' || typeof param=='number'); |
|---|
| 100 | } |
|---|
| 101 | } |
|---|