watch.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /**
  2. * Watch Plugin
  3. * @version 1.0
  4. * @author dron
  5. * @create 2013-05-07
  6. */
  7. Tracker.setupWatchPlugin = function(){
  8. Tracker.Plugins.addOn( "watch", function(){
  9. var tmpl, template, window, document, log, time, startBtnId, stopBtnId, clearBtnId,
  10. stateId, logerId, started, buttonEventBind, stateEvent, start, stop, clear, hooking,
  11. originalArrivedSnippetGroupFlag, buttonEnable, activeCodeCache, eventBuild,
  12. original__tracker__, new__tracker__, showState, arrivedSnippetGroupCache,
  13. buttonStateChange, logHtml;
  14. tmpl = Tracker.Util.tmpl;
  15. arrivedSnippetGroupCache = {};
  16. stateEvent = Tracker.Event.bind( {} );
  17. time = function( date ){
  18. var t = [ date.getHours(), date.getMinutes(), date.getSeconds() ].join( ":" );
  19. t = t.replace( /\b(\d)\b/g, "0$1" );
  20. return t;
  21. };
  22. Tracker.Plugins.addStyle( [
  23. ".red-dot{ display: inline; margin-left: 2px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACvElEQVQ4ja2T30uaYRTHT7W61ULDzFez1BaKYslkF7MfmNaVpLCbqOwNohiyGSuCzLUWBrpCWrTRUiIi2IgVW60NuqiNYbZs/bD8Vc5aqy3a3/Ds1MXcWFdjB76c9z3POZ/n+7w8L8D/jBQUC6VITQVNejqUZ2RAGeYyzKq0NOClpEAGrl0aV1DnTS0MBtzjcOAhRcFjoRCeoNwCATh4POjA+k2UFGt/hRyHb2dmwkBeHli4XJaVyWxz8PnPHBT1vA2f71IUa/TqVRgoKoKuigq4rlYnhykWC2gcduIuDQzGtVmx+MtmeTnZNRpJsKqKrKtU5KVYfNQlld6YVCrBo9PBo56eJEAjkYAdLd9is7NmhMLEtk5HDvv6SMJuJ/tWK4mYzWRNKiXzhYVHXoOB9wIBy6OjSYCxpATcIhF0UFT7mkx2MRCjaRKtqyNhk4ns6PVkQ60mfj6fzNXVPXhbWQlrvwNorRYmi4vBq1K98mVnk6BGQ8J4hMh5xsEgQtcpiviYTLJqNi99qK6G4MREEnDHZIJ5vR5mtNo3/qwsspmTQ8IFBSSWn09iuGsI37fYbPIR19ZpejlgNEJ8ejoJuN/cDO/r6+GdxeL4xOORHXSxl5tLDgQCcojax1qIwyEbXC7ZsdudW42NcLywkAQM9fZCoL0dEh6P2KdUnoaxMYE7f0MX30WiC0gEgSty+elX7Nm1WuFHIJAE9NjtsOfxwG5LC8Td7hq/XH4WR/vHqBOEJDD7ZbKzz4ODNSGahj2XC1YWF5MAAd60w9VViPX3Q6S1FY69Xkmou9u13dCwHESFbDbXiccjiTY1QdRmg9OlJTAYDH/eRIVCAQc+HyTGxiCGjqIWC4TxrGH8NlGExjo7IT40BGfYU19be/n/cO5kwOmE11NTMDsyArPDw780Nz4OT7FWWlp6+fC/xk/27ybygyy2GgAAAABJRU5ErkJggg==) no-repeat center center; }",
  24. "#code-content .lines .arrive-2{ background-color: #ffba93; color: #000; }",
  25. "#plugin-watch-page{ }",
  26. "#plugin-watch-page .header{ height: 126px; background-color: #fafafa; border-bottom: 1px solid #d5d5d5; }",
  27. "#plugin-watch-page .header .title{ line-height: 42px; padding-left: 30px; }",
  28. "#plugin-watch-page .header .control{ padding-left: 30px; height: 42px; }",
  29. "#plugin-watch-page .header .control .btn{ margin-right: 5px; }",
  30. "#plugin-watch-page .header .state{ padding-left: 30px; line-height: 42px; color: #666; }",
  31. "#plugin-watch-page .header .state .text{ }",
  32. "#plugin-watch-page .body{ position: absolute; left: 0; right: 0; top: 127px; bottom: 0; padding: 10px; background-color: #1d1e1a; }",
  33. "#plugin-watch-page .body .logger{ line-height: 20px; color: #f6f6f6; }",
  34. "#plugin-watch-page .body .logger .line{ }",
  35. "#plugin-watch-page .body .logger .line .time{ display: inline-block; width: 80px; }",
  36. "#plugin-watch-page .body .logger .line .content{ }"
  37. ].join( "" ) );
  38. template = {
  39. page: tmpl( [
  40. "<div class='header'>",
  41. "<div class='title'>点击开始监控,即可发现从监控开始到监控结束之间活动的代码</div>", // TODO: unicode
  42. "<div class='control'>",
  43. "<button id='<%= startBtnId %>' class='btn'>开始监控</button>",
  44. "<button id='<%= stopBtnId %>' class='btn disabled'>停止监控</button>",
  45. "<button id='<%= clearBtnId %>' class='btn disabled'>清除结果</button>",
  46. "</div>",
  47. "<div class='state' id='<%= stateId %>'>",
  48. "<%= stateHtml %>",
  49. "</div>",
  50. "</div>",
  51. "<div class='body scrollable'>",
  52. "<div class='logger' id='<%= logerId %>'>",
  53. "</div>",
  54. "</div>"
  55. ].join( "" ) ),
  56. state: tmpl( [
  57. "<span class='text' style='color: <%= color %>;'><%= text %></span>",
  58. ].join( "" ) ),
  59. logLine: tmpl( [
  60. "<span class='time'><%= time %></span>",
  61. "<span class='content'><%= content %></span>"
  62. ].join( "" ) )
  63. };
  64. activeCodeCache = function(){
  65. var cache = {};
  66. return {
  67. add: function( id ){
  68. if( !cache[ id ] )
  69. cache[ id ] = 1;
  70. },
  71. get: function( id ){
  72. return cache[ id ];
  73. },
  74. clear: function(){
  75. for( var i in cache )
  76. delete cache[ i ];
  77. }
  78. }
  79. }();
  80. showState = function( stateText, color ){
  81. color = color || "#999";
  82. document.getElementById( stateId ).innerHTML = template.state( {
  83. text: stateText,
  84. color: color
  85. } );
  86. };
  87. log = function( c ){
  88. var t = time( new Date ), logerEl;
  89. var line = document.createElement( "div" );
  90. line.className = "line";
  91. line.innerHTML = template.logLine( { time: t, content: c } );
  92. logerEl = document.getElementById( logerId );
  93. logerEl.appendChild( line );
  94. logHtml = logerEl.innerHTML;
  95. };
  96. buttonEventBind = function( buttonId, buttonHandler ){
  97. Tracker.Event.add( document.getElementById( buttonId ), "click", function(){
  98. if( !Tracker.Util.hasClass( this, "disabled" ) )
  99. buttonHandler.call( null );
  100. } );
  101. };
  102. buttonEnable = function( buttonId, enable ){
  103. var button = document.getElementById( buttonId );
  104. if( enable )
  105. Tracker.Util.removeClass( button, "disabled" );
  106. else
  107. Tracker.Util.addClass( button, "disabled" );
  108. };
  109. new__tracker__ = function( groupId ){
  110. var code;
  111. Tracker.StatusPool.arrivedSnippetGroupPut( groupId );
  112. if( !arrivedSnippetGroupCache[ groupId ] )
  113. arrivedSnippetGroupCache[ groupId ] = 1;
  114. if( code = Tracker.StatusPool.snippetGroupToCodeGet( groupId ) ){
  115. if( activeCodeCache.get( code.id ) )
  116. return ;
  117. activeCodeCache.add( code.id );
  118. // TODO: unicode 编码
  119. log( "发现新的活动代码在 " + ( code.fullUrl || code.fileName ) +
  120. "&nbsp; <a href='#' action='show-code' data-code-id='" + code.id +
  121. "' onclick='return false;'>查看</a>" );
  122. }else{
  123. log( "发现新的活动代码在 " + groupId );
  124. }
  125. };
  126. start = function(){
  127. var pageWindow = Tracker.View.ControlFrame.getWindow( "tracker_page" );
  128. pageWindow.__tracker__ = new__tracker__;
  129. Tracker.StatusPool.arrivedSnippetGroupFlagSet( 2 );
  130. showState( "监控进行中...", "#c00" );
  131. log( "监控开始" );
  132. hooking = true;
  133. stateEvent.fire( "stateChange", "start" );
  134. };
  135. stop = function(){
  136. var pageWindow = Tracker.View.ControlFrame.getWindow( "tracker_page" );
  137. pageWindow.__tracker__ = original__tracker__;
  138. Tracker.StatusPool.arrivedSnippetGroupFlagSet( 1 );
  139. showState( "已停止" );
  140. log( "监控结束" );
  141. activeCodeCache.clear();
  142. hooking = false;
  143. stateEvent.fire( "stateChange", "stop" );
  144. };
  145. clear = function(){
  146. for( var groupId in arrivedSnippetGroupCache ){
  147. Tracker.StatusPool.arrivedSnippetGroupDelete( groupId, 2 );
  148. delete arrivedSnippetGroupCache[ groupId ];
  149. }
  150. document.getElementById( logerId ).innerHTML = logHtml = "";
  151. log( "清除完成" );
  152. buttonEnable( clearBtnId, false );
  153. };
  154. eventBuild = function(){
  155. var topNav, titleEl;
  156. Tracker.Event.add( document.getElementById( logerId ), "click", function( e ){
  157. var target, codeId;
  158. target = e.target;
  159. if( target.getAttribute( "action" ) == "show-code" ){
  160. codeId = target.getAttribute( "data-code-id" );
  161. Tracker.View.ControlPanel.activeTab( "code-list" );
  162. Tracker.View.ControlPanel.showCodeDetail( codeId, 2 );
  163. }
  164. } );
  165. topNav = document.getElementById( "top-nav" );
  166. Tracker.Util.forEach( topNav.childNodes , function( li ){
  167. if( li.getAttribute( "data-name" ) == "watch" ){
  168. titleEl = li;
  169. titleEl.setAttribute( "data-html-backup", li.innerHTML );
  170. }
  171. } );
  172. topNav.tabEvent.on( "active", function( index, name ){
  173. if( hooking ){
  174. if( name == "watch" ){
  175. titleEl.innerHTML = titleEl.getAttribute( "data-html-backup" );
  176. }else{
  177. titleEl.innerHTML = titleEl.getAttribute( "data-html-backup" )
  178. .replace( /<\/a>/i, "<span class='red-dot'>&#12288;</span></a>" );
  179. }
  180. }
  181. } );
  182. };
  183. buttonStateChange = function( state ){
  184. if( state == "start" ){
  185. buttonEnable( startBtnId, false );
  186. buttonEnable( stopBtnId, true );
  187. buttonEnable( clearBtnId, false );
  188. }else if( state == "stop" ){
  189. buttonEnable( startBtnId, true );
  190. buttonEnable( stopBtnId, false );
  191. buttonEnable( clearBtnId, true );
  192. }
  193. };
  194. this.onStartUp( function( win, doc ){
  195. window = win;
  196. document = doc;
  197. var pageWindow = Tracker.View.ControlFrame.getWindow( "tracker_page" );
  198. original__tracker__ = pageWindow.__tracker__;
  199. this.body.innerHTML = template.page( {
  200. stateHtml: template.state( { text: "准备就绪", color: null } ),
  201. startBtnId: startBtnId = Tracker.Util.id(),
  202. stopBtnId: stopBtnId = Tracker.Util.id(),
  203. clearBtnId: clearBtnId = Tracker.Util.id(),
  204. stateId: stateId = Tracker.Util.id(),
  205. logerId: logerId = Tracker.Util.id()
  206. } );
  207. buttonEventBind( startBtnId, start );
  208. buttonEventBind( stopBtnId, stop );
  209. buttonEventBind( clearBtnId, clear );
  210. if( !started ){
  211. log( "活动监视器初始化完成" );
  212. log( "准备就绪" );
  213. stateEvent.on( "stateChange", buttonStateChange );
  214. }else{
  215. if( hooking ){
  216. buttonStateChange( "start" );
  217. showState( "监控进行中...", "#c00" );
  218. }else{
  219. buttonStateChange( "stop" );
  220. }
  221. if( logHtml )
  222. document.getElementById( logerId ).innerHTML = logHtml;
  223. }
  224. eventBuild();
  225. started = true;
  226. } );
  227. this.onActive( function(){
  228. } );
  229. } );
  230. };