请选择 进入手机版 | 继续访问电脑版
收藏本站腾讯微博新浪微博
点点网模板设计大赛 phpchina

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 用悬赏 三天解决问题 解决访问速度慢 论坛支持农历生日 - 给官方提建议

论坛活动及任务 归纳网站最新活动 地图任务 邮件更新任务:保护帐号安全

积分换实物,来参加蓝色理想积分兑换吧! 联系招聘客服 蓝色理想帮你找工作! 万元奖励等你拿——点点网模板设计大赛

查看: 1960|回复: 11

[转载]prototype-1.4.0源码解读,好东西,要看看哦! [复制链接]

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:03:32 |显示全部楼层
  1. /*
  2. prototype-1.4.0注释版本 by http://www.x2blog.cn/supNate/

  3. prototype框架最早是出于方便Ruby开发人员进行JavaScript开发所构建的,从这个版本上更加体现的淋漓尽致。
  4. 比起1.3.1版本,1.4.0中的编程思想和技巧更加令人拍案叫绝,对于开拓编程思路很有帮助。

  5. 该版本主要加入了迭代器思想,也是Ruby中的一个核心概念,从而使用此框架进行JavaScript开发几乎可以避免for循环的使用。
  6. /*----------------------------------------------------------------------------------------------------*/


  7. /*
  8. 定义prototype对象,告知版本信息,有利于程序的自动检测
  9. ScriptFragment是正则表达式,用于捕获字符串中的<script>标记及其中的内容
  10. emptyFunction:空函数
  11. K:返回参数自身的函数,后面会有应用

  12. 在这里使用了直接定义对象的语法:
  13. var obj={
  14.         property1:value1,
  15.         property2:value2,
  16.         ....
  17. }
  18. 后面会经常用到
  19. */
  20. var Prototype = {
  21.   Version: '1.4.0',
  22.   ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

  23.   emptyFunction: function() {},
  24.   K: function(x) {return x}
  25. }

  26. /*
  27. 定义创建类的模式,使用此模式创建的类能够实现构造函数
  28. 其中initialize是一个抽象方法,apply使得能对其保持参数。
  29. 如果直接调用this.initialize(arguments),则整个参数数组作为了一个参数。
  30. */
  31. var Class = {
  32.   create: function() {
  33.     return function() {
  34.       this.initialize.apply(this, arguments);
  35.     }
  36.   }
  37. }

  38. //表示命名空间或者抽象类的东西,使代码逻辑更加清楚
  39. var Abstract = new Object();

  40. /*
  41. 将source的所有属性复制到destination
  42. 例如:
  43. var a={};
  44. var b={p:1};
  45. Object.extent(a,b);
  46. alert(a.p);
  47. 可以看到a具有了属性p且值等于1。
  48. 如果属性相同则覆盖。
  49. */
  50. Object.extend = function(destination, source) {
  51.   for (property in source) {
  52.     destination[property] = source[property];
  53.   }
  54.   return destination;
  55. }
  56. /*
  57. 相比prototype-1.3.1这里少了下面的函数:
  58. Object.prototype.extend = function(object) {
  59.   return Object.extend.apply(this, [this, object]);
  60. }
  61. 所以原先基于1.3.1框架的js脚本升级到1.4.0时会产生兼容性问题。只要在1.4.0里加上上述函数即可。
  62. 去掉的原因大概因为为每个object都增加extend方法显的很浪费,毕竟95%的对象是不会用到的。
  63. 而且增加了extend方法也为反射枚举带来一定的麻烦,这从后面Hash对象的用法可以看到。
  64. */

  65. /*
  66. 将对象转换为字符串,这里能够更详细一些,只要对象自定义了inspect函数。而不是原来对象的toString总是[object]。
  67. 例如后面对数组定义了inspect函数,使得
  68. var arr=[1,2,3];
  69. -》arr.inspect()=="[1,2,3]";
  70. */
  71. Object.inspect = function(object) {
  72.   try {
  73.     if (object == undefined) return 'undefined';
  74.     if (object == null) return 'null';
  75.     return object.inspect ? object.inspect() : object.toString();
  76.   } catch (e) {
  77.     if (e instanceof RangeError) return '...';
  78.     throw e;
  79.   }
  80. }

  81. /*
  82. 一个很重要的方法,能够将函数绑定到某个对象运行
  83. 和1.3.1版本相比,原来不能在绑定的时候就添加参数,而现在可以。
  84. 例如:
  85. var obj1={p:"obj1"};
  86. var obj2={
  87.         p:"obj2",
  88.         method:function(arg){
  89.                 alert(arg+this.p);
  90.         }
  91. }
  92. obj2.method("this is ");//显示“this is obj2”;
  93. obj2.method.bind(obj1,"now this is ");//显示“now this is obj1”;
  94. 最后一句在1.3.1中必须写为:
  95. obj2.method.bind(obj1)("now this is ");//显示“now this is obj1”;
  96. */
  97. Function.prototype.bind = function() {
  98.   var __method = this, args = $A(arguments), object = args.shift();
  99.   return function() {
  100.     return __method.apply(object, args.concat($A(arguments)));
  101.   }
  102. }
  103. /*
  104. 将函数作为对象的事件监听器,这样可以产生独立而且通用的事件处理程序,例如要对单击事件进行处理:
  105. function clickHandler(element){
  106.         //处理element的单击事件
  107. }

  108. 假设有节点node1,则:
  109. node1.onclick=function(){
  110.         clickHandler.bindAsEventListener(this)(event||window.event);
  111. }
  112. */
  113. Function.prototype.bindAsEventListener = function(object) {
  114.   var __method = this;
  115.   return function(event) {
  116.     return __method.call(object, event || window.event);
  117.   }
  118. }

  119. /*
  120. 所有的数字类型都是Number类的实例,下面就是给Number类定义一些方法
  121. */
  122. Object.extend(Number.prototype, {
  123.         /*
  124.         将数字转换为颜色的形式
  125.         */
  126.   toColorPart: function() {
  127.     var digits = this.toString(16);
  128.     if (this < 16) return '0' + digits;
  129.     return digits;
  130.   },
  131.         //加1
  132.   succ: function() {
  133.     return this + 1;
  134.   },
  135.         /*
  136.         执行指定次数的循环,例如获取10个随机数
  137.         var ran=[]
  138.         var c=10;
  139.         c.times(function(){
  140.                 ran.push(Math.random());
  141.         });
  142.         $R是ObjectRange对象的快捷创建形式,后面会有介绍。
  143.         */
  144.   times: function(iterator) {
  145.     $R(0, this, true).each(iterator);
  146.     return this;
  147.   }
  148. });

  149. /*
  150. Try对象,仅有一个方法these
  151. */
  152. var Try = {
  153.         /*
  154.         根据参数指定的函数进行调用,返回第一个调用成功的值
  155.         在后面跨浏览器建立XMLHttpRequest对象时就用到了。
  156.         如果所有都不成功则返回undefined
  157.         */
  158.   these: function() {
  159.     var returnValue;

  160.     for (var i = 0; i < arguments.length; i++) {
  161.       var lambda = arguments[i];
  162.       try {
  163.         returnValue = lambda();
  164.         break;
  165.       } catch (e) {}
  166.     }

  167.     return returnValue;
  168.   }
  169. }

  170. /*--------------------------------------------------------------------------*/


  171. /*
  172. 定时器类,比起window.setInterval函数,该类能够使得回调函数不会被并发调用,见onTimerEvent的注释。
  173. */
  174. var PeriodicalExecuter = Class.create();
  175. PeriodicalExecuter.prototype = {
  176.         /*
  177.         构造函数,指定回调函数和执行频率,单位为秒
  178.         */
  179.   initialize: function(callback, frequency) {
  180.     this.callback = callback;
  181.     this.frequency = frequency;
  182.     this.currentlyExecuting = false;
  183.     this.registerCallback();
  184.   },
  185.         /*
  186.         开始执行定时器,一般不要显示调用,在构造函数中被调用
  187.         注意这里写为:
  188.         this.onTimerEvent.bind(this)
  189.         如果写为:
  190.         this.onTimerEvent
  191.         则onTimerEvent中的函数的this指针将指向window对象,即setInterval的默认对象。
  192.         */
  193.   registerCallback: function() {
  194.     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  195.   },
  196.         /*
  197.         相当于回调函数的一个代理。
  198.         在传统的setInterval函数中,时间一到,便强制执行回调函数,而这里加入了currentlyExecuting属性判断,
  199.         则如果callback函数的执行时间超过了一个时间片,则阻止其被重复执行。
  200.         */
  201.   onTimerEvent: function() {
  202.     if (!this.currentlyExecuting) {
  203.       try {
  204.         this.currentlyExecuting = true;
  205.         this.callback();
  206.       } finally {
  207.         this.currentlyExecuting = false;
  208.       }
  209.     }
  210.   }
  211. }

  212. /*--------------------------------------------------------------------------*/
  213. /*
  214. 很方便的一个快速链接函数,能够获得参数所指定的页面节点,如果有多个参数则返回数组。
  215. 参数的形式既可以是节点的id值,也可以是节点的引用,即$($("someId"))和$("someId")是等价的;
  216. */
  217. function $() {
  218.   var elements = new Array();

  219.   for (var i = 0; i < arguments.length; i++) {
  220.     var element = arguments[i];
  221.     if (typeof element == 'string')
  222.       element = document.getElementById(element);

  223.     if (arguments.length == 1)
  224.       return element;

  225.     elements.push(element);
  226.   }

  227.   return elements;
  228. }

  229. /*
  230. 为字符串对象添加方法,和前面为Number添加方法的原理相同
  231. */
  232. Object.extend(String.prototype, {
  233.         /*
  234.         将Html转换为纯文本,例如:
  235.         var s="<font color='red'>hello</font>";
  236.         s.stripTags()将得到“hello”。
  237.         */
  238.   stripTags: function() {
  239.     return this.replace(/<\/?[^>]+>/gi, '');
  240.   },
  241.         /*
  242.         删除文本中的脚本代码(<script xxx>...</script>)
  243.         */
  244.   stripScripts: function() {
  245.     return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  246.   },
  247.         //提取字符串中的脚本,返回所有脚本内容组成的数组
  248.   extractScripts: function() {
  249.     var matchAll = new RegExp(Prototype.ScriptFragment, 'img');//先找到所有包括<script>的代码标记
  250.     var matchOne = new RegExp(Prototype.ScriptFragment, 'im');        //再对每个脚本删除<script>标记
  251.     return (this.match(matchAll) || []).map(function(scriptTag) {
  252.       return (scriptTag.match(matchOne) || ['', ''])[1];
  253.     });
  254.   },
  255.         //先提取字符串中的脚本块,再执行这些脚本
  256.   evalScripts: function() {
  257.     return this.extractScripts().map(eval);
  258.   },
  259.         /*
  260.         利用浏览器本身的机制对Html字符串进行编码,例如将<转换为&lt;
  261.         */
  262.   escapeHTML: function() {
  263.     var div = document.createElement('div');
  264.     var text = document.createTextNode(this);
  265.     div.appendChild(text);
  266.     return div.innerHTML;
  267.   },
  268.         /*
  269.         对Html进行解码
  270.         */
  271.   unescapeHTML: function() {
  272.     var div = document.createElement('div');
  273.     div.innerHTML = this.stripTags();
  274.     return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
  275.   },
  276.         //获取查询字符串数组,例如通过document.location.toQueryParams()就可以得到由键和值组成的哈希表(用对象表示)。
  277.   toQueryParams: function() {
  278.     var pairs = this.match(/^\??(.*)$/)[1].split('&');
  279.     return pairs.inject({}, function(params, pairString) {
  280.       var pair = pairString.split('=');
  281.       params[pair[0]] = pair[1];
  282.       return params;
  283.     });
  284.   },
  285.         //将字符串转换为字符数组
  286.   toArray: function() {
  287.     return this.split('');
  288.   },
  289.         /*
  290.         将用"-"连接的字符串骆驼化。例如:
  291.         var s="background-color";
  292.         alert(s.camelize());
  293.         将得到“backgroundColor”。
  294.         */
  295.   camelize: function() {
  296.     var oStringList = this.split('-');
  297.     if (oStringList.length == 1) return oStringList[0];

  298.     var camelizedString = this.indexOf('-') == 0
  299.       ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
  300.       : oStringList[0];

  301.     for (var i = 1, len = oStringList.length; i < len; i++) {
  302.       var s = oStringList[i];
  303.       camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
  304.     }

  305.     return camelizedString;
  306.   },
  307.         /*
  308.         inspect是观察的意思。这里大概就是将字符串转换为可观察的形式。这里将转义字符写成转义前的字符串形式,
  309.         例如:
  310.         var s="abc\ndef";

  311.         alert(s);
  312.         将得到两行字符串,上一行是abc,下一行是def
  313.         而
  314.         alert(s.inspect());
  315.         将得到abc\ndef
  316.         即给字符串赋值时的形式,这和数组的inspect作用类似。
  317.         */
  318.   inspect: function() {
  319.     return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
  320.   }
  321. });

  322. //做一个名称链接
  323. String.prototype.parseQuery = String.prototype.toQueryParams;

  324. //定义了两个异常对象,主要用于迭代控制
  325. var $break    = new Object();
  326. var $continue = new Object();

  327. /*
  328. 这是一个非常Ruby的机制,事实上可以将Enumerable看作一个枚举接口,
  329. 而_each是必须实现的方法,只要实现了此方法的类,都可以调用接口类中的其他成员。
  330. 例如后面Array就实现了此接口,也是最典型的应用
  331. */
  332. var Enumerable = {
  333.         /*
  334.         对可枚举对象的每个成员调用iterator(迭代器)方法,
  335.         如果迭代器方法抛出$continue异常,则继续执行,如果抛出$break异常,则不再继续迭代
  336.        
  337.         其中调用了_each这个抽象方法,
  338.         _each是由具体的继承于Enumerable的类实现的

  339.         index计数器的作用是用于告诉迭代器当前执行到第几个元素,是迭代器可选实现的。
  340.         */
  341.   each: function(iterator) {
  342.     var index = 0;
  343.     try {
  344.       this._each(function(value) {
  345.         try {
  346.           iterator(value, index++);
  347.         } catch (e) {
  348.           if (e != $continue) throw e;
  349.         }
  350.       });
  351.     } catch (e) {
  352.       if (e != $break) throw e;
  353.     }
  354.   },
  355.         /*
  356.         判断枚举对象中的所有元素是否都能使得迭代器返回true。如果没有指定迭代器,则判断所有元素是否都对应于布尔类型的true
  357.         如果所有都满足,则返回true;否则返回false;
  358.         注意这里就使用了$break异常,用于实现“逻辑与”操作的短路效果
  359.         另外值得注意的一个技巧是使用了!!将一个变量强制转换为布尔类型,可以参考:http://www.x2blog.cn/supNate/?tid=4669
  360.         */
  361. all: function(iterator) {
  362. var result = true;
  363. this.each(function(value, index) {
  364. result = result && !!(iterator || Prototype.K)(value, index);
  365. if (!result) throw $break;
  366. });
  367. return result;
  368. },
  369.         /*
  370.         判断枚举对象中的所有元素是否有满足指定迭代器的值(返回true),如果有则返回true,否则返回false
  371.         其原理和all方法类似

  372.         如果数组为空,仍然返回true,这一点有点匪夷所思。
  373.         */
  374.   any: function(iterator) {
  375.     var result = true;
  376.     this.each(function(value, index) {
  377.       if (result = !!(iterator || Prototype.K)(value, index))
  378.         throw $break;
  379.     });
  380.     return result;
  381.   },
  382.         /*
  383.         返回所有枚举元素通过迭代器执行的结果,作为数组返回
  384.         */
  385.   collect: function(iterator) {
  386.     var results = [];
  387.     this.each(function(value, index) {
  388.       results.push(iterator(value, index));
  389.     });
  390.     return results;
  391.   },
  392.         /*
  393.         返回第一个能够使得迭代器返回true的枚举元素的值,如果没有true,则返回"undefined",即result未被赋值
  394.         这有可能是作者考虑的一个小失误,毕竟返回"undefined"并不是一个好的风格(仅是猜测)
  395.         */
  396.   detect: function (iterator) {
  397.     var result;
  398.     this.each(function(value, index) {
  399.       if (iterator(value, index)) {
  400.         result = value;
  401.         throw $break;
  402.       }
  403.     });
  404.     return result;
  405.   },
  406.         /*
  407.         返回所有能够使得迭代器返回true的枚举元素,作为数组返回。
  408.         */
  409.   findAll: function(iterator) {
  410.     var results = [];
  411.     this.each(function(value, index) {
  412.       if (iterator(value, index))
  413.         results.push(value);
  414.     });
  415.     return results;
  416.   },
  417.         /*
  418.         grep是unix类操作系统下的一个经典命令,而这里则是JavaScript的一个类似实现
  419.         pattern是正则模式,对所有符合此模式的枚举元素进行迭代器运算,并将运算结果保存到数组中并返回。
  420.         需要注意,这里的iterator参数是可选的,此时仅仅对枚举元素进行模式匹配,返回所有的匹配结果
  421.         */
  422.   grep: function(pattern, iterator) {
  423.     var results = [];
  424.     this.each(function(value, index) {
  425.       var stringValue = value.toString();
  426.       if (stringValue.match(pattern))
  427.         results.push((iterator || Prototype.K)(value, index));
  428.     })
  429.     return results;
  430.   },
  431.         /*
  432.         判断枚举对象中是否包含指定值的枚举元素,这里仍然使用了each方法,而不是循环,可见prototype致力于提供一种ruby化的编程方式,
  433.         如果用循环实现,则是类似于以下的代码:
  434.         for(var i=0;i<this.length;i++){
  435.                 if(this[i]==object)return true;
  436.         }
  437.         而该函数中,定义了迭代器:
  438.         function(value) {
  439.       if (value == object) {
  440.         found = true;
  441.         throw $break;
  442.       }
  443.     }
  444.         这个迭代器作为each方法的参数。
  445.        
  446.         */
  447.   include: function(object) {
  448.     var found = false;
  449.     this.each(function(value) {
  450.       if (value == object) {
  451.         found = true;
  452.         throw $break;
  453.       }
  454.     });
  455.     return found;
  456.   },

  457.         /*
  458.         字面意思是“注入”,其作用相当于将memo作为联系各个迭代器的全局变量,每次迭代都对其进行操作,返回操作的最后结果。例如对于数组:
  459.         var arr=[1,2,3];
  460.         现在想将其字符串化为:123
  461.         如果不调用join方法,传统做法是:
  462.         var s="";
  463.         for(var i=0;i<arr.length;i++){
  464.                 s+=arr[i];
  465.         }
  466.         现在通过调用inject函数,则:
  467.         var s=arr.inject("",function(memo,value){return memo+value});
  468.         两者运行的结果是完全相同的。
  469.         */
  470.   inject: function(memo, iterator) {
  471.     this.each(function(value, index) {
  472.       memo = iterator(memo, value, index);
  473.     });
  474.     return memo;
  475.   },

  476.         /*
  477.         在所有枚举元素上调用method方法,并可以给这个方法传递参数
  478.         返回所有method的执行结果,作为数组返回
  479.         */
  480.   invoke: function(method) {
  481.     var args = $A(arguments).slice(1);
  482.     return this.collect(function(value) {
  483.       return value[method].apply(value, args);
  484.     });
  485.   },
  486.         /*
  487.         返回最大的迭代器返回值
  488.         */
  489.   max: function(iterator) {
  490.     var result;
  491.     this.each(function(value, index) {
  492.       value = (iterator || Prototype.K)(value, index);
  493.       if (value >= (result || value))
  494.         result = value;
  495.     });
  496.     return result;
  497.   },
  498.         /*
  499.         返回最小的迭代器返回值
  500.         */
  501.   min: function(iterator) {
  502.     var result;
  503.     this.each(function(value, index) {
  504.       value = (iterator || Prototype.K)(value, index);
  505.       if (value <= (result || value))
  506.         result = value;
  507.     });
  508.     return result;
  509.   },
  510.         /*
  511.         按照迭代器的返回结果,将枚举元素分为两个数组trues和falses,其中trues包括迭代器返回true的枚举元素,falses则相反。
  512.         */
  513.   partition: function(iterator) {
  514.     var trues = [], falses = [];
  515.     this.each(function(value, index) {
  516.       ((iterator || Prototype.K)(value, index) ?
  517.         trues : falses).push(value);
  518.     });
  519.     return [trues, falses];
  520.   },
  521.         /*
  522.         返回所有枚举元素的property属性
  523.         */
  524.   pluck: function(property) {
  525.     var results = [];
  526.     this.each(function(value, index) {
  527.       results.push(value[property]);
  528.     });
  529.     return results;
  530.   },

  531.         /*
  532.         返回所有迭代器执行结果为false的枚举元素
  533.         */
  534.   reject: function(iterator) {
  535.     var results = [];
  536.     this.each(function(value, index) {
  537.       if (!iterator(value, index))
  538.         results.push(value);
  539.     });
  540.     return results;
  541.   },
  542.         /*
  543.         结构复杂的一个函数,作用是根据迭代器iterator的结果对枚举元素进行排序。使iterator执行结果小的元素排在前面。
  544.         主要包括三个函数的调用:
  545.         1。collect方法,返回的每个数组元素包括:值和迭代器运行该值的结果,用{value:value,criteria:iterator(value,index)}得到
  546.         2。对collect返回的数组执行sort方法,这时数组对象内置的对象,参数是一个委托函数,用于指定排序规则。其标准是对迭代器返回的值排序,小的在前面
  547.         3。对sort的结果执行pluck方法,即返回value属性的值,于是最后还是返回的枚举对象中的原有值,只是根据迭代器iterator的结果对这些元素进行排序
  548.         */
  549.   sortBy: function(iterator) {
  550.     return this.collect(function(value, index) {
  551.       return {value: value, criteria: iterator(value, index)};
  552.     }).sort(function(left, right) {
  553.       var a = left.criteria, b = right.criteria;
  554.       return a < b ? -1 : a > b ? 1 : 0;
  555.     }).pluck('value');
  556.   },

  557.         /*
  558.         将枚举对象转换为数组,使用了collect方法和Prototype.K函数,减少了重复代码
  559.         */
  560.   toArray: function() {
  561.     return this.collect(Prototype.K);
  562.   },
  563.         /*
  564.         压缩函数,实现复杂,作用尚不能体会-_-。
  565.         接收的参数需要是可枚举对象,可以有多个参数。最后一个参数是迭代器,可选。
  566.         作用是将自身和参数组成的二维阵列进行行列对换,并切除多余的数据,或补充缺少的数据(用undefined)。切换后的行数由调用者中元素的个数决定,而列数是数组参数的个数加1。
  567.         每个数组参数的第一个元素顺序组成第一行,第二个元素顺序组成第二行,依次类推。直到调用者中的元素用完为止。
  568.         迭代器的作用就是对转换后的每一行进行一次运算。
  569.         例如:
  570.         var arr1=[1,2,3];
  571.         var arr2=[4,5,6];
  572.         var arr3=[7,8,9];
  573.         var arr=arr1.zip(arr2,arr3);

  574.         //使用迭代器输出结果,inspect用于输出数组语法表示的数组字符串,后面有介绍
  575.         arr.each(function(s){
  576.                         document.write(s.inspect());
  577.                         document.write("<br/>");
  578.                 }
  579.         );
  580.         得到的结果为:
  581.         [1, 4, 7]
  582.         [2, 5, 8]
  583.         [3, 6, 9]

  584.         如果让arr1=[1,2],其他不变,则执行结果为:
  585.         [1, 4, 7]
  586.         [2, 5, 8]

  587.         */
  588.   zip: function() {
  589.     var iterator = Prototype.K, args = $A(arguments);
  590.     if (typeof args.last() == 'function')
  591.       iterator = args.pop();
  592.         //将自身枚举对象作为一个元素,与参数(也是可枚举的)组成一个数组,并将枚举对象转换为数组(通过$A迭代器)
  593.     var collections = [this].concat(args).map($A);

  594.     return this.map(function(value, index) {
  595.       iterator(value = collections.pluck(index));
  596.       return value;
  597.     });
  598.   },
  599.         /*
  600.         这实际上这是一个待实现的抽象方法,在Array对象中有对其进行的重定义
  601.         所以将this转换为数组(toArray()),再调用inspect。
  602.         对于非数组形式的枚举对象,则会加上'#<Enumerable:....>'这样的形式
  603.         */
  604.   inspect: function() {
  605.     return '#<Enumerable:' + this.toArray().inspect() + '>';
  606.   }
  607. }
  608. //对Enumerable基类的一些方法做了快速链接
  609. Object.extend(Enumerable, {
  610.   map:     Enumerable.collect,
  611.   find:    Enumerable.detect,
  612.   select:  Enumerable.findAll,
  613.   member:  Enumerable.include,
  614.   entries: Enumerable.toArray
  615. });

  616. /*
  617. 将一个对象转换为数组。
  618. 对于字符串则直接变为字符数组,例如$A("abc")将得到,["a","b","c"]
  619. 否则集合对象变为数组,这类对象包括函数的参数集合arguments,<select>的options集合,
  620. <form>的elements集合等等,一个节点的所有子结点childNodes等等。
  621. */
  622. var $A = Array.from = function(iterable) {
  623. if (!iterable) return [];
  624. if (iterable.toArray) {
  625. return iterable.toArray();
  626. } else {
  627. var results = [];
  628. for (var i = 0; i < iterable.length; i++)
  629. results.push(iterable[i]);
  630. return results;
  631. }
  632. }
