1 /** 
  2  * JET (Javascript Extension Tools) 
  3  * Copyright (c) 2009, All rights reserved.
  4  *
  5  * @fileOverview Jx!
  6  * @version 1.0
  7  * @author  Kinvix(<a href="mailto:Kinvix@gmail.com">Kinvix@gmail.com</a>)
  8  * @description 
  9  * 
 10  */
 11 
 12 /** 
 13  * @description
 14  * Package: jet.console
 15  *
 16  * Need package:
 17  * jet.core.js
 18  * jet.base.js
 19  * jet.array.js
 20  * jet.string.js
 21  * jet.dom.js
 22  * jet.browser.js
 23  * jet.event.js
 24  */
 25 
 26 
 27 /**
 28  * 10.[Browser part]: console 控制台
 29  */
 30 Jx().$package(function(J){
 31     var $ = J.dom.id,
 32         $D = J.dom,
 33         $E = J.event,
 34         $S = J.string/*,
 35         $H = J.http*/;
 36         
 37     
 38     var topNamespace = this,
 39         query = J.string.mapQuery(window.location.search);
 40     /*var _open=window.open;
 41     var open=function(sURL, sName, sFeatures, bReplace){
 42         if(sName == undefined){
 43             sName="_blank";
 44         };
 45         if(sFeatures == undefined){
 46             sFeatures="";
 47         };
 48         if(bReplace == undefined){
 49             bReplace=false;
 50         };
 51         
 52         var win=_open(sURL, sName, sFeatures, bReplace);
 53         if(!win){
 54             J.out("你的机器上有软件拦截了弹出窗口");
 55             return false;
 56         }
 57         
 58         return true;
 59     };
 60     window.open = open;*/
 61     /**
 62      * 日志对象
 63      * @author tealin
 64      * @class Log
 65      * @ignore
 66      * @memberOf console
 67      * @name Log
 68      */
 69     var Log = new J.Class(
 70         
 71         {
 72         _defaultType : 3,
 73         _defaultTag : 'information',
 74         _defaultTemplate : '<%=msg%>(<%=type%>#<%=tag%>@<%=time%>)',
 75         /**
 76          * 信息类型常量,一共五种类型:<br/><br/>
 77          * PROFILE  : 0 <br/>
 78          * WARNING  : 1 <br/>
 79          * ERROR    : 2 <br/>
 80          * INFO     : 3 <br/>
 81          * DEBUG    : 4 <br/>
 82          * 
 83          * @type Object
 84          */
 85         TYPE : ['PROFILE' ,'WARNING', 'ERROR', 'INFO','DEBUG'],
 86 
 87         init : function(option){
 88             this.msg = option.msg||'';
 89             this.tag = option.tag||this._defaultTag;
 90             this.type = J.isUndefined(option.type)?this._defaultType:option.type;
 91             this.time = new Date().valueOf();
 92             this._template = option.template||this._defaultTemplate;
 93         },
 94 //      setTemplate : function(template){
 95 //          this._template = template;
 96 //          try{
 97 //              this.toString();
 98 //          }catch(e){
 99 //              alert("格式错误!输入格式类似为:<%=msg%>(<%=type%>#<%=tag%>@<%=time%>)");
100 //          }
101 //      },
102         /**
103          * 格式化输出
104          * @param {Object} data 模版数据
105          * @param {Boolen} isEncode 是否转义
106          * @param {String} template 输出模版
107          * @return {String} 输出字符串
108          */
109         format : function(data,isEncode,template){
110             template = template||this._template;
111             if(isEncode){
112                 return $S.encodeHtml($S.template(template,data));
113             }else{
114                 return $S.template(template,data);
115             }
116         },
117         /**
118          * 格式化数据对象
119          * @return {Object} 数据对象
120          */
121         parseOption : function(){
122             var context = this;
123             var option = {
124                 msg : context.msg,
125                 time : context.time,
126                 type : context.TYPE[context.type],
127                 tag : context.tag       
128             }
129             return option;
130         },
131         /**
132          * 普通输出函数
133          * @param {Boolen} isEncode 是否转义
134          * @param {String} template 输出模版
135          * @return {String} 输出字符串
136          */
137         toString : function(isEncode,template){
138             return this.format(this.parseOption(),isEncode,template||this._template);
139         }
140     });
141     
142     
143     
144     
145     
146     J.config={
147         debugLevel: 1
148     };
149     
150     
151     
152     
153     
154     /**
155      * Jx 控制台,用于显示调试信息以及进行一些简单的脚本调试等操作。可以配合 J.debug J.runtime 来进行数据显示和调试.
156      * 
157      * @type console
158      * @namespace
159      * @name console
160      */
161     J.console = {
162         /**
163          * 在console里显示信息
164          * 
165          * @param {String} msg 信息
166          * @param {Number} type 信息类型
167          * 
168          * @example
169          * J.console.print("这里是提示信息",J.console.TYPE.ERROR)
170          */
171 //      print : function(msg, type){
172 //          if(J.console.log){
173 //              J.console.log((type === 4 ? (new Date() + ":") : "") + msg);
174 //          }
175 //      }
176     };
177 
178     /**
179      * 数据监控和上报系统
180      * 
181      * @ignore
182      * @type J.Report
183      */
184     J.Report = {
185         /**
186          * 数据分析上报接口
187          * 
188          * @param {string} source 数据来源
189          * @param {number} type 数据返回结果,<br/> <br/>1 加载完成 <br/>2 加载失败 <br/>3 数据异常
190          *            无法解释/截断 <br/>4 速度超时 <br/>5 访问无权限 <br/> 对应的转义符是 %status%
191          * 
192          * @param {string} url 请求的数据路径
193          * @param {number} time 响应时间
194          * @ignore
195          */
196         receive : J.emptyFunc,
197     
198         /**
199          * 添加监控规则,
200          * 
201          * @param {String} url 需要监控的url
202          * @param {String} reportUrl 出现异常后上报的地址 上报地址有几个变量替换 <br/>%status% 数据状态
203          *            <br/>%percent% 统计百分比 <br/>%url% 监听的url地址,自动encode
204          *            <br/>%fullUrl% 监听的完整的url地址,包括这个地址请求时所带 <br/>%source% js处理来源
205          *            <br/>%time% 请求花掉的时间 <br/>%scale% 比例,通常是指 1:n 其中的 n 就是 %scale%
206          * 
207          * <br/>
208          * @example
209          * J.Report.addRule("http://imgcache.qq.com/data2.js","http://imgcache.qq.com/ok?flag1=3234&flag2=%status%&1=%percent%&flag4=123456");
210          * @ignore
211          */
212         addRule : J.emptyFunc
213     };
214     
215     
216 
217     
218     J.extend(J.console,
219     /**
220      * @lends console
221      */
222     {
223         /**
224          * 是否进行了初始化
225          * 
226          * @type Boolean
227          */
228         _isCreated : false,
229         /**
230          * 日志记录最大数目
231          */
232         _maxLength : 1000,
233     
234         /**
235          * console表现模板
236          * 
237          * @type String
238          */
239         _html :    '<div id="ConsoleBoxHead" class="consoleBoxHead">\
240                         <a href="###" id="ConsoleCloseButton" class="consoleCloseButton" title="关闭">X</a>\
241                         <a href="###" id="ConsoleClearButton" class="consoleCloseButton" title="清除所有日志">C</a>\
242                         <a href="###" id="ConsoleRefreshButton" class="consoleCloseButton" title="还原所有日志">R</a>\
243                         <a href="###" id="ConsoleHelpButton" class="consoleCloseButton" title="控制台帮助">H</a>\
244                         <h5 class="title" title="控制台">Console</h5>\
245                     </div>\
246                     <div id="consoleMain" class="consoleMain">\
247                         <ul id="ConsoleOutput" class="consoleOutput"></ul>\
248                     </div>\
249                     <div class="consoleInputBox">\
250                         ><input id="ConsoleInput" class="consoleInput" title="请输入控制台指令或者Javascript语句..." />\
251                     </div>',
252 
253         /**
254          * console的css文本
255          *
256          * @type String
257          */
258         _cssText :    '\
259                         html{\
260                             _background:url(about:blank);\
261                         }\
262                         \
263                         .consoleBox{\
264                             display:none;\
265                             position:fixed;\
266                             _position: absolute;\
267                             _top:expression(documentElement.scrollTop+documentElement.clientHeight-this.offsetHeight);\
268                             _left:expression(documentElement.scrollLeft+documentElement.clientWidth-this.offsetWidth-200);\
269                             right: 200px;\
270                             bottom: 30px;\
271                             z-index: 10000000;\
272                             border: 2px solid #bbb;\
273                             padding: 5px;\
274                             width: 300px;\
275                             height:310px;\
276                             background: #000;\
277                             box-shadow: 1px 1px 20px rgba(0, 0, 0, 0.75);\
278                             filter: Alpha(opacity:75);\
279                             font-family: "Courier New", Consolas, "LucidaConsole", Monaco, monospace;\
280                             font-size: 12px;\
281                             color: #fff;\
282                         }\
283                         \
284                         html.webkit .consoleBox{\
285                             background: rgba(0,0,0,0.75);\
286                         }\
287                         \
288                         .consoleBoxHead{\
289                             height:20px;\
290                             background: rgba(255,255,255,0.15);\
291                             overflow:hidden;\
292                             cursor:default;\
293                             padding: 2px;\
294                         }\
295                         \
296                         .consoleBoxHead .title{\
297                             margin:0;\
298                             padding: 0 0 0 3px;\
299                             height:20px;\
300                             line-height:20px;\
301                             font-family: Verdana;\
302                         }\
303                         \
304                         .consoleBoxHead .consoleCloseButton{\
305                             float:right;\
306                             border:0px solid #000;\
307                             width:20px;\
308                             height:18px;\
309                             line-height:16px;\
310                             background: white;\
311                             margin:1px 1px;\
312                             padding:0px;\
313                             color:#666;\
314                             font-family: Verdana;\
315                             font-weight:bold;\
316                             cursor:pointer;\
317                             border-radius:3px;\
318                             -moz-border-radius:3px;\
319                             -webkit-border-radius:3px;\
320                             text-align:center;\
321                             text-decoration:none;\
322                         }\
323                         \
324                         .consoleBoxHead .consoleCloseButton:hover{\
325                             background: orange;\
326                             color:white;\
327                             text-decoration:none;\
328                         }\
329                         \
330                         #ConsoleCloseButton:hover{\
331                             background: red;\
332                         }\
333                         \
334                         #ConsoleClearButton:hover{\
335                             background: blue;\
336                         }\
337                         \
338                         #ConsoleRefreshButton:hover{\
339                             background: green;\
340                         }\
341                         \
342                         .consoleMain{\
343                             position:relative;\
344                             top:2px;\
345                             bottom:0px;\
346                             width:100%;\
347                             height:255px;\
348                             overflow:auto;\
349                         }\
350                         html.mobileSafari .consoleMain{\
351                             overflow:hidden;\
352                         }\
353                         \
354                         ul.consoleOutput{\
355                             display:block;\
356                             margin:0;\
357                             padding:0;\
358                             width:100%;\
359                             list-style:none;\
360                         }\
361                         \
362                         ul.consoleOutput li{\
363                             list-style:none;\
364                             padding:3px;\
365                             border-bottom:1px solid #333333;\
366                             word-break: break-all;\
367                             word-wrap: break-word;\
368                             overflow: hidden;\
369                             zoom: 1;\
370                         }\
371                         \
372                         .consoleOutput .log_icon{\
373                             width:13px;\
374                             height:13px;\
375                             background:#fff;\
376                             overflow:hidden;\
377                             float:left;\
378                             margin-top:2px;\
379                             font-weight:bold;\
380                             text-align:center;\
381                             font-size:12px;\
382                             color:#8B8B8B;\
383                             line-height:135%;\
384                             cursor:default;\
385                             border-radius:3px;\
386                             -moz-border-radius:3px;\
387                             -webkit-border-radius:3px;\
388                         }\
389                         \
390                         .consoleOutput .log_text{\
391                             margin: 0px 0px 0px 20px;\
392                             line-height:150%;\
393                             zoom: 1;\
394                         }\
395                         \
396                         .log_error_type{}\
397                         \
398                         .log_error_type .log_icon{\
399                             background:#FF0000;\
400                             color:#660000;\
401                         }\
402                         \
403                         .log_error_type .log_text{\
404                             color:#FF0000;\
405                         }\
406                         \
407                         .log_warning_type{}\
408                         \
409                         .log_warning_type .log_icon{\
410                             background:#FFFF00;\
411                             color:#8C7E00;\
412                         }\
413                         \
414                         .log_warning_type .log_text{\
415                             color:#FFFF00;\
416                         }\
417                         \
418                         .log_debug_type{}\
419                         \
420                         .log_debug_type .log_icon{\
421                             background:#33CC00;\
422                             color:#006600;\
423                         }\
424                         \
425                         .log_debug_type .log_text{\
426                             color:#33cc00;\
427                         }\
428                         \
429                         .log_info_type{}\
430                         \
431                         .log_info_type .log_icon{\
432                             background:#0066FF;\
433                             color:#000066\
434                         }\
435                         \
436                         .log_info_type .log_text{\
437                             color:#0066FF;\
438                         }\
439                         \
440                         .log_profile_type{}\
441                         \
442                         .log_profile_type .log_icon{\
443                         }\
444                         \
445                         .log_profile_type .log_text{\
446                             color:white;\
447                         }\
448                         \
449                         #JxConsole .consoleInputBox{\
450                             font-family: Verdana;\
451                             font-size:12px;\
452                             margin:5px 0;\
453                             padding:2px 0;\
454                             border-top:1px solid #aaa;\
455                             width:100%;\
456                             color:#CCFF00;\
457                         }\
458                         \
459                         #JxConsole  input.consoleInput{\
460                             border:0px solid #666;\
461                             background:transparent;\
462                             color:#CCFF00;\
463                             font-family: "Courier New", Consolas, "LucidaConsole", Monaco, monospace;\
464                             font-size:12px;\
465                             width:285px;\
466                             height:25px;\
467                             margin-left:3px;\
468                             outline:none;\
469                         }\
470                          ',
471 
472         /**
473          * 提示框是否打开了
474          * 
475          * @type Boolean
476          */
477         _opened : false,
478         
479         //日志记录对象
480         _log_record: [],
481         
482         _cmd_history:[],
483         _cmd_last_index:0,
484         /**
485          * 是否为自定义的控制台 
486          */
487         isCustomConsole : true,
488         _templateArr : ['<%=msg%>','<%=msg%>(<%=type%>#<%=tag%>@<%=time%>)'],
489         _templateType :0,
490     
491         /**
492          * 样式类
493          * 
494          * @type Array
495          */
496         _typeInfo : [["log_profile_type", "└"], ["log_warning_type", "!"], ["log_error_type", "x"], ["log_info_type", "i"],["log_debug_type", "√"]],
497         TYPE : {
498             PROFILE : 0,
499             WARNING : 1,
500             ERROR : 2,
501             INFO : 3,
502             DEBUG : 4
503         },
504 
505         /**
506          * 显示console
507          */
508         show : function() {
509             if (!this._isCreated) {
510                 this._create();
511             }
512             this._opened = true;
513             
514             this._main.style.display = "block";
515             this.render();
516             
517                 
518             //输入焦点过来
519             window.setTimeout(J.bind(this.focusCommandLine, this), 0);
520         },
521     
522         /**
523          * 隐藏console
524          */
525         hide : function(e) {
526             e && e.preventDefault();
527             this.clear();
528             J.console._main.style.display = "none";
529             J.console._opened = false;
530             
531         },
532         
533         /**
534          * 开启console
535          */
536         enable : function() {
537             J.option.console = true;
538             this.show();
539             
540         },
541         
542         /**
543          * 关闭console
544          */
545         disable : function() {
546             J.option.console = false;
547             this.hide();
548             
549         },
550     
551         /**
552          * 初始化控制台
553          * 
554          * @ignore
555          */
556         _init : function() {
557             // 快捷键开启
558             $E.on(document, "keydown", J.bind(this.handleDocumentKeydown, this));
559             if (J.option.console) {
560                 this.show();
561             }
562             this.setToDebug();
563             //this.out("Welcome to JET(Javascript Extension Tools)...");
564         },
565         /**
566          * 建立控制台面板,初始化DOM事件监听
567          */
568         _create:function(){
569 
570             $D.createStyleNode(this._cssText);
571             //$H.loadCss(J.path+"jx.console.css");
572             this._main = document.createElement("div");
573             
574             this._main.id="JxConsole";
575             this._main.style.display="none";
576             this._main.className = "consoleBox";
577             this._main.innerHTML = this._html;
578             window.document.body.appendChild(this._main);
579             var w = $D.getClientWidth(),
580                 h = $D.getClientHeight(),
581                 w1 = 300,
582                 h1 = 310,
583                 l = w - 210 - w1,
584                 t = h - 50 - h1; 
585             $D.setStyle(this._main,"top",t+"px");
586             $D.setStyle(this._main,"left",l+"px");
587             
588             
589             this._headEl = $("ConsoleBoxHead");
590             this._inputEl = $("ConsoleInput");
591             this._closeButtonEl = $("ConsoleCloseButton");
592             this._clsButtonEl = $("ConsoleClearButton");
593             this._refreshButtonEl = $("ConsoleRefreshButton");
594             this._helpButtonEl = $("ConsoleHelpButton");
595             this._outputEl = $("ConsoleOutput");
596             this._consoleMainEl = $("consoleMain");
597             if(J.ui && J.ui.Drag){
598                 new J.ui.Drag(this._headEl,this._main);
599             }
600     
601             // 绑定方法
602             $E.on(this._inputEl, "keyup", J.bind(this.onInputKeyup,this));
603             $E.on(this._clsButtonEl, "click", J.bind(this.clear,this));
604             $E.on(this._refreshButtonEl, "click", J.bind(this.refresh,this));
605             $E.on(this._helpButtonEl, "click", J.bind(this.help,this));
606             $E.on(this._closeButtonEl, "click", J.bind(this.hide,this));
607             
608             
609             //mobileSafari下控制台滚动条
610             var options = {
611                 hScrollbar: true,
612                 vScrollbar: true,
613                 checkDOMChanges: false,
614                 desktopCompatibility: true
615             };
616             
617             if(J.browser.mobileSafari){
618                 if(J.ui && J.ui.iScroll && !this.consoleScroller){
619                     this.consoleScroller = new J.ui.iScroll(this._outputEl, options);
620                     //$D.setStyle(this._outputEl,"overflow","");
621                     J.debug("!!!!2", "console");
622                 }
623             }
624 
625             
626             this._isCreated = true;
627             
628             
629             
630             
631         },
632         
633         handleDocumentKeydown: function(e){
634             switch(e.keyCode){
635                 case 192:   // `~键:192
636                     if(e.ctrlKey&&e.shiftKey){
637                         
638                         this.toggleShow();
639                         e.preventDefault();
640                     }
641                     break;
642                 default: break;
643             }
644         },
645         
646         focusCommandLine: function(){
647             this._inputEl.focus();
648         },
649         /**
650          * 控制台开关
651          */
652         toggleShow:function(){
653             if(this._opened){
654                 this.hide();
655                 
656                 //J.option.debug = J.DEBUG.NO_DEBUG;
657             }else{
658                 this.show();
659                 //J.option.debug = J.DEBUG.SHOW_ALL;
660                 
661             }
662             
663         },
664         
665         /**
666          * 控制台记录信息
667          * 
668          * @param {String} msg 要输出的信息
669          * @param {Number} type 要输出的信息的类型,可选项
670          * @return {String} 返回要输出的信息
671          */
672         outConsoleShow:function(msg, type){
673             this.outConsole(msg, type);
674             
675             if ((!this._opened) && J.option.console) {
676                 this.show();
677             }
678         },
679         
680         /**
681          * 向控制台输出信息并显示
682          * 
683          * @param {String} msg 要输出的信息
684          * @param {Number} type 要输出的信息的类型,可选项
685          * @return {String} 返回要输出的信息
686          */
687         outConsole: function(log) {
688             if(this._opened){
689                 var _item = document.createElement("li");
690                 this._outputEl.appendChild(_item);
691                 
692                 var _ti = J.console._typeInfo[log.type] || J.console._typeInfo[0];
693                 var template = this._templateArr[this._templateType];
694                 _item.className = _ti[0];
695                 _item.innerHTML = '<div class="log_icon" title="'+_ti[0]+'">' + _ti[1] + '</div><div class="log_text">' + log.toString(true,template)+'</div>';
696                 if(this.consoleScroller){
697                     this.consoleScroller.refresh();
698                 }
699                 this._consoleMainEl.scrollTop = this._consoleMainEl.scrollHeight;
700             }
701         },
702         /**
703          * 往控制台打印
704          * @param {String} html 打印的信息
705          */
706         print : function(html){
707             var _item = document.createElement("li");
708             this._outputEl.appendChild(_item);
709             _item.innerHTML = html;
710             this._consoleMainEl.scrollTop = this._consoleMainEl.scrollHeight;
711         },
712         /**
713          * 向控制台输出信息的方法,通过url里面的consolefilter参数可以控制tag输出
714          * 
715          * @param {String} msg 要输出的信息
716          * @param {String} tag 自定义标签
717          * @param {Number} type 要输出的信息的类型,可选项
718          * @return {String} 返回要输出的信息
719          */
720         out:function(msg,tag,type){ 
721             //type = J.isUndefined(type)?0:type;
722             var template = this._templateArr[this._templateType];
723             var log = new Log({
724                         msg : msg,
725                         tag : tag,
726                         type : type
727                     });
728             this.logRecord(log);
729             //如果需要过滤显示的话需要特殊处理
730             if(query&&query.consolefilter){
731                 var consolefilter = query.consolefilter;
732                 if(log.tag == consolefilter){
733                     if(!this.isCustomConsole){
734                         topNamespace.console.log(log.toString(false,template));
735                     }else{
736                         this.outConsole(log);
737                     }
738                 }
739             }else{
740                 if(!this.isCustomConsole){
741                     topNamespace.console.log(log.toString(false,template));
742                 }else{
743                     this.outConsole(log);
744                 }
745             }
746         },
747         /**
748          * 关键日志正常输出
749          * @param {String} msg 输出的日志
750          * @tag {String} tag 日志标志,默认为system
751          */
752 
753         profile : function(msg,tag){
754             var type = 0;
755             tag = tag||"system";
756             this.out(msg,tag,type);
757         },
758         /**
759          * 关键日志警告输出
760          * @param {String} msg 输出的日志
761          * @tag {String} tag 日志标志,默认为system
762          */
763 
764         warn : function(msg,tag){
765             var type = 1;
766             this.out(msg,tag,type);
767         },
768         /**
769          * 关键日志错误输出
770          * @param {String} msg 输出的日志
771          * @tag {String} tag 日志标志,默认为system
772          */
773 
774         error : function(msg,tag){
775             var type = 2;
776             this.out(msg,tag,type);
777         },
778         /**
779          * 日志灌水输出
780          * @param {String} msg 输出的日志
781          * @tag {String} tag 日志标志,默认为system
782          */
783 
784         info : function(msg,tag){
785             var type = 3;
786             this.out(msg,tag,type);
787         },
788         /**
789          * 日志调试输出
790          * @param {String} msg 输出的日志
791          * @tag {String} tag 日志标志,默认为system
792          */
793 
794         debug : function(msg,tag){
795             var type = 4;
796             this.out(msg,tag,type);
797         },
798         /**
799          * 设置debug类型,是firebug or custom
800          */
801         setToDebug:function(){
802             if(query.console&&query.console == "firebug"){
803                 this.isCustomConsole = false;
804             }else{
805                 this.isCustomConsole = true;
806             }
807         },
808         /**
809          * 关闭out输出
810          */
811         setToNoDebug:function(){
812             this.out = J.emptyFunc;
813         },
814         /**
815          * log记录,当有query.console的时候,不限记录数量,没有时限制最大数量
816          * @param {Log} log 日志对象
817          */
818         logRecord: function(log){
819             this._log_record.push(log);
820             if(!query.console){
821                 if(this._log_record.length>this._maxLength){
822                     this._log_record.shift();   
823                 }
824             }
825         },
826         /**
827          * 设置模版类型
828          * @param {Number} temp 模版类型
829          */
830         setTemplate : function(temp){
831             if(this._templateArr[temp]){
832                 this._templateType = temp;
833             }
834         },
835         /**
836          * 过滤输出,支持正则,不区分大小写
837          * @param {RegExp} s 过滤的字符活正则
838          * @return {String} 过滤后的结果
839          */
840         filter : function(s){
841             var reg = new RegExp(s,"i");
842             var result = [];
843             var logArr = this._log_record;
844             J.array.forEach(logArr,function(log){
845                 var logStr = log.toString(true);
846                 if(reg.test(logStr)){
847                     result.push(log);
848                 }
849             });
850             return result;
851         },
852         /**
853          * 过滤type
854          * @param {Array} logArr 日志数组
855          * @param {Number} type 类型
856          * @return {Array} logArr 匹配的日志数组
857          */
858         filterByType : function(logArr,type){
859             var result = [];
860             logArr = logArr||[];
861             J.array.forEach(logArr,function(log){
862                 var isFound = false;
863                 J.array.forEach(type,function(i){
864                     if(log.type == i){
865                         isFound = true;
866                     }
867                 });
868                 if(isFound){
869                     result.push(log);
870                 }
871             });
872             return result;
873         },
874         /**
875          * 过滤tag
876          * @param {Array} logArr 日志数组
877          * @param {String} tag 类型
878          * @return {Array} logArr 匹配的日志数组
879          */
880         filterByTag : function(logArr,tag){
881             var result = [];
882             logArr = logArr||[];
883             J.array.forEach(logArr,function(log){
884                 var isFound = false;
885                 J.array.forEach(tag,function(i){
886                     if(log.tag == i){
887                         isFound = true;
888                     }
889                 });
890                 if(isFound){
891                     result.push(log);
892                 }
893             });
894             return result;
895         },
896         /**
897          * 过滤Msg
898          * @param {Array} logArr 日志数组
899          * @param {String} msg 类型
900          * @return {Array} logArr 匹配的日志数组
901          */
902         filterByMsg : function(logArr,msg){
903             var result = [];
904             logArr = logArr||[];
905             J.array.forEach(logArr,function(log){
906                 var isFound = false;
907                 J.array.forEach(msg,function(i){
908                     if(log.msg.indexOf(i)>-1){
909                         isFound = true;
910                     }
911                 });
912                 if(isFound){
913                     result.push(log);
914                 }
915             });
916             return result;
917         },
918         /**
919          * 获取日志报告
920          * @author tealin
921          * @param {Int|Array} type 需要报告的类型,多选时用数组表示
922          * @param {String|Array} tag 需要报告的标志,多选时用数组表示
923          * @param {String|Array} msg 需要报告筛选的信息,多选时用数组表示
924          * @return {String} log 日志对象
925          */
926         getReport : function(type,tag,msg){
927             var result = [];
928             var logArr = this._log_record;
929             var context = this;
930             
931             //格式化各个参数
932             if(!type||type == ""){
933                 type = false;
934             }else if(!J.isArray(type)){
935                 type = [type];
936             }
937             if(!tag||tag == ""){
938                 tag = false;
939             }else if(!J.isArray(tag)){
940                 tag = [tag];
941             }
942             if(!msg||msg == ""){
943                 msg = false;
944             }else if(!J.isArray(msg)){
945                 msg = [msg];
946             }
947             if(type){
948                 logArr = this.filterByType(logArr,type);
949             }
950             if(tag){
951                 logArr = this.filterByTag(logArr,tag);
952             }
953             if(msg){
954                 logArr = this.filterByMsg(logArr,msg);
955             }
956             J.array.forEach(logArr,function(log){
957                 result.push(log.toString(false,context._templateArr[1]));
958                 
959             });
960             return result.join(",");
961         },
962         /**
963          * 渲染log列表
964          * @author tealin
965          */
966         render : function(logArr,isShowAll){
967             var num = 15;
968             var logArr = logArr||this._log_record;
969             if(!isShowAll){
970                 logArr = logArr.slice(-num);
971             }
972             var context = this;
973             //避免重复
974             context.clear();
975             J.array.forEach(logArr,function(log){
976                 context.outConsole(log);
977             });
978         },
979         /**
980          * 清空log
981          */
982         clear : function(e) {
983             e && e.preventDefault();
984             J.console._outputEl.innerHTML = "";
985         },
986         /**
987          * 刷新控制台
988          */
989         refresh : function(e){
990             e && e.preventDefault();
991             this.clear();
992             this.render();
993         },
994         /**
995          * 显示帮助
996          */
997         help : function(e){
998             e && e.preventDefault();
999             var _rv = "<< Console Help >><br/>\
1000                                 help|h  : 控制台帮助<br/>\
1001                                 clear|cls : 清空控制台输出<br/>\
1002                                 refresh|r : 刷新控制台输出<br/>\
1003                                 filter|f : 过滤控制台输出<br/>\
1004                                 setTemplate|s : 设置输出模版类型<br/>\
1005                                 hide  : 隐藏控制台,或者使用 Ctrl+Shift+`[~] 快捷键";
1006             this.print(_rv);
1007         },
1008         onInputKeyup : function(e){
1009             switch(e.keyCode){
1010                 case 13://执行命令
1011                     this._cmd_history.push(J.console._inputEl.value);
1012                     this._cmd_last_index=this._cmd_history.length;
1013                     this._execCommand(J.console._inputEl.value);
1014                     break;
1015                 case 38://上一命令
1016                     if(this._cmd_history.length==0)return;
1017                     var s="";
1018                     if(this._cmd_last_index>0){
1019                         this._cmd_last_index--;
1020                         s=this._cmd_history[this._cmd_last_index];
1021                     }else{
1022                         this._cmd_last_index=-1;
1023                     }
1024                     J.console._inputEl.value=s;
1025                     break;
1026                 case 40://下一命令
1027                     if(this._cmd_history.length==0)return;
1028                     var s="";
1029                     if(this._cmd_last_index<this._cmd_history.length-1){
1030                         this._cmd_last_index++;
1031                         s=this._cmd_history[this._cmd_last_index];
1032                     }else{
1033                         this._cmd_last_index=this._cmd_history.length;
1034                     }
1035                     J.console._inputEl.value=s;
1036                     break;
1037                 default:
1038                     break;
1039             }
1040         },
1041         /**
1042          * 执行命令
1043          * @param {String} cmd 命令
1044          */
1045         _execCommand : function(cmd) {
1046             // 控制台命令
1047             if(cmd == "help"||cmd == "h"){
1048                 this.help();
1049             }else if(cmd == "clear"||cmd == "cls"){//清除控制台
1050                 J.console.clear();
1051             }else if(cmd == "hide"){//隐藏控制台
1052                 J.console.hide();
1053             }else if(cmd == "refresh"||cmd == "r"){
1054                 this.refresh();
1055             }else if(cmd == "showall"||cmd == "sa"){
1056                 this.clear();
1057                 this.render(null,true);
1058             }else if(new RegExp(/^(?:filter|f)(?:\(|\s+)(.+)(?:\)|\s*)$/i).test(cmd)){//过滤
1059                 var filterCmd = RegExp.$1;
1060                 var result = eval("this.filter('"+filterCmd+"')");
1061                 if(result.length>0){
1062                     this.render(result,true);
1063                 }else{
1064                     this.clear();
1065                     this.out("NO RESULT!",1);
1066                 }
1067             }else if(new RegExp(/^(?:setTemplate|s)(?:\(|\s+)(\d+)(?:\)|\s*)$/i).test(cmd)){
1068                 var temp = parseInt(RegExp.$1);
1069                 this.setTemplate(temp);
1070                 this.refresh();
1071             }else{//执行js脚本
1072                 this._execScript(cmd);
1073             }
1074             J.console._inputEl.value = "";
1075         },
1076         /**
1077          * 执行js代码
1078          * @param {String} cmd 代码
1079          */
1080         _execScript : function(cmd){
1081             var _rv = '<span style="color:#ccff00">' + cmd + '</span><br/>';
1082             try {
1083                 _rv += (eval(cmd) || "").toString().replace(/</g, "<").replace(/>/g, ">")
1084                 J.console.print(_rv, 0);
1085             } catch (e) {
1086                 _rv += e.description;
1087                 J.console.print(_rv, 1);
1088             }
1089         }
1090     });
1091     
1092 
1093     J.profile = J.console.profile;
1094     J.warn = J.console.warn;
1095     J.error = J.console.error;
1096     J.info = J.console.info;
1097     // log === info
1098     J.log = J.console.log = J.console.info;
1099     J.debug = J.console.debug;
1100     
1101     
1102     
1103     
1104     $E.onDomReady(function(){
1105         J.console._init();
1106         if(query.console == "true"){
1107             J.console=J.extend(J.console,{
1108                 'profile':J.emptyFunc,
1109                 'warn':J.emptyFunc,
1110                 'error':J.emptyFunc,
1111                 'info':J.emptyFunc,
1112                 'debug':J.emptyFunc
1113             });
1114             J.console.show();
1115             
1116         }
1117     });
1118     
1119     /**
1120      * runtime处理工具静态类
1121      * @ignore
1122      */
1123     J.runtime = (function() {
1124         /**
1125          * 是否debug环境
1126          * @ignore
1127          * @return {Boolean} 是否呢
1128          */
1129         function isDebugMode() {
1130             return (J.config.debugLevel > 0);
1131         }
1132     
1133         /**
1134          * log记录器
1135          * 
1136          * @ignore
1137          * @param {String} msg 信息记录器
1138          * @param {String} type log的类型
1139          */
1140         function log(msg, type) {
1141             var info;
1142             if (isDebugMode()) {
1143                 info = msg + '\n=STACK=\n' + stack();
1144             } else {
1145                 if (type == 'error') {
1146                     info = msg;
1147                 }// else if (type == 'warn') {
1148                     // TBD
1149                 //}
1150             }
1151             J.Debug.errorLogs.push(info);
1152         }
1153     
1154         /**
1155          * 警告信息记录
1156          * @ignore
1157          * @param {String} sf 信息模式
1158          * @param {All} args 填充参数
1159          */
1160         function warn(sf, args) {
1161             log(write.apply(null, arguments), 'warn');
1162         }
1163     
1164         /**
1165          * 错误信息记录
1166          * @ignore
1167          * @param {String} sf 信息模式
1168          * @param {All} args 填充参数
1169          */
1170         function error(sf, args) {
1171             log(write.apply(null, arguments), 'error');
1172         }
1173     
1174         /**
1175          * 获取当前的运行堆栈信息
1176          * @ignore
1177          * @param {Error} e 可选,当时的异常对象
1178          * @param {Arguments} a 可选,当时的参数表
1179          * @return {String} 堆栈信息
1180          */
1181         function stack(e, a) {
1182             /**
1183              * @ignore
1184              */
1185             function genTrace(ee, aa) {
1186                 if (ee.stack) {
1187                     return ee.stack;
1188                 } else if (ee.message.indexOf("\nBacktrace:\n") >= 0) {
1189                     var cnt = 0;
1190                     return ee.message.split("\nBacktrace:\n")[1].replace(/\s*\n\s*/g, function() {
1191                         cnt++;
1192                         return (cnt % 2 == 0) ? "\n" : " @ ";
1193                     });
1194                 } else {
1195                     var entry = (aa.callee == stack) ? aa.callee.caller : aa.callee;
1196                     var eas = entry.arguments;
1197                     var r = [];
1198                     for (var i = 0, len = eas.length; i < len; i++) {
1199                         r.push((typeof eas[i] == 'undefined') ? ("<u>") : ((eas[i] === null) ? ("<n>") : (eas[i])));
1200                     }
1201                     var fnp = /function\s+([^\s\(]+)\(/;
1202                     var fname = fnp.test(entry.toString()) ? (fnp.exec(entry.toString())[1]) : ("<ANON>");
1203                     return (fname + "(" + r.join() + ");").replace(/\n/g, "");
1204                 }
1205             }
1206     
1207             var res;
1208     
1209             if ((e instanceof Error) && (typeof arguments == 'object') && (!!arguments.callee)) {
1210                 res = genTrace(e, a);
1211             } else {
1212                 try {
1213                     ({}).sds();
1214                 } catch (err) {
1215                     res = genTrace(err, arguments);
1216                 }
1217             }
1218     
1219             return res.replace(/\n/g, " <= ");
1220         }
1221     
1222         return {
1223             /**
1224              * 获取当前的运行堆栈信息
1225              * @ignore
1226              * @param {Error} e 可选,当时的异常对象
1227              * @param {Arguments} a 可选,当时的参数表
1228              * @return {String} 堆栈信息
1229              */
1230             stack : stack,
1231             /**
1232              * 警告信息记录
1233              * @ignore
1234              * @param {String} sf 信息模式
1235              * @param {All} args 填充参数
1236              */
1237             warn : warn,
1238             /**
1239              * 错误信息记录
1240              * @ignore
1241              * @param {String} sf 信息模式
1242              * @param {All} args 填充参数
1243              */
1244             error : error,
1245             
1246             /**
1247              * 是否调试模式
1248              * @ignore
1249              */
1250             isDebugMode : isDebugMode
1251         };
1252     
1253     })();
1254 
1255 });
1256 
1257 
1258 
1259 
1260 
1261 
1262 
1263 
1264 
1265 
1266 
1267 
1268 
1269 
1270