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

Changeset 8537

Show
Ignore:
Timestamp:
01/03/08 01:50:36 (2 years ago)
Author:
tobie
Message:

prototype: Make Element#insert standard-compliant. Fixes an issue in FF3b2 when inserting HTML or text inside DOM nodes which aren't (yet) appended to the document.

Files:

Legend:

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

    r8515 r8537  
    11*SVN* 
     2 
     3* Make Element#insert standard-compliant. Fixes an issue in FF3b2 when inserting HTML or text inside DOM nodes which aren't (yet) appended to the document. [Tobie Langel] 
    24 
    35* Add some missing semicolons to the source tree.  Closes #10659.  [Richard Quadling] 
  • spinoffs/prototype/trunk/src/dom.js

    r8448 r8537  
    120120          insertions = {bottom:insertions}; 
    121121     
    122     var content, t, range
     122    var content, insert, tagName, childNodes
    123123     
    124124    for (position in insertions) { 
    125125      content  = insertions[position]; 
    126126      position = position.toLowerCase(); 
    127       t = Element._insertionTranslations[position]; 
     127      insert = Element._insertionTranslations[position]; 
    128128 
    129129      if (content && content.toElement) content = content.toElement(); 
    130130      if (Object.isElement(content)) { 
    131         t.insert(element, content); 
     131        insert(element, content); 
    132132        continue; 
    133133      } 
     
    135135      content = Object.toHTML(content); 
    136136       
    137       range = element.ownerDocument.createRange(); 
    138       t.initializeRange(element, range); 
    139       t.insert(element, range.createContextualFragment(content.stripScripts())); 
     137      tagName = ((position == 'before' || position == 'after') 
     138        ? element.parentNode : element).tagName.toUpperCase(); 
     139       
     140      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 
     141       
     142      if (position == 'top' || position == 'after') childNodes.reverse(); 
     143      childNodes.each(insert.curry(element)); 
    140144       
    141145      content.evalScripts.bind(content).defer(); 
     
    663667  } 
    664668}; 
    665  
    666  
    667 if (!document.createRange || Prototype.Browser.Opera) { 
    668   Element.Methods.insert = function(element, insertions) { 
    669     element = $(element); 
    670  
    671     if (Object.isString(insertions) || Object.isNumber(insertions) || 
    672         Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 
    673           insertions = { bottom: insertions }; 
    674      
    675     var t = Element._insertionTranslations, content, position, pos, tagName; 
    676      
    677     for (position in insertions) { 
    678       content  = insertions[position]; 
    679       position = position.toLowerCase(); 
    680       pos      = t[position]; 
    681  
    682       if (content && content.toElement) content = content.toElement(); 
    683       if (Object.isElement(content)) { 
    684         pos.insert(element, content); 
    685         continue; 
    686       } 
    687       
    688       content = Object.toHTML(content); 
    689       tagName = ((position == 'before' || position == 'after') 
    690         ? element.parentNode : element).tagName.toUpperCase(); 
    691       
    692       if (t.tags[tagName]) { 
    693         var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 
    694         if (position == 'top' || position == 'after') fragments.reverse(); 
    695         fragments.each(pos.insert.curry(element)); 
    696       } 
    697       else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); 
    698        
    699       content.evalScripts.bind(content).defer(); 
    700     } 
    701      
    702     return element; 
    703   }; 
    704 } 
    705669 
    706670if (Prototype.Browser.Opera) {  
     
    993957Element._getContentFromAnonymousElement = function(tagName, html) { 
    994958  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; 
    995   div.innerHTML = t[0] + html + t[1]; 
    996   t[2].times(function() { div = div.firstChild }); 
     959  if (t) { 
     960    div.innerHTML = t[0] + html + t[1]; 
     961    t[2].times(function() { div = div.firstChild }); 
     962  } else div.innerHTML = html; 
    997963  return $A(div.childNodes); 
    998964}; 
    999965 
    1000966Element._insertionTranslations = { 
    1001   before: { 
    1002     adjacency: 'beforeBegin', 
    1003     insert: function(element, node) { 
    1004       element.parentNode.insertBefore(node, element); 
    1005     }, 
    1006     initializeRange: function(element, range) { 
    1007       range.setStartBefore(element);       
    1008     } 
    1009   }, 
    1010   top: { 
    1011     adjacency: 'afterBegin', 
    1012     insert: function(element, node) { 
    1013       element.insertBefore(node, element.firstChild); 
    1014     }, 
    1015     initializeRange: function(element, range) { 
    1016       range.selectNodeContents(element); 
    1017       range.collapse(true); 
    1018     } 
    1019   }, 
    1020   bottom: { 
    1021     adjacency: 'beforeEnd', 
    1022     insert: function(element, node) { 
    1023       element.appendChild(node); 
    1024     } 
    1025   }, 
    1026   after: { 
    1027     adjacency: 'afterEnd', 
    1028     insert: function(element, node) { 
    1029       element.parentNode.insertBefore(node, element.nextSibling); 
    1030     }, 
    1031     initializeRange: function(element, range) { 
    1032       range.setStartAfter(element); 
    1033     } 
     967  before: function(element, node) { 
     968    element.parentNode.insertBefore(node, element); 
     969  }, 
     970  top: function(element, node) { 
     971    element.insertBefore(node, element.firstChild); 
     972  }, 
     973  bottom: function(element, node) { 
     974    element.appendChild(node); 
     975  }, 
     976  after: function(element, node) { 
     977    element.parentNode.insertBefore(node, element.nextSibling); 
    1034978  }, 
    1035979  tags: { 
     
    1043987 
    1044988(function() { 
    1045   this.bottom.initializeRange = this.top.initializeRange; 
    1046989  Object.extend(this.tags, { 
    1047990    THEAD: this.tags.TBODY, 
  • spinoffs/prototype/trunk/test/unit/dom.html

    r8266 r8537  
    597597    }}, 
    598598     
     599    testNewElementInsert: function() {with(this) { 
     600      var container = new Element('div'); 
     601      element = new Element('div'); 
     602      container.insert(element); 
     603       
     604      element.insert({ before: '<p>a paragraph</p>' }); 
     605      assertEqual('<p>a paragraph</p><div></div>', getInnerHTML(container)); 
     606      element.insert({ after: 'some text' }); 
     607      assertEqual('<p>a paragraph</p><div></div>some text', getInnerHTML(container)); 
     608       
     609      element.insert({ top: '<p>a paragraph</p>' }); 
     610      assertEqual('<p>a paragraph</p>', getInnerHTML(element)); 
     611      element.insert('some text'); 
     612      assertEqual('<p>a paragraph</p>some text', getInnerHTML(element)); 
     613    }}, 
     614     
    599615    testInsertionBackwardsCompatibility: function() {with(this) { 
    600616      new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before');