|
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 代码
- Element.addMethods({
-
- sayHello: function() {
-
- alert(‘hello!’);
-
- }
- });
$(anything).sayHello();
//弹出对话框 hello
<o:p> </o:p>
复杂点的用法,加上参数:
js 代码
- Element.addMethods({
-
- ajaxUpdate: function(element, url, options){
-
- element = $(element);
-
- element.update('
-
- new Ajax.Updater(element, url, options);
-
- return element;
-
- }
-
- });
$(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 代码
- Form.Element.Methods.processing = function(element, text) {
-
- element = $(element);
-
- if (element.tagName.toLowerCase() == 'input' && ['button', 'submit'].include(element.type))
-
- element.value = typeof text == 'undefined' ? 'Please wait...' : text;
-
- return element.disable();
-
- };
-
- Element.addMethods();
然后就可以通过$(someInputElement).processing()来调用了。<o:p></o:p>
借用这个机制,可以方便的把自己写的方法加入进来。比如我上一篇博客提到的无刷上传。
言归正传,看看prototype是怎么实现这个机制的。以下是实现的源代码:(1.6rc)
js 代码
- Element.addMethods = function(methods) {
-
- var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
-
-
-
- if (!methods) {
-
- Object.extend(Form, Form.Methods);
-
- Object.extend(Form.Element, Form.Element.Methods);
-
- Object.extend(Element.Methods.ByTag, {
-
- "FORM": Object.clone(Form.Methods),
-
- "INPUT": Object.clone(Form.Element.Methods),
-
- "SELECT": Object.clone(Form.Element.Methods),
-
- "TEXTAREA": Object.clone(Form.Element.Methods)
-
- });
-
- }
-
-
-
- if (arguments.length == 2) {
-
- var tagName = methods;
-
- methods = arguments[1];
-
- }
-
-
-
- if (!tagName) Object.extend(Element.Methods, methods || { });
-
- else {
-
- if (Object.isArray(tagName)) tagName.each(extend);
-
- else extend(tagName);
-
- }
-
-
-
- function extend(tagName) {
-
- tagName = tagName.toUpperCase();
-
- if (!Element.Methods.ByTag[tagName])
-
- Element.Methods.ByTag[tagName] = { };
-
- Object.extend(Element.Methods.ByTag[tagName], methods);
-
- }
-
-
-
- function copy(methods, destination, onlyIfAbsent) {
-
- onlyIfAbsent = onlyIfAbsent || false;
-
- for (var property in methods) {
-
- var value = methods[property];
-
- if (!Object.isFunction(value)) continue;
-
- if (!onlyIfAbsent || !(property in destination))
-
- destination[property] = value.methodize();
-
- }
-
- }
-
-
-
- function findDOMClass(tagName) {
-
- var klass;
-
- var trans = {
-
- "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
-
- "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
-
- "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
-
- "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
-
- "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
-
- "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
-
- "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
-
- "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
-
- "FrameSet", "IFRAME": "IFrame"
-
- };
-
- if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
-
- if (window[klass]) return window[klass];
-
- klass = 'HTML' + tagName + 'Element';
-
- if (window[klass]) return window[klass];
-
- klass = 'HTML' + tagName.capitalize() + 'Element';
-
- if (window[klass]) return window[klass];
-
-
-
- window[klass] = { };
-
- window[klass].prototype = document.createElement(tagName).__proto__;
-
- return window[klass];
-
- }此方法用来在各种不同的浏览器中找到正确的html dom 类名,然后返回之
-
-
-
-
-
- if (F.ElementExtensions) {
-
- copy(Element.Methods, HTMLElement.prototype);
-
- copy(Element.Methods.Simulated, HTMLElement.prototype, true);
-
- }
-
-
-
- if (F.SpecificElementExtensions) {
-
- for (var tag in Element.Methods.ByTag) {
-
- var klass = findDOMClass(tag);
-
- if (Object.isUndefined(klass)) continue;
-
- copy(T[tag], klass.prototype);
-
- }
-
- }
-
-
-
- Object.extend(Element, Element.Methods);
-
- delete Element.ByTag;
-
-
-
- if (Element.extend.refresh) Element.extend.refresh();
-
- Element.cache = { };
-
- };
至此,一个强大的功能诞生!附件是一个小小的实现
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|