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

Ticket #7358: extensions.diff

File extensions.diff, 8.4 kB (added by savetheclocktower, 2 years ago)

Patch (including unit tests)

  • trunk/test/unit/dom.html

    old new  
    256256 
    257257  var testVar = 'to be updated'; 
    258258 
     259  Element.addMethods("LI", { 
     260    pancakes: function(element) { return "pancakes"; } 
     261  }); 
     262   
     263  Element.addMethods("DIV", { 
     264    waffles: function(element) { return "waffles"; } 
     265  }); 
     266   
     267  Element.addMethods($w("li div"), { 
     268    orangeJuice: function(element) { return "orange juice"; } 
     269  }); 
     270 
    259271  new Test.Unit.Runner({ 
    260272 
    261273    testDollarFunction: function() { with(this) { 
     
    271283      var elt = $('testdiv'); 
    272284      assertIdentical(elt, $(elt)); 
    273285      assertRespondsTo('hide', elt); 
     286      assertRespondsTo('childOf', elt); 
    274287    }}, 
    275288     
    276289    testGetElementsByClassName: function() {with(this) { 
     
    282295     
    283296    testInsertWithTR: function() {with(this) { 
    284297      new Insertion.After('second_row', '<tr id="third_row"><td>Third Row</td></tr>'); 
    285       assert($('second_row').childOf('table')); 
     298      assert($('second_row').descendantOf('table')); 
    286299    }}, 
    287300     
    288301    testElementVisible: function(){with(this) { 
     
    801814      elem.scrollTo(); 
    802815      assertEqual(Position.page(elem)[1], 0);       
    803816      window.scrollTo(0, 0); 
    804     }} 
     817    }}, 
    805818     
     819    testSpecificElementMethods: function() {with(this) { 
     820      var elem = $('navigation_test_f'); 
     821       
     822      assert(Element.Methods.ByTag[elem.tagName]); 
     823      assertRespondsTo('pancakes', elem); 
     824      assertEqual("pancakes", elem.pancakes()); 
     825       
     826      var elem2 = $('test-visible'); 
     827 
     828      assert(Element.Methods.ByTag[elem2.tagName]); 
     829      assertUndefined(elem2.pancakes); 
     830      assertRespondsTo('waffles', elem2); 
     831      assertEqual("waffles", elem2.waffles()); 
     832       
     833      assertRespondsTo('orangeJuice', elem); 
     834      assertRespondsTo('orangeJuice', elem2); 
     835      assertEqual("orange juice", elem.orangeJuice()); 
     836      assertEqual("orange juice", elem2.orangeJuice()); 
     837    }}     
    806838  }, 'testlog'); 
    807839 
    808840// ]]> 
  • trunk/src/prototype.js

    old new  
    33var Prototype = { 
    44  Version: '<%= PROTOTYPE_VERSION %>', 
    55  BrowserFeatures: { 
    6     XPath: !!document.evaluate 
     6    XPath: !!document.evaluate, 
     7    ElementExtensions: !!window.HTMLElement, 
     8    SpecificElementExtensions:  
     9      (document.createElement('div').__proto__ !==  
     10       document.createElement('form').__proto__) 
    711  }, 
    812   
    913  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 
  • trunk/src/dom.js

    old new  
    4141if (!window.Element) 
    4242  var Element = new Object(); 
    4343 
     44 
    4445Element.extend = function(element) { 
    45   if (!element || _nativeExtensions || element.nodeType == 3) return element; 
    46    
    47   if (!element._extended && element.tagName && element != window) { 
    48     var methods = Object.clone(Element.Methods), cache = Element.extend.cache; 
    49      
    50     if (element.tagName == 'FORM') 
    51       Object.extend(methods, Form.Methods); 
    52     if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))  
    53       Object.extend(methods, Form.Element.Methods); 
    54      
    55     Object.extend(methods, Element.Methods.Simulated); 
    56        
    57     for (var property in methods) { 
    58       var value = methods[property]; 
    59       if (typeof value == 'function' && !(property in element)) 
    60         element[property] = cache.findOrStore(value); 
    61     } 
     46  var F = Prototype.BrowserFeatures; 
     47  if (!element || !element.tagName || element.nodeType == 3 ||  
     48   element._extended || F.SpecificElementExtensions || element == window)  
     49    return element; 
     50 
     51  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,  
     52   T = Element.Methods.ByTag; 
     53 
     54  // extend methods for all tags (Safari doesn't need this) 
     55  if (!F.ElementExtensions) { 
     56    Object.extend(methods, Element.Methods),  
     57    Object.extend(methods, Element.Methods.Simulated);       
    6258  } 
    63    
     59 
     60  // extend methods for specific tags 
     61  if (T[tagName]) Object.extend(methods, T[tagName]); 
     62 
     63  for (var property in methods) { 
     64    var value = methods[property]; 
     65    if (typeof value == 'function' && !(property in element)) 
     66      element[property] = cache.findOrStore(value); 
     67  } 
     68 
    6469  element._extended = true; 
    6570  return element; 
    6671}; 
     
    471476  } 
    472477}; 
    473478 
     479Element.Methods.ByTag = {}; 
     480 
    474481// IE is missing .innerHTML support for TABLE-related elements 
    475482if (document.all && !window.opera){ 
    476483  Element.Methods.update = function(element, html) { 
     
    510517 
    511518Object.extend(Element, Element.Methods); 
    512519 
    513 var _nativeExtensions = false; 
     520if (!Prototype.BrowserFeatures.ElementExtensions &&  
     521 document.createElement('div').__proto__) { 
     522  window.HTMLElement = {}; 
     523  window.HTMLElement.prototype = document.createElement('div').__proto__; 
     524  Prototype.BrowserFeatures.ElementExtensions = true; 
     525
    514526 
    515 if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 
    516   ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { 
    517     var className = 'HTML' + tag + 'Element'; 
    518     if(window[className]) return; 
    519     var klass = window[className] = {}; 
    520     klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; 
    521   }); 
    522  
    523527Element.addMethods = function(methods) { 
    524   Object.extend(Element.Methods, methods || {}); 
     528  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; 
     529  if (arguments.length == 2) { 
     530    var tagName = methods; 
     531    methods = arguments[1]; 
     532  } 
    525533   
     534  if (!tagName) 
     535    Object.extend(Element.Methods, methods || {});   
     536  else { 
     537    if (tagName.constructor == Array) { 
     538      tagName.each(extend); 
     539    } 
     540    else extend(tagName); 
     541  } 
     542   
     543  function extend(tagName) { 
     544    tagName = tagName.toUpperCase(); 
     545    if (!Element.Methods.ByTag[tagName]) 
     546      Element.Methods.ByTag[tagName] = {}; 
     547    Object.extend(Element.Methods.ByTag[tagName], methods); 
     548  } 
     549 
    526550  function copy(methods, destination, onlyIfAbsent) { 
    527551    onlyIfAbsent = onlyIfAbsent || false; 
    528552    var cache = Element.extend.cache; 
     
    533557    } 
    534558  } 
    535559   
    536   if (typeof HTMLElement != 'undefined') { 
     560  function findDOMClass(tagName) { 
     561    var klass; 
     562    var trans = {        
     563      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",  
     564      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", 
     565      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", 
     566      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",  
     567      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":  
     568      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":  
     569      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": 
     570      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":  
     571      "FrameSet", "IFRAME": "IFrame" 
     572    }; 
     573    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; 
     574    if (window[klass]) return window[klass]; 
     575    klass = 'HTML' + tagName + 'Element'; 
     576    if (window[klass]) return window[klass]; 
     577    klass = 'HTML' + tagName.capitalize() + 'Element'; 
     578    if (window[klass]) return window[klass]; 
     579     
     580    window[klass] = {}; 
     581    window[klass].prototype = document.createElement(tagName).__proto__; 
     582    return window[klass]; 
     583  } 
     584   
     585  if (F.ElementExtensions) { 
    537586    copy(Element.Methods, HTMLElement.prototype); 
    538587    copy(Element.Methods.Simulated, HTMLElement.prototype, true); 
    539     copy(Form.Methods, HTMLFormElement.prototype); 
    540     [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { 
    541       copy(Form.Element.Methods, klass.prototype); 
    542     }); 
    543     _nativeExtensions = true; 
    544588  } 
    545 
     589   
     590  if (F.SpecificElementExtensions) { 
     591    for (var tag in Element.Methods.ByTag) { 
     592      var klass = findDOMClass(tag); 
     593      if (typeof klass == "undefined") continue; 
     594      copy(T[tag], klass.prototype); 
     595    } 
     596  }   
     597}; 
    546598 
    547599var Toggle = new Object(); 
    548600Toggle.display = Element.toggle; 
  • trunk/src/form.js

    old new  
    305305  } 
    306306}); 
    307307 
     308Object.extend(Element.Methods.ByTag, { 
     309  "FORM":     Form.Methods, 
     310  "INPUT":    Form.Element.Methods, 
     311  "SELECT":   Form.Element.Methods, 
     312  "TEXTAREA": Form.Element.Methods 
     313});