1 
  2 /**
  3  * 2.[Javascript core]: 常用工具函数扩展
  4  */
  5 Jx().$package(function(J){
  6     var isUndefined,
  7         isNull,
  8         isNumber,
  9         isString,
 10         isBoolean,
 11         isObject,
 12         isArray,
 13         isArguments,
 14         isFunction,
 15         $typeof,
 16         
 17         $return,
 18         $try,
 19         
 20         emptyFunc,
 21         
 22         checkJSON,
 23         random,
 24         extend,
 25         clone,
 26         now,
 27         timedChunk,
 28 
 29         getLength,
 30 
 31 
 32         rebuild,
 33         pass,
 34         bind,
 35         bindNoEvent,
 36 
 37         
 38 
 39         
 40         Class;
 41 
 42     /**
 43      * 判断变量的值是否是 undefined
 44      * Determines whether or not the provided object is undefined
 45      * 
 46      * @method isUndefined
 47      * @memberOf Jx.prototype
 48      * 
 49      * @param {Mixed} o 传入被检测变量的名称
 50      * @return {Boolean} 当 o 的值是 undefined 时返回 true
 51      */
 52     isUndefined = function(o) {
 53         return typeof(o) === "undefined";
 54     };
 55         
 56     /**
 57      * 判断变量的值是否是 null
 58      * Determines whether or not the provided object is null
 59      * 
 60      * @method isNull
 61      * @memberOf Jx.prototype
 62      * 
 63      * @param {Mixed} o 传入被检测变量的名称
 64      * @return {Boolean} 当 o 的值是 null 时返回 true
 65      */
 66     isNull = function(o) {
 67         return o === null;
 68     };
 69     
 70     /**
 71      * 判断变量的类型是否是 Number
 72      * Determines whether or not the provided object is a number
 73      * 
 74      * @memberOf Jx.prototype
 75      * @name isNumber
 76      * @function
 77      * @param {Mixed} o 传入被检测变量的名称
 78      * @return {Boolean} 当 o 的类型是 number 时返回 true
 79      */
 80     isNumber = function(o) {
 81         return (o === 0 || o) && o.constructor === Number;
 82     };
 83     
 84     /**
 85      * 判断变量的类型是否是 Boolean
 86      * Determines whether or not the provided object is a boolean
 87      * 
 88      * 
 89      * @method isBoolean
 90      * @memberOf Jx.prototype
 91      * 
 92      * @static
 93      * @param {Mixed} o 传入被检测变量的名称
 94      * @return {Boolean} 当 o 的类型是 boolean 时返回 true
 95      */
 96     isBoolean = function(o) {
 97         return (o === false || o) && (o.constructor === Boolean);
 98     };
 99     
100     /**
101      * 判断变量的类型是否是 String
102      * Determines whether or not the provided object is a string
103      * 
104      * 
105      * @method isString
106      * @memberOf Jx.prototype
107      * 
108      * @static
109      * @param {Mixed} o 传入被检测变量的名称
110      * @return {Boolean} 当 o 的类型是 string 时返回 true
111      */
112     isString = function(o) {
113         return (o === "" || o) && (o.constructor === String);
114     };
115     
116     /**
117      * 判断变量的类型是否是 Object
118      * Determines whether or not the provided object is a object
119      * 
120      * 
121      * @method isObject
122      * @memberOf Jx.prototype
123      * 
124      * @param {Mixed} o 传入被检测变量的名称
125      * @return {Boolean} 当 o 的类型是 object 时返回 true
126      */
127     isObject = function(o) {
128         return o && (o.constructor === Object || Object.prototype.toString.call(o) === "[object Object]");
129     };
130     
131     /**
132      * 判断变量的类型是否是 Array
133      * Determines whether or not the provided object is a array
134      * 
135      * 
136      * @method isArray
137      * @memberOf Jx.prototype
138      * 
139      * @param {Mixed} o 传入被检测变量的名称
140      * @return {Boolean} 当 o 的类型是 array 时返回 true
141      */
142     isArray = function(o) {
143         return o && (o.constructor === Array || Object.prototype.toString.call(o) === "[object Array]");
144     };
145     
146     /**
147      * 判断变量的类型是否是 Arguments
148      * Determines whether or not the provided object is a arguments
149      * 
150      * 
151      * @method isArguments
152      * @memberOf Jx.prototype
153      * 
154      * @param {Mixed} o 传入被检测变量的名称
155      * @return {Boolean} 当 o 的类型是 arguments 时返回 true
156      */
157     isArguments = function(o) {
158         return o && o.callee && isNumber(o.length) ? true : false;
159     };
160     
161     /**
162      * 判断变量的类型是否是 Function
163      * Determines whether or not the provided object is a function
164      * 
165      * 
166      * @method isFunction
167      * @memberOf Jx.prototype
168      * 
169      * @param {Mixed} o 传入被检测变量的名称
170      * @return {Boolean} 当 o 的类型是 function 时返回 true
171      */
172     isFunction = function(o) {
173         return o && (o.constructor === Function);
174     };
175     
176     /**
177      * 判断变量类型的方法
178      * Determines the type of object
179      * 
180      * 
181      * @method $typeof
182      * @memberOf Jx.prototype
183      * 
184      * @param {Mixed} o 传入被检测变量的名称
185      * @return {String} 返回变量的类型,如果不识别则返回 other
186      */
187     $typeof = function(o) {
188         if(isUndefined(o)){
189             return "undefined";
190         }else if(isNull(o)){
191             return "null";
192         }else if(isNumber(o)){
193             return "number";
194         }else if(isBoolean(o)){
195             return "boolean";
196         }else if(isString(o)){
197             return "string";
198         }else if(isObject(o)){
199             return "object";
200         }else if(isArray(o)){
201             return "array";
202         }else if(isArguments(o)){
203             return "arguments";
204         }else if(isFunction(o)){
205             return "function";
206         }else{
207             return "other";
208         }
209         
210     };
211     /**
212      * @ignore
213      */
214     checkJSON = function(){
215         
216         return true;
217     };
218     
219     /**
220      * 生成随机数的方法
221      * 
222      * @method random
223      * @memberOf Jx.prototype
224      * 
225      * @param {Number} min 生成随机数的最小值
226      * @param {Number} max 生成随机数的最大值
227      * @return {Number} 返回生成的随机数
228      */
229     random = function(min, max){
230         return Math.floor(Math.random() * (max - min + 1) + min);
231     };
232     
233     
234     
235     /**
236      * 克隆一个对象
237      * 
238      * @method clone
239      * @memberOf Jx.prototype
240      * 
241      * @param {Object} o 要克隆的对象
242      * @return {Object} 返回通过克隆创建的对象
243      * 
244      * @example
245      * Jx().$package(function(J){
246      *     var objA = {name: "Kinvix"};
247      *     // 克隆一个 objA 对象,并存入 objB 中。
248      *     var objB = J.clone(objA);
249      * };
250      */
251     clone = function(o){
252         /**
253          * @ignore
254          */
255         var tempClass = function(){};
256         tempClass.prototype = o;
257         
258         // 返回新克隆的对象
259         return (new tempClass());
260     };
261 
262     
263 
264     
265 
266     
267     
268     
269     /**
270      * 生成一个返回值是传入的 value 值的函数
271      * 
272      * @method $return
273      * @memberOf Jx.prototype
274      * 
275      * @param {Mixed} value 要返回的值
276      * @return {Mixed} 返回一个返回值是 value 的函数
277      */
278     $return = function(result){
279         return J.isFunction(result) ? result : function(){
280                 return result;
281             };
282     };
283     
284     /**
285      * 从第一个函数开始try,直到尝试出第一个可以成功执行的函数就停止继续后边的函数,并返回这个个成功执行的函数结果
286      * 
287      * @method $try
288      * @memberOf Jx.prototype
289      * 
290      * @param {Function} fn1, fn2, .... 要尝试的函数
291      * @return {Mixed} 返回第一个成功执行的函数的返回值
292      * 
293      * @example
294      * Jx().$package(function(J){
295      *     // 按顺序执行 funcA, funcB, funcC,当中途有一个 func 的执行结果返回 true 则不再往下执行,并返回成功执行的 func 的返回值;
296      *     J.$try(funcA, funcB, funcC);
297      * };
298      */
299     $try = function(){
300         var i,
301             l = arguments.length,
302             result;
303             
304         for(i = 0; i < l; i++){
305             try{
306                 result = arguments[i]();
307                 // 如果上边语句执行成功则执行break跳出循环
308                 break;
309             }catch(e){
310                 J.out("C.错误:[" + e.name + "] "+e.message+", " + e.fileName+", 行号:"+e.lineNumber+"; stack:"+typeof e.stack, 2);
311             }
312         }
313         return result;
314     };
315     
316     /**
317      * 对一个对象或数组进行扩展
318      * 
319      * @method extend
320      * @memberOf Jx.prototype
321      * 
322      * @param {Mixed} beExtendObj 被扩展的对象或数组
323      * @param {Mixed} extendObj1, extendObj2, .... 用来参照扩展的对象或数组
324      * @return {Mixed} 返回被扩展后的对象或数组
325      * 
326      * @example
327      * Jx().$package(function(J){
328      *     // 用 objB 和objC 扩展 objA 对象;
329      *     J.extend(objA, objB, objC);
330      * };
331      * 
332      */
333     extend = function(beExtendObj, extendObj1, extendObj2){
334         var a = arguments,
335             i,
336             p,
337             beExtendObj,
338             extendObj;
339             
340         if(a.length === 1){
341             beExtendObj = this;
342             i=0;
343         }else{
344             beExtendObj = a[0] || {};
345             i=1;
346         }
347         
348         for(; i<arguments.length; i++){
349             extendObj = arguments[i];
350             for(p in extendObj){
351                 var src = beExtendObj[p],
352                     obj = extendObj[p];
353                 if ( src === obj ){
354                     continue;
355                 }
356                 
357                 if ( obj && isObject(obj) && !isArray(obj) && !obj.nodeType && !isFunction(obj)){
358                     src = beExtendObj[p] || {};//2010-12-28
359                     beExtendObj[p] = extend( src, 
360                         // Never move original objects, clone them
361                         obj || ( obj.length != null ? [ ] : { } ));
362 
363                 // Don't bring in undefined values
364                 }else if ( obj !== undefined ){
365                     beExtendObj[p] = obj;
366                 }
367             }
368         }
369 
370         return beExtendObj;
371     };
372     
373     
374     /*
375     extend = function(beExtendObj, target, extendObj2) {
376         
377         // copy reference to target object
378         var target = arguments[0] || {}, 
379         i = 2, 
380         length = arguments.length, 
381         options;
382     
383     
384         target = arguments[1] || {};
385 
386 
387     
388         // Handle case when target is a string or something (possible in deep copy)
389         if ( typeof target !== "object" && !J.isFunction(target) ){
390             target = {};
391         }
392         // extend jQuery itself if only one argument is passed
393         if ( length == i ) {
394             target = this;
395             --i;
396         }
397     
398         for ( ; i < length; i++ ){
399             // Only deal with non-null/undefined values
400             if ( (options = arguments[ i ]) != null ){
401                 // Extend the base object
402                 for ( var name in options ) {
403                     var src = target[ name ], 
404                         copy = options[ name ];
405     
406                     // Prevent never-ending loop
407                     if ( target === copy ){
408                         continue;
409                     }
410                     // Recurse if we're merging object values
411                     if ( copy && typeof copy === "object" && !copy.nodeType ){
412                         target[ name ] = extend( target, 
413                             // Never move original objects, clone them
414                             src || ( copy.length != null ? [ ] : { } )
415                         , copy );
416     
417                     // Don't bring in undefined values
418                     }else if ( copy !== undefined ){
419                         target[ name ] = copy;
420                     }
421                 }
422             }
423         }
424         // Return the modified object
425         return target;
426     };
427     */
428     
429     /**
430      * 获取当前时间的函数
431      * 
432      * @method now
433      * @memberOf Jx.prototype
434      * 
435      * 
436      * 
437      * @example
438      * alert(J.now());
439      * 
440      */
441     now = function(){
442         return +new Date;
443     }
444     
445     
446     /**
447      * 通用分时处理函数
448      * 
449      * @method timedChunk
450      * @memberOf Jx.prototype
451      * 
452      * 
453      * 
454      * @example
455      * Jx().$package(function(J){
456      * };
457      * 
458      */
459     timedChunk = function(items, process, context, isShift, callback) {
460         var todo = items.concat(), delay = 25;
461         if(isShift){
462             todo = items;
463         }
464  
465         window.setTimeout(function() {
466             var start = +new Date();
467  
468             do {
469                 process.call(context, todo.shift());
470             } while(todo.length > 0 && (+new Date() - start < 50));
471  
472             if(todo.length > 0) {
473                 window.setTimeout(arguments.callee, delay);
474             } else if(callback) {
475                 callback(items);
476             }
477  
478         }, delay);
479     }
480     
481 
482     
483     /**
484      * 获取对象自身具有的属性和方法的数量
485      * 
486      * @method getLength
487      * @memberOf Jx.prototype
488      * 
489      * @param {Object} obj 要获取的对象
490      * @return {Number} 返回对象自身具有属性和方法的数量
491      */
492     getLength = function(obj) {
493         var p,
494             count = 0;
495         for(p in obj){
496             if(obj.hasOwnProperty(p)){
497                 count++;
498             }
499         }
500         return count;
501     };
502     
503     /**
504      * 一个空函数函数
505      * 
506      * @memberOf Jx.prototype
507      */
508     emptyFunc = function(){};
509     
510 
511 
512         
513     /**
514      * 函数的重构方法
515      * 
516      * 
517      * @private
518      * @memberOf Jx.prototype
519      * @param {Object} option 选项对象
520      * @return {Function} 返回重构后的函数的执行结果
521      */
522     rebuild = function(func, option){
523         option = option || {};
524         
525         func.$$rebuildedFunc = func.$$rebuildedFunc || function(){
526             var self2 = this,
527                 scope,
528                 args,
529                 returns;
530             scope = option.contextObj || self2;
531             args = Array.prototype.slice.call(arguments, 0);
532 
533             if(args !== undefined){
534                 args = args.concat(option.arguments);
535             }
536             if(option.event === false){
537                 args = args.slice(1);
538             }
539 
540             return func.apply(scope, args);
541         };
542 
543         return func.$$rebuildedFunc;
544     };
545     
546     /**
547      * 给函数传入参数并执行
548      * 
549      * @memberOf Jx.prototype
550      * @param {Mixed} args 参数列表
551      * @return {Mixed} 返回函数执行结果
552      * 
553      * @example
554      * Jx().$package(function(J){
555      *     // 将"a"、"b"两个字符串传入funcA函数并执行
556      *     funcA.pass("a","b");
557      * };
558      * 
559      */
560     pass = function(func, var_args) {
561         var slice = Array.prototype.slice;
562         var a = slice.call(arguments, 1);
563         return function(){
564             var context = this;
565             return func.apply(context, a.concat(slice.call(arguments)));
566         };
567     };
568     /*
569     pass = function(func){
570         var args = Array.prototype.slice.call(arguments, 1);
571         return rebuild(func, {contextObj: null, arguments: args});
572     };
573     */
574     
575     /*
576      * 给函数绑定一个上下文对象再执行
577      * 
578      * @memberOf Jx.prototype
579      * @param {Object} contextObj 要绑定的上下文对象
580      * @param {Mixed} args 参数列表
581      * @return {Mixed} 返回函数执行结果
582      * 
583      * @example
584      * Jx().$package(function(J){
585      *     // 以 contextObjB 对象为上下文对象 this 来执行funcA函数
586      *     funcA.bind(contextObjB);
587      * };
588      * 
589      */
590     /*
591     bind = function(func, contextObj){
592         var args = Array.prototype.slice.call(arguments, 2);
593         //args = [this].extend(args);
594         return rebuild(func, {contextObj: contextObj, arguments: args});
595     };
596     */
597     
598     /**
599      * 将一个函数绑定给一个对象作方法,返回的函数将总被传入{@code obj} as {@code this}
600      * 
601      * @memberOf Jx.prototype
602      * @param {Function} func 要绑定的函数
603      * @param {Object} contextObj 要绑定的对象
604      * @param {Mixed} args 参数列表,长度任意
605      * @return {Function} 返回一个被绑定this上下文对象的函数
606      * 
607      * @example
608      * Jx().$package(function(J){
609      *   funcB = J.bind(funcA, obj, a, b)
610      *   funcB(c, d) // 相当于执行 funcA.call(obj, a, b, c, d)
611      * };
612      */
613     
614     bind = function(func, context, var_args) {
615         var slice = Array.prototype.slice;
616         var a = slice.call(arguments, 2);
617         return function(){
618             return func.apply(context, a.concat(slice.call(arguments)));
619         };
620     };
621     
622 
623 
624     
625     
626 
627     
628     
629     /**
630      * 创建Class类的类
631      * Class
632      * @class 
633      * @memberOf Jx
634      * @param {Object} option = {extend: superClass} 在option对象的extend属性中指定要继承的对象,可以不写
635      * @param {Object} object 扩展的对象
636      * @return {Object} 返回生成的日期时间字符串
637      * 
638      * @example
639      * Jx().$package(function(J){
640      *     var Person = new J.Class({
641      *      init : function(name){
642      *          this.name = name;
643      *          alert("init");
644      *      },
645      *      showName : function(){
646      *          alert(this.name);
647      *  
648      *      }
649      *  
650      *  });
651      *  
652      *  // 继承Person
653      *     var Person2 = new J.Class({extend : Person}, {
654      *      init : function(name){
655      *          this.name = name;
656      *          alert("init");
657      *      },
658      *      showName : function(){
659      *          alert(this.name);
660      *  
661      *      }
662      *  
663      *  });
664      *     
665      * };
666      * 
667      */
668     Class = function(){
669         var length = arguments.length;
670         var option = arguments[length-1];
671         
672         option.init = option.init || function(){};
673         
674         // 如果参数中有要继承的父类
675         if(length === 2){
676             /**
677              * @ignore
678              */
679             var superClass = arguments[0].extend;
680             
681             /**
682              * @ignore
683              */
684             var tempClass = function() {};
685             tempClass.prototype = superClass.prototype;
686             
687             /**
688              * @ignore
689              */
690             var subClass = function() {
691                 this.init.apply(this, arguments);
692             }
693             
694             // 加一个对父类原型引用的静态属性
695             subClass.superClass = superClass.prototype;
696             //subClass.superClass = superClass;
697             /**
698              * @ignore
699              */
700             subClass.callSuper = function(context,func){
701                 var slice = Array.prototype.slice;
702                 var a = slice.call(arguments, 2);
703                 var func = subClass.superClass[func];
704                 //var func = subClass.superClass.prototype[func];
705                 if(func){
706                     func.apply(context, a.concat(slice.call(arguments)));
707                 }
708             };
709             
710             // 指定原型
711             subClass.prototype = new tempClass();
712             
713             // 重新指定构造函数
714             subClass.prototype.constructor = subClass;
715             
716             J.extend(subClass.prototype, option);
717             
718             /**
719              * @ignore
720              */
721             subClass.prototype.init = function(){
722                 // 调用父类的构造函数
723                 // subClass.superClass.init.apply(this, arguments);
724                 // 调用此类自身的构造函数
725                 option.init.apply(this, arguments);
726             };
727             
728             return subClass;
729             
730         // 如果参数中没有父类,则单纯构建一个类
731         }else if(length === 1){
732             /**
733              * @ignore
734              */
735             var newClass = function() {
736                 // 加了return,否则init返回的对象不生效
737                 return this.init.apply(this, arguments);
738             }
739             newClass.prototype = option;
740             return newClass;
741         }
742         
743         
744     };
745     
746     var Chunk = new Class({
747         init : function(items, process, context, isShift, callback) {
748             var todo = items.concat(), delay = 25;
749             if(isShift){
750                 todo = items;
751             }
752             //this.timeout;
753              this.timeout = window.setTimeout(function() {
754                 var start = +new Date();
755      
756                 do {
757                     process.call(context, todo.shift());
758                 } while(todo.length > 0 && (+new Date() - start < 50));
759      
760                 if(todo.length > 0) {
761                     this.timeout = window.setTimeout(arguments.callee, delay);
762                 } else if(callback) {
763                     callback(items);
764                 }
765      
766             }, delay);
767         },
768         stop : function(){
769             clearTimeout(this.timeout);
770         }
771     
772     });
773     /*
774     Class = function(obj){
775         var tempClass = function() {
776             this.init.apply(this, arguments);
777         }
778         tempClass.prototype = obj;
779         return tempClass;
780     };
781     */
782     
783     
784     
785     
786     
787     J.isUndefined = isUndefined;
788     J.isNull = isNull;
789     J.isNumber = isNumber;
790     J.isString = isString;
791     J.isBoolean = isBoolean;
792     J.isObject = isObject;
793     J.isArray = isArray;
794     J.isArguments = isArguments;
795     J.isFunction = isFunction;
796     J.$typeof = $typeof;
797     
798     J.$return = $return;
799     J.$try = $try;
800     
801     J.emptyFunc = emptyFunc;
802     
803     J.clone = clone;
804 
805     J.getLength = getLength;
806     J.checkJSON = checkJSON;
807     J.random = random;
808     J.extend = extend;
809     
810     J.now = now;
811     J.timedChunk = timedChunk;
812     
813     
814     J.rebuild = rebuild;
815     J.pass = pass;
816     J.bind = bind;
817     J.bindNoEvent = bindNoEvent;
818     
819 
820     
821     J.Class = Class;
822     J.Chunk = Chunk;
823     
824 
825 
826 });
827