Fix tabs vs spaces in initial workaround commit
[jquery.git] / test / otherlibs / scriptaculous / 1.8.1 / builder.js
1 // script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
3 // Copyright (c) 2005-2007 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         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(/"/,'&quot;') + '"');
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 }