Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 6725

Show
Ignore:
Timestamp:
05/12/07 05:01:56 (1 year ago)
Author:
sam
Message:

Merge -r6634:HEAD from ../branches/dom.

* Make Element#update and Element#insert work for SELECT tags in IE and Opera. [Tobie Langel]

* Make Element#insert and Element#update better handle TABLE related elements in IE and Opera. Closes #7776, #8040, #7550, #7776, #7938. [Tobie Langel]

* Make Element#readAttribute('title') work in Opera. [Tobie Langel]

* Make Element#replace work with form elements in Firefox and Safari. Closes #8010, #7989. [dsl239, Tobie Langel]

* Add Element#wrap which wraps the element inside a new one. Closes #5732. [P. Vande, Tobie Langel]

* Make Element into a constructor: new Element(tagName, attributes). Add Element#writeAttribute which accepts a hash of attributes or a name/value pair. Closes #7476. [Mislav Marohnić, haraldmartin, Tobie Langel]

* Insertion overhaul: Add Element.insert(content[, position = 'Bottom']). Deprecate Insertion (kept for backwards compatibility). Make Ajax.Updater option.insertion accept both Insertion.Top or the now preferred 'Top'. Closes #7907. [Tobie Langel]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • spinoffs/prototype/trunk/CHANGELOG

    r6723 r6725  
    11*SVN* 
     2 
     3* Make Element#update and Element#insert work for SELECT tags in IE and Opera. [Tobie Langel] 
     4 
     5* Make Element#insert and Element#update better handle TABLE related elements in IE and Opera. Closes #7776, #8040, #7550, #7776, #7938. [Tobie Langel] 
     6 
     7* Make Element#readAttribute('title') work in Opera. [Tobie Langel] 
     8 
     9* Make Element#replace work with form elements in Firefox and Safari. Closes #8010, #7989. [dsl239, Tobie Langel] 
     10 
     11* Add Element#wrap which wraps the element inside a new one. Closes #5732. [P. Vande, Tobie Langel] 
     12 
     13* Make Element into a constructor: new Element(tagName, attributes). Add Element#writeAttribute which accepts a hash of attributes or a name/value pair. Closes #7476. [Mislav Marohnić, haraldmartin, Tobie Langel] 
     14 
     15* Insertion overhaul: Add Element.insert(content[, position = 'Bottom']). Deprecate Insertion (kept for backwards compatibility). Make Ajax.Updater option.insertion accept both Insertion.Top or the now preferred 'Top'. Closes #7907. [Tobie Langel] 
    216 
    317* Refactor Element.extend and eliminate Element.extend.cache.  [sam] 
  • spinoffs/prototype/trunk/src/ajax.js

    r6626 r6725  
    255255  updateContent: function() { 
    256256    var receiver = this.container[this.success() ? 'success' : 'failure']; 
    257     var response = this.transport.responseText
    258      
    259     if (!this.options.evalScripts) response = response.stripScripts(); 
     257    var response = this.transport.responseText, options = this.options
     258     
     259    if (!options.evalScripts) response = response.stripScripts(); 
    260260     
    261261    if (receiver = $(receiver)) { 
    262       if (this.options.insertion) 
    263         new this.options.insertion(receiver, response); 
    264       else 
    265         receiver.update(response); 
     262      if (options.insertion) { 
     263        if (typeof options.insertion == 'string') 
     264          receiver.insert(response, options.insertion); 
     265        else options.insertion(receiver, response); 
     266      }  
     267      else receiver.update(response); 
    266268    } 
    267269     
  • spinoffs/prototype/trunk/src/dom.js

    r6723 r6725  
    3838/*--------------------------------------------------------------------------*/ 
    3939 
    40 if (!window.Element) var Element = {}; 
     40(function() { 
     41  var element = this.Element; 
     42  this.Element = function(tagName, attributes) { 
     43    attributes = attributes || {}; 
     44    tagName = tagName.toLowerCase(); 
     45    var cache = Element.cache; 
     46    if (Prototype.Browser.IE && attributes.name) { 
     47      tagName = '<' + tagName + ' name="' + attributes.name + '">'; 
     48      delete attributes.name; 
     49      return Element.writeAttribute(document.createElement(tagName), attributes); 
     50    } 
     51    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 
     52    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 
     53  }; 
     54  Object.extend(this.Element, element || {}); 
     55}).call(window); 
     56 
     57Element.cache = {}; 
    4158 
    4259Element.Methods = { 
     
    8198    } else { 
    8299      var range = element.ownerDocument.createRange(); 
    83       range.selectNodeContents(element); 
     100      range.selectNode(element); 
    84101      element.parentNode.replaceChild( 
    85102        range.createContextualFragment(html.stripScripts()), element); 
     
    89106  }, 
    90107   
     108  insert: function(element, content, position) { 
     109    element = $(element); 
     110    position = (position || 'bottom').toLowerCase(); 
     111    var t = Element._insertionTranslations[position], range; 
     112     
     113    if (content && content.ownerDocument === document) { 
     114      t.insert(element, content); 
     115      return element; 
     116    } 
     117     
     118    content = content.toString(); 
     119     
     120    range = element.ownerDocument.createRange(); 
     121    t.initializeRange(element, range); 
     122    t.insert(element, range.createContextualFragment(content.stripScripts())); 
     123 
     124    content.evalScripts.bind(content).defer(); 
     125    return element; 
     126  }, 
     127   
     128  wrap: function(element, wrapper) { 
     129    element = $(element); 
     130    wrapper = wrapper || 'div'; 
     131    if (typeof wrapper == 'string') wrapper = new Element(wrapper); 
     132    else Element.extend(wrapper); 
     133    element.parentNode.replaceChild(wrapper, element); 
     134    wrapper.appendChild(element); 
     135    return element; 
     136  }, 
     137 
    91138  inspect: function(element) { 
    92139    element = $(element); 
     
    194241    if (Prototype.Browser.IE) { 
    195242      if (!element.attributes) return null; 
    196       var t = Element._attributeTranslations
     243      var t = Element._attributeTranslations.read
    197244      if (t.values[name]) return t.values[name](element, name); 
    198245      if (t.names[name])  name = t.names[name]; 
     
    201248    }     
    202249    return element.getAttribute(name); 
     250  }, 
     251   
     252  writeAttribute: function(element, name, value) { 
     253    element = $(element); 
     254    var attributes = {}, t = Element._attributeTranslations.write; 
     255     
     256    if (typeof name == 'object') attributes = name; 
     257    else attributes[name] = value === undefined ? true : value; 
     258     
     259    for (var attr in attributes) { 
     260      var name = t.names[attr] || attr, value = attributes[attr]; 
     261      if (t.values[attr]) name = t.values[attr](element, value); 
     262      if (value === false || value === null) 
     263        element.removeAttribute(name); 
     264      else if (value === true) 
     265        element.setAttribute(name, name); 
     266      else element.setAttribute(name, value); 
     267    } 
     268    return element; 
    203269  }, 
    204270   
     
    388454    element._overflow = null; 
    389455    return element; 
    390   }   
     456  }, 
     457 
     458  cumulativeOffset: function(element) { 
     459    var valueT = 0, valueL = 0; 
     460    do { 
     461      valueT += element.offsetTop  || 0; 
     462      valueL += element.offsetLeft || 0; 
     463      element = element.offsetParent; 
     464    } while (element); 
     465    return Element._returnOffset(valueL, valueT); 
     466  }, 
     467 
     468  positionedOffset: function(element) { 
     469    var valueT = 0, valueL = 0; 
     470    do { 
     471      valueT += element.offsetTop  || 0; 
     472      valueL += element.offsetLeft || 0; 
     473      element = element.offsetParent; 
     474      if (element) { 
     475        if (element.tagName == 'BODY') break; 
     476        var p = Element.getStyle(element, 'position'); 
     477        if (p == 'relative' || p == 'absolute') break; 
     478      } 
     479    } while (element); 
     480    return Element._returnOffset(valueL, valueT); 
     481  }, 
     482 
     483  absolutize: function(element) { 
     484    element = $(element); 
     485    if (element.style.position == 'absolute') return; 
     486    // Position.prepare(); // To be done manually by Scripty when it needs it. 
     487 
     488    var offsets = element.positionedOffset(); 
     489    var top     = offsets[1]; 
     490    var left    = offsets[0]; 
     491    var width   = element.clientWidth; 
     492    var height  = element.clientHeight; 
     493 
     494    element._originalLeft   = left - parseFloat(element.style.left  || 0); 
     495    element._originalTop    = top  - parseFloat(element.style.top || 0); 
     496    element._originalWidth  = element.style.width; 
     497    element._originalHeight = element.style.height; 
     498 
     499    element.style.position = 'absolute'; 
     500    element.style.top    = top + 'px'; 
     501    element.style.left   = left + 'px'; 
     502    element.style.width  = width + 'px'; 
     503    element.style.height = height + 'px'; 
     504    return element; 
     505  }, 
     506 
     507  relativize: function(element) { 
     508    element = $(element); 
     509    if (element.style.position == 'relative') return; 
     510    // Position.prepare(); // To be done manually by Scripty when it needs it. 
     511 
     512    element.style.position = 'relative'; 
     513    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0); 
     514    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 
     515 
     516    element.style.top    = top + 'px'; 
     517    element.style.left   = left + 'px'; 
     518    element.style.height = element._originalHeight; 
     519    element.style.width  = element._originalWidth; 
     520    return element; 
     521  }, 
     522 
     523  cumulativeScrollOffset: function(element) { 
     524    var valueT = 0, valueL = 0; 
     525    do { 
     526      valueT += element.scrollTop  || 0; 
     527      valueL += element.scrollLeft || 0;  
     528      element = element.parentNode; 
     529    } while (element); 
     530    return Element._returnOffset(valueL, valueT); 
     531  }, 
     532   
     533  getOffsetParent: function(element) { 
     534    if (element.offsetParent) return $(element.offsetParent); 
     535    if (element == document.body) return $(element); 
     536 
     537    while ((element = element.parentNode) && element != document.body) 
     538      if (Element.getStyle(element, 'position') != 'static') 
     539        return $(element); 
     540 
     541    return $(document.body); 
     542  }, 
     543 
     544  viewportOffset: function(forElement) { 
     545    var valueT = 0, valueL = 0; 
     546 
     547    var element = forElement; 
     548    do { 
     549      valueT += element.offsetTop  || 0; 
     550      valueL += element.offsetLeft || 0; 
     551 
     552      // Safari fix 
     553      if (element.offsetParent == document.body) 
     554        if (Element.getStyle(element,'position')=='absolute') break; 
     555 
     556    } while (element = element.offsetParent); 
     557 
     558    element = forElement; 
     559    do { 
     560      if (!window.opera || element.tagName=='BODY') { 
     561        valueT -= element.scrollTop  || 0; 
     562        valueL -= element.scrollLeft || 0; 
     563      } 
     564    } while (element = element.parentNode); 
     565 
     566    return Element._returnOffset(valueL, valueT); 
     567  }, 
     568 
     569  clonePosition: function(element, source) { 
     570    var options = Object.extend({ 
     571      setLeft:    true, 
     572      setTop:     true, 
     573      setWidth:   true, 
     574      setHeight:  true, 
     575      offsetTop:  0, 
     576      offsetLeft: 0 
     577    }, arguments[2] || {}) 
     578 
     579    // find page position of source 
     580    source = $(source); 
     581    var p = source.viewportOffset(); 
     582 
     583    // find coordinate system to use 
     584    element = $(element); 
     585    var delta = [0, 0]; 
     586    var parent = null; 
     587    // delta [0,0] will do fine with position: fixed elements,  
     588    // position:absolute needs offsetParent deltas 
     589    if (Element.getStyle(element,'position') == 'absolute') { 
     590      parent = element.getOffsetParent(); 
     591      delta = parent.getViewportOffset(); 
     592    } 
     593 
     594    // correct by body offsets (fixes Safari) 
     595    if (parent == document.body) { 
     596      delta[0] -= document.body.offsetLeft; 
     597      delta[1] -= document.body.offsetTop;  
     598    } 
     599 
     600    // set position 
     601    if(options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px'; 
     602    if(options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px'; 
     603    if(options.setWidth)  element.style.width = source.offsetWidth + 'px'; 
     604    if(options.setHeight) element.style.height = source.offsetHeight + 'px'; 
     605    return element; 
     606  } 
    391607}; 
    392608 
    393609Object.extend(Element.Methods, { 
    394   childOf: Element.Methods.descendantOf, 
    395610  childElements: Element.Methods.immediateDescendants 
    396611}); 
     612 
     613Element._attributeTranslations = { 
     614  write: { 
     615    names: { 
     616      className: 'class', 
     617      htmlFor:   'for'       
     618    },  
     619    values: {} 
     620  } 
     621}; 
     622 
     623 
     624if (!document.createRange || Prototype.Browser.Opera) { 
     625  Element.Methods.insert = function(element, content, position) { 
     626    element = $(element); 
     627    position = (position || 'bottom').toLowerCase(); 
     628    var t = Element._insertionTranslations, pos = t[position], tagName; 
     629     
     630    if (content && content.ownerDocument === document) { 
     631      pos.insert(element, content); 
     632      return element; 
     633    } 
     634 
     635    content = content.toString(); 
     636    tagName = ((position == 'before' || position == 'after') 
     637      ? element.parentNode : element).tagName.toUpperCase(); 
     638     
     639    if (t.tags[tagName]) { 
     640      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 
     641      if (position == 'top' || position == 'after') fragments.reverse(); 
     642      fragments.each(pos.insert.curry(element)); 
     643    } 
     644    else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); 
     645     
     646    content.evalScripts.bind(content).defer(); 
     647    return element; 
     648  } 
     649} 
    397650 
    398651if (Prototype.Browser.Opera) {  
     
    407660      default: return Element._getStyle(element, style);  
    408661    } 
    409   };  
     662  }; 
     663  Element.Methods._readAttribute = Element.Methods.readAttribute;  
     664  Element.Methods.readAttribute = function(element, attribute) {  
     665    if (attribute == 'title') return element.title;  
     666    return Element._readAttribute(element, attribute); 
     667  };   
    410668} 
     669 
    411670else if (Prototype.Browser.IE) { 
    412671  Element.Methods.getStyle = function(element, style) { 
     
    424683    if (value == 'auto') { 
    425684      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) 
    426         return element['offset'+style.capitalize()] + 'px'; 
     685        return element['offset' + style.capitalize()] + 'px'; 
    427686      return null; 
    428687    } 
     
    442701  }; 
    443702 
    444   // IE is missing .innerHTML support for TABLE-related elements 
    445   Element.Methods.update = function(element, html) { 
    446     element = $(element); 
    447     html = typeof html == 'undefined' ? '' : html.toString(); 
    448     var tagName = element.tagName.toUpperCase();   
    449     if (['THEAD','TBODY','TR','TD'].include(tagName)) { 
    450       var div = document.createElement('div'); 
    451       switch (tagName) { 
    452         case 'THEAD': 
    453         case 'TBODY': 
    454           div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>'; 
    455           depth = 2; 
    456           break; 
    457         case 'TR': 
    458           div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>'; 
    459           depth = 3; 
    460           break; 
    461         case 'TD': 
    462           div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>'; 
    463           depth = 4; 
     703  Element._attributeTranslations = { 
     704    read: { 
     705      names: { 
     706        colspan:   "colSpan", 
     707        rowspan:   "rowSpan", 
     708        valign:    "vAlign", 
     709        datetime:  "dateTime", 
     710        accesskey: "accessKey", 
     711        tabindex:  "tabIndex", 
     712        enctype:   "encType", 
     713        maxlength: "maxLength", 
     714        readonly:  "readOnly", 
     715        longdesc:  "longDesc" 
     716      }, 
     717      values: { 
     718        _getAttr: function(element, attribute) { 
     719          return element.getAttribute(attribute, 2); 
     720        }, 
     721        _flag: function(element, attribute) { 
     722          return $(element).hasAttribute(attribute) ? attribute : null; 
     723        }, 
     724        style: function(element) { 
     725          return element.style.cssText.toLowerCase(); 
     726        }, 
     727        title: function(element) { 
     728          var node = element.getAttributeNode('title'); 
     729          return node.specified ? node.nodeValue : null; 
     730        } 
    464731      } 
    465       $A(element.childNodes).each(function(node) { element.removeChild(node) }); 
    466       depth.times(function() { div = div.firstChild }); 
    467       $A(div.childNodes).each(function(node) { element.appendChild(node) }); 
    468     } else { 
    469       element.innerHTML = html.stripScripts(); 
    470     } 
    471     html.evalScripts.bind(html).defer(); 
    472     return element; 
    473   } 
     732    } 
     733  }; 
     734   
     735  Element._attributeTranslations.write = { 
     736    names: Object.extend({ 
     737        'class': 'className', 
     738        'for':   'htmlFor'     
     739      }, Element._attributeTranslations.read.names), 
     740    values: { 
     741      checked: function(element, value) { 
     742        element.checked = !!value; 
     743      }, 
     744       
     745      style: function(element, value) { 
     746        element.style.cssText = value ? value : ''; 
     747      } 
     748    } 
     749  }; 
     750   
     751  (function() { 
     752    Object.extend(this, { 
     753      href: this._getAttr, 
     754      src:  this._getAttr, 
     755      type: this._getAttr, 
     756      disabled: this._flag, 
     757      checked:  this._flag, 
     758      readonly: this._flag, 
     759      multiple: this._flag 
     760    }); 
     761  }).call(Element._attributeTranslations.read.values); 
    474762} 
     763 
    475764else if (Prototype.Browser.Gecko) { 
    476765  Element.Methods.setOpacity = function(element, value) { 
     
    482771} 
    483772 
    484 Element._attributeTranslations = { 
    485   names: { 
    486     colspan:   "colSpan", 
    487     rowspan:   "rowSpan", 
    488     valign:    "vAlign", 
    489     datetime:  "dateTime", 
    490     accesskey: "accessKey", 
    491     tabindex:  "tabIndex", 
    492     enctype:   "encType", 
    493     maxlength: "maxLength", 
    494     readonly:  "readOnly", 
    495     longdesc:  "longDesc" 
    496   }, 
    497   values: { 
    498     _getAttr: function(element, attribute) { 
    499       return element.getAttribute(attribute, 2); 
     773else if (Prototype.Browser.WebKit) { 
     774  // Safari returns margins on body which is incorrect if the child is absolutely 
     775  // positioned.  For performance reasons, redefine Position.cumulativeOffset for 
     776  // KHTML/WebKit only. 
     777  Element.Methods.cumulativeOffset = function(element) { 
     778    var valueT = 0, valueL = 0; 
     779    do { 
     780      valueT += element.offsetTop  || 0; 
     781      valueL += element.offsetLeft || 0; 
     782      if (element.offsetParent == document.body) 
     783        if (Element.getStyle(element, 'position') == 'absolute') break; 
     784         
     785      element = element.offsetParent; 
     786    } while (element); 
     787     
     788    return [valueL, valueT]; 
     789  } 
     790
     791 
     792if (Prototype.Browser.IE || Prototype.Browser.Opera) { 
     793  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements 
     794  Element.Methods.update = function(element, html) { 
     795    element = $(element); 
     796    html = typeof html == 'undefined' ? '' : html.toString(); 
     797    var tagName = element.tagName.toUpperCase(); 
     798     
     799    if (Element._insertionTranslations.tags[tagName]) { 
     800      $A(element.childNodes).each(function(node) { element.removeChild(node) }); 
     801      Element._getContentFromAnonymousElement(tagName, html.stripScripts()) 
     802        .each(function(node) { element.appendChild(node) }); 
     803    }  
     804    else element.innerHTML = html.stripScripts(); 
     805     
     806    html.evalScripts.bind(html).defer(); 
     807    return element; 
     808  }; 
     809
     810 
     811Element._returnOffset = function(l, t) { 
     812  var result = [l, t]; 
     813  result.left = l; 
     814  result.top = t; 
     815  return result; 
     816}; 
     817 
     818Element._getContentFromAnonymousElement = function(tagName, html) { 
     819  var div = new Element('div'); t = Element._insertionTranslations.tags[tagName] 
     820  div.innerHTML = t[0] + html + t[1]; 
     821  t[2].times(function() { div = div.firstChild }); 
     822  return $A(div.childNodes); 
     823}; 
     824 
     825Element._insertionTranslations = { 
     826  before: { 
     827    adjacency: 'beforeBegin', 
     828    insert: function(element, node) { 
     829      element.parentNode.insertBefore(node, element); 
    500830    }, 
    501     _flag: function(element, attribute) { 
    502       return $(element).hasAttribute(attribute) ? attribute : null; 
     831    initializeRange: function(element, range) { 
     832      range.setStartBefore(element);       
     833    } 
     834  }, 
     835  top: { 
     836    adjacency: 'afterBegin', 
     837    insert: function(element, node) { 
     838      element.insertBefore(node, element.firstChild); 
    503839    }, 
    504     style: function(element) { 
    505       return element.style.cssText.toLowerCase(); 
     840    initializeRange: function(element, range) { 
     841      range.selectNodeContents(element); 
     842      range.collapse(true); 
     843    } 
     844  }, 
     845  bottom: { 
     846    adjacency: 'beforeEnd', 
     847    insert: function(element, node) { 
     848      element.appendChild(node); 
     849    } 
     850  }, 
     851  after: { 
     852    adjacency: 'afterEnd', 
     853    insert: function(element, node) { 
     854      element.parentNode.insertBefore(node, element.nextSibling); 
    506855    }, 
    507     title: function(element) { 
    508       var node = element.getAttributeNode('title'); 
    509       return node.specified ? node.nodeValue : null; 
    510     } 
     856    initializeRange: function(element, range) { 
     857      range.setStartAfter(element); 
     858    } 
     859  }, 
     860  tags: { 
     861    TABLE:  ['<table>',                '</table>',                   1], 
     862    TBODY:  ['<table><tbody>',         '</tbody></table>',           2], 
     863    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3], 
     864    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], 
     865    SELECT: ['<select>',               '</select>',                  1] 
    511866  } 
    512867}; 
    513868 
    514869(function() { 
    515   Object.extend(this, { 
    516     href: this._getAttr, 
    517     src:  this._getAttr, 
    518     type: this._getAttr, 
    519     disabled: this._flag, 
    520     checked:  this._flag, 
    521     readonly: this._flag, 
    522     multiple: this._flag 
     870  this.bottom.initializeRange = this.top.initializeRange; 
     871  Object.extend(this.tags, { 
     872    THEAD: this.tags.TBODY, 
     873    TFOOT: this.tags.TBODY, 
     874    TH:    this.tags.TD 
    523875  }); 
    524 }).call(Element._attributeTranslations.values); 
     876}).call(Element._insertionTranslations); 
    525877 
    526878Element.Methods.Simulated = { 
    527879  hasAttribute: function(element, attribute) { 
    528     var t = Element._attributeTranslations, node; 
     880    var t = Element._attributeTranslations.read, node; 
    529881    attribute = t.names[attribute] || attribute; 
    530882    node = $(element).getAttributeNode(attribute); 
     
    6721024   
    6731025  if (Element.extend.refresh) Element.extend.refresh(); 
     1026  Element.cache = {}; 
    6741027}; 
    675  
    676 var Toggle = { display: Element.toggle }; 
    677  
    678 /*--------------------------------------------------------------------------*/ 
    679  
    680 Abstract.Insertion = function(adjacency) { 
    681   this.adjacency = adjacency; 
    682 } 
    683  
    684 Abstract.Insertion.prototype = { 
    685   initialize: function(element, content) { 
    686     this.element = $(element); 
    687     this.content = content.stripScripts(); 
    688      
    689     if (this.adjacency && this.element.insertAdjacentHTML) { 
    690       try { 
    691         this.element.insertAdjacentHTML(this.adjacency, this.content); 
    692       } catch (e) { 
    693         var tagName = this.element.tagName.toUpperCase(); 
    694         if (['TBODY', 'TR'].include(tagName)) { 
    695           this.insertContent(this.contentFromAnonymousTable()); 
    696         } else { 
    697           throw e; 
    698         } 
    699       } 
    700     } else { 
    701       this.range = this.element.ownerDocument.createRange(); 
    702       if (this.initializeRange) this.initializeRange(); 
    703       this.insertContent([this.range.createContextualFragment(this.content)]); 
    704     } 
    705  
    706     content.evalScripts.bind(content).defer();    
    707   }, 
    708    
    709   contentFromAnonymousTable: function() { 
    710     var div = document.createElement('div'); 
    711     div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 
    712     return $A(div.childNodes[0].childNodes[0].childNodes); 
    713   } 
    714 } 
    715  
    716 var Insertion = new Object(); 
    717  
    718 Insertion.Before = Class.create(); 
    719 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 
    720   initializeRange: function() { 
    721     this.range.setStartBefore(this.element); 
    722   }, 
    723    
    724   insertContent: function(fragments) { 
    725     fragments.each((function(fragment) { 
    726       this.element.parentNode.insertBefore(fragment, this.element); 
    727     }).bind(this)); 
    728   } 
    729 }); 
    730  
    731 Insertion.Top = Class.create(); 
    732 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 
    733   initializeRange: function() { 
    734     this.range.selectNodeContents(this.element); 
    735     this.range.collapse(true); 
    736   }, 
    737    
    738   insertContent: function(fragments) { 
    739     fragments.reverse(false).each((function(fragment) { 
    740       this.element.insertBefore(fragment, this.element.firstChild); 
    741     }).bind(this)); 
    742   } 
    743 }); 
    744  
    745 Insertion.Bottom = Class.create(); 
    746 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 
    747   initializeRange: function() { 
    748     this.range.selectNodeContents(this.element); 
    749     this.range.collapse(this.element); 
    750   }, 
    751    
    752   insertContent: function(fragments) { 
    753     fragments.each((function(fragment) { 
    754       this.element.appendChild(fragment); 
    755     }).bind(this)); 
    756   } 
    757 }); 
    758  
    759 Insertion.After = Class.create(); 
    760 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 
    761   initializeRange: function() { 
    762     this.range.setStartAfter(this.element); 
    763   }, 
    764    
    765   insertContent: function(fragments) { 
    766     fragments.each((function(fragment) { 
    767       this.element.parentNode.insertBefore(fragment,  
    768         this.element.nextSibling); 
    769     }).bind(this)); 
    770   } 
    771 }); 
    7721028 
    7731029/*--------------------------------------------------------------------------*/ 
  • spinoffs/prototype/trunk/src/enumerable.js

    r6601 r6725  
    1 var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead')
     1var $break = {}
    22 
    33var Enumerable = { 
  • spinoffs/prototype/trunk/src/prototype.js

    r6556 r6725  
    3030<%= include 'enumerable.js', 'array.js', 'hash.js', 'range.js' %> 
    3131 
    32 <%= include 'ajax.js', 'dom.js', 'selector.js', 'form.js', 'event.js', 'position.js' %> 
     32<%= include 'ajax.js', 'dom.js', 'selector.js', 'form.js', 'event.js', 'deprecated.js' %> 
    3333 
    3434Element.addMethods(); 
  • spinoffs/prototype/trunk/src/string.js

    r6556 r6725  
    8383 
    8484  unescapeHTML: function() { 
    85     var div = document.createElement('div'); 
     85    var div = new Element('div'); 
    8686    div.innerHTML = this.stripTags(); 
    8787    return div.childNodes[0] ? (div.childNodes.length > 1 ?  
  • spinoffs/prototype/trunk/test/unit/ajax.html

    r6558 r6725  
    3030// <![CDATA[ 
    3131  var responderCounter = 0; 
    32  
     32   
     33  // lowercase comparison because of MSIE which presents HTML tags in uppercase 
     34  var sentence = ("Pack my box with <em>five dozen</em> liquor jugs! " + 
     35  "Oh, how <strong>quickly</strong> daft jumping zebras vex...").toLowerCase(); 
     36   
    3337  new Test.Unit.Runner({ 
    3438     
     
    7781      new Ajax.Updater("content", "fixtures/content.html", { method:'get' }); 
    7882       
    79       // lowercase comparison because of MSIE which presents HTML tags in uppercase 
    80       var sentence = ("Pack my box with <em>five dozen</em> liquor jugs! " + 
    81         "Oh, how <strong>quickly</strong> daft jumping zebras vex...").toLowerCase(); 
    82  
    8383      wait(1000,function(){ 
    8484        assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); 
     
    9696          assertEqual("", $("content2").innerHTML); 
    9797        }); 
     98      });  
     99    }}, 
     100     
     101    testUpdaterWithInsertion: function() {with(this) { 
     102      $('content').update(); 
     103      new Ajax.Updater("content", "fixtures/content.html", { method:'get', insertion: Insertion.Top }); 
     104      wait(1000,function(){ 
     105        assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); 
     106        $('content').update(); 
     107        new Ajax.Updater("content", "fixtures/content.html", { method:'get', insertion: 'bottom' });       
     108        wait(1000,function(){ 
     109          assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); 
     110        }); 
    98111      }); 
    99112    }}, 
    100      
     113        
    101114    testResponders: function(){with(this) { 
    102115      // check for internal responder 
  • spinoffs/prototype/trunk/test/unit/dom.html

    r6597 r6725  
    147147<div id="testdiv-replace-container-4"><div id="testdiv-replace-4"></div></div> 
    148148<div id="testdiv-replace-container-5"><div id="testdiv-replace-5"></div></div> 
     149<div id="testform-replace-container"><p>some text</p><form id="testform-replace"><input id="testinput-replace" type="text" /></form><p>some text</p></div> 
    149150 
    150151<div id="element_with_visible_overflow" style="overflow:visible">V</div> 
     
    224225</form> 
    225226 
     227<!-- writeAttributes  --> 
     228<p id="write_attribute_para"></a> 
     229<a id="write_attribute_link" href="test.html"></a> 
     230<form action="/dev/null" id="write_attribute_form" method="get" accept-charset="utf-8"> 
     231  <label id="write_attribute_label"></label> 
     232  <input type="checkbox" name="write_attribute_checkbox" value="" id="write_attribute_checkbox"> 
     233  <input type="checkbox" checked="checked" name="write_attribute_checked_checkbox" value="" id="write_attribute_checked_checkbox"> 
     234  <input type="text" name="write_attribute_input" value="" id="write_attribute_input"> 
     235  <select id="write_attribute_select"> 
     236    <option>Cat</option> 
     237    <option>Dog</option> 
     238  </select> 
     239</form> 
     240 
     241<table id="write_attribute_table"> 
     242  <tr><td id="write_attribute_td">A</td><td>B</td></tr> 
     243  <tr><td>C</td></tr> 
     244  <tr><td>D</td><td>E</td><td>F</td></tr> 
     245</table> 
     246 
    226247<div id="dom_attribute_precedence"> 
    227248  <form action="blech" method="post"> 
     
    268289<div id="ancestor"><div id="child"><div><div id="great-grand-child"></div></div></div></div> 
    269290<div id="not-in-the-family"></div> 
     291 
     292<div id="insertions-container"><div id="insertions-main"><p>some content.</p></div></div> 
     293<div id="insertions-node-container"><div id="insertions-node-main"><p>some content.</p></div></div> 
     294<div id="element-insertions-container"><div id="element-insertions-main"><p>some content.</p></div></div> 
     295<table id="table_for_insertions"></table> 
     296<table id="table_for_row_insertions"><tr id="row_1"></tr></table> 
     297<form method="post" action="blah"> 
     298  <select id="select_for_update" name="select_for_update"> 
     299    <option>option 1</option> 
     300    <option>option 2</option> 
     301  </select> 
     302  <select id="select_for_insert_bottom" name="select_for_insert_bottom"> 
     303    <option>option 1</option> 
     304    <option>option 2</option> 
     305  </select> 
     306  <select id="select_for_insert_top" name="select_for_insert_top"> 
     307    <option>option 1</option> 
     308    <option>option 2</option> 
     309  </select> 
     310</form> 
     311<div id="wrap-container"><p id="wrap"></p></div> 
     312 
     313<!-- Positioning methods bench --> 
     314<div id="body_absolute" style="position: absolute; top: 10px; left: 10px"> 
     315  <div id="absolute_absolute" style="position: absolute; top: 10px; left:10px"> </div> 
     316  <div id="absolute_relative" style="position: relative; top: 10px; left:10px"> 
     317    <div style="height:10px">test<span id="inline">test</span></div> 
     318    <div id="absolute_relative_undefined"> </div> 
     319  </div> 
     320</div> 
     321  
    270322<!-- Tests follow --> 
    271323<script type="text/javascript" language="javascript" charset="utf-8"> 
     
    273325 
    274326  var testVar = 'to be updated', testVar2 = ''; 
    275  
     327  var getInnerHTML = function(id) { 
     328    return $(id).innerHTML.toString().toLowerCase().gsub(/[\r\n\t]/, ''); 
     329  }; 
    276330  Element.addMethods({ 
    277331    hashBrowns: function(element) { return 'hash browns'; } 
     
    314368      assertElementsMatch(document.getElementsByClassName('B', 'class_names_ul')); 
    315369    }}, 
    316      
    317     testInsertWithTR: function() {with(this) { 
    318       new Insertion.After('second_row', '<tr id="third_row"><td>Third Row</td></tr>'); 
     370 
     371    testElementInsertWithHTML: function() {with(this) { 
     372      Element.insert('insertions-main', '<p><em>before</em> text</p><p>more testing</p>', 'before'); 
     373      assert(getInnerHTML('insertions-container').startsWith('<p><em>before</em> text</p><p>more testing</p>')); 
     374      Element.insert('insertions-main', '<p><em>after</em> text</p><p>more testing</p>', 'after'); 
     375      assert(getInnerHTML('insertions-container').endsWith('<p><em>after</em> text</p><p>more testing</p>')); 
     376      Element.insert('insertions-main', '<p><em>top</em> text.</p><p>more testing</p>', 'top'); 
     377      assert(getInnerHTML('insertions-main').startsWith('<p><em>top</em> text.</p><p>more testing</p>')); 
     378      Element.insert('insertions-main', '<p><em>bottom</em> text.</p><p>more testing</p>', 'bottom'); 
     379      assert(getInnerHTML('insertions-main').endsWith('<p><em>bottom</em> text.</p><p>more testing</p>')); 
     380    }}, 
     381 
     382    testElementInsertWithDOMNode: function() {with(this) { 
     383      var createParagraph = function(text) { 
     384        var p = document.createElement('p'); 
     385        p.appendChild(document.createTextNode(text)); 
     386        return p; 
     387      } 
     388      Element.insert('insertions-node-main', createParagraph('node before'), 'before'); 
     389      assert(getInnerHTML('insertions-node-container').startsWith('<p>node before</p>')); 
     390      Element.insert('insertions-node-main', createParagraph('node after'), 'after'); 
     391      assert(getInnerHTML('insertions-node-container').endsWith('<p>node after</p>')); 
     392      Element.insert('insertions-node-main', createParagraph('node top'), 'top'); 
     393      assert(getInnerHTML('insertions-node-main').startsWith('<p>node top</p>')); 
     394      Element.insert('insertions-node-main', createParagraph('node bottom'), 'bottom'); 
     395      assert(getInnerHTML('insertions-node-main').endsWith('<p>node bottom</p>')); 
     396      assertEqual($('insertions-node-main'), $('insertions-node-main').insert(document.createElement('p'))); 
     397    }}, 
     398     
     399    testElementInsertWithNonString: function() {with(this) { 
     400      Element.insert('insertions-main', 3, 'bottom'); 
     401      assert(getInnerHTML('insertions-main').endsWith('3')); 
     402    }}, 
     403 
     404    testElementInsertInTables: function() {with(this) { 
     405      Element.insert('second_row', '<tr id="third_row"><td>Third Row</td></tr>', 'after'); 
    319406      assert($('second_row').descendantOf('table')); 
     407       
     408      $('a_cell').insert('hello world', 'top'); 
     409      assert($('a_cell').innerHTML.startsWith('hello world')); 
     410      $('a_cell').insert('<td>hi planet</td>', 'after'); 
     411      assertEqual('hi planet', $('a_cell').next().innerHTML); 
     412      $('table_for_insertions').insert('<tr><td>a cell!</td></tr>'); 
     413      assert($('table_for_insertions').innerHTML.gsub('\r\n', '').toLowerCase().include('<tr><td>a cell!</td></tr>')); 
     414      $('row_1').insert('<tr></tr><tr></tr><tr><td>last</td></tr>', 'after'); 
     415      assertEqual('last', $A($('table_for_row_insertions').getElementsByTagName('tr')).last().lastChild.innerHTML); 
     416    }}, 
     417     
     418    testElementInsertInSelect: function() {with(this) { 
     419      var selectTop = $('select_for_insert_top'), selectBottom = $('select_for_insert_bottom'); 
     420      selectBottom.insert('<option value="33">option 33</option><option selected="selected">option 45</option>'); 
     421      assertEqual('option 45', selectBottom.getValue()); 
     422      selectTop.insert('<option value="A">option A</option><option value="B" selected="selected">option B</option>', 'top'); 
     423      assertEqual(4, selectTop.options.length); 
     424    }}, 
     425         
     426    testElementMethodInsert: function() {with(this) { 
     427      $('element-insertions-main').insert('some text before','before'); 
     428      assert(getInnerHTML('element-insertions-container').startsWith('some text before')); 
     429      $('element-insertions-main').insert('some text after', 'after'); 
     430      assert(getInnerHTML('element-insertions-container').endsWith('some text after')); 
     431      $('element-insertions-main').insert('some text top', 'top'); 
     432      assert(getInnerHTML('element-insertions-main').startsWith('some text top')); 
     433      $('element-insertions-main').insert('some text bottom', 'bottom'); 
     434      assert(getInnerHTML('element-insertions-main').endsWith('some text bottom')); 
     435       
     436      $('element-insertions-main').insert('some more text at the bottom'); 
     437      assert(getInnerHTML('element-insertions-main').endsWith('some more text at the bottom')); 
     438    }}, 
     439     
     440    testInsertionBackwardsCompatibility: function() {with(this) { 
     441      new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before'); 
     442      assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before')); 
     443      new Insertion.After('element-insertions-main', 'some backward-compatibility testing after'); 
     444      assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing after')); 
     445      new Insertion.Top('element-insertions-main', 'some backward-compatibility testing top'); 
     446      assert(getInnerHTML('element-insertions-main').startsWith('some backward-compatibility testing top')); 
     447      new Insertion.Bottom('element-insertions-main', 'some backward-compatibility testing bottom'); 
     448      assert(getInnerHTML('element-insertions-main').endsWith('some backward-compatibility testing bottom')); 
     449    }}, 
     450     
     451    testElementWrap: function() {with(this) { 
     452      var element = $('wrap'), parent = document.createElement('div'); 
     453      element.wrap('div'); 
     454      assert(getInnerHTML('wrap-container').startsWith('<div><p')); 
     455      element.wrap(parent); 
     456      assert(getInnerHTML('wrap-container').startsWith('<div><div><p')); 
     457      assert(typeof parent.setStyle == 'function'); 
     458      element.wrap(); 
     459      assert(getInnerHTML('wrap-container').startsWith('<div><div><div><p')); 
    320460    }}, 
    321461     
     
    415555    }}, 
    416556     
     557    testElementUpdateInSelect: function() {with(this) { 
     558      var select = $('select_for_update'); 
     559      select.update('<option value="3">option 3</option><option selected="selected">option 4</option>'); 
     560      assertEqual('option 4', select.getValue()); 
     561    }}, 
     562     
    417563    testElementReplace: function() {with(this) { 
    418564      $('testdiv-replace-1').replace('hello from div!'); 
     
    420566       
    421567      $('testdiv-replace-2').replace(123); 
    422       assertEqual('123', $('testdiv-replace-container-2').innerHTML) 
     568      assertEqual('123', $('testdiv-replace-container-2').innerHTML); 
    423569       
    424570      $('testdiv-replace-3').replace(); 
    425       assertEqual('', $('testdiv-replace-container-3').innerHTML) 
    426     }}, 
    427      
    428  
     571      assertEqual('', $('testdiv-replace-container-3').innerHTML); 
     572       
     573      $('testinput-replace').replace('<p>hello world</p>'); 
     574      assertEqual('<p>hello world</p>', 
     575        $('testform-replace').innerHTML.gsub('\r\n', '').toLowerCase()); 
     576 
     577      $('testform-replace').replace('<form></form>'); 
     578      assertEqual('<p>some text</p><form></form><p>some text</p>', 
     579        $('testform-replace-container').innerHTML.gsub('\r\n', '').toLowerCase()); 
     580    }}, 
     581     
    429582    testElementReplaceWithScript: function() {with(this) { 
    430583      $('testdiv-replace-4').replace('hello from div!<script>testVarReplace="hello!"</'+'script>');