复制代码
西部数码顶级域名注册商39元抢注!
yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:05:33 |显示全部楼层

接着来

  1. /*
  2. 让数组继承于Enumarable对象(基类)
  3. */
  4. Object.extend(Array.prototype, Enumerable);
  5. /*
  6. 做一个链接,prototype中一般私有的成员或抽象成员都用下划线开头,这里的_reverse大概就是起一个说明性的作用,将其作为抽象方法使用。
  7. */
  8. Array.prototype._reverse = Array.prototype.reverse;

  9. /*
  10. 为数组对象添加一些快捷方法
  11. */
  12. Object.extend(Array.prototype, {
  13.         /*
  14.         迭代器方法,源于Ruby中的迭代器用法
  15.         _each方法的作用就是将数组的每个元素作为iterator函数的参数,并执行iterator方法。例如对于数组:var arr=[1,2,3,4,5,6];
  16.         如果要显示其中的每个元素,通常的做法是
  17.         for(var i=0;i<arr.length;i++){
  18.                 alert(arr[i]);
  19.         }
  20.         而使用此方法则:
  21.         arr._each(function(s){alert(s)});
  22.         因此,在Ruby的代码中很少出现循环,这个函数使得JavaScript同样也能够实现。
  23.         */
  24.   _each: function(iterator) {
  25.     for (var i = 0; i < this.length; i++)
  26.       iterator(this[i]);
  27.   },

  28.         //清空数组
  29.   clear: function() {
  30.     this.length = 0;
  31.     return this;
  32.   },
  33.         //获取第一个元素的值
  34.   first: function() {
  35.     return this[0];
  36.   },
  37.         //获取最后一个元素的值
  38.   last: function() {
  39.     return this[this.length - 1];
  40.   },

  41.         /*
  42.         用于删除一个数组中的未定义值和null值
  43.         这里的select是从Emurable中继承的方法,而select又是findAll函数的别名
  44.         */
  45.   compact: function() {
  46.     return this.select(function(value) {
  47.       return value != undefined || value != null;
  48.     });
  49.   },
  50.         /*
  51.         将一个枚举对象中的所有数组元素全部展开,最后返回一个数组,是一个递归的过程
  52.         */
  53.   flatten: function() {
  54.     return this.inject([], function(array, value) {
  55.       return array.concat(value.constructor == Array ?
  56.         value.flatten() : [value]);
  57.     });
  58.   },
  59.         /*
  60.         从数组中删除参数指定的元素,返回删除后的结果
  61.         */
  62.   without: function() {
  63.     var values = $A(arguments);
  64.     return this.select(function(value) {
  65.       return !values.include(value);
  66.     });
  67.   },
  68.         /*
  69.         返回一个元素在数组中的索引
  70.         */
  71.   indexOf: function(object) {
  72.     for (var i = 0; i < this.length; i++)
  73.       if (this[i] == object) return i;
  74.     return -1;
  75.   },
  76.         /*
  77.         将数组元素顺序逆转,inline用于确保是数组
  78.         */
  79.   reverse: function(inline) {
  80.     return (inline !== false ? this : this.toArray())._reverse();
  81.   },
  82.         /*
  83.         取出数组的第一个元素并返回
  84.         */
  85.   shift: function() {
  86.     var result = this[0];
  87.     for (var i = 0; i < this.length - 1; i++)
  88.       this[i] = this[i + 1];
  89.     this.length--;
  90.     return result;
  91.   },
  92.         /*
  93.         返回数组的字符串表示
  94.         */
  95.   inspect: function() {
  96.     return '[' + this.map(Object.inspect).join(', ') + ']';
  97.   }
  98. });
  99. /*
  100. 定义哈希对象的通用操作
  101. */
  102. var Hash = {
  103.         /*
  104.         实现可枚举接口。
  105.         对hash对象中的每个元素进行迭代操作,迭代器被认为接收一个数组参数,数组的第一个元素是key,第二个元素是value
  106.         同时,此数组对象还增加了两个属性key和value。分表表示键和值。
  107.         */
  108.   _each: function(iterator) {
  109.     for (key in this) {
  110.       var value = this[key];
  111.       if (typeof value == 'function') continue;//不处理方法
  112.       var pair = [key, value];
  113.       pair.key = key;
  114.       pair.value = value;
  115.       iterator(pair);
  116.     }
  117.   },
  118.         /*
  119.         返回所有的键组成的数组
  120.         */
  121.   keys: function() {
  122.     return this.pluck('key');
  123.   },
  124.         /*
  125.         返回所有的值组成的数组
  126.         */
  127.   values: function() {
  128.     return this.pluck('value');
  129.   },
  130.         /*
  131.         将两个hash对象合并,如果键相同,则用参数中相应键对应的值覆盖调用者的。
  132.         */
  133.   merge: function(hash) {
  134.     return $H(hash).inject($H(this), function(mergedHash, pair) {
  135.       mergedHash[pair.key] = pair.value;
  136.       return mergedHash;
  137.     });
  138.   },
  139.         /*
  140.         将hash对象转换为查询字符串表示的形式
  141.         */
  142.   toQueryString: function() {
  143.     return this.map(function(pair) {
  144.       return pair.map(encodeURIComponent).join('=');
  145.     }).join('&');
  146.   },
  147.         /*
  148.         获取hash对象的字符串表示
  149.         */
  150.   inspect: function() {
  151.     return '#<Hash:{' + this.map(function(pair) {
  152.       return pair.map(Object.inspect).join(': ');
  153.     }).join(', ') + '}>';
  154.   }
  155. }

  156. /*
  157. 将一个对象转换为哈希对象,对象的属性名(方法名)作为key,值作为value
  158. 同时hash对象也是一个可枚举对象
  159. */
  160. function $H(object) {
  161. /*
  162. object || {}使得参数为空时也能够创建一个hash对象
  163. */
  164. var hash = Object.extend({}, object || {});
  165. Object.extend(hash, Enumerable);
  166. Object.extend(hash, Hash);
  167. return hash;
  168. }

  169. /*
  170. 又一个实现Enumerable接口的对象。
  171. 有了这个类,基本上就可以完全避免使用for循环了,一个例子,计算1到100的和:
  172. 传统写法:
  173. var s=0;
  174. for(var i=0;i<=100;i++){
  175.         s+=i;
  176. }
  177. document.write(s);

  178. 使用ObjectRange:
  179. var s=$R(0,100,false).inject(0,function(s,i){
  180.         return s+i;
  181. });
  182. document.write(s);
  183. */
  184. ObjectRange = Class.create();
  185. Object.extend(ObjectRange.prototype, Enumerable);
  186. Object.extend(ObjectRange.prototype, {
  187.         /*
  188.         构造函数,start表示开始的位置,end表示结束的位置,exclusive表示是否排除最后一个索引位置
  189.         exclusive=true时对应于:
  190.         for(var i=start;i<end;i++){
  191.                 //语句
  192.         }
  193.         exclusive=false时对应于:
  194.         for(var i=start;i<=end;i++){
  195.                 //语句
  196.         }
  197.         */
  198.   initialize: function(start, end, exclusive) {
  199.     this.start = start;
  200.     this.end = end;
  201.     this.exclusive = exclusive;
  202.   },
  203.         /*
  204.         实现枚举接口的_each方法
  205.         相当于:
  206.         for(var i=start;i<end;i++){
  207.                 iterator(i);
  208.         }
  209.         */
  210.   _each: function(iterator) {
  211.     var value = this.start;
  212.     do {
  213.       iterator(value);
  214.       value = value.succ();
  215.     } while (this.include(value));
  216.   },
  217.         /*
  218.         判断是否包含指定的索引
  219.         */
  220.   include: function(value) {
  221.     if (value < this.start)
  222.       return false;
  223.     if (this.exclusive)
  224.       return value < this.end;
  225.     return value <= this.end;
  226.   }
  227. });
  228. /*
  229. 做一个快速链接,用于生成ObjectRange对象
  230. */
  231. var $R = function(start, end, exclusive) {
  232.   return new ObjectRange(start, end, exclusive);
  233. }

  234. /*
  235. 封装XMLHttpRequest的相关操作
  236. */
  237. var Ajax = {
  238. //浏览器兼容的获取XMLHttpRequest对象的函数
  239. getTransport: function() {
  240. return Try.these(
  241. function() {return new ActiveXObject('Msxml2.XMLHTTP')},
  242. function() {return new ActiveXObject('Microsoft.XMLHTTP')},
  243. function() {return new XMLHttpRequest()}
  244. ) || false;
  245. },
  246. //当前激活的请求数目
  247. activeRequestCount: 0
  248. }

  249. /*
  250. Ajax的返回值
  251. */
  252. Ajax.Responders = {
  253.   responders: [],

  254.         //实现枚举接口的_each方法
  255.   _each: function(iterator) {
  256.     this.responders._each(iterator);
  257.   },

  258.   register: function(responderToAdd) {
  259.     if (!this.include(responderToAdd))
  260.       this.responders.push(responderToAdd);
  261.   },

  262.   unregister: function(responderToRemove) {
  263.     this.responders = this.responders.without(responderToRemove);
  264.   },

  265.   dispatch: function(callback, request, transport, json) {
  266.     this.each(function(responder) {
  267.       if (responder[callback] && typeof responder[callback] == 'function') {
  268.         try {
  269.           responder[callback].apply(responder, [request, transport, json]);
  270.         } catch (e) {}
  271.       }
  272.     });
  273.   }
  274. };
  275. /*
  276. 让Ajax.Responders可枚举迭代
  277. */
  278. Object.extend(Ajax.Responders, Enumerable);

  279. Ajax.Responders.register({
  280. onCreate: function() {
  281. Ajax.activeRequestCount++;
  282. },

  283. onComplete: function() {
  284. Ajax.activeRequestCount--;
  285. }
  286. });

  287. //定义Ajax的基类
  288. Ajax.Base = function() {};
  289. Ajax.Base.prototype = {
  290.         /*
  291.         设置XMLHttp调用的参数,提供了默认值:method:'post',异步,无参数
  292.         */
  293.   setOptions: function(options) {
  294.     this.options = {
  295.       method:       'post',
  296.       asynchronous: true,
  297.       parameters:   ''
  298.     }
  299.     Object.extend(this.options, options || {});
  300.   },
  301.         /*
  302.         判断请求是否成功
  303.         */
  304.   responseIsSuccess: function() {
  305.     return this.transport.status == undefined
  306.         || this.transport.status == 0
  307.         || (this.transport.status >= 200 && this.transport.status < 300);
  308.   },
  309.         /*
  310.         判断请求是否失败
  311.         */
  312.   responseIsFailure: function() {
  313.     return !this.responseIsSuccess();
  314.   }
  315. }

  316. //定义一个Ajax请求类
  317. Ajax.Request = Class.create();
  318. Ajax.Request.Events =
  319.   ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

  320. Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  321.   initialize: function(url, options) {
  322.     this.transport = Ajax.getTransport();
  323.     this.setOptions(options);
  324.     this.request(url);
  325.   },

  326.   request: function(url) {
  327.     var parameters = this.options.parameters || '';
  328.     if (parameters.length > 0) parameters += '&_=';

  329.     try {
  330.       this.url = url;
  331.       if (this.options.method == 'get' && parameters.length > 0)
  332.         this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

  333.       Ajax.Responders.dispatch('onCreate', this, this.transport);

  334.       this.transport.open(this.options.method, this.url,
  335.         this.options.asynchronous);

  336.       if (this.options.asynchronous) {
  337.         this.transport.onreadystatechange = this.onStateChange.bind(this);
  338.         setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
  339.       }

  340.       this.setRequestHeaders();

  341.       var body = this.options.postBody ? this.options.postBody : parameters;
  342.       this.transport.send(this.options.method == 'post' ? body : null);

  343.     } catch (e) {
  344.       this.dispatchException(e);
  345.     }
  346.   },

  347.   setRequestHeaders: function() {
  348.     var requestHeaders =
  349.       ['X-Requested-With', 'XMLHttpRequest',
  350.        'X-Prototype-Version', Prototype.Version];

  351.     if (this.options.method == 'post') {
  352.       requestHeaders.push('Content-type',
  353.         'application/x-www-form-urlencoded');

  354.       /* Force "Connection: close" for Mozilla browsers to work around
  355.        * a bug where XMLHttpReqeuest sends an incorrect Content-length
  356.        * header. See Mozilla Bugzilla #246651.
  357.        */
  358.       if (this.transport.overrideMimeType)
  359.         requestHeaders.push('Connection', 'close');
  360.     }

  361.     if (this.options.requestHeaders)
  362.       requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

  363.     for (var i = 0; i < requestHeaders.length; i += 2)
  364.       this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
  365.   },

  366.   onStateChange: function() {
  367.     var readyState = this.transport.readyState;
  368.     if (readyState != 1)
  369.       this.respondToReadyState(this.transport.readyState);
  370.   },

  371.   header: function(name) {
  372.     try {
  373.       return this.transport.getResponseHeader(name);
  374.     } catch (e) {}
  375.   },

  376.   evalJSON: function() {
  377.     try {
  378.       return eval(this.header('X-JSON'));
  379.     } catch (e) {}
  380.   },

  381.   evalResponse: function() {
  382.     try {
  383.       return eval(this.transport.responseText);
  384.     } catch (e) {
  385.       this.dispatchException(e);
  386.     }
  387.   },

  388.   respondToReadyState: function(readyState) {
  389.     var event = Ajax.Request.Events[readyState];
  390.     var transport = this.transport, json = this.evalJSON();

  391.     if (event == 'Complete') {
  392.       try {
  393.         (this.options['on' + this.transport.status]
  394.          || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
  395.          || Prototype.emptyFunction)(transport, json);
  396.       } catch (e) {
  397.         this.dispatchException(e);
  398.       }

  399.       if ((this.header('Content-type') || '').match(/^text\/javascript/i))
  400.         this.evalResponse();
  401.     }

  402.     try {
  403.       (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
  404.       Ajax.Responders.dispatch('on' + event, this, transport, json);
  405.     } catch (e) {
  406.       this.dispatchException(e);
  407.     }

  408.     /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
  409.     if (event == 'Complete')
  410.       this.transport.onreadystatechange = Prototype.emptyFunction;
  411.   },

  412.   dispatchException: function(exception) {
  413.     (this.options.onException || Prototype.emptyFunction)(this, exception);
  414.     Ajax.Responders.dispatch('onException', this, exception);
  415.   }
  416. });

  417. Ajax.Updater = Class.create();

  418. Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  419.   initialize: function(container, url, options) {
  420.     this.containers = {
  421.       success: container.success ? $(container.success) : $(container),
  422.       failure: container.failure ? $(container.failure) :
  423.         (container.success ? null : $(container))
  424.     }

  425.     this.transport = Ajax.getTransport();
  426.     this.setOptions(options);

  427.     var onComplete = this.options.onComplete || Prototype.emptyFunction;
  428.     this.options.onComplete = (function(transport, object) {
  429.       this.updateContent();
  430.       onComplete(transport, object);
  431.     }).bind(this);

  432.     this.request(url);
  433.   },

  434.   updateContent: function() {
  435.     var receiver = this.responseIsSuccess() ?
  436.       this.containers.success : this.containers.failure;
  437.     var response = this.transport.responseText;

  438.     if (!this.options.evalScripts)
  439.       response = response.stripScripts();

  440.     if (receiver) {
  441.       if (this.options.insertion) {
  442.         new this.options.insertion(receiver, response);
  443.       } else {
  444.         Element.update(receiver, response);
  445.       }
  446.     }

  447.     if (this.responseIsSuccess()) {
  448.       if (this.onComplete)
  449.         setTimeout(this.onComplete.bind(this), 10);
  450.     }
  451.   }
  452. });

  453. Ajax.PeriodicalUpdater = Class.create();
  454. Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  455.   initialize: function(container, url, options) {
  456.     this.setOptions(options);
  457.     this.onComplete = this.options.onComplete;

  458.     this.frequency = (this.options.frequency || 2);
  459.     this.decay = (this.options.decay || 1);

  460.     this.updater = {};
  461.     this.container = container;
  462.     this.url = url;

  463.     this.start();
  464.   },

  465.   start: function() {
  466.     this.options.onComplete = this.updateComplete.bind(this);
  467.     this.onTimerEvent();
  468.   },

  469.   stop: function() {
  470.     this.updater.onComplete = undefined;
  471.     clearTimeout(this.timer);
  472.     (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  473.   },

  474.   updateComplete: function(request) {
  475.     if (this.options.decay) {
  476.       this.decay = (request.responseText == this.lastText ?
  477.         this.decay * this.options.decay : 1);

  478.       this.lastText = request.responseText;
  479.     }
  480.     this.timer = setTimeout(this.onTimerEvent.bind(this),
  481.       this.decay * this.frequency * 1000);
  482.   },

  483.   onTimerEvent: function() {
  484.     this.updater = new Ajax.Updater(this.container, this.url, this.options);
  485.   }
  486. });
  487. document.getElementsByClassName = function(className, parentElement) {
  488.   var children = ($(parentElement) || document.body).getElementsByTagName('*');
  489.   return $A(children).inject([], function(elements, child) {
  490.     if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
  491.       elements.push(child);
  492.     return elements;
  493.   });
  494. }

  495. /*--------------------------------------------------------------------------*/
  496. //定义一些Html节点通用的操作
  497. if (!window.Element) {
  498.   var Element = new Object();
  499. }
