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