Found a better detect for deleting an expando, added back in removeAttribute as it...
[jquery.git] / test / otherlibs / scriptaculous / 1.7.0 / builder.js
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
8 var 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 }