terom@27: // script.aculo.us builder.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 terom@27: terom@27: // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) terom@27: // terom@27: // script.aculo.us is freely distributable under the terms of an MIT-style license. terom@27: // For details, see the script.aculo.us web site: http://script.aculo.us/ terom@27: terom@27: var Builder = { terom@27: NODEMAP: { terom@27: AREA: 'map', terom@27: CAPTION: 'table', terom@27: COL: 'table', terom@27: COLGROUP: 'table', terom@27: LEGEND: 'fieldset', terom@27: OPTGROUP: 'select', terom@27: OPTION: 'select', terom@27: PARAM: 'object', terom@27: TBODY: 'table', terom@27: TD: 'table', terom@27: TFOOT: 'table', terom@27: TH: 'table', terom@27: THEAD: 'table', terom@27: TR: 'table' terom@27: }, terom@27: // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, terom@27: // due to a Firefox bug terom@27: node: function(elementName) { terom@27: elementName = elementName.toUpperCase(); terom@27: terom@27: // try innerHTML approach terom@27: var parentTag = this.NODEMAP[elementName] || 'div'; terom@27: var parentElement = document.createElement(parentTag); terom@27: try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 terom@27: parentElement.innerHTML = "<" + elementName + ">"; terom@27: } catch(e) {} terom@27: var element = parentElement.firstChild || null; terom@27: terom@27: // see if browser added wrapping tags terom@27: if(element && (element.tagName.toUpperCase() != elementName)) terom@27: element = element.getElementsByTagName(elementName)[0]; terom@27: terom@27: // fallback to createElement approach terom@27: if(!element) element = document.createElement(elementName); terom@27: terom@27: // abort if nothing could be created terom@27: if(!element) return; terom@27: terom@27: // attributes (or text) terom@27: if(arguments[1]) terom@27: if(this._isStringOrNumber(arguments[1]) || terom@27: (arguments[1] instanceof Array) || terom@27: arguments[1].tagName) { terom@27: this._children(element, arguments[1]); terom@27: } else { terom@27: var attrs = this._attributes(arguments[1]); terom@27: if(attrs.length) { terom@27: try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 terom@27: parentElement.innerHTML = "<" +elementName + " " + terom@27: attrs + ">"; terom@27: } catch(e) {} terom@27: element = parentElement.firstChild || null; terom@27: // workaround firefox 1.0.X bug terom@27: if(!element) { terom@27: element = document.createElement(elementName); terom@27: for(attr in arguments[1]) terom@27: element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; terom@27: } terom@27: if(element.tagName.toUpperCase() != elementName) terom@27: element = parentElement.getElementsByTagName(elementName)[0]; terom@27: } terom@27: } terom@27: terom@27: // text, or array of children terom@27: if(arguments[2]) terom@27: this._children(element, arguments[2]); terom@27: terom@27: return element; terom@27: }, terom@27: _text: function(text) { terom@27: return document.createTextNode(text); terom@27: }, terom@27: terom@27: ATTR_MAP: { terom@27: 'className': 'class', terom@27: 'htmlFor': 'for' terom@27: }, terom@27: terom@27: _attributes: function(attributes) { terom@27: var attrs = []; terom@27: for(attribute in attributes) terom@27: attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + terom@27: '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); terom@27: return attrs.join(" "); terom@27: }, terom@27: _children: function(element, children) { terom@27: if(children.tagName) { terom@27: element.appendChild(children); terom@27: return; terom@27: } terom@27: if(typeof children=='object') { // array can hold nodes and text terom@27: children.flatten().each( function(e) { terom@27: if(typeof e=='object') terom@27: element.appendChild(e) terom@27: else terom@27: if(Builder._isStringOrNumber(e)) terom@27: element.appendChild(Builder._text(e)); terom@27: }); terom@27: } else terom@27: if(Builder._isStringOrNumber(children)) terom@27: element.appendChild(Builder._text(children)); terom@27: }, terom@27: _isStringOrNumber: function(param) { terom@27: return(typeof param=='string' || typeof param=='number'); terom@27: }, terom@27: build: function(html) { terom@27: var element = this.node('div'); terom@27: $(element).update(html.strip()); terom@27: return element.down(); terom@27: }, terom@27: dump: function(scope) { terom@27: if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope terom@27: terom@27: var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + terom@27: "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + terom@27: "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ terom@27: "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ terom@27: "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ terom@27: "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); terom@27: terom@27: tags.each( function(tag){ terom@27: scope[tag] = function() { terom@27: return Builder.node.apply(Builder, [tag].concat($A(arguments))); terom@27: } terom@27: }); terom@27: } terom@27: }