123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275 |
- window.Tracker = window.Tracker || {};
- Tracker.View = (function( window ){
- var global, host, location, push, join, version;
- version = "1.8.9";
- global = window;
- host = global.document;
- location = global.location;
- var View = function(){
- return {
- templates: {
- url: Tracker.Util.tmpl( "<a href='<%= url %>' target='_blank'><%= url %></a>" ),
- frameset: Tracker.Util.tmpl( [
- "<!DOCTYPE html>",
- "<html>",
- "<head>",
- "<meta charset='<%= charset %>'>",
- "<meta name='description' content='fehelper-tracker-frame'>",
- "<title><%= title %></title>",
- "<style type='text/css'>",
- "html, body{ margin: 0; padding: 0; overflow: hidden; width: 100%; height: 100%; position: relative; }",
- ".fullness{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; }",
- "#tracker_proxy {display:none;}",
- "#wrapper{}",
- "#tracker_controller_ct{ z-index: 10; }",
- "#tracker_page_ct{ top: 43px; z-index: 20; background-color: #fff; }",
- "body.control-power-mode #tracker_page_ct{ z-index: 0; }",
- "body.hidden-page-mode #tracker_page_ct{ display: none; }",
- "iframe{ border: 0; width: 100%; height: 100%; }",
- "</style>",
- "</head>",
- "<body>",
- "<div id='wrapper' class='fullness'>",
- "<div id='tracker_proxy'><input type=\"button\" id=\"btnTrackerProxy\"></div>",
- "<div id='tracker_controller_ct' class='fullness'><iframe src='about:blank' id='tracker_controller' name='tracker_controller' frameborder='no'></iframe></div>",
- "<div id='tracker_page_ct' class='fullness'><iframe src='<%= url %>' id='tracker_page' name='tracker_page' frameborder='no'></iframe></div>",
- "</div>",
- "</body>",
- "</html>"
- ].join( "" ) ),
- controllerPage: Tracker.Util.tmpl( [
- "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Frameset//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd'>",
- "<html>",
- "<head>",
- "<meta charset='<%= charset %>'>",
- "<meta name='author' content='dron'>",
- "<title>Tracker!</title>",
- "<link href='<%= trackerCss %>' type='text/css' rel='stylesheet' />",
- "</head>",
- "<body>",
- "<%= header %>",
- "<div class='main' id='main'>",
- "<ul id='pages' class='unstyled tab-content'>",
- "<% if( mode == 'embed' ){ %>",
- "<li class='tab-content-active target-web-page'></li>",
- "<% } %>",
- "<li class='<%= mode == 'embed' ? '' : 'tab-content-active' %>'>",
- "<%= codeList %>",
- "<%= codeDetail %>",
- "</li>",
- "</ul>",
- "</div>",
- "<script> window.readyState = 'done'; </script>",
- "</body>",
- "</html>"
- ].join( "" ) ),
- controllerTopbar: Tracker.Util.tmpl( [
- "<div id='loading' class='navbar'>",
- "<div class='navbar-inner'>",
- "<span>请稍等,收集中...</span>",
- "<span id='waitTime'></span>",
- "</div>",
- "</div>",
- "<div id='top-navbar' class='navbar'>",
- "<div class='navbar-inner'>",
- '<a href="http://www.baidufe.com/feheler" target="_blank" class="fe-icon pull-left" action="frame#close">',
- '<img src="' + chrome.runtime.getURL('/static/img/fe-16.png') + '" alt="FeHelper">',
- "FeHelper:",
- '</a>',
- "<span class='fe-title'>Js覆盖面检测</span>",
- "<ul id='top-nav' class='nav pull-left' data-target='pages'>",
- "<% if( mode == 'embed' ){ %>",
- "<li><a href='' onclick='return false'>当前网页</a></li>",
- "<li data-name='code-list' class='active'><a href='' onclick='return false'>代码列表</a></li>",
- "<% }else{ %>",
- "<li class='active' data-name='code-list'><a href='' onclick='return false'>代码列表</a></li>",
- "<% } %>",
- "</ul>",
- "<ul class='nav pull-right'>",
- "<li class='dropdown'>",
- "<a href='' onclick='return false;' class='dropdown-toggle' data-toggle='dropdown'>",
- "视图切换",
- "<b class='caret'></b>",
- "</a>",
- "<ul class='dropdown-menu'>",
- "<li><a id='window-mode-trigger' action='frame#toggle' href='#' onclick='return false;'>单窗口模式</a></li>",
- "<li><a action='frame#close' href='#' onclick='return false;'>关闭控制台</a></li>",
- "</ul>",
- "</li>",
- "<li><a href='http://www.baidufe.com/fehelper/feedback.html' target='_blank'>意见反馈</a></li>",
- "</ul>",
- "</div>",
- "</div>",
- ].join( "" ) ),
- controllerCodeList: Tracker.Util.tmpl( [
- "<table class='table compact-width'>",
- "<thead>",
- "<tr>",
- "<th width='<%= widthIndex %>'>#</th>",
- "<th width='<%= widthName %>'>名称</th>",
- "<th width='<%= widthType %>'>类型</th>",
- "<th width='<%= widthCover %>'>执行覆盖</th>",
- "<th width='<%= widthCoverLine %>'>执行行数</th>",
- "<th width='<%= widthLines %>'>总行数</th>",
- "<th width='<%= widthSize %>'>原始大小</th>",
- "<th width='<%= widthBSize %>'>解压大小</th>",
- "<th width='<%= widthLoadConsum %>'>加载耗时</th>",
- "<th width='<%= widthRunConsum %>'>运行耗时</th>",
- "<th width='<%= widthRError %>'>执行报错</th>",
- "<th width='<%= widthSError %>'>语法错误</th>",
- "<th width='<%= widthState %>'>状态</th>",
- "<th width='*'> </th>",
- "</tr>",
- "</thead>",
- "</table>",
- "<div id='list-codes' class='scrollable'>",
- "<table class='table table-striped table-hover table-condensed'>",
- "<colgroup>",
- "<col width='<%= widthIndex %>'>",
- "<col width='<%= widthName %>'>",
- "<col width='<%= widthType %>'>",
- "<col width='<%= widthCover %>'>",
- "<col width='<%= widthCoverLine %>'>",
- "<col width='<%= widthLines %>'>",
- "<col width='<%= widthSize %>'>",
- "<col width='<%= widthBSize %>'>",
- "<col width='<%= widthLoadConsum %>'>",
- "<col width='<%= widthRunConsum %>'>",
- "<col width='<%= widthRError %>'>",
- "<col width='<%= widthSError %>'>",
- "<col width='<%= widthState %>'>",
- "</colgroup>",
- "<tbody id='list-codes-tbody'>",
- "</tbody>",
- "</table>",
- "</div>"
- ].join( "" ) ),
- controllerCodeDetail: Tracker.Util.tmpl( [
- "<div id='code-detail' class='absolute'>",
- "<div class='code-toolbar clearfix'>",
- "<ul class='code-toolbar-inner'>",
- "<li class='close-button-like'><button class='close' action='code#close'>×</button></li>",
- "<li class='tab-like'>",
- "<ul id='code-detail-head' class='nav nav-tabs' data-target='code-detail-body'>",
- "<li class='active'><a href='' onclick='return false;'>代码</a></li>",
- "<li><a href='' onclick='return false;'>信息</a></li>",
- "</ul>",
- "</li>",
- "<li class='label-like right tab-desc tab-desc-0'>新活动</li>",
- "<li class='image-like right tab-desc tab-desc-0'><div class='hooking image'></div></li>",
- "<li class='label-like right tab-desc tab-desc-0'>未执行</li>",
- "<li class='image-like right tab-desc tab-desc-0'><div class='unarrive image'></div></li>",
- "<li class='label-like right tab-desc tab-desc-0'>已执行</li>",
- "<li class='image-like right tab-desc tab-desc-0'><div class='arrive image'></div></li>",
- "<li class='label-like right tab-desc tab-desc-0'>图例:</li>",
- "</ul>",
- "</div>",
- "<ul class='unstyled tab-content' id='code-detail-body'>",
- "<li class='tab-content-active'>",
- "<div id='code-content' class='relative scrollable'></div>",
- "</li>",
- "<li class='scrollable'>",
- "<div id='code-info'></div>",
- "</li>",
- "</ul>",
- "</div>"
- ].join( "" ) ),
- controllerCodeInfo: Tracker.Util.tmpl( [
- "<dl class='group'>",
- "<dt>来源</dt>",
- "<dd><%= fileName %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>类型</dt>",
- "<dd><%= type %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>执行覆盖率</dt>",
- "<dd><%= rate %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>执行行数</dt>",
- "<dd><%= arriveRowsCount %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>总行数</dt>",
- "<dd><%= rowsCount %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>原始大小</dt>",
- "<dd><%= size %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>解压大小</dt>",
- "<dd><%= bsize %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>加载耗时</dt>",
- "<dd><%= loadConsum %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>运行耗时</dt>",
- "<dd><%= runConsum %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>执行报错</dt>",
- "<dd><%= rerror %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>语法错误</dt>",
- "<dd><%= serror %></dd>",
- "</dl>",
- "<dl class='group'>",
- "<dt>状态</dt>",
- "<dd><%= state %></dd>",
- "</dl>",
- ].join( "" ) ),
- codeListLine: Tracker.Util.tmpl( [
- "<tr data-code-id='<%= id %>'>",
- "<td><div class='ellipsisable' style='width: <%= widthIndex %>px;'><%= index %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthName %>px;'><%= fileName %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthType %>px;'><%= type %></div></td>",
- "<td><div id='code-<%= id %>-rate' class='ellipsisable' style='width: <%= widthCover %>px;'><%= rate %></div></td>",
- "<td><div id='code-<%= id %>-arriveRowsCount' class='ellipsisable' style='width: <%= widthCoverLine %>px;'><%= arriveRowsCount %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthLines %>px;'><%= rowsCount %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthSize %>px;'><%= size %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthBSize %>px;'><%= bsize %></div></td>",
- "<td><div id='code-<%= id %>-loadConsum' class='ellipsisable' style='width: <%= widthLoadConsum %>px;'><%= loadConsum %></div></td>",
- "<td><div id='code-<%= id %>-runConsum' class='ellipsisable' style='width: <%= widthRunConsum %>px;'><%= runConsum %></div></td>",
- "<td><div id='code-<%= id %>-runErrors' class='ellipsisable' style='width: <%= widthRError %>px;'><%= rerror %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthSError %>px;'><%= serror %></div></td>",
- "<td><div class='ellipsisable' style='width: <%= widthState %>px;'><%= state %></div></td>",
- "<td></td>",
- "</tr>"
- ].join( "" ) )
- },
- Loading: function(){
- var layer, span1, span2, animateTimer, count, progress, body;
- count = progress = 0;
- body = host.body;
- var create = function(){
- var span;
- layer = Tracker.Util.makeElement( "div", "position: fixed; padding: 30px; border: 1px solid rgba(255, 255, 255, .2); border-radius: 10px; background: #000; font-size: 20px; line-height: 20px; text-align: center; color: #fff; top: 50px; left: 50px; box-shadow: 0 0 5px #fff; z-index: 65535; font-family: 'Courier New', 'Heiti SC', 'Microsoft Yahei';" );
- layer.innerHTML = "正在分析网页 <span>...</span> <span>(0/0)</span>";
- body.appendChild( layer );
- host.documentElement.scrollTop = body.scrollTop = 0;
- span = layer.getElementsByTagName( "span" );
- span1 = span[0];
- span2 = span[1];
- };
- var animate = function(){
- var count, word, n, s, e;
- count = 0;
- word = "......";
- clearInterval( animateTimer );
- animateTimer = setInterval( function(){
- n = count % 7;
- s = word.substr( 0, n );
- e = word.substr( 0, 6 - n );
- span1.innerHTML = s + "<span style='color: #000;'>" +
- e + "</span>";
- count += 1;
- }, 100 );
- };
- return {
- show: function(){
- if( !layer )
- create();
- else
- layer.style.display = "block";
- animate();
- },
- hide: function(){
- if( layer )
- layer.style.display = "none";
- clearInterval( animateTimer );
- },
- text: function( text ){
- var me, pm;
- if( layer )
- layer.innerHTML = text;
- me = this;
- pm = new Tracker.Promise();
- clearInterval( animateTimer );
- setTimeout( function(){
- me.hide();
- pm.resolve();
- }, 2e3 );
- return pm;
- },
- addCount: function(){
- count ++;
- span2.innerHTML = "(" + ( progress / count * 100 ).toFixed( 2 ) + "%)";
- },
- addProgress: function(){
- progress ++;
- span2.innerHTML = "(" + ( progress / count * 100 ).toFixed( 2 ) + "%)";
- }
- }
- }(),
- ControlFrame: function(){
- var document = window.document, controlWindow, hasCreateEmbeded = false,
- currentMode = "embed", pageBuilder, controllerBuilder;
- var config = {
- windowWidth: 800,
- windowHeight: 600
- };
- var lookupForWindowReady = function( target ){
- var pm, timer, timer2, now, timeout, clear;
- pm = new Tracker.Promise();
- timeout = 5000;
- now = Tracker.Util.time();
- clear = function(){
- clearInterval( timer );
- clearTimeout( timer2 );
- };
- timer = setInterval( function(){
- if( target.readyState == "complete" ){
- clear();
- pm.resolve();
- }
- }, 10 );
- timer2 = setTimeout( function(){
- pm.reject();
- }, timeout );
- return pm;
- };
- return Tracker.Event.bind( {
- state: "preshow",
- pageBuilder: function( fn ){
- pageBuilder = fn;
- },
- controllerBuilder: function( fn ){
- controllerBuilder = fn;
- },
- show: function(){
- var controller, page, window;
- if( currentMode === "embed" ){
- controller = document.getElementById( "tracker_controller_ct" ),
- page = document.getElementById( "tracker_page_ct" ),
- controller.style.display = "block",
- page.style.top = "";
- }else if( currentMode === "window" ){
- window = this.getWindow( "tracker_controller" );
- if( window && !window.closed )
- window.focus();
- else
- this.createWindow();
- }
- this.state = "show";
- this.fire( "show" );
- },
- hide: function(){
- var controller, page;
- if( currentMode === "embed" )
- controller = document.getElementById( "tracker_controller_ct" ),
- page = document.getElementById( "tracker_page_ct" ),
- controller.style.display = "none",
- page.style.top = "0";
- else if( currentMode === "window" )
- controlWindow.close();
- this.state = "hide";
- this.fire( "hide" );
- },
- toggleMode: function(){
- this.removeControllerFrame();
- if( currentMode === "embed" )
- currentMode = "window",
- this.createWindow();
- else if( currentMode === "window" )
- currentMode = "embed",
- this.createEmbed(),
- this.show();
- },
- getMode: function(){
- return currentMode;
- },
- getWindow: function( name ){
- // name: tracker_main | tracker_page | tracker_controller
- var w;
- if( !arguments.length || name === "tracker_main" )
- return window;
- if( currentMode === "window" && name === "tracker_controller" )
- return controlWindow;
- else if( w = window.frames[ name ] )
- return window.document.getElementById( name ).contentWindow;
- },
- // privates
- createEmbed: function(){
- var page, controller;
- Tracker.Promise.when(
- hasCreateEmbeded ? [ controllerBuilder( "embed" ) ] :
- [ pageBuilder(), controllerBuilder( "embed" ) ]
- ).then( Tracker.Util.bind( function( pageHtml, controllerHtml ){
- if( !controllerHtml )
- controllerHtml = pageHtml,
- pageHtml = null;
- if( pageHtml ){
- window.name = "tracker_main";
- this.write( "tracker_main", View.templates.frameset( {
- url: location.href,
- title: document.title,
- charset: document.characterSet || "utf-8"
- } ) );
- this.write( "tracker_page", pageHtml );
- var pageWin = this.getWindow( "tracker_page" );
- // 整个页面都加载完成了,可以开始script inject了
- this.fire('pageLoad',window,pageWin);
- }
- this.write( "tracker_controller", controllerHtml );
- controller = this.getWindow( "tracker_controller" );
- lookupForWindowReady( controller.document ).then( Tracker.Util.bind( function(){
- this.fire( "controllerLoad", controller, controller.document );
- }, this ) );
- }, this ) );
- hasCreateEmbeded = true;
- },
- createWindow: function( conf ){
- var width = screen.width - 200, height = screen.height - 200,
- left = 100, top = 100, controller;
- controlWindow = window.open( "about:blank", "", "width=" + width +
- ", height=" + height + ", left=" + left + ", top=" + top +
- ", toolbar=no, menubar=no, resizable=yes, status=no, " +
- "location=no, scrollbars=yes" );
- controllerBuilder( "window" ).then( Tracker.Util.bind( function( html ){
- this.write( "tracker_controller", html );
- controller = this.getWindow( "tracker_controller" );
- lookupForWindowReady( controller.document ).then( Tracker.Util.bind( function(){
- this.fire( "controllerLoad", controller, controller.document );
- }, this ) );
- }, this ) );
- },
- removeControllerFrame: function(){
- this.hide();
- if( currentMode === "embed" )
- this.write( "tracker_controller", "about:blank" );
- else if( currentMode === "window" )
- controlWindow = null;
- },
- write: function( name, content ){
- var document, i, l, t, timer, write;
- document = this.getWindow( name ).document;
- document.open( "text/html", "replace" );
- if( name == "tracker_page" ){
- i = 0;
- t = 10240; // 10k/ms
- l = content.length;
- write = function(){
- c = content.substr( i, t );
- document.write( c );
- i += t;
- if( i > l )
- document.close(),
- clearInterval( timer );
- };
- timer = setInterval( write, 1 );
- }else{
- document.write( content );
- document.close();
- }
- }
- } );
- }(),
- ControlPanel: function(){
- var actions, window, document, currentSelectedCode, updateInterval, codeEl,
- codeIndex;
- actions = {};
- codeIndex = 0;
- var rate = function( code ){
- var r, c;
- r = code.arriveRowsCount / code.rowsCount * 100 || 0;
- c = r == 0 ? "stress" : "";
- return "<span class='" + c + "'>" + r.toFixed( 1 ) + "%</span>";
- };
- var size = function( number ){
- return ( number / 1024 ).toFixed( 1 ) + "k";
- };
- var yesno = function( bool ){
- return ( bool && bool.length ) ?
- "<span class='stress'>是<span>" : "否";
- };
- var state = function( state ){
- switch( state ){
- case "normal":
- return "正常";
- case "timeout":
- return "<span class='stress'>超时</span>";
- case "empty":
- return "<span class='stress'>无内容</span>";
- }
- };
- var type = function( code ){
- switch( code.type ){
- case "embed":
- return "内嵌";
- case "link":
- return "文件链接";
- case "append":
- return "动态插入";
- };
- };
- var time = function( time, s ){
- if( time == -1 )
- return "-1";
- if( !s )
- return time + "ms";
- else
- return ( time / 1000 ).toFixed( 2 ) + "s";
- };
- var width = function(){
- var mapping, offsets;
- mapping = {
- index: 30, name: 220, type: 90, cover: 60, "cover-line": 60, lines: 60,
- size: 60, bsize: 60, rerror: 60, serror: 60, state: 50, loadConsum: 60,
- runConsum: 60
- };
- offsets = {
- };
- return function( name, type ){
- return mapping[ name ] + ( offsets[ type ] || 0 );
- };
- }();
- var withWidths = function( data ){
- var widths = {
- widthIndex: width( "index" ),
- widthName: width( "name" ),
- widthType: width( "type" ),
- widthCover: width( "cover" ),
- widthCoverLine: width( "cover-line" ),
- widthLines: width( "lines" ),
- widthSize: width( "size" ),
- widthBSize: width( "bsize" ),
- widthRError: width( "rerror" ),
- widthSError: width( "serror" ),
- widthState: width( "state" ),
- widthLoadConsum: width( "loadConsum" ),
- widthRunConsum: width( "runConsum" )
- };
- if( !data )
- return widths;
- for( var i in widths )
- data[ i ] = widths[ i ];
- return data;
- };
- var codeTemplate = function( code ){
- return View.templates.codeListLine( withWidths( {
- id: code.id,
- index: ++ codeIndex,
- fileName: code.fileName,
- type: type( code ),
- rate: rate( code ),
- arriveRowsCount: code.arriveRowsCount,
- rowsCount: code.rowsCount,
- size: size( code.size ),
- bsize: size( code.beautifySize ),
- rerror: yesno( code.runErrors ),
- serror: yesno( code.syntaxErrors ),
- state: state( code.state ),
- runConsum: time( code.runConsum ),
- loadConsum: time( code.loadConsum )
- } ) );
- };
- var codeListTemplate = function( codeList ){
- var htmls;
- htmls = [];
- if( codeList.length ){
- Tracker.Util.forEach( codeList, function( code, index ){
- htmls[ index ] = codeTemplate( code );
- } );
- return htmls.join( "" );
- }else{
- return "<tr><td colspan='20'><div class='none'>该网页没有任何JS代码</div></td></tr>";
- }
- };
- var makeCodeTr = function( code ){
- var layer, html;
- layer = document.createElement( "tbody" );
- html = codeTemplate( code );
- layer.innerHTML = html;
- return layer.firstChild;
- };
- var asnyShowCode = function(){
- var timer, timeout, interval, prepare, partCount, nowIndex, init,
- currentDisposeLines, gutterEl, linesEl, regx1, regx2, ckeyIdRegx, result,
- linesCount, h1, h2, focusOnFlag, focusOnFlagTarget;
- timeout = 1;
- partCount = 100;
- regx1 = /\x00/g;
- regx2 = /\x01/g;
- ckeyIdRegx = /id=ckey-(\d+)/g;
- h1 = [];
- h2 = [];
- init = function(){
- nowIndex = 0;
- linesCount = 0;
- window.clearInterval( timer );
- };
- prepare = function(){
- var innerElId = Tracker.Util.id();
- var gutterId = Tracker.Util.id();
- var linesId = Tracker.Util.id();
- codeEl.innerHTML = "<div id='" + innerElId + "' class='block clearfix' " +
- "style='height: " + ( linesCount * 20 + 10 ) + "px;'>" +
- "<div id='" + gutterId + "' class='gutter'></div>" +
- "<div id='" + linesId + "' class='lines'></div></div>";
- codeEl.scrollTop = 0;
- gutterEl = document.getElementById( gutterId );
- linesEl = document.getElementById( linesId );
- };
- interval = function(){
- var t, p1, p2, a;
- h1.length = h2.length = 0;
- for( var i = 0; i < partCount; i ++ ){
- if( nowIndex >= linesCount ){
- init();
- break;
- }
- t = Tracker.Util.html( currentDisposeLines[ nowIndex ] ).replace( regx1, "<" )
- .replace( regx2, ">" );
- t = t.replace( ckeyIdRegx, function( all, id ){
- a = Tracker.StatusPool.arrivedSnippetGet( id );
- if( a & 2 )
- a = 2;
- else if( a & 1 )
- a = 1;
- if( focusOnFlag && !focusOnFlagTarget && focusOnFlag == a ){
- focusOnFlagTarget = id;
- focusOnFlag = 0;
- }
- return a ? all + " class='arrive arrive-" + a + "'" : all;
- } );
- h1.push( Tracker.Util.tag( nowIndex + 1, "pre" ) );
- h2.push( Tracker.Util.tag( t || " ", "pre" ) );
- nowIndex ++;
- }
- p1 = document.createElement( "div" );
- p2 = document.createElement( "div" );
- p1.innerHTML = h1.join( "" );
- p2.innerHTML = h2.join( "" );
- gutterEl.appendChild( p1 );
- linesEl.appendChild( p2 );
- if( focusOnFlagTarget ){
- document.getElementById( "ckey-" + focusOnFlagTarget ).scrollIntoView();
- focusOnFlagTarget = undefined;
- }
- };
- result = function( code, _focusOnFlag ){
- init();
- focusOnFlag = _focusOnFlag;
- if( code.state == "empty" ){
- codeEl.innerHTML = "<div class='empty-code'>" +
- "内容为空</div>"; // 内容为空
- }else if( code.state == "timeout" ){
- codeEl.innerHTML = "<div class='timeout-code'>" +
- "解析超时</div>"; // 解析超时
- }else{
- currentDisposeLines = code.linesViewHtml;
- linesCount = currentDisposeLines.length;
- prepare();
- timer = window.setInterval( interval, timeout );
- }
- };
- result.clear = init;
- return result;
- }();
- var setupBootstrapPatch = function(){
- var setupDropdownMenu = function(){
- var lastOpen;
- var setup = function( el ){
- var dropdownMenu = el.querySelector( ".dropdown-menu" );
- Tracker.Event.add( dropdownMenu, "click", function( e ){
- Tracker.Util.removeClass( el, "open" );
- lastOpen = null;
- e.stopPropagation();
- Tracker.TrackerGlobalEvent.fire( "bootstrap: dropdown.close" );
- } );
- Tracker.Event.add( el, "click", function( e ){
- Tracker.Util.addClass( el, "open" );
- if( lastOpen && lastOpen != el )
- Tracker.Util.removeClass( lastOpen, "open" );
- lastOpen = el;
- Tracker.TrackerGlobalEvent.fire( "bootstrap: dropdown.open" );
- e.stopPropagation();
- } );
- };
- return function(){
- var dropdowns = document.querySelectorAll( ".dropdown" );
- for( var i = 0, l = dropdowns.length; i < l; i ++ )
- setup( dropdowns[ i ] );
- Tracker.Event.add( document, "click", function(){
- var found;
- for( var i = 0, l = dropdowns.length; i < l; i ++ )
- if( Tracker.Util.hasClass( dropdowns[ i ], "open" ) )
- found = true,
- Tracker.Util.removeClass( dropdowns[ i ], "open" );
- if( found )
- Tracker.TrackerGlobalEvent.fire( "bootstrap: dropdown.close" );
- } );
- }
- }();
- var setupModalDialog = function(){
- var open = function( modal ){
- return function(){
- modal.style.display = "block";
- Tracker.TrackerGlobalEvent.fire( "bootstrap: dialog.open" );
- }
- };
- var close = function( modal ){
- return function(){
- modal.style.display = "none";
- Tracker.TrackerGlobalEvent.fire( "bootstrap: dialog.close" );
- }
- };
- var setup = function( modal ){
- var closeBtns = modal.querySelectorAll( ".modal-header .close, .modal-footer .btn" );
- var fclose = close( modal );
- var fopen = open( modal );
- for( var i = 0, l = closeBtns.length; i < l; i ++ )
- Tracker.Event.add( closeBtns[ i ], "click", fclose );
- modal.open = fopen;
- };
- return function(){
- var modals = document.querySelectorAll( ".modal" );
- for( var i = 0, l = modals.length; i < l; i ++ )
- setup( modals[ i ] );
- }
- }();
- var setupTab = function(){
- var setup = function( tab ){
- var target = tab.getAttribute( "data-target" );
- if( !target )
- return ;
- target = document.getElementById( target );
- var heads = tab.childNodes;
- var bodys = target.childNodes;
- tab.active = function( index ){
- Tracker.Util.removeClass( heads[ tab.actived ], "active" );
- Tracker.Util.removeClass( bodys[ tab.actived ], "tab-content-active" );
- Tracker.Util.addClass( heads[ index ], "active" );
- Tracker.Util.addClass( bodys[ index ], "tab-content-active" );
- tab.actived = index;
- tab.tabEvent.fire( "active",
- index, heads[ index ].getAttribute( "data-name" ) );
- };
- Tracker.Event.add( tab, "click", function( e ){
- var li;
- li = Tracker.Util.findParent( e.target, "li", this );
- Tracker.Util.forEach( this.childNodes, function( l, index ){
- if( li === l ){
- if( tab.actived == index )
- return ;
- tab.active( index );
- }
- } );
- } );
- tab.tabEvent = Tracker.Event.bind();
- tab.actived = 0;
- };
- return function(){
- var tabs = document.querySelectorAll( ".nav" );
- for( var i = tabs.length - 1; i >= 0; i -- )
- setup( tabs[ i ] );
- };
- }();
- return function(){
- setupDropdownMenu();
- setupModalDialog();
- setupTab();
- };
- }();
- var autoUpdateCodeFn = function(){
- Tracker.CodeList.each( function( code ){
- if( !code.lastUpdate || code.lastUpdate < code.lastModified )
- View.ControlPanel.updateCode( code );
- } );
- };
- return Tracker.Event.bind( {
- bindWindow: function( win ){
- window = win;
- document = window.document;
- codeEl = document.getElementById( "code-content" );
- },
- addCode: function( code ){
- var tbody, tr, index;
- if( !document )
- return ;
- tbody = document.getElementById( "list-codes-tbody" );
- index = Tracker.CodeList.count() - 1;
- if( code instanceof Array ){
- tbody.innerHTML = codeListTemplate( code );
- }else if( code instanceof Tracker.Code ){
- code.onReady( function(){
- // code.index = index;
- tr = makeCodeTr( code );
- tbody.appendChild( tr );
- } );
- }
- },
- showCodeDetail: function( id, focusOnFlag ){
- var codeDetailHeadTab, actived;
- codeDetailHeadTab = document.getElementById( "code-detail-head" );
- actived = codeDetailHeadTab.actived;
- currentSelectedCode = id || null;
- document.getElementById( "code-detail" ).style.display =
- id ? "block" : "none";
- if( id ){
- if( actived === 0 )
- this.showCode( id, focusOnFlag );
- else if( actived == 1 )
- this.showCodeInfo( id, focusOnFlag );
- var elementListCodes = document.getElementById( "list-codes" );
- var trs = elementListCodes.querySelectorAll( "tr" );
- Tracker.Util.forEach( trs, function( tr ){
- if( tr.getAttribute( "data-code-id" ) == id )
- Tracker.Util.addClass( tr, "info" );
- else
- Tracker.Util.removeClass( tr, "info" );
- } );
- }
- },
- showCode: function( id, focusOnFlag ){
- if( id ){
- code = Tracker.CodeList.get( id );
- asnyShowCode( code, focusOnFlag );
- }
- },
- showCodeInfo: function( id, focusOnFlag ){
- var elementCodeInfo, code;
- elementCodeInfo = document.getElementById( "code-info" );
- code = Tracker.CodeList.get( id );
- elementCodeInfo.innerHTML = View.templates.controllerCodeInfo( {
- // id: code.id,
- // index: ++ codeIndex,
- fileName: code.fullUrl ?
- View.templates.url( { url: code.fullUrl } ) :
- "来自页面",
- type: type( code ),
- rate: rate( code ),
- arriveRowsCount: code.arriveRowsCount,
- rowsCount: code.rowsCount,
- size: size( code.size ),
- bsize: size( code.beautifySize ),
- rerror: yesno( code.runErrors ),
- serror: yesno( code.syntaxErrors ),
- state: state( code.state ),
- loadConsum: time( code.loadConsum ),
- runConsum: time( code.runConsum )
- } );
- },
- updateCode: function( code ){
- if( currentSelectedCode == code.id )
- this.showCodeDetail( code.id );
- var rateEl, arriveRowsCountEl, runErrorsEl, runConsumEl, loadConsumEl;
- rateEl = document.getElementById( "code-" + code.id + "-rate" );
- arriveRowsCountEl = document.getElementById( "code-" + code.id +
- "-arriveRowsCount" );
- runErrorsEl = document.getElementById( "code-" + code.id + "-runErrors" );
- runConsumEl = document.getElementById( "code-" + code.id + "-runConsum" );
- loadConsumEl = document.getElementById( "code-" + code.id + "-loadConsum" );
- if( !rateEl )
- return;
- rateEl.innerHTML = rate( code );
- arriveRowsCountEl.innerHTML = code.arriveRowsCount;
- runErrorsEl.innerHTML = yesno( code.runErrors );
- runConsumEl.innerHTML = time( code.runConsum );
- loadConsumEl.innerHTML = time( code.loadConsum );
- code.lastUpdate = Tracker.Util.time();
- },
- autoUpdateCodeStart: function(){
- updateInterval = setInterval( autoUpdateCodeFn, 5e2 );
- },
- autoUpdateCodeStop: function(){
- clearInterval( updateInterval );
- },
- activeTab: function( name ){
- var topNav, baseIndex;
- topNav = document.getElementById( "top-nav" );
- baseIndex = 0;
- if( View.ControlFrame.getMode() == "embed" )
- baseIndex = 1;
- if( typeof name != "undefined" ){
- if( !topNav.active )
- return ;
- if( name == "code-list" )
- name = baseIndex + 0;
- topNav.active( name );
- }else{
- return topNav.actived;
- }
- },
- setControlPower: function( bool, hiddenPage ){
- var parent, window, b, c1, c2;
- if( View.ControlFrame.getMode() == "embed" ){
- parent = View.ControlFrame.getWindow( "tracker_main" );
- window = View.ControlFrame.getWindow( "tracker_controller" );
- c1 = bool ? Tracker.Util.addClass : Tracker.Util.removeClass;
- c2 = hiddenPage ? Tracker.Util.addClass : Tracker.Util.removeClass;
- b = parent.document.body;
- c1( b, "control-power-mode" );
- c2( b, "hidden-page-mode" );
- }
- },
- actions: function( acts ){
- for( var name in acts )
- actions[ name ] = acts[ name ];
- },
- htmlBuilder: function(){
- var pm = new Tracker.Promise(), mode;
- codeIndex = 0;
- mode = View.ControlFrame.getMode();
- Tracker.Util.delay( function(){
- pm.resolve( View.templates.controllerPage( withWidths( {
- charset: global.document.characterSet || "utf-8",
- trackerCss: chrome.runtime.getURL('/static/css/js-tracker.css'),
- header: View.templates.controllerTopbar( {
- mode: mode
- } ),
- codeList: View.templates.controllerCodeList( withWidths() ),
- codeDetail: View.templates.controllerCodeDetail(),
- mode: mode,
- version: version,
- uid: host.tracker_uid
- } ) ) );
- } );
- return pm;
- },
- eventBuilder: function(){
- var me = this;
- var elementListCodes = document.getElementById( "list-codes" );
- var elementCodeDetail = document.getElementById( "code-detail" );
- var elementCodeToolbarInner = document.querySelector( ".code-toolbar-inner" );
- var elementCodeDetailHead = document.getElementById( "code-detail-head" );
- var elementCodeContent = document.getElementById( "code-content" );
- var tr, focusInList;
- var tabDescRegx = /tab-desc-(\d+)/;
- Tracker.Event.add( elementListCodes, {
- click: function( e ){
- var codeId;
- if( tr = Tracker.Util.findParent( e.target, "tr", elementListCodes ) )
- if( codeId = tr.getAttribute( "data-code-id" ) )
- focusInList = true,
- codeId == currentSelectedCode ||
- View.ControlPanel.showCodeDetail( codeId );
- }
- } );
- Tracker.Event.add( elementCodeDetail, {
- click: function(){
- focusInList = false;
- }
- } );
- Tracker.Event.add( document, {
- mouseup: function( e ){
- var action;
- if( ( action = e.target.getAttribute( "action" ) ) &&
- actions[ action ] )
- actions[ action ].call( me, e.target );
- },
- keydown: function( e ){
- var selectId;
- // command + R, F5
- if( ( e.metaKey && e.keyCode == 82 ) || e.keyCode == 116 ){
- if( View.ControlFrame.getMode() == "window" ){
- e.preventDefault && e.preventDefault();
- }
- }
- if( focusInList && currentSelectedCode ){
- var offset = 0;
- if( e.keyCode == 38 ){ // up
- offset = -1;
- }else if( e.keyCode == 40 ){ // down
- offset = 1;
- }
- if( offset ){
- var trs = elementListCodes.querySelectorAll( "tr" ),
- nowIndex = -1, tr;
- for(var i = 0, l = trs.length; i < l; i ++){
- if( trs[i].getAttribute( "data-code-id" ) ==
- currentSelectedCode ){
- nowIndex = i;
- break;
- }
- }
- if( nowIndex > -1 ){
- nowIndex = ( nowIndex += offset ) < 0 ?
- 0 : nowIndex == trs.length ?
- nowIndex - 1 : nowIndex;
- tr = trs[ nowIndex ];
- selectId = tr.getAttribute( "data-code-id" );
- if( currentSelectedCode != selectId )
- View.ControlPanel.showCodeDetail( selectId );
- e.preventDefault && e.preventDefault();
- }
- }
- }
- }
- // mousewheel: function( e ){
- // e.preventDefault();
- // }
- } );
- if( !actions[ "code#close" ] ){
- actions[ "code#close" ] = function( e ){
- focusInList = true;
- View.ControlPanel.showCodeDetail( false );
- };
- }
- if( View.ControlFrame.getMode() == "window" )
- document.getElementById( "window-mode-trigger" ).innerHTML = "内嵌模式";
- var lastScrollLeft = 0;
- Tracker.Event.add( elementCodeContent, {
- scroll: function( e ){
- if( this.scrollLeft == 0 )
- this.scrollLeft = 1;
- if( this.scrollLeft == this.scrollWidth - this.clientWidth )
- this.scrollLeft -= 1;
- if( lastScrollLeft == this.scrollLeft )
- return ;
- var gutter = this.querySelector( ".gutter" );
- gutter.style.left = this.scrollLeft + "px";
- lastScrollLeft = this.scrollLeft;
- }
- } );
- setupBootstrapPatch();
- elementCodeDetailHead.tabEvent.on( "active", function( index ){
- if( this.currentShown != currentSelectedCode ){
- this.currentShown = currentSelectedCode;
- if( index == 0 )
- View.ControlPanel.showCode( currentSelectedCode );
- else if( index == 1 )
- View.ControlPanel.showCodeInfo( currentSelectedCode );
- }
- var tabDescs = elementCodeToolbarInner.querySelectorAll( ".tab-desc" );
- Tracker.Util.forEach( tabDescs, function( tabDesc ){
- tabDescRegx.test( tabDesc.className );
- tabDesc.style.display = RegExp.$1 == index ? "" : "none";
- } );
- } );
- if( currentSelectedCode )
- this.showCodeDetail( currentSelectedCode );
- }
- } );
- }()
- }
- }();
- return View;
- })(this);
|