builder.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
  2. // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
  3. //
  4. // script.aculo.us is freely distributable under the terms of an MIT-style license.
  5. // For details, see the script.aculo.us web site: http://script.aculo.us/
  6. var Builder = {
  7. NODEMAP: {
  8. AREA: 'map',
  9. CAPTION: 'table',
  10. COL: 'table',
  11. COLGROUP: 'table',
  12. LEGEND: 'fieldset',
  13. OPTGROUP: 'select',
  14. OPTION: 'select',
  15. PARAM: 'object',
  16. TBODY: 'table',
  17. TD: 'table',
  18. TFOOT: 'table',
  19. TH: 'table',
  20. THEAD: 'table',
  21. TR: 'table'
  22. },
  23. // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
  24. // due to a Firefox bug
  25. node: function(elementName) {
  26. elementName = elementName.toUpperCase();
  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. // see if browser added wrapping tags
  35. if(element && (element.tagName.toUpperCase() != elementName))
  36. element = element.getElementsByTagName(elementName)[0];
  37. // fallback to createElement approach
  38. if(!element) element = document.createElement(elementName);
  39. // abort if nothing could be created
  40. if(!element) return;
  41. // attributes (or text)
  42. if(arguments[1])
  43. if(this._isStringOrNumber(arguments[1]) ||
  44. (arguments[1] instanceof Array) ||
  45. arguments[1].tagName) {
  46. this._children(element, arguments[1]);
  47. } else {
  48. var attrs = this._attributes(arguments[1]);
  49. if(attrs.length) {
  50. try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
  51. parentElement.innerHTML = "<" +elementName + " " +
  52. attrs + "></" + elementName + ">";
  53. } catch(e) {}
  54. element = parentElement.firstChild || null;
  55. // workaround firefox 1.0.X bug
  56. if(!element) {
  57. element = document.createElement(elementName);
  58. for(attr in arguments[1])
  59. element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
  60. }
  61. if(element.tagName.toUpperCase() != elementName)
  62. element = parentElement.getElementsByTagName(elementName)[0];
  63. }
  64. }
  65. // text, or array of children
  66. if(arguments[2])
  67. this._children(element, arguments[2]);
  68. return element;
  69. },
  70. _text: function(text) {
  71. return document.createTextNode(text);
  72. },
  73. ATTR_MAP: {
  74. 'className': 'class',
  75. 'htmlFor': 'for'
  76. },
  77. _attributes: function(attributes) {
  78. var attrs = [];
  79. for(attribute in attributes)
  80. attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
  81. '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
  82. return attrs.join(" ");
  83. },
  84. _children: function(element, children) {
  85. if(children.tagName) {
  86. element.appendChild(children);
  87. return;
  88. }
  89. if(typeof children=='object') { // array can hold nodes and text
  90. children.flatten().each( function(e) {
  91. if(typeof e=='object')
  92. element.appendChild(e)
  93. else
  94. if(Builder._isStringOrNumber(e))
  95. element.appendChild(Builder._text(e));
  96. });
  97. } else
  98. if(Builder._isStringOrNumber(children))
  99. element.appendChild(Builder._text(children));
  100. },
  101. _isStringOrNumber: function(param) {
  102. return(typeof param=='string' || typeof param=='number');
  103. },
  104. build: function(html) {
  105. var element = this.node('div');
  106. $(element).update(html.strip());
  107. return element.down();
  108. },
  109. dump: function(scope) {
  110. if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
  111. var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
  112. "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
  113. "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
  114. "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
  115. "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
  116. "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
  117. tags.each( function(tag){
  118. scope[tag] = function() {
  119. return Builder.node.apply(Builder, [tag].concat($A(arguments)));
  120. }
  121. });
  122. }
  123. }