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

Changeset 6636

Show
Ignore:
Timestamp:
04/30/07 09:02:01 (2 years ago)
Author:
tobie
Message:

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'. ref. #7907

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • spinoffs/prototype/branches/dom/CHANGELOG

    r6626 r6636  
    11*SVN* 
     2 
     3* 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] 
    24 
    35* Add Function#curry, Function#delay, Function#defer, and Function#wrap.  Closes #8134.  [Andrew Dupont, Tobie Langel, sam] 
  • spinoffs/prototype/branches/dom/src/ajax.js

    r6626 r6636  
    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/branches/dom/src/dom.js

    r6626 r6636  
    125125  }, 
    126126   
     127  insert: function(element, content, position) { 
     128    element = $(element); 
     129    position = (position || 'bottom').toLowerCase(); 
     130    var t = Element._insertionTranslations[position], fragments, stripped; 
     131     
     132    if(content && content.ownerDocument === document)  
     133      return t.insert(element, content); 
     134 
     135    content = content.toString(); 
     136    stripped = content.stripScripts(); 
     137     
     138    if (element.insertAdjacentHTML) { 
     139      try { 
     140        element.insertAdjacentHTML(t.adjacency, stripped); 
     141      } catch (e) { 
     142        var tagName = element.tagName.toUpperCase(); 
     143        if (['THEAD','TBODY','TR','TD'].include(tagName)) { 
     144          fragments = Element._getContentFromAnonymousTable(content, tagName); 
     145          if(position == 'top') fragments.reverse(); 
     146          fragments.each(t.insert.curry(element)); 
     147        } else { throw e } 
     148      } 
     149    } else { 
     150      var range = element.ownerDocument.createRange(); 
     151      t.initializeRange(element, range); 
     152      fragments = [range.createContextualFragment(stripped)]; 
     153      if(position == 'top') fragments.reverse(); 
     154      fragments.each(t.insert.curry(element)); 
     155    } 
     156    content.evalScripts.bind(content).defer();    
     157    return element; 
     158  }, 
     159 
    127160  inspect: function(element) { 
    128161    element = $(element); 
     
    428461 
    429462Object.extend(Element.Methods, { 
    430   childOf: Element.Methods.descendantOf, 
    431463  childElements: Element.Methods.immediateDescendants 
    432464}); 
     
    446478} 
    447479else if (Prototype.Browser.IE) { 
     480  Element._getContentFromAnonymousTable = function(html, tagName) { 
     481    var div = document.createElement('div'), depth; 
     482      switch (tagName) { 
     483        case 'THEAD': 
     484        case 'TBODY': 
     485          div.innerHTML = '<table><tbody>' +  html + '</tbody></table>'; 
     486          depth = 2; 
     487          break; 
     488        case 'TR': 
     489          div.innerHTML = '<table><tbody><tr>' +  html + '</tr></tbody></table>'; 
     490          depth = 3; 
     491          break; 
     492        case 'TD': 
     493          div.innerHTML = '<table><tbody><tr><td>' +  html + '</td></tr></tbody></table>'; 
     494          depth = 4; 
     495      } 
     496      depth.times(function() { div = div.firstChild }); 
     497      return $A(div.childNodes); 
     498  }; 
     499   
    448500  Element.Methods.getStyle = function(element, style) { 
    449501    element = $(element); 
     
    484536    var tagName = element.tagName.toUpperCase();   
    485537    if (['THEAD','TBODY','TR','TD'].include(tagName)) { 
    486       var div = document.createElement('div'); 
    487       switch (tagName) { 
    488         case 'THEAD': 
    489         case 'TBODY': 
    490           div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>'; 
    491           depth = 2; 
    492           break; 
    493         case 'TR': 
    494           div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>'; 
    495           depth = 3; 
    496           break; 
    497         case 'TD': 
    498           div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>'; 
    499           depth = 4; 
    500       } 
    501538      $A(element.childNodes).each(function(node) { element.removeChild(node) }); 
    502       depth.times(function() { div = div.firstChild }); 
    503       $A(div.childNodes).each(function(node) { element.appendChild(node) }); 
     539      Element._getContentFromAnonymousTable(html.stripScripts(), tagName).each( 
     540        element.appendChild); 
    504541    } else { 
    505542      element.innerHTML = html.stripScripts(); 
     
    517554  }; 
    518555} 
     556 
     557Element._insertionTranslations = { 
     558  before: { 
     559    adjacency: 'beforeBegin', 
     560    insert: function(element, node) { 
     561      element.parentNode.insertBefore(node, element); 
     562    }, 
     563    initializeRange: function(element, range) { 
     564      range.setStartBefore(element);       
     565    } 
     566  }, 
     567  top: { 
     568    adjacency: 'afterBegin', 
     569    insert: function(element, node) { 
     570      element.insertBefore(node, element.firstChild); 
     571    }, 
     572    initializeRange: function(element, range) { 
     573      range.selectNodeContents(element); 
     574      range.collapse(true); 
     575    } 
     576  }, 
     577  bottom: { 
     578    adjacency: 'beforeEnd', 
     579    insert: function(element, node) { 
     580      element.appendChild(node); 
     581    } 
     582  }, 
     583  after: { 
     584    adjacency: 'afterEnd', 
     585    insert: function(element, node) { 
     586      element.parentNode.insertBefore(node, element.nextSibling); 
     587    }, 
     588    initializeRange: function(element, range) { 
     589      range.setStartAfter(element); 
     590    } 
     591  } 
     592}; 
     593Element._insertionTranslations.bottom.initializeRange =  
     594Element._insertionTranslations.top.initializeRange; 
    519595 
    520596Element._attributeTranslations = { 
     
    669745}; 
    670746 
    671 var Toggle = { display: Element.toggle }; 
    672  
    673 /*--------------------------------------------------------------------------*/ 
    674  
    675 Abstract.Insertion = function(adjacency) { 
    676   this.adjacency = adjacency; 
    677 } 
    678  
    679 Abstract.Insertion.prototype = { 
    680   initialize: function(element, content) { 
    681     this.element = $(element); 
    682     this.content = content.stripScripts(); 
    683      
    684     if (this.adjacency && this.element.insertAdjacentHTML) { 
    685       try { 
    686         this.element.insertAdjacentHTML(this.adjacency, this.content); 
    687       } catch (e) { 
    688         var tagName = this.element.tagName.toUpperCase(); 
    689         if (['TBODY', 'TR'].include(tagName)) { 
    690           this.insertContent(this.contentFromAnonymousTable()); 
    691         } else { 
    692           throw e; 
    693         } 
    694       } 
    695     } else { 
    696       this.range = this.element.ownerDocument.createRange(); 
    697       if (this.initializeRange) this.initializeRange(); 
    698       this.insertContent([this.range.createContextualFragment(this.content)]); 
    699     } 
    700  
    701     content.evalScripts.bind(content).defer();    
    702   }, 
    703    
    704   contentFromAnonymousTable: function() { 
    705     var div = document.createElement('div'); 
    706     div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 
    707     return $A(div.childNodes[0].childNodes[0].childNodes); 
    708   } 
    709 } 
    710  
    711 var Insertion = new Object(); 
    712  
    713 Insertion.Before = Class.create(); 
    714 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 
    715   initializeRange: function() { 
    716     this.range.setStartBefore(this.element); 
    717   }, 
    718    
    719   insertContent: function(fragments) { 
    720     fragments.each((function(fragment) { 
    721       this.element.parentNode.insertBefore(fragment, this.element); 
    722     }).bind(this)); 
    723   } 
    724 }); 
    725  
    726 Insertion.Top = Class.create(); 
    727 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 
    728   initializeRange: function() { 
    729     this.range.selectNodeContents(this.element); 
    730     this.range.collapse(true); 
    731   }, 
    732    
    733   insertContent: function(fragments) { 
    734     fragments.reverse(false).each((function(fragment) { 
    735       this.element.insertBefore(fragment, this.element.firstChild); 
    736     }).bind(this)); 
    737   } 
    738 }); 
    739  
    740 Insertion.Bottom = Class.create(); 
    741 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 
    742   initializeRange: function() { 
    743     this.range.selectNodeContents(this.element); 
    744     this.range.collapse(this.element); 
    745   }, 
    746    
    747   insertContent: function(fragments) { 
    748     fragments.each((function(fragment) { 
    749       this.element.appendChild(fragment); 
    750     }).bind(this)); 
    751   } 
    752 }); 
    753  
    754 Insertion.After = Class.create(); 
    755 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 
    756   initializeRange: function() { 
    757     this.range.setStartAfter(this.element); 
    758   }, 
    759    
    760   insertContent: function(fragments) { 
    761     fragments.each((function(fragment) { 
    762       this.element.parentNode.insertBefore(fragment,  
    763         this.element.nextSibling); 
    764     }).bind(this)); 
    765   } 
    766 }); 
    767  
    768747/*--------------------------------------------------------------------------*/ 
    769748 
  • spinoffs/prototype/branches/dom/src/enumerable.js

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

    r6556 r6636  
    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', 'position.js', 'deprecated.js' %> 
    3333 
    3434Element.addMethods(); 
  • spinoffs/prototype/branches/dom/test/unit/ajax.html

    r6558 r6636  
    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/branches/dom/test/unit/dom.html

    r6597 r6636  
    268268<div id="ancestor"><div id="child"><div><div id="great-grand-child"></div></div></div></div> 
    269269<div id="not-in-the-family"></div> 
     270 
     271<div id="insertions-container"><div id="insertions-main"><p>some content.</p></div></div> 
     272<div id="insertions-node-container"><div id="insertions-node-main"><p>some content.</p></div></div> 
     273<div id="element-insertions-container"><div id="element-insertions-main"><p>some content.</p></div></div> 
     274<div id="wrap-container"><p id="wrap"></p></div> 
    270275<!-- Tests follow --> 
    271276<script type="text/javascript" language="javascript" charset="utf-8"> 
     
    273278 
    274279  var testVar = 'to be updated', testVar2 = ''; 
    275  
     280  var getInnerHTML = function(id) { 
     281    return $(id).innerHTML.toString().toLowerCase().gsub(/[\r\n\t]/, ''); 
     282  }; 
    276283  Element.addMethods({ 
    277284    hashBrowns: function(element) { return 'hash browns'; } 
     
    314321      assertElementsMatch(document.getElementsByClassName('B', 'class_names_ul')); 
    315322    }}, 
    316      
    317     testInsertWithTR: function() {with(this) { 
    318       new Insertion.After('second_row', '<tr id="third_row"><td>Third Row</td></tr>'); 
     323 
     324    testElementInsertWithHTML: function() {with(this) { 
     325      Element.insert('insertions-main', '<p><em>before</em> text</p><p>more testing</p>', 'before'); 
     326      assert(getInnerHTML('insertions-container').startsWith('<p><em>before</em> text</p><p>more testing</p>')); 
     327      Element.insert('insertions-main', '<p><em>after</em> text</p><p>more testing</p>', 'after'); 
     328      assert(getInnerHTML('insertions-container').endsWith('<p><em>after</em> text</p><p>more testing</p>')); 
     329      Element.insert('insertions-main', '<p><em>top</em> text.</p><p>more testing</p>', 'top'); 
     330      assert(getInnerHTML('insertions-main').startsWith('<p><em>top</em> text.</p><p>more testing</p>')); 
     331      Element.insert('insertions-main', '<p><em>bottom</em> text.</p><p>more testing</p>', 'bottom'); 
     332      assert(getInnerHTML('insertions-main').endsWith('<p><em>bottom</em> text.</p><p>more testing</p>')); 
     333    }}, 
     334 
     335    testElementInsertWithDOMNode: function() {with(this) { 
     336      var createParagraph = function(text) { 
     337        var p = document.createElement('p'); 
     338        p.appendChild(document.createTextNode(text)); 
     339        return p; 
     340      } 
     341      Element.insert('insertions-node-main', createParagraph('node before'), 'before');; 
     342      assert(getInnerHTML('insertions-node-container').startsWith('<p>node before</p>')); 
     343      Element.insert('insertions-node-main', createParagraph('node after'), 'after');; 
     344      assert(getInnerHTML('insertions-node-container').endsWith('<p>node after</p>')); 
     345      Element.insert('insertions-node-main', createParagraph('node top'), 'top');; 
     346      assert(getInnerHTML('insertions-node-main').startsWith('<p>node top</p>')); 
     347      Element.insert('insertions-node-main', createParagraph('node bottom'), 'bottom');; 
     348      assert(getInnerHTML('insertions-node-main').endsWith('<p>node bottom</p>')); 
     349    }}, 
     350     
     351    testElementInsertWithNonString: function() {with(this) { 
     352      Element.insert('insertions-main', 3, 'bottom'); 
     353      assert(getInnerHTML('insertions-main').endsWith('3')); 
     354    }}, 
     355 
     356    testElementInsertWithTR: function() {with(this) { 
     357      Element.insert('second_row', '<tr id="third_row"><td>Third Row</td></tr>', 'after'); 
    319358      assert($('second_row').descendantOf('table')); 
    320359    }}, 
    321360     
     361    testElementMethodInsert: function() {with(this) { 
     362      $('element-insertions-main').insert('some text before','before'); 
     363      assert(getInnerHTML('element-insertions-container').startsWith('some text before')); 
     364      $('element-insertions-main').insert('some text after', 'after'); 
     365      assert(getInnerHTML('element-insertions-container').endsWith('some text after')); 
     366      $('element-insertions-main').insert('some text top', 'top'); 
     367      assert(getInnerHTML('element-insertions-main').startsWith('some text top')); 
     368      $('element-insertions-main').insert('some text bottom', 'bottom'); 
     369      assert(getInnerHTML('element-insertions-main').endsWith('some text bottom')); 
     370       
     371      $('element-insertions-main').insert('some more text at the bottom'); 
     372      assert(getInnerHTML('element-insertions-main').endsWith('some more text at the bottom')); 
     373    }}, 
     374     
     375    testInsertionBackwardsCompatibility: function() {with(this) { 
     376      new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before'); 
     377      assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before')); 
     378      new Insertion.After('element-insertions-main', 'some backward-compatibility testing after'); 
     379      assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing after')); 
     380      new Insertion.Top('element-insertions-main', 'some backward-compatibility testing top'); 
     381      assert(getInnerHTML('element-insertions-main').startsWith('some backward-compatibility testing top')); 
     382      new Insertion.Bottom('element-insertions-main', 'some backward-compatibility testing bottom'); 
     383      assert(getInnerHTML('element-insertions-main').endsWith('some backward-compatibility testing bottom')); 
     384    }}, 
     385 
    322386    testElementVisible: function(){with(this) { 
    323387      assertNotEqual('none', $('test-visible').style.display); 
     
    442506      }); 
    443507    }}, 
    444      
     508         
    445509    testElementSelectorMethod: function() {with(this) { 
    446510      var testSelector = $('container').getElementsBySelector('p.test');