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( "<%= url %>" ),
frameset: Tracker.Util.tmpl( [
"",
"",
"
",
"",
"",
"<%= title %>",
"",
"",
"",
"",
"",
""
].join( "" ) ),
controllerPage: Tracker.Util.tmpl( [
"",
"",
"",
"",
"",
"Tracker!",
"",
"",
"",
"<%= header %>",
"",
"
",
"<% if( mode == 'embed' ){ %>",
"",
"<% } %>",
"- '>",
"<%= codeList %>",
"<%= codeDetail %>",
"
",
"
",
"
",
"",
"",
""
].join( "" ) ),
controllerTopbar: Tracker.Util.tmpl( [
"",
"
",
"请稍等,收集中...",
"",
"
",
"
",
"",
"
",
'
',
'
',
"FeHelper:",
'',
"
Js覆盖面检测",
"
",
"<% if( mode == 'embed' ){ %>",
"- 当前网页
",
"- 代码列表
",
"<% }else{ %>",
"- 代码列表
",
"<% } %>",
"
",
"
",
"
",
"
",
].join( "" ) ),
controllerCodeList: Tracker.Util.tmpl( [
"",
"",
"",
"| # | ",
"名称 | ",
"类型 | ",
"执行覆盖 | ",
"执行行数 | ",
"总行数 | ",
"原始大小 | ",
"解压大小 | ",
"加载耗时 | ",
"运行耗时 | ",
"执行报错 | ",
"语法错误 | ",
"状态 | ",
" | ",
"
",
"",
"
",
""
].join( "" ) ),
controllerCodeDetail: Tracker.Util.tmpl( [
"",
"
",
"
",
"- ",
"",
"
",
"- ",
"",
"
",
"
",
"
"
].join( "" ) ),
controllerCodeInfo: Tracker.Util.tmpl( [
"",
"- 来源
",
"- <%= fileName %>
",
"
",
"",
"- 类型
",
"- <%= type %>
",
"
",
"",
"- 执行覆盖率
",
"- <%= rate %>
",
"
",
"",
"- 执行行数
",
"- <%= arriveRowsCount %>
",
"
",
"",
"- 总行数
",
"- <%= rowsCount %>
",
"
",
"",
"- 原始大小
",
"- <%= size %>
",
"
",
"",
"- 解压大小
",
"- <%= bsize %>
",
"
",
"",
"- 加载耗时
",
"- <%= loadConsum %>
",
"
",
"",
"- 运行耗时
",
"- <%= runConsum %>
",
"
",
"",
"- 执行报错
",
"- <%= rerror %>
",
"
",
"",
"- 语法错误
",
"- <%= serror %>
",
"
",
"",
"- 状态
",
"- <%= state %>
",
"
",
].join( "" ) ),
codeListLine: Tracker.Util.tmpl( [
"",
"<%= index %> | ",
"<%= fileName %> | ",
"<%= type %> | ",
"<%= rate %> | ",
"<%= arriveRowsCount %> | ",
"<%= rowsCount %> | ",
"<%= size %> | ",
"<%= bsize %> | ",
"<%= loadConsum %> | ",
"<%= runConsum %> | ",
"<%= rerror %> | ",
"<%= serror %> | ",
"<%= state %> | ",
" | ",
"
"
].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 = "正在分析网页 ... (0/0)";
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 + "" +
e + "";
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 "" + r.toFixed( 1 ) + "%";
};
var size = function( number ){
return ( number / 1024 ).toFixed( 1 ) + "k";
};
var yesno = function( bool ){
return ( bool && bool.length ) ?
"是" : "否";
};
var state = function( state ){
switch( state ){
case "normal":
return "正常";
case "timeout":
return "超时";
case "empty":
return "无内容";
}
};
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 "该网页没有任何JS代码 |
";
}
};
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 = "";
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 = "" +
"内容为空
"; // 内容为空
}else if( code.state == "timeout" ){
codeEl.innerHTML = "" +
"解析超时
"; // 解析超时
}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);