复制代码
租服务器,上51IDC | [长沙]招聘:PHP经理10K/WEB前端6K/PHP开发6K

使用道具 举报

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:06:14 |显示全部楼层

coming next

  1. Object.extend(Element, {
  2.         /*
  3.         判断节点是否可见
  4.         */
  5.   visible: function(element) {
  6.     return $(element).style.display != 'none';
  7.   },
  8.         /*
  9.         切换节点的可见状态
  10.         */
  11.   toggle: function() {
  12.     for (var i = 0; i < arguments.length; i++) {
  13.       var element = $(arguments[i]);
  14.       Element[Element.visible(element) ? 'hide' : 'show'](element);
  15.     }
  16.   },
  17.         /*
  18.         隐藏参数所指定的节点
  19.         */
  20.   hide: function() {
  21.     for (var i = 0; i < arguments.length; i++) {
  22.       var element = $(arguments[i]);
  23.       element.style.display = 'none';
  24.     }
  25.   },
  26.         /*
  27.         显示参数所指定的节点
  28.         */
  29.   show: function() {
  30.     for (var i = 0; i < arguments.length; i++) {
  31.       var element = $(arguments[i]);
  32.       element.style.display = '';
  33.     }
  34.   },
  35.         /*
  36.         删除一个节点
  37.         */
  38.   remove: function(element) {
  39.     element = $(element);
  40.     element.parentNode.removeChild(element);
  41.   },
  42.         /*
  43.         用指定html填充element表示的节点
  44.         setTimeout是极具技巧的用法,让人惊叹。
  45.         update函数之所以会取代:element.innerHTML=html的用法,主要因为它实现了浏览器的兼容性:
  46.         (1)对于IE,如果给innerHTML赋值的字符串中含有脚本标记,脚本是被忽略的,不起作用;而firefox则会执行脚本;
  47.         (2)setTimeout使得可以在函数内可以通过eval定义全局函数,这是由于setTimeout的默认空间就是全局空间决定的(它是window对象的方法,而所有全局变量和全局函数实际上都是window对象的属性和方法)。
  48.         */
  49.   update: function(element, html) {
  50.     $(element).innerHTML = html.stripScripts();
  51.     setTimeout(function() {html.evalScripts()}, 10);
  52.   },
  53.         //获取节点的高度
  54.   getHeight: function(element) {
  55.     element = $(element);
  56.     return element.offsetHeight;
  57.   },
  58.         //获取一个元素的class,返回一个数组,包括了所有的class名称,ClassNames后面实现
  59.   classNames: function(element) {
  60.     return new Element.ClassNames(element);
  61.   },
  62.         /*判断一个元素是否具有指定的class值*/
  63.   hasClassName: function(element, className) {
  64.     if (!(element = $(element))) return;
  65.     return Element.classNames(element).include(className);
  66.   },
  67.         //为一个节点添加class名称
  68.   addClassName: function(element, className) {
  69.     if (!(element = $(element))) return;
  70.     return Element.classNames(element).add(className);
  71.   },
  72.         //从一个节点移除一个class名称
  73.   removeClassName: function(element, className) {
  74.     if (!(element = $(element))) return;
  75.     return Element.classNames(element).remove(className);
  76.   },

  77.   // removes whitespace-only text node children
  78.   //删除空白文本节点,使用此方法能够使得childNodes属性对所有浏览器兼容,否则ie不认为空白文本节点是子节点。而firefox则会认为这些节点是子节点。
  79.   cleanWhitespace: function(element) {
  80.     element = $(element);
  81.     for (var i = 0; i < element.childNodes.length; i++) {
  82.       var node = element.childNodes[i];
  83.       if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
  84.         Element.remove(node);
  85.     }
  86.   },
  87.         //判断一个节点是否为空,如果全是空白内容,也认为空
  88.   empty: function(element) {
  89.     return $(element).innerHTML.match(/^\s*$/);
  90.   },
  91.         /*
  92.         将滚动条滚动到指定节点的位置
  93.         */
  94.   scrollTo: function(element) {
  95.     element = $(element);
  96.     var x = element.x ? element.x : element.offsetLeft,
  97.         y = element.y ? element.y : element.offsetTop;
  98.     window.scrollTo(x, y);
  99.   },
  100.         /*
  101.         得到指定节点的指定样式的绝对值。
  102.         即可以获得继承得到的样式。
  103.         */
  104.   getStyle: function(element, style) {
  105.     element = $(element);
  106.     var value = element.style[style.camelize()];
  107.     if (!value) {
  108.       if (document.defaultView && document.defaultView.getComputedStyle) {
  109.         var css = document.defaultView.getComputedStyle(element, null);
  110.         value = css ? css.getPropertyValue(style) : null;
  111.       } else if (element.currentStyle) {
  112.         value = element.currentStyle[style.camelize()];
  113.       }
  114.     }

  115.     if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
  116.       if (Element.getStyle(element, 'position') == 'static') value = 'auto';

  117.     return value == 'auto' ? null : value;
  118.   },
  119.         /*
  120.         设置指定节点的样式,这里可以由style参数同时指定多个属性
  121.         例如:
  122.         Element.setStyle($("someElement"),{color:'#ff0000',background-color:'#000000'});
  123.         就将指定节点的样式设置为红字黑底
  124.         */
  125.   setStyle: function(element, style) {
  126.     element = $(element);
  127.     for (name in style)
  128.       element.style[name.camelize()] = style[name];
  129.   },

  130.         /*
  131.         返回节点的宽度和高度,以{width:xx,height:xx}形式返回。
  132.         该方法使得无论节点可见与否,都能够获取其显示时的大小。
  133.         */
  134.   getDimensions: function(element) {
  135.     element = $(element);
  136.     if (Element.getStyle(element, 'display') != 'none')
  137.       return {width: element.offsetWidth, height: element.offsetHeight};

  138.     // All *Width and *Height properties give 0 on elements with display none,
  139.     // so enable the element temporarily
  140.     var els = element.style;
  141.     var originalVisibility = els.visibility;
  142.     var originalPosition = els.position;
  143.     els.visibility = 'hidden';
  144.     els.position = 'absolute';
  145.     els.display = '';
  146.     var originalWidth = element.clientWidth;
  147.     var originalHeight = element.clientHeight;
  148.     els.display = 'none';
  149.     els.position = originalPosition;
  150.     els.visibility = originalVisibility;
  151.     return {width: originalWidth, height: originalHeight};
  152.   },
  153.         /*
  154.         使的元素相对定位
  155.         */
  156.   makePositioned: function(element) {
  157.     element = $(element);
  158.     var pos = Element.getStyle(element, 'position');
  159.     if (pos == 'static' || !pos) {
  160.       element._madePositioned = true;
  161.       element.style.position = 'relative';
  162.       // Opera returns the offset relative to the positioning context, when an
  163.       // element is position relative but top and left have not been defined
  164.       if (window.opera) {
  165.         element.style.top = 0;
  166.         element.style.left = 0;
  167.       }
  168.     }
  169.   },
  170.         /*
  171.         取消节点的相对定位。
  172.         */
  173.   undoPositioned: function(element) {
  174.     element = $(element);
  175.     if (element._madePositioned) {
  176.       element._madePositioned = undefined;
  177.       element.style.position =
  178.         element.style.top =
  179.         element.style.left =
  180.         element.style.bottom =
  181.         element.style.right = '';
  182.     }
  183.   },
  184.         /*
  185.        
  186.         */
  187.   makeClipping: function(element) {
  188.     element = $(element);
  189.     if (element._overflow) return;
  190.     element._overflow = element.style.overflow;
  191.     if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
  192.       element.style.overflow = 'hidden';
  193.   },

  194.   undoClipping: function(element) {
  195.     element = $(element);
  196.     if (element._overflow) return;
  197.     element.style.overflow = element._overflow;
  198.     element._overflow = undefined;
  199.   }
  200. });
