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

Changeset 6048

Show
Ignore:
Timestamp:
01/27/07 19:45:34 (2 years ago)
Author:
sam
Message:

prototype: Fix $(form).serialize() in Safari and add support for extending specific tags to Element.addMethods. Closes #7358.

Files:

Legend:

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

    r6047 r6048  
    11*SVN* 
     2 
     3* Fix $(form).serialize() in Safari and add support for extending specific tags to Element.addMethods.  Closes #7358.  [Andrew Dupont] 
    24 
    35* Add String.prototype.startsWith, String.prototype.endsWith, and String.prototype.include.  Closes #7075.  [Tobie Langel] 
  • spinoffs/prototype/trunk/src/dom.js

    r6002 r6048  
    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     } 
    62   } 
    63    
     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);       
     58  } 
     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; 
     
    471476  } 
    472477}; 
     478 
     479Element.Methods.ByTag = {}; 
    473480 
    474481// IE is missing .innerHTML support for TABLE-related elements 
     
    511518Object.extend(Element, Element.Methods); 
    512519 
    513 var _nativeExtensions = false; 
    514  
    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   }); 
     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
    522526 
    523527Element.addMethods = function(methods) { 
    524   Object.extend(Element.Methods, methods || {}); 
    525    
     528  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; 
     529  if (arguments.length == 2) { 
     530    var tagName = methods; 
     531    methods = arguments[1]; 
     532  } 
     533   
     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; 
     
    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; 
    544   } 
    545 
     588  } 
     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(); 
  • spinoffs/prototype/trunk/src/form.js

    r5997 r6048  
    157157 
    158158Object.extend(Form.Element, Form.Element.Methods); 
     159Object.extend(Element.Methods.ByTag, { 
     160  "FORM":     Object.clone(Form.Methods), 
     161  "INPUT":    Object.clone(Form.Element.Methods), 
     162  "SELECT":   Object.clone(Form.Element.Methods), 
     163  "TEXTAREA": Object.clone(Form.Element.Methods) 
     164}); 
     165 
     166/*--------------------------------------------------------------------------*/ 
     167 
    159168var Field = Form.Element; 
    160169var $F = Form.Element.getValue; 
     
    305314  } 
    306315}); 
    307  
  • spinoffs/prototype/trunk/src/prototype.js

    r5102 r6048  
    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   
  • spinoffs/prototype/trunk/test/unit/dom.html

    r6002 r6048  
    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 
     
    272284      assertIdentical(elt, $(elt)); 
    273285      assertRespondsTo('hide', elt); 
     286      assertRespondsTo('childOf', elt); 
    274287    }}, 
    275288     
     
    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     
     
    802815      assertEqual(Position.page(elem)[1], 0);       
    803816      window.scrollTo(0, 0); 
    804     }} 
    805      
     817    }}, 
     818     
     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 
  • spinoffs/prototype/trunk/test/unit/form.html

    r5997 r6048  
    281281      assertEqual('nvm%5B%5D=One&nvm%5B%5D=Three&evu=&evm%5B%5D=&evm%5B%5D=Three', Form.serialize('form_fieldset')); 
    282282      assertEqual('vu=1&vm%5B%5D=1&vm%5B%5D=3&nvu=One&nvm%5B%5D=One&nvm%5B%5D=Three&evu=&evm%5B%5D=&evm%5B%5D=Three', Form.serialize('form_wrapper')); 
    283     }}  
     283    }}, 
     284     
     285    testFormMethodsOnExtendedElements: function() {with(this) { 
     286      assertEqual(Form.serialize('form'), $('form').serialize()); 
     287      assertEqual(Form.Element.serialize('input_enabled'), $('input_enabled').serialize()); 
     288      assertNotEqual($('form').serialize, $('input_enabled').serialize); 
     289       
     290      Element.addMethods('INPUT',  { anInputMethod: function(input)  { return 'input'  } }); 
     291      Element.addMethods('SELECT', { aSelectMethod: function(select) { return 'select' } }); 
     292 
     293      document.getElementById('tf_text')._extended = false; 
     294      document.getElementById('tf_selectOne')._extended = false; 
     295 
     296      assert($('tf_text').anInputMethod); 
     297      assert(!$('tf_text').aSelectMethod); 
     298      assertEqual('input', $('tf_text').anInputMethod()); 
     299 
     300      assert($('tf_selectOne').aSelectMethod); 
     301      assert(!$('tf_selectOne').anInputMethod);       
     302      assertEqual('select', $('tf_selectOne').aSelectMethod()); 
     303    }} 
    284304     
    285305  }, 'testlog');