Prototype 'Element.addMethods()' 笔记

Prototype 提供了方便的扩展机制让用户可以把自定义的方法加入到框架中。用户可以在独立的文件中编写代码,而不用修改prototype.js本身,大大的增加了代码的可维护性,和可扩展性。这个方法就是Element.addMethods()

在官方的文档中对这个方法的介绍是:

Element.addMethods makes it possible to mix in your own methods to the Element object, which you can later use as methods of extended elements - those returned by the $() utility, for example - or as methods of Element.

方法原型是Element .addMethods([methods])<o:p></o:p>

一个最简单的使用:<o:p></o:p>

js 代码
 
  1. Element.addMethods({  
  2.  
  3.   sayHello: function() {  
  4.   
  5.    alert(‘hello!’);  
  6.   
  7.   } 

  8. });  

$(anything).sayHello();

//弹出对话框 hello

<o:p> </o:p>

复杂点的用法,加上参数:

js 代码
 
  1. Element.addMethods({  
  2.   
  3.   ajaxUpdate: function(element, url, options){  
  4.   
  5.     element = $(element);  
  6.   
  7.     element.update('
  8.   
  9.     new Ajax.Updater(element, url, options);  
  10.   
  11.     return element;  
  12.   
  13.   }  
  14.   
  15. });  

$(element).ajaxUpdate('/new/content');

// ->返回 HTMLElement

<o:p> </o:p>

仔细看一下Prototype.js最后一行调用了这一个方法,但是不带任何参数。文档里面说明,这样的用法是遍历Element.Methods, Element.Methods.Simulated, Form.Methods Form.Element.Methods对象,把所有的方法加入到相应的元素中。例如:<o:p></o:p>

js 代码
 
  1.  Form.Element.Methods.processing = function(element, text) {  
  2.   
  3.   element = $(element);  
  4.   
  5.   if (element.tagName.toLowerCase() == 'input' && ['button', 'submit'].include(element.type))  
  6.   
  7.     element.value = typeof text == 'undefined' ? 'Please wait...' : text;  
  8.   
  9.   return element.disable();  
  10.   
  11. };  
  12.   
  13. Element.addMethods();  

然后就可以通过$(someInputElement).processing()来调用了。<o:p></o:p>

借用这个机制,可以方便的把自己写的方法加入进来。比如我上一篇博客提到的无刷上传。

言归正传,看看prototype是怎么实现这个机制的。以下是实现的源代码:(1.6rc)

js 代码
 
  1. Element.addMethods = function(methods) {  
  2.   
  3.   var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;  
  4.   
  5. //  
  6.   
  7.   if (!methods) { //如果没有提供参数,那么默认初始化全部方法  
  8.   
  9.     Object.extend(Form, Form.Methods);  
  10.   
  11.     Object.extend(Form.Element, Form.Element.Methods);  
  12.   
  13.     Object.extend(Element.Methods.ByTag, {  
  14.   
  15.       "FORM":     Object.clone(Form.Methods),  
  16.   
  17.       "INPUT":    Object.clone(Form.Element.Methods),  
  18.   
  19.       "SELECT":   Object.clone(Form.Element.Methods),  
  20.   
  21.       "TEXTAREA": Object.clone(Form.Element.Methods)  
  22.   
  23.     });  
  24.   
  25.   }//继承Methods里面所有的方法  
  26.   
  27.    
  28.   
  29.   if (arguments.length == 2) {//如果提供的参数是2个  
  30.   
  31.     var tagName = methods;//把第一个参数视为tagName  
  32.   
  33. methods = arguments[1];  
  34.   
  35.   }  
  36.   
  37. //如果没有定义tagName,那么默认把methods添加到Element.Methods中  
  38.   
  39.   if (!tagName) Object.extend(Element.Methods, methods || { });  
  40.   
  41.   else {  
  42.   
  43.     if (Object.isArray(tagName)) tagName.each(extend);  
  44.   
  45.     else extend(tagName);  
  46.   
  47.   }//调用extent方法,如果tagName是数组,那么依次调用extent方法。  
  48.   
  49.    
  50.   
  51.   function extend(tagName) {  
  52.   
  53.     tagName = tagName.toUpperCase();  
  54.   
  55.     if (!Element.Methods.ByTag[tagName])  
  56.   
  57.       Element.Methods.ByTag[tagName] = { };  
  58.   
  59.     Object.extend(Element.Methods.ByTag[tagName], methods);  
  60.   
  61.   } //在Element.Methods.ByTag中存放以tagName为标识的继承了methods的对象  
  62.   
  63.    
  64.   
  65.   function copy(methods, destination, onlyIfAbsent) {  
  66.   
  67.     onlyIfAbsent = onlyIfAbsent || false;  
  68.   
  69.     for (var property in methods) {  
  70.   
  71.       var value = methods[property];  
  72.   
  73.       if (!Object.isFunction(value)) continue;  
  74.   
  75.       if (!onlyIfAbsent || !(property in destination))  
  76.   
  77.         destination[property] = value.methodize();  
  78.   
  79.     }  
  80.   
  81.   }//此方法用来把methods里面的所有方法复制到destination中  
  82.   
  83.    
  84.   
  85.   function findDOMClass(tagName) {  
  86.   
  87.     var klass;  
  88.   
  89.     var trans = {  
  90.   
  91.       "OPTGROUP""OptGroup""TEXTAREA""TextArea""P""Paragraph",  
  92.   
  93.       "FIELDSET""FieldSet""UL""UList""OL""OList""DL""DList",  
  94.   
  95.       "DIR""Directory""H1""Heading""H2""Heading""H3""Heading",  
  96.   
  97.       "H4""Heading""H5""Heading""H6""Heading""Q""Quote",  
  98.   
  99.       "INS""Mod""DEL""Mod""A""Anchor""IMG""Image""CAPTION":  
  100.   
  101.       "TableCaption""COL""TableCol""COLGROUP""TableCol""THEAD":  
  102.   
  103.       "TableSection""TFOOT""TableSection""TBODY""TableSection""TR":  
  104.   
  105.       "TableRow""TH""TableCell""TD""TableCell""FRAMESET":  
  106.   
  107.       "FrameSet""IFRAME""IFrame"  
  108.   
  109.     };  
  110.   
  111.     if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';  
  112.   
  113.     if (window[klass]) return window[klass];  
  114.   
  115.     klass = 'HTML' + tagName + 'Element';  
  116.   
  117.     if (window[klass]) return window[klass];  
  118.   
  119.     klass = 'HTML' + tagName.capitalize() + 'Element';  
  120.   
  121.     if (window[klass]) return window[klass];  
  122.   
  123.    
  124.   
  125.     window[klass] = { };  
  126.   
  127.     window[klass].prototype = document.createElement(tagName).__proto__;  
  128.   
  129.     return window[klass];  
  130.   
  131.   }此方法用来在各种不同的浏览器中找到正确的html dom 类名,然后返回之  
  132.   
  133.    
  134.   
  135. //接着处理,下面就是该把对应每个标签的自定义方法绑定到标签的prototype上了。  
  136.   
  137.   if (F.ElementExtensions) {  
  138.   
  139.     copy(Element.Methods, HTMLElement.prototype);  
  140.   
  141.     copy(Element.Methods.Simulated, HTMLElement.prototype, true);  
  142.   
  143.   }  
  144.   
  145.    
  146.   
  147.   if (F.SpecificElementExtensions) {  
  148.   
  149.     for (var tag in Element.Methods.ByTag) {  
  150.   
  151.       var klass = findDOMClass(tag);  
  152.   
  153.       if (Object.isUndefined(klass)) continue;  
  154.   
  155.       copy(T[tag], klass.prototype);  
  156.   
  157.     }  
  158.   
  159.   }//把Element.Methods.ByTag里面的方法绑定到相应的tagName上  
  160.   
  161.    
  162.   
  163.   Object.extend(Element, Element.Methods);//把Element.Methods里的方法绑到Element里  
  164.   
  165.   delete Element.ByTag; //删掉Element.ByTag;  
  166.   
  167.    
  168.   
  169.   if (Element.extend.refresh) Element.extend.refresh();  
  170.   
  171.   Element.cache = { };//刷新并清空缓存,扫尾。  
  172.   
  173. };  
至此,一个强大的功能诞生!附件是一个小小的实现

你可能感兴趣的:(html,Ajax,框架,prototype,F#)