复制代码

使用道具 举报

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:06:59 |显示全部楼层

coming next

  1. var Toggle = new Object();
  2. Toggle.display = Element.toggle;

  3. /*--------------------------------------------------------------------------*/

  4. Abstract.Insertion = function(adjacency) {
  5.   this.adjacency = adjacency;
  6. }

  7. Abstract.Insertion.prototype = {
  8.   initialize: function(element, content) {
  9.     this.element = $(element);
  10.     this.content = content.stripScripts();

  11.     if (this.adjacency && this.element.insertAdjacentHTML) {
  12.       try {
  13.         this.element.insertAdjacentHTML(this.adjacency, this.content);
  14.       } catch (e) {
  15.         if (this.element.tagName.toLowerCase() == 'tbody') {
  16.           this.insertContent(this.contentFromAnonymousTable());
  17.         } else {
  18.           throw e;
  19.         }
  20.       }
  21.     } else {
  22.       this.range = this.element.ownerDocument.createRange();
  23.       if (this.initializeRange) this.initializeRange();
  24.       this.insertContent([this.range.createContextualFragment(this.content)]);
  25.     }

  26.     setTimeout(function() {content.evalScripts()}, 10);
  27.   },

  28.   contentFromAnonymousTable: function() {
  29.     var div = document.createElement('div');
  30.     div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
  31.     return $A(div.childNodes[0].childNodes[0].childNodes);
  32.   }
  33. }

  34. var Insertion = new Object();

  35. Insertion.Before = Class.create();
  36. Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  37.   initializeRange: function() {
  38.     this.range.setStartBefore(this.element);
  39.   },

  40.   insertContent: function(fragments) {
  41.     fragments.each((function(fragment) {
  42.       this.element.parentNode.insertBefore(fragment, this.element);
  43.     }).bind(this));
  44.   }
  45. });

  46. Insertion.Top = Class.create();
  47. Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  48.   initializeRange: function() {
  49.     this.range.selectNodeContents(this.element);
  50.     this.range.collapse(true);
  51.   },

  52.   insertContent: function(fragments) {
  53.     fragments.reverse(false).each((function(fragment) {
  54.       this.element.insertBefore(fragment, this.element.firstChild);
  55.     }).bind(this));
  56.   }
  57. });

  58. Insertion.Bottom = Class.create();
  59. Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  60.   initializeRange: function() {
  61.     this.range.selectNodeContents(this.element);
  62.     this.range.collapse(this.element);
  63.   },

  64.   insertContent: function(fragments) {
  65.     fragments.each((function(fragment) {
  66.       this.element.appendChild(fragment);
  67.     }).bind(this));
  68.   }
  69. });

  70. Insertion.After = Class.create();
  71. Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  72.   initializeRange: function() {
  73.     this.range.setStartAfter(this.element);
  74.   },

  75.   insertContent: function(fragments) {
  76.     fragments.each((function(fragment) {
  77.       this.element.parentNode.insertBefore(fragment,
  78.         this.element.nextSibling);
  79.     }).bind(this));
  80.   }
  81. });

  82. /*--------------------------------------------------------------------------*/

  83. Element.ClassNames = Class.create();
  84. Element.ClassNames.prototype = {
  85.   initialize: function(element) {
  86.     this.element = $(element);
  87.   },

  88.   _each: function(iterator) {
  89.     this.element.className.split(/\s+/).select(function(name) {
  90.       return name.length > 0;
  91.     })._each(iterator);
  92.   },

  93.   set: function(className) {
  94.     this.element.className = className;
  95.   },

  96.   add: function(classNameToAdd) {
  97.     if (this.include(classNameToAdd)) return;
  98.     this.set(this.toArray().concat(classNameToAdd).join(' '));
  99.   },

  100.   remove: function(classNameToRemove) {
  101.     if (!this.include(classNameToRemove)) return;
  102.     this.set(this.select(function(className) {
  103.       return className != classNameToRemove;
  104.     }).join(' '));
  105.   },

  106.   toString: function() {
  107.     return this.toArray().join(' ');
  108.   }
  109. }

  110. Object.extend(Element.ClassNames.prototype, Enumerable);
