仿照jQuery进行一些简单的框架封装(欢迎指教~)

  1 (function(window,undefined){
  2     var arr = [],
  3         push = arr.push,
  4         slice = arr.slice;
  5     //首先要做的就是封装一个parseHtml函数
  6     //要注意的是,parthHtml要放在一个自调用函数内
  7     var parseHtml = (function(){
  8         //做一个模板
  9         var div = document.createElement('div');
 10         //这个函数是用来创建标签
 11         function parseHtml(html){
 12             var res = [];
 13             //这边是将具有html语义的字符串放在模板div中,div里面的就有这些标签了
 14             div.innerHTML = html;
 15             //这个时候div里有标签元素,循环遍历div里面的元素
 16             for(var i = 0;i < div.childNodes.length;i++){
 17                 //这边是将div模板里面的元素一一放到res数组里,因为这边的div.childNodes[i]是单个元素,可以直接push进数组
 18                 res.push(div.childNodes[i]);
 19             }
 20             //完成之后,将div里面的元素清除掉,方便下一次使用
 21             div.innerHTML = '';
 22             //将这个数组返回
 23             return res;
 24         }
 25         return parseHtml;
 26     })();
 27     //封装insertBefore方法
 28     function prependChild(parent,element){//传入的元素是父元素,要插入的元素
 29         var first = parent.firstChild;//将父元素中的第一个元素取出来
 30         parent.insertBefore(element,first);//使用insertBefore方法将element插入到父元素的第一个子元素的前面
 31     }
 32     //封装cc函数
 33     function cc(html){
 34         //这边返回的是cc原型对象里面的一个方法创建出来的实例
 35         return new cc.fn.init(html);
 36     }
 37     //这边是为了后面书写方便
 38     cc.fn = cc.prototype = {
 39         constructor : cc,
 40         length : 0,
 41         //这两个属性要加到原型上
 42         selector: '',//这两个属性在init所创建的实例之中还会用到,所以要加到这个原型上面
 43         type : 'cc',
 44         init : function(html){//这个函数的作用就是:1.创建实例;2.在这个函数里面对所传入的参数进行一个判断
 45             this.events = {};
 46             if(html == ''){//这边判断传入的参数是不是一个空字符串
 47                 return;//如果传入的是一个空字符串,那么就直接返回this,注意,这边虽然没写返回this,但是他是默认的
 48             }else if(cc.isString(html)){//这边是当传入的html是字符串的时候
 49                 if(/^</.test(html)){//这边的html是标签组成的字符串
 50                     push.apply(this,parseHtml(html));
 51                 }else{//这边的html是选择器字符串
 52                     //这边的this指的是通过:cc.prototype.init这个函数创建出来的实例
 53                     push.apply(this,select(html));
 54                     //将这个实例的selector设置成html
 55                     this.selector = html;
 56                 }
 57             }else if(html && html.type === 'cc'){//这边是当传入的html是一个cc对象的时候
 58                 push.apply(this,html);
 59                 this.selector = html.selector;
 60                 this.events = html.events;
 61             }else if(html && html.nodeType){//这边是当传入的是一个dom对象的时候,因为dom对象都有nodeType属性
 62                 this[0] = html;
 63                 this.length = 1;
 64             }else if(typeof html === 'function'){//这边是当传入的是一个函数的时候,进入里面
 65                 var oldfunc = onload;//将原来onload里面的函数取出来
 66                 if(typeof oldfunc === 'function'){
 67                     onload = function(){
 68                         oldfunc();
 69                         html();
 70                     }
 71                 }else{
 72                     onload = html;
 73                 }
 74             }
 75         }
 76     };
 77     //将封装好的select方法放到这里面
 78     var select = (function () {
 79       //这是一个异常与捕获的代码,它表示的意思是:如果push方法出现了错误那么就需要重写push方法
 80       try {
 81           //这边是自己模拟一个场景,来使用系统的push方法,如果可以实现的话就证明系统支持push方法
 82           //这种方法是系统能力检测中的方法功能检测
 83           var div = document.createElement( 'div' );
 84           div.innerHTML = '<p></p>';
 85           var arr = [];
 86           push.apply( arr, div.getElementsByTagName( 'p' ));
 87       } catch ( e ) {
 88           //这边是当try里面的push方法不执行的时候,会进入这里面
 89           //在这里面将push重新定义了一下,将其变为一个对象,这个对象里面有一个push方法
 90           var push = {
 91             //将apply变成了push对象里面的一个方法
 92             apply: function ( array1, array2 ) {
 93               for ( var i = 0; i < array2.length; i++ ) {
 94                 //注意这边的赋值
 95                 array1[ array1.length++ ] = array2[ i ]; 
 96               }
 97             }
 98           };
 99       }
100       // 正则表达式
101       //这句正则表达式是为了匹配系统中是否有自带的方法
102       var rnative = /{s*[native/;
103       var rtrim = /^s+|s+$/g;
104       //这个是为了匹配出          Id         类名     通配符 标签名
105       //                          1           2         3       4
106       var rbaseselector = /^(?:#([w-]+)|.([w-]+)|(*)|(w+))$/;
107       // 基本函数, support 对象, 验证 qsa 与 byclass
108       var support = {};
109       //基本函数里面的一个属性,实质上是为了看一下系统中是否有该方法(使用正则来判断)
110       support.qsa = rnative.test( document.querySelectorAll + '' );
111       //同上
112       support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' );
113       support.trim = rnative.test( String.prototype.trim + '' );
114       support.indexOf = rnative.test( Array.prototype.indexOf + '' );
115       // 基本方法
116       //封装了getElementsByClassName函数,这是为了解决兼容问题
117       //传入两个参数,一个是className,另一个是node-->这个node指的是从页面上的node元素开始查找这个className
118       function getByClassName ( className, node ) {
119           //如果没有传入node的话就给它一个默认值:document
120           node = node || document;
121           //声明一些变量
122           var allElem, res = [], i;
123           //首先做判断,如果系统有这个方法会使用系统的
124           if ( support.getElementsByClassName ) {
125               //直接使用定义的push方法
126               return push.apply(res,node.getElementsByClassName( className ));
127           } else {
128               allElem = node.getElementsByTagName( '*' );
129               for ( i = 0; i < allElem.length; i++ ) {
130                 if ( allElem[ i ].className === className ) {
131                   res.push( allElem[ i ] );
132                 }
133               }
134               return res;
135           }
136       }
137       // 自定义实现 trim 方法,该方法是将字符串中的指定的东西去掉
138       var myTrim = function ( str ) {
139            // 表示两端去空格, 然后返回去除空格的结果
140            if ( support.trim ) {
141                return str.trim();
142            } else {
143                // 自定义实现
144           //这边是将rtrim转换成空字符串,即将空格去掉了
145                return str.replace( rtrim, '' );
146            }
147       }
148       //这边封装的是indexOf方法,传入三个参数,数组,要搜索的东西,要搜索的东西在数组里面的开始索引(从第几个开始找)
149       var myIndexOf = function ( array, search, startIndex ) {
150           //首先将索引赋值,如果传入了索引,那么就让开始的索引等于它,如果没有传入那么就让它从零开始找
151           startIndex = startIndex || 0;
152           //这边还是先判断系统有没有这种方法
153           if ( support.indexOf ) {
154             //这里表示系统有这种方法,那么就直接使用就OK了,将结果返回
155             return array.indexOf( search, startIndex );
156           } else {
157             //如果没有的话,我们就自己动手封装一个
158             //对这个数组进行一个遍历,遍历的初始值就是从startIndex开始
159             for ( var i = startIndex; i < array.length; i++ ) {
160               //判断一下,如果数组里面有值与要查询的值相等,那么就返回这个索引值
161               if ( array[ i ] === search ) {
162                 return i;
163               }
164             }
165             //当遍历完成之后,如果还是没有找到的话,就返回-1
166             return -1;
167           }
168       }
169       //封装一个去重的函数,传入的参数是一个数组
170       var unique = function ( array ) {
171           //声明一个空数组,用于接收去重之后的元素
172           var resArray = [], i = 0;
173           //对传入的数组进行一个遍历
174           for ( ; i < array.length; i++ ) {
175             //做一个判断,如果说resArray里面没有arr里面的元素,则将arr里面的元素放到resArray里面
176             //注意,这边使用的是之前封装好的myIndexOf方法
177             if ( myIndexOf( resArray, array[ i ] ) == -1 ) {
178               //使用的是前面封装好的push方法
179               resArray.push( array[ i ] );
180             }
181           }
182           //将这个数组返回
183           return resArray;
184       } 
185       //这边封装的是四种基本选择器,ID选择器,类选择器,通配符选择器,标签选择器
186       function basicSelect ( selector, node ) {
187           //这边的node指的是要在哪一个下面去寻找selector
188           node = node || document;
189           var m, res;
190           if ( m = rbaseselector.exec( selector ) ) {
191             if ( m[ 1 ] ) { // id选择器
192               res = document.getElementById( m[ 1 ] );
193               if ( res ) {//如果res不是一个空的话,进入
194                 return [ res ];
195               } else {//当res为空的话返回一个空数组
196                 return [];
197               }
198             } else if ( m[ 2 ] ) {  // class选择器
199               return getByClassName( m[ 2 ], node );
200             } else if ( m[ 3 ] ) {//通配符选择器
201               return node.getElementsByTagName( m[ 3 ] );
202             } else if ( m[ 4 ] ) {//标签选择器
203               return node.getElementsByTagName( m[ 4 ] );
204             }
205           }
206           return [];
207       }
208       //封装一个组合选择器,这里面的标签使用逗号隔开的
209       function select ( selector, results ) {
210             results = results || [];
211           var m, temp, selectors, i, subselector;
212           //这边是如果传入的selector不是一个字符串的话,那么返回空数组
213           if ( typeof selector != 'string' ) return results;
214           // 表明参数都没有问题, 接下来就是如何选择
215           // 首先判断 qsa 是否可用
216           // 然后再 一步步的 自己实现
217           if ( support.qsa ) {//如果系统有querySelectorAll方法,那么就使用
218             push.apply( results, document.querySelectorAll( selector ) );
219           } else {
220             // 不存在再来考虑自己实现
221             //首先将传入的参数以逗号隔开,放到一个数组里面
222             selectors = selector.split( ',' );
223             // 循环遍历这个数组
224             for ( i = 0; i < selectors.length; i++ ) {
225               //在这个循环里面对数组里面的每一个元素进行一个去除空格的操作,保证数据是我们想要的形式
226               subselector = myTrim( selectors[ i ] );
227               // 接下来就是 处理 subselector,使用正则进行判断
228               if ( rbaseselector.test( subselector ) ) {
229                 // 基本选择器
230                 //如果匹配到了就将匹配到的传入到基本的四种选择器函数只中,返回一个数组,将这个数组进行一个push
231                 push.apply( results, basicSelect( subselector ) );
232               } else {
233                 //如果匹配不到那么就使用 select2 函数
234                 select2( subselector, results );
235               }
236             }
237           }
238           // 返回 result注意,这个数组要进行一个去重操作
239           return unique( results );
240       }
241       //封装一个后代选择器的函数,传入两个参数
242       function select2 ( selector, results ) {
243           results = results || [];
244           //将这个参数以逗号隔开
245           var selectors = selector.split( ' ' );
246           //声明一个数组,这个数组用于存放元素,以及一个node数组,这个数组用于存放从哪一个元素开始找
247           var arr = [], node = [ document ];
248           for ( var j = 0; j < selectors.length; j++ ) {
249             for ( var i = 0; i < node.length; i++ ) {
250               //因为这边寻找的是后代选择器,所以只要找到最后面的并将其返回就可以了
251               push.apply( arr, basicSelect( selectors[ j ], node[ i ] ));
252             } 
253             //在结束的时候将arr里面的值全部给node,要注意此时node里面的值的作用是什么
254             node = arr;
255             //将arr清空
256             arr = [];
257           }
258           //在最后将最后一次获取到的node值赋给results
259           //这里面的值是最后一次获取到的元素,也就是说是要获取的子代元素中的的最后一个元素
260           push.apply( results, node );
261           return results;
262       }
263       return select;
264     })();
265     //让init这个方法的原型与cc这个构造函数的原型相等,这样init的原型里面就有init的方法
266     cc.fn.init.prototype = cc.fn;
267     //给cc以及cc原型添加一个混入的方法
268     cc.extend = cc.fn.extend = function extend(obj){
269         for(var k in obj){
270             this[k] = obj[k];
271         }
272     }
273     //给cc混入方法,这些方法都是静态方法
274     cc.extend({
275         //给cc混入一个isString方法
276         isString : function(html){
277             return typeof html === "string";
278         },
279         //给cc混入一个each方法
280         each : function(arr,fnc){
281             var i;
282             if(arr instanceof Array || arr.length >= 0){
283                 for(i = 0; i < arr.length; i ++){
284                     fnc.call(arr[i],i,arr[i]);
285                 }
286             }else {
287                 for( i in arr){
288                     fnc.call(arr[i],i,arr[i]);
289                 }
290             }
291             return arr;
292         },
293         map : function(arr,fnc){
294             var i,tmp,res=[];
295             if(arr instanceof Array || arr.length >= 0){
296                 for(i =0;i<arr.length;i++){
297                     //这边的tmp的值是这边fnc的返回值,如果说fnc这个函数里面没有返回值的话(return),那么tmp就是undefined
298                     tmp = fnc(arr[i],i);
299                     if(tmp != null){
300                         res.push(tmp);
301                     }
302                 }
303             }else{
304                 for(i in arr){
305                     tmp = fnc(arr[i],i);
306                     if(tmp != null){
307                         res.push(tmp);
308                     }
309                 }
310             }
311             return res;
312         },
313         //获取到样式
314         getStyle : function(dom,styleName){
315             if(dom.currentStyle){
316                 return dom.currentStyle[styleName];
317             }else{
318                 return window.getComputedStyle(dom)[styleName];
319             }
320         },
321         getText : function(dom,list){
322             var node = dom.childNodes;
323             for(var i = 0;i < node.length;i ++){
324                 if(node[i].nodeType == 3){
325                     list.push(node[i].nodeValue);
326                 }
327                 if(node[i].nodeType == 1){
328                     cc.getText(node[i],list);
329                 }
330             }
331         }
332     });
333     //核心方法
334     cc.fn.extend({
335         //将调用该方法的对象变成数组模式
336         toArray : function(){
337             //法一:
338             /*var res = [];
339             for(var i = 0;i < this.length; i ++){
340                 res.push(this[i]);
341             }
342             return res;*/
343             //法二:
344             //这句话的意思是:this.slice(0);--->this指的是实例对象,调用slice将其从一个伪数组变成一个数组
345             return slice.call(this , 0);
346         },
347         //get方法是通过索引值来返回调用该方法的对象/数组里面的对应的值
348         get : function(index){
349             if(index === undefined){
350                 return this.toArray();
351             }
352             return this[index];
353         },
354         //这边的eq返回的是dom对象,这是与get方法的区别,简单地说就是eq返回的是一个init对象,而get返回的是一个元素
355         eq : function(num){
356             var dom;
357             if(num >= 0){
358                 dom = this.get(num);
359             }else{
360                 dom = this.get(this.length + num);
361             }
362             return cc(dom);
363         },
364         each : function(fnc){
365             return cc.each(this,fnc);
366         },
367         map : function(fnc){
368             return cc.map(this,fnc);
369         }
370     });
371     //对DOM的操作方法
372     cc.fn.extend({
373         //给cc的原型混入一个appendTo方法,注意这边的原型是与init的原型是一至的
374         //首先要明白,appendTo方法是将appendT之前的元素添加到appendTo的括号里
375         appendTo : function(selector){
376             //首先声明一个ccObj对象,这个对象是和this一样,是init的实例对象
377             //当我们将selector传入其中时,它会解析出来传入的是一个什么样的参数
378             //这边的selector参数,其实就是appendTo括号里面的内容
379             var ccObj = this.constructor(selector);
380             //这边声明一个新的init的实例对象,这是为了仿照jQuery里面链式原理的写法
381             //这边执行完该方法之后,返回的是一个dom对象
382             var newObj = this.constructor();
383             //这边循环遍历this,这个this指的就是appendTo前面的内容
384             for(var i = 0;i < this.length;i ++){
385                 //这边循环遍历的是解析了传入参数selector之后得到的一个对象ccObj
386                 for(var j = 0;j < ccObj.length;j ++){
387                     //声明一个变量temp
388                     var temp;
389                     if(j == ccObj.length-1){//当j循环到最后一个的时候,进入这个循环
390                         //将this[i]赋值给temp
391                         temp = this[i];
392                     }else{
393                         //这种情况就是当j值还没有到最后一个的时候
394                         temp = this[i].cloneNode(true);
395                     }
396                     //将temp里面的值,放到之前创建的newobj中,这是为了仿照jQuery里面的链式结构
397                     push.call(newObj , temp);
398                     //将temp添加到ccObj中,temp里面存放的是this伪数组里面的值
399                     ccObj[j].appendChild(temp);
400                 }
401             }
402             //这个是:即使完成了这个appendTo操作,返回值依旧是一个cc对象
403             return newObj;
404         },
405         //首先要明确的是:append方法是将append括号里面的加到append前面的元素中
406         append: function(selector){
407             //还是一样,先声明一个cc对象,这个对象里面是将传入的参数进行解析
408             var ccObj = this.constructor(selector);
409             //这个循环的是创建的cc对象
410             for(var i = 0;i < ccObj.length;i ++){
411                 //这个循环的是this这个伪数组
412                 for(var j = 0;j < this.length;j ++){
413                     var temp;
414                     if(j == this.length-1){//这边的做法可以参照appendTo的方法封装
415                         temp = ccObj[i];
416                         this[j].appendChild(temp);
417                     }else{
418                         temp = ccObj[i].cloneNode(true);
419                         this[j].appendChild(temp);
420                     }
421                 }
422             }
423             return this;
424         },
425         prependTo : function(selector){
426             var ccObj = this.constructor(selector);
427             var newObj = this.constructor();
428             for(var i = 0;i< this.length;i ++){
429                 for(var j = 0;j < ccObj.length;j ++){
430                     var temp;
431                     if(j == ccObj.length-1){
432                         temp = this[i];
433                     }else{
434                         temp = this[i].cloneNode(true);
435                     }
436                     push.call(newObj,temp);
437                     prependChild(ccObj[j],temp);
438                 }
439             }
440             return newObj;
441         },
442         prepend : function(selector){
443             var ccObj = this.constructor(selector);
444             for(var i = 0;i < ccObj.length;i ++){
445                 for(var j = 0;j < this.length;j ++){
446                     var temp;
447                     if(j == this.length-1){
448                         temp = ccObj[i];
449                         prependChild(this[j],temp);
450                     }else{
451                         temp = ccObj[i].cloneNode(true);
452                         prependChild(this[j],temp);
453                     }
454                 }
455             }
456             return this;
457         }
458     });
459     //事件处理模块
460     cc.fn.extend({
461         on : function(type,fn){
462             if(!this.events[type]){//当this中的events属性里面没有type的时候,进入这个里面
463                 this.events[type] = [];//给它提供一个空数组
464                 //当cc对象中的元素被点击的时候我们应该把数组中保存的函数拿出来一一执行
465                  //我们应该为cc对象中的元素添加事件处理函数
466                 var iObj = this;//将this赋值给iObj,此时iObj就表示创建出来的实例对象
467                 //这边的this指的是实例对象
468                 this.each(function(){//调用这个实例的each方法
469                     var fnc = function(e){//fnc执行的时机是type事件执行的时候,在这个时候跟着传入一个e,这个e是事件参数    
470                         for(var i = 0;i < iObj.events[type].length;i ++){
471                             //iObj.events[type][i]指的是:找到iObj对象->events属性->type数组->第i个函数,将之执行
472                             //iObj.events[type][i]指的是:函数
473                             //在执行的时候,这边的this指的是执行点击的这个dom元素
474                             iObj.events[type][i].call(this,e);//这边将e传入到这个执行的函数中
475                         }
476                     }
477                     //如果系统支持addEventListener方法就用它添加事件处理函数f,否则使用attachEvent
478                     //事件参数e是从哪里来的?就是从事件绑定的函数来的
479                     //我们通过addEventListener绑定事件的处理函数为f,那么f就带有了事件参数e
480                     if(this.addEventListener){
481                         this.addEventListener(type,fnc);
482                     }else{
483                         this.attachEvent('on' + type,fnc);
484                     }
485                 });
486             }
487             this.events[type].push(fn);
488             return this;
489         },
490         off : function(type,fn){
491             var arr = this.events[type];
492             if(arr){
493                 for(var i = arr.length;i >= 0;i --){
494                     if(arr[i] == fn){
495                         arr.splice(i,1);
496                     }
497                 }
498             }
499             return this;
500         }
501     });
502     //其他事件
503     //其他事件的添加是将这些字符串用split方法分隔
504     var arr = 
505     ("blur focus focusin focusout load resize scroll unload click dblclick " +
506       "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
507       "change select submit keydown keypress keyup error contextmenu").split(' '); 
508       //调用cc的each方法,这个方法里面传入的一个参数是数组,一个参数是函数fnc
509     cc.each(arr,function(i,v){
510         //在这个fnc中,
511         cc.fn[v] = function(fn){
512             this.on(v,fn);
513             return this;
514         }
515     });
516     cc.fn.extend({
517         hover : function(fn1,fn2){
518             this.mouseover(fn1);
519             this.mouseout(fn2);
520             return this;
521         },
522         toggle : function(){
523             var i = 0;
524             var args = arguments;
525             this.on('click' , function(e){
526                 args[i % args.length].call(this , e);
527                 i ++;
528             });
529         }
530     });
531     //样式操作
532     cc.fn.extend({
533         css : function(option){
534             var args = arguments,
535                 argsLength = arguments.length;
536             if(argsLength == 2){
537                 if(cc.isString(args[0]) && cc.isString(args[1])){
538                     return this.each(function(){
539                         this.style[args[0]] = args[1];
540                     })
541                 }
542             }
543             if(argsLength == 1){
544                 if(cc.isString(option)){
545                     return this[0].style[option] || cc.getStyle(this[0],option)
546                 }
547                 if(typeof option === 'object'){
548                     return this.each(function(){
549                         for(var k in option){
550                             this.style[k] = option[k];
551                         }
552                     })
553                 }
554             }
555         },
556         addClass : function(name){
557             return this.each(function(){
558                 var classText = this.className;
559                 if(classText){
560                     if((' ' + classText +' ').indexOf(' ' + name + ' ') ==-1){
561                         this.className += ' ' + name;//这边是将这个name添加到dom的className中
562                     }
563                 }else{
564                     this.className = name;
565                 }
566             })
567         },
568         removeClass : function(name){
569             return this.each(function(){
570                 var classText = this.className;
571                 if(classText){
572                     var arr = classText.split(' ');
573                     for(var i = arr.length;i >= 0;i --){
574                         if(arr[i] == name){
575                             arr.splice(i,1);
576                         }
577                     }
578                     this.className = arr.join(' ');
579                 }
580             })
581         },
582         hasClass : function(name){
583             //法一
584             /*var boolean;
585             this.each(function(){
586                 var classText = this.className;
587                 if(classText){
588                     var arr = classText.split(' ');
589                     for(var i = 0;i < arr.length;i ++){
590                         if(arr[i] == name){
591                             boolean = true;
592                             return;
593                         }
594                     }
595                     boolean = false;
596                     return;
597                 }
598                 boolean = false;
599                 return;
600             });
601             return boolean;*/
602             //法二
603             for(var i = 0;i < this.length;i ++){
604                 if((' ' + this[i].className + ' ').indexOf(' ' + name + ' ') != -1){
605                     return true;
606                 }
607             }
608             return false;
609         },
610         toggleClass : function(name){
611             if(this.hasClass(name)){
612                 this.removeClass(name);
613             }else{
614                 this.addClass(name);
615             }
616         }
617     });
618     //属性操作
619     cc.fn.extend({
620         attr: function(name,value){
621             //第一种情况:有value值以及value值为空时
622             if(value || value == ''){
623                 //这时要传入的name以及value都要是字符串
624                 if(cc.isString(name) && cc.isString(value)){
625                     this.each(function(){
626                         this.setAttribute(name,value);//设置属性
627                     })
628                 }
629             }else{//这种情况是当只传了name且name为字符串
630                 if(cc.isString(name)){
631                     //这个时候是获取该属性
632                     return this[0].getAttribute(name);
633                 }
634             }
635             //这个是当以上两种都不符合时:
636             return this;
637         },
638         prop : function(name,value){
639             if(value || value == ''){
640                 if(cc.isString(name) && cc.isString(value)){
641                     this.each(function(){
642                         this[name] = value;
643                     })
644                 }else{
645                     if(cc.isString(name)){
646                         return this[name];
647                     }
648                 }
649             }
650             return this;
651         },
652         val : function(value){
653             return this.attr('value',value);
654         },
655         html : function(html){
656             return this.prop('innerHTML',html);
657         },
658         text : function(){
659             var res = [];
660             cc.getText(this[0],res);
661             return res.join(' ');
662         }
663     });
664     //给cc原型添加anmite属性
665     cc.fn.extend({
666         animate : function(property,time,fn,easing){
667             var iObj = this
668                 flag = false;
669             this.each(function(){
670                 move(this,property,time,fn,easing);
671             });
672             return this;
673             function move(node,property,time,fn,easing){//需要传入的参数有:元素,元素要移动的距离,动画执行的时长
674                 var start = {};
675                 for(var k in property){
676                     start[k] = parseInt(cc.getStyle(node,k));
677                 }
678                 var    startTime = + new Date;//开始的时间
679                 iObj.timer = setInterval(function(){//设置定时器
680                     var currentTime = + new Date,//当前时间
681                         deltaTime = currentTime - startTime;//当前时间与开始事件的差值,这个差值可以得到的是已经过去了多久
682                     if(deltaTime >= time){//这边如果差值大于规定的时长之后,进入这个判断里面
683                         clearInterval(iObj.timer);//这时候要清除计时器
684                         deltaTime = time;//将差值赋值为要求的时长
685                         flag = true;
686                     }
687                     easing = easing || 'change';
688                     for(var k in property){
689                         node.style[k] = start[k] 
690                                       + g(deltaTime,time,start[k],parseInt(property[k]),easing) 
691                                       + 'px';
692                     }
693                     if(flag && fn){
694                         fn.call(iObj);
695                         return;
696                     }
697                 },20);
698             };
699             function g(deltaTime,time,start,end,easing){
700                 if(easing == 'line'){
701                     return ((end - start)/time)*deltaTime;
702                 }else if(easing == 'change'){
703                     var distance = end - start;//需要移动的距离
704                     //法一:
705                     //return distance*Math.sin(daleTime*Math.PI/2/time);
706                     //法二:
707                     return distance*(Math.log(deltaTime + 1) / Math.log(time + 1));
708                 }
709             }
710         },
711         timer : null,
712         stop : function(){
713             clearInterval(this.timer);
714             this.timer = null;
715         }
716     })
717     //在桌面上可以使用I以及cc来调用沙箱内部的cc函数
718     window.C = window.cc = cc;
719 })(window);
原文地址:https://www.cnblogs.com/199316xu/p/6431376.html