复制代码

使用道具 举报

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:07:45 |显示全部楼层

coming next

  1. var Field = {
  2.   clear: function() {
  3.     for (var i = 0; i < arguments.length; i++)
  4.       $(arguments[i]).value = '';
  5.   },

  6.   focus: function(element) {
  7.     $(element).focus();
  8.   },

  9.   present: function() {
  10.     for (var i = 0; i < arguments.length; i++)
  11.       if ($(arguments[i]).value == '') return false;
  12.     return true;
  13.   },

  14.   select: function(element) {
  15.     $(element).select();
  16.   },

  17.   activate: function(element) {
  18.     element = $(element);
  19.     element.focus();
  20.     if (element.select)
  21.       element.select();
  22.   }
  23. }

  24. /*--------------------------------------------------------------------------*/

  25. var Form = {
  26.   serialize: function(form) {
  27.     var elements = Form.getElements($(form));
  28.     var queryComponents = new Array();

  29.     for (var i = 0; i < elements.length; i++) {
  30.       var queryComponent = Form.Element.serialize(elements[i]);
  31.       if (queryComponent)
  32.         queryComponents.push(queryComponent);
  33.     }

  34.     return queryComponents.join('&');
  35.   },

  36.   getElements: function(form) {
  37.     form = $(form);
  38.     var elements = new Array();

  39.     for (tagName in Form.Element.Serializers) {
  40.       var tagElements = form.getElementsByTagName(tagName);
  41.       for (var j = 0; j < tagElements.length; j++)
  42.         elements.push(tagElements[j]);
  43.     }
  44.     return elements;
  45.   },

  46.   getInputs: function(form, typeName, name) {
  47.     form = $(form);
  48.     var inputs = form.getElementsByTagName('input');

  49.     if (!typeName && !name)
  50.       return inputs;

  51.     var matchingInputs = new Array();
  52.     for (var i = 0; i < inputs.length; i++) {
  53.       var input = inputs[i];
  54.       if ((typeName && input.type != typeName) ||
  55.           (name && input.name != name))
  56.         continue;
  57.       matchingInputs.push(input);
  58.     }

  59.     return matchingInputs;
  60.   },

  61.   disable: function(form) {
  62.     var elements = Form.getElements(form);
  63.     for (var i = 0; i < elements.length; i++) {
  64.       var element = elements[i];
  65.       element.blur();
  66.       element.disabled = 'true';
  67.     }
  68.   },

  69.   enable: function(form) {
  70.     var elements = Form.getElements(form);
  71.     for (var i = 0; i < elements.length; i++) {
  72.       var element = elements[i];
  73.       element.disabled = '';
  74.     }
  75.   },

  76.   findFirstElement: function(form) {
  77.     return Form.getElements(form).find(function(element) {
  78.       return element.type != 'hidden' && !element.disabled &&
  79.         ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
  80.     });
  81.   },

  82.   focusFirstElement: function(form) {
  83.     Field.activate(Form.findFirstElement(form));
  84.   },

  85.   reset: function(form) {
  86.     $(form).reset();
  87.   }
  88. }

  89. Form.Element = {
  90.   serialize: function(element) {
  91.     element = $(element);
  92.     var method = element.tagName.toLowerCase();
  93.     var parameter = Form.Element.Serializers[method](element);

  94.     if (parameter) {
  95.       var key = encodeURIComponent(parameter[0]);
  96.       if (key.length == 0) return;

  97.       if (parameter[1].constructor != Array)
  98.         parameter[1] = [parameter[1]];

  99.       return parameter[1].map(function(value) {
  100.         return key + '=' + encodeURIComponent(value);
  101.       }).join('&');
  102.     }
  103.   },

  104.   getValue: function(element) {
  105.     element = $(element);
  106.     var method = element.tagName.toLowerCase();
  107.     var parameter = Form.Element.Serializers[method](element);

  108.     if (parameter)
  109.       return parameter[1];
  110.   }
  111. }

  112. Form.Element.Serializers = {
  113.         //对input标记序列化
  114.   input: function(element) {
  115.     switch (element.type.toLowerCase()) {
  116.       case 'submit':
  117.       case 'hidden':
  118.       case 'password':
  119.       case 'text':
  120.         return Form.Element.Serializers.textarea(element);
  121.       case 'checkbox':
  122.       case 'radio':
  123.         return Form.Element.Serializers.inputSelector(element);
  124.     }
  125.     return false;
  126.   },
  127.         //对单选框和复选框序列化
  128.   inputSelector: function(element) {
  129.     if (element.checked)
  130.       return [element.name, element.value];
  131.   },
  132.         //对文本框序列化
  133.   textarea: function(element) {
  134.     return [element.name, element.value];
  135.   },
  136.         //对下拉列表框序列化
  137.   select: function(element) {
  138.     return Form.Element.Serializers[element.type == 'select-one' ?
  139.       'selectOne' : 'selectMany'](element);
  140.   },
  141.         //对单选下拉列表框序列化
  142.   selectOne: function(element) {
  143.     var value = '', opt, index = element.selectedIndex;
  144.     if (index >= 0) {
  145.       opt = element.options[index];
  146.       value = opt.value;
  147.       if (!value && !('value' in opt))
  148.         value = opt.text;
  149.     }
  150.     return [element.name, value];
  151.   },
  152.         //对多选下拉列表框序列化
  153.   selectMany: function(element) {
  154.     var value = new Array();
  155.     for (var i = 0; i < element.length; i++) {
  156.       var opt = element.options[i];
  157.       if (opt.selected) {
  158.         var optValue = opt.value;
  159.         if (!optValue && !('value' in opt))
  160.           optValue = opt.text;
  161.         value.push(optValue);
  162.       }
  163.     }
  164.     return [element.name, value];
  165.   }
  166. }

  167. /*--------------------------------------------------------------------------*/

  168. var $F = Form.Element.getValue;
复制代码

使用道具 举报

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:08:42 |显示全部楼层

coming next

  1. /*--------------------------------------------------------------------------*/

  2. Abstract.TimedObserver = function() {}
  3. Abstract.TimedObserver.prototype = {
  4.   initialize: function(element, frequency, callback) {
  5.     this.frequency = frequency;
  6.     this.element   = $(element);
  7.     this.callback  = callback;

  8.     this.lastValue = this.getValue();
  9.     this.registerCallback();
  10.   },

  11.   registerCallback: function() {
  12.     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  13.   },

  14.   onTimerEvent: function() {
  15.     var value = this.getValue();
  16.     if (this.lastValue != value) {
  17.       this.callback(this.element, value);
  18.       this.lastValue = value;
  19.     }
  20.   }
  21. }

  22. Form.Element.Observer = Class.create();
  23. Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  24.   getValue: function() {
  25.     return Form.Element.getValue(this.element);
  26.   }
  27. });

  28. Form.Observer = Class.create();
  29. Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  30.   getValue: function() {
  31.     return Form.serialize(this.element);
  32.   }
  33. });

  34. /*--------------------------------------------------------------------------*/

  35. Abstract.EventObserver = function() {}
  36. Abstract.EventObserver.prototype = {
  37.   initialize: function(element, callback) {
  38.     this.element  = $(element);
  39.     this.callback = callback;

  40.     this.lastValue = this.getValue();
  41.     if (this.element.tagName.toLowerCase() == 'form')
  42.       this.registerFormCallbacks();
  43.     else
  44.       this.registerCallback(this.element);
  45.   },

  46.   onElementEvent: function() {
  47.     var value = this.getValue();
  48.     if (this.lastValue != value) {
  49.       this.callback(this.element, value);
  50.       this.lastValue = value;
  51.     }
  52.   },

  53.   registerFormCallbacks: function() {
  54.     var elements = Form.getElements(this.element);
  55.     for (var i = 0; i < elements.length; i++)
  56.       this.registerCallback(elements[i]);
  57.   },

  58.   registerCallback: function(element) {
  59.     if (element.type) {
  60.       switch (element.type.toLowerCase()) {
  61.         case 'checkbox':
  62.         case 'radio':
  63.           Event.observe(element, 'click', this.onElementEvent.bind(this));
  64.           break;
  65.         case 'password':
  66.         case 'text':
  67.         case 'textarea':
  68.         case 'select-one':
  69.         case 'select-multiple':
  70.           Event.observe(element, 'change', this.onElementEvent.bind(this));
  71.           break;
  72.       }
  73.     }
  74.   }
  75. }

  76. Form.Element.EventObserver = Class.create();
  77. Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  78.   getValue: function() {
  79.     return Form.Element.getValue(this.element);
  80.   }
  81. });

  82. Form.EventObserver = Class.create();
  83. Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  84.   getValue: function() {
  85.     return Form.serialize(this.element);
  86.   }
  87. });
  88. if (!window.Event) {
  89.   var Event = new Object();
  90. }

  91. Object.extend(Event, {
  92.   KEY_BACKSPACE: 8,
  93.   KEY_TAB:       9,
  94.   KEY_RETURN:   13,
  95.   KEY_ESC:      27,
  96.   KEY_LEFT:     37,
  97.   KEY_UP:       38,
  98.   KEY_RIGHT:    39,
  99.   KEY_DOWN:     40,
  100.   KEY_DELETE:   46,

  101.   element: function(event) {
  102.     return event.target || event.srcElement;
  103.   },

  104.   isLeftClick: function(event) {
  105.     return (((event.which) && (event.which == 1)) ||
  106.             ((event.button) && (event.button == 1)));
  107.   },

  108.   pointerX: function(event) {
  109.     return event.pageX || (event.clientX +
  110.       (document.documentElement.scrollLeft || document.body.scrollLeft));
  111.   },

  112.   pointerY: function(event) {
  113.     return event.pageY || (event.clientY +
  114.       (document.documentElement.scrollTop || document.body.scrollTop));
  115.   },

  116.   stop: function(event) {
  117.     if (event.preventDefault) {
  118.       event.preventDefault();
  119.       event.stopPropagation();
  120.     } else {
  121.       event.returnValue = false;
  122.       event.cancelBubble = true;
  123.     }
  124.   },

  125.   // find the first node with the given tagName, starting from the
  126.   // node the event was triggered on; traverses the DOM upwards
  127.   findElement: function(event, tagName) {
  128.     var element = Event.element(event);
  129.     while (element.parentNode && (!element.tagName ||
  130.         (element.tagName.toUpperCase() != tagName.toUpperCase())))
  131.       element = element.parentNode;
  132.     return element;
  133.   },

  134.   observers: false,

  135.   _observeAndCache: function(element, name, observer, useCapture) {
  136.     if (!this.observers) this.observers = [];
  137.     if (element.addEventListener) {
  138.       this.observers.push([element, name, observer, useCapture]);
  139.       element.addEventListener(name, observer, useCapture);
  140.     } else if (element.attachEvent) {
  141.       this.observers.push([element, name, observer, useCapture]);
  142.       element.attachEvent('on' + name, observer);
  143.     }
  144.   },

  145.   unloadCache: function() {
  146.     if (!Event.observers) return;
  147.     for (var i = 0; i < Event.observers.length; i++) {
  148.       Event.stopObserving.apply(this, Event.observers[i]);
  149.       Event.observers[i][0] = null;
  150.     }
  151.     Event.observers = false;
  152.   },

  153.   observe: function(element, name, observer, useCapture) {
  154.     var element = $(element);
  155.     useCapture = useCapture || false;

  156.     if (name == 'keypress' &&
  157.         (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
  158.         || element.attachEvent))
  159.       name = 'keydown';

  160.     this._observeAndCache(element, name, observer, useCapture);
  161.   },

  162.   stopObserving: function(element, name, observer, useCapture) {
  163.     var element = $(element);
  164.     useCapture = useCapture || false;

  165.     if (name == 'keypress' &&
  166.         (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
  167.         || element.detachEvent))
  168.       name = 'keydown';

  169.     if (element.removeEventListener) {
  170.       element.removeEventListener(name, observer, useCapture);
  171.     } else if (element.detachEvent) {
  172.       element.detachEvent('on' + name, observer);
  173.     }
  174.   }
  175. });
复制代码

使用道具 举报

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-2-25 14:10:44 |显示全部楼层

coming next 不过后来没有再注释,不过到家可以到这里看

http://www.prototypejs.org/api/

  1. /* prevent memory leaks in IE */
  2. Event.observe(window, 'unload', Event.unloadCache, false);
  3. var Position = {
  4.   // set to true if needed, warning: firefox performance problems
  5.   // NOT neeeded for page scrolling, only if draggable contained in
  6.   // scrollable elements
  7.   includeScrollOffsets: false,

  8.   // must be called before calling withinIncludingScrolloffset, every time the
  9.   // page is scrolled
  10.   prepare: function() {
  11.     this.deltaX =  window.pageXOffset
  12.                 || document.documentElement.scrollLeft
  13.                 || document.body.scrollLeft
  14.                 || 0;
  15.     this.deltaY =  window.pageYOffset
  16.                 || document.documentElement.scrollTop
  17.                 || document.body.scrollTop
  18.                 || 0;
  19.   },

  20.   realOffset: function(element) {
  21.     var valueT = 0, valueL = 0;
  22.     do {
  23.       valueT += element.scrollTop  || 0;
  24.       valueL += element.scrollLeft || 0;
  25.       element = element.parentNode;
  26.     } while (element);
  27.     return [valueL, valueT];
  28.   },

  29.   cumulativeOffset: function(element) {
  30.     var valueT = 0, valueL = 0;
  31.     do {
  32.       valueT += element.offsetTop  || 0;
  33.       valueL += element.offsetLeft || 0;
  34.       element = element.offsetParent;
  35.     } while (element);
  36.     return [valueL, valueT];
  37.   },

  38.   positionedOffset: function(element) {
  39.     var valueT = 0, valueL = 0;
  40.     do {
  41.       valueT += element.offsetTop  || 0;
  42.       valueL += element.offsetLeft || 0;
  43.       element = element.offsetParent;
  44.       if (element) {
  45.         p = Element.getStyle(element, 'position');
  46.         if (p == 'relative' || p == 'absolute') break;
  47.       }
  48.     } while (element);
  49.     return [valueL, valueT];
  50.   },

  51.   offsetParent: function(element) {
  52.     if (element.offsetParent) return element.offsetParent;
  53.     if (element == document.body) return element;

  54.     while ((element = element.parentNode) && element != document.body)
  55.       if (Element.getStyle(element, 'position') != 'static')
  56.         return element;

  57.     return document.body;
  58.   },

  59.   // caches x/y coordinate pair to use with overlap
  60.   within: function(element, x, y) {
  61.     if (this.includeScrollOffsets)
  62.       return this.withinIncludingScrolloffsets(element, x, y);
  63.     this.xcomp = x;
  64.     this.ycomp = y;
  65.     this.offset = this.cumulativeOffset(element);

  66.     return (y >= this.offset[1] &&
  67.             y <  this.offset[1] + element.offsetHeight &&
  68.             x >= this.offset[0] &&
  69.             x <  this.offset[0] + element.offsetWidth);
  70.   },

  71.   withinIncludingScrolloffsets: function(element, x, y) {
  72.     var offsetcache = this.realOffset(element);

  73.     this.xcomp = x + offsetcache[0] - this.deltaX;
  74.     this.ycomp = y + offsetcache[1] - this.deltaY;
  75.     this.offset = this.cumulativeOffset(element);

  76.     return (this.ycomp >= this.offset[1] &&
  77.             this.ycomp <  this.offset[1] + element.offsetHeight &&
  78.             this.xcomp >= this.offset[0] &&
  79.             this.xcomp <  this.offset[0] + element.offsetWidth);
  80.   },

  81.   // within must be called directly before
  82.   overlap: function(mode, element) {
  83.     if (!mode) return 0;
  84.     if (mode == 'vertical')
  85.       return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
  86.         element.offsetHeight;
  87.     if (mode == 'horizontal')
  88.       return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
  89.         element.offsetWidth;
  90.   },

  91.   clone: function(source, target) {
  92.     source = $(source);
  93.     target = $(target);
  94.     target.style.position = 'absolute';
  95.     var offsets = this.cumulativeOffset(source);
  96.     target.style.top    = offsets[1] + 'px';
  97.     target.style.left   = offsets[0] + 'px';
  98.     target.style.width  = source.offsetWidth + 'px';
  99.     target.style.height = source.offsetHeight + 'px';
  100.   },

  101.   page: function(forElement) {
  102.     var valueT = 0, valueL = 0;

  103.     var element = forElement;
  104.     do {
  105.       valueT += element.offsetTop  || 0;
  106.       valueL += element.offsetLeft || 0;

  107.       // Safari fix
  108.       if (element.offsetParent==document.body)
  109.         if (Element.getStyle(element,'position')=='absolute') break;

  110.     } while (element = element.offsetParent);

  111.     element = forElement;
  112.     do {
  113.       valueT -= element.scrollTop  || 0;
  114.       valueL -= element.scrollLeft || 0;
  115.     } while (element = element.parentNode);

  116.     return [valueL, valueT];
  117.   },

  118.   clone: function(source, target) {
  119.     var options = Object.extend({
  120.       setLeft:    true,
  121.       setTop:     true,
  122.       setWidth:   true,
  123.       setHeight:  true,
  124.       offsetTop:  0,
  125.       offsetLeft: 0
  126.     }, arguments[2] || {})

  127.     // find page position of source
  128.     source = $(source);
  129.     var p = Position.page(source);

  130.     // find coordinate system to use
  131.     target = $(target);
  132.     var delta = [0, 0];
  133.     var parent = null;
  134.     // delta [0,0] will do fine with position: fixed elements,
  135.     // position:absolute needs offsetParent deltas
  136.     if (Element.getStyle(target,'position') == 'absolute') {
  137.       parent = Position.offsetParent(target);
  138.       delta = Position.page(parent);
  139.     }

  140.     // correct by body offsets (fixes Safari)
  141.     if (parent == document.body) {
  142.       delta[0] -= document.body.offsetLeft;
  143.       delta[1] -= document.body.offsetTop;
  144.     }

  145.     // set position
  146.     if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
  147.     if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
  148.     if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
  149.     if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  150.   },

  151.   absolutize: function(element) {
  152.     element = $(element);
  153.     if (element.style.position == 'absolute') return;
  154.     Position.prepare();

  155.     var offsets = Position.positionedOffset(element);
  156.     var top     = offsets[1];
  157.     var left    = offsets[0];
  158.     var width   = element.clientWidth;
  159.     var height  = element.clientHeight;

  160.     element._originalLeft   = left - parseFloat(element.style.left  || 0);
  161.     element._originalTop    = top  - parseFloat(element.style.top || 0);
  162.     element._originalWidth  = element.style.width;
  163.     element._originalHeight = element.style.height;

  164.     element.style.position = 'absolute';
  165.     element.style.top    = top + 'px';;
  166.     element.style.left   = left + 'px';;
  167.     element.style.width  = width + 'px';;
  168.     element.style.height = height + 'px';;
  169.   },

  170.   relativize: function(element) {
  171.     element = $(element);
  172.     if (element.style.position == 'relative') return;
  173.     Position.prepare();

  174.     element.style.position = 'relative';
  175.     var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
  176.     var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

  177.     element.style.top    = top + 'px';
  178.     element.style.left   = left + 'px';
  179.     element.style.height = element._originalHeight;
  180.     element.style.width  = element._originalWidth;
  181.   }
  182. }

  183. // Safari returns margins on body which is incorrect if the child is absolutely
  184. // positioned.  For performance reasons, redefine Position.cumulativeOffset for
  185. // KHTML/WebKit only.
  186. if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  187.   Position.cumulativeOffset = function(element) {
  188.     var valueT = 0, valueL = 0;
  189.     do {
  190.       valueT += element.offsetTop  || 0;
  191.       valueL += element.offsetLeft || 0;
  192.       if (element.offsetParent == document.body)
  193.         if (Element.getStyle(element, 'position') == 'absolute') break;

  194.       element = element.offsetParent;
  195.     } while (element);

  196.     return [valueL, valueT];
  197.   }
  198. }
复制代码

使用道具 举报

井底的蛙

银牌会员 手机认证 

帖子
1467
体力
2566
威望
7
居住地
上海市 长宁区
发表于 2008-2-25 14:15:47 |显示全部楼层
无用
对于新人来说:还是看不懂
对于高手来说:不加或者自己加更好,再或者根本不用,用的都是自己的类库
深夜,我,拖着疲惫的步伐迈向心中的理想。

使用道具 举报

帖子
112
体力
237
威望
0
居住地
广东省 深圳市
发表于 2008-2-25 17:00:09 |显示全部楼层
很长很强大
感觉没必要
自己要的东西自己能写,何必费力气去研究别人写的东西呢。
不写拉倒~

使用道具 举报

帖子
4
体力
31
威望
0
发表于 2008-2-25 21:11:34 |显示全部楼层
看看还是不错的

使用道具 举报

yaohaixiao 楼主

会武术的科学家

实习版主

帖子
2051
体力
5602
威望
45
居住地
浙江省 杭州市
发表于 2008-3-4 14:53:02 |显示全部楼层

回复 #10 blankyao 的帖子

是啊,这里不是要我们一定就用prototype,而是希望大家学习分析别人怎么设计开发程序和一些面向对象脚本写法的技巧
看看总是有益的,是吗?

使用道具 举报

willko 
帖子
222
体力
423
威望
0
居住地
广东省 深圳市
发表于 2008-3-4 15:36:48 |显示全部楼层
几时弄个jquery版的

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|安久科技提供CDN|blueidea.com ( 京ICP备05002321号 )  

GMT+8, 2012-2-13 12:02 , Processed in 0.145776 second(s), 8 queries , Gzip On, Memcache On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部