├── index.php
├── docs
├── .DS_Store
├── img
│ ├── blank.png
│ ├── screenshot.png
│ ├── screenshot-bsize.png
│ ├── screenshot-code.png
│ ├── screenshot-error.png
│ ├── screenshot-line.png
│ ├── screenshot-name.png
│ ├── screenshot-rate.png
│ ├── screenshot-size.png
│ ├── screenshot-state.png
│ ├── screenshot-type.png
│ ├── screenshot-serror.png
│ ├── screenshot-arriveline.png
│ ├── screenshot-loadconsum.png
│ └── screenshot-runconsum.png
├── js
│ ├── docs.js.gz
│ ├── jquery.lazyload.min.js.gz
│ ├── jquery.lazyload.min.js
│ └── docs.js
├── css
│ ├── docs.css.gz
│ └── docs.css
├── changelog.json
└── index.html
├── bootstrap
├── js
│ ├── .DS_Store
│ ├── jquery.min.js.gz
│ ├── zepto.min.js.gz
│ ├── bootstrap.min.js.gz
│ ├── zepto.min.js
│ ├── bootstrap.min.js
│ └── jquery.min.js
├── css
│ └── bootstrap.min.css.gz
└── img
│ ├── docs-masthead-pattern.png
│ ├── glyphicons-halflings.png
│ └── glyphicons-halflings-white.png
├── README.md
├── tracker.js
├── cache.php
├── controller-resources
├── controller.css
└── controller.less
├── proxy.php
└── plugins
├── watch.js
└── general.js
/index.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/.DS_Store
--------------------------------------------------------------------------------
/docs/img/blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/blank.png
--------------------------------------------------------------------------------
/docs/js/docs.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/js/docs.js.gz
--------------------------------------------------------------------------------
/docs/css/docs.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/css/docs.css.gz
--------------------------------------------------------------------------------
/bootstrap/js/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/js/.DS_Store
--------------------------------------------------------------------------------
/docs/img/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot.png
--------------------------------------------------------------------------------
/bootstrap/js/jquery.min.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/js/jquery.min.js.gz
--------------------------------------------------------------------------------
/bootstrap/js/zepto.min.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/js/zepto.min.js.gz
--------------------------------------------------------------------------------
/docs/img/screenshot-bsize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-bsize.png
--------------------------------------------------------------------------------
/docs/img/screenshot-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-code.png
--------------------------------------------------------------------------------
/docs/img/screenshot-error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-error.png
--------------------------------------------------------------------------------
/docs/img/screenshot-line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-line.png
--------------------------------------------------------------------------------
/docs/img/screenshot-name.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-name.png
--------------------------------------------------------------------------------
/docs/img/screenshot-rate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-rate.png
--------------------------------------------------------------------------------
/docs/img/screenshot-size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-size.png
--------------------------------------------------------------------------------
/docs/img/screenshot-state.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-state.png
--------------------------------------------------------------------------------
/docs/img/screenshot-type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-type.png
--------------------------------------------------------------------------------
/docs/img/screenshot-serror.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-serror.png
--------------------------------------------------------------------------------
/bootstrap/css/bootstrap.min.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/css/bootstrap.min.css.gz
--------------------------------------------------------------------------------
/bootstrap/js/bootstrap.min.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/js/bootstrap.min.js.gz
--------------------------------------------------------------------------------
/docs/img/screenshot-arriveline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-arriveline.png
--------------------------------------------------------------------------------
/docs/img/screenshot-loadconsum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-loadconsum.png
--------------------------------------------------------------------------------
/docs/img/screenshot-runconsum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/img/screenshot-runconsum.png
--------------------------------------------------------------------------------
/docs/js/jquery.lazyload.min.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/docs/js/jquery.lazyload.min.js.gz
--------------------------------------------------------------------------------
/bootstrap/img/docs-masthead-pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/img/docs-masthead-pattern.png
--------------------------------------------------------------------------------
/bootstrap/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Tracker
2 | =======
3 |
4 | 一个用于检测网页 JavaScript/CSS 资源使用情况的书签栏工具,无须安装,可直接在浏览器中使用!
5 |
6 | 项目主页
7 |
8 | http://ucren.com/tracker
--------------------------------------------------------------------------------
/bootstrap/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChineseDron/Tracker/HEAD/bootstrap/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/tracker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Tracker Cacher
3 | * @version 0.9
4 | * @author dron
5 | * @create 2013-04-16
6 | */
7 |
8 | void function( version, script, analyzer, parent ){
9 | if( window != window.parent )
10 | return ;
11 |
12 | if( typeof __trackerCollector__ != "undefined" )
13 | return window.alert( "您正在使用 Tracker 客户端版!" );
14 |
15 | if( /msie/i.test( navigator.userAgent ) )
16 | return window.alert( "您使用的浏览器相对传统,建议换 chrome/firefox/safari 试试!" );
17 |
18 | version = "1.9.1" + Math.random();
19 | analyzer = "http://www.ucren.com/tracker/cache.php?file=./tracker-analyzer.js&version=" + version;
20 | script = document.createElement( "script" );
21 | script.type = "text/javascript";
22 | script.charset = "utf-8";
23 | script.src = analyzer;
24 | parent = document.head || document.body || document.documentElement;
25 |
26 | parent.appendChild( script );
27 | }();
--------------------------------------------------------------------------------
/cache.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/changelog.json:
--------------------------------------------------------------------------------
1 | [
2 | { "version": "1.9.1", "description": "改进 controller.css 由 less 构建|修复 getHtmlComments 筛选节点时的错误|修复 getWindow 不能正确获取的错误|修复 script 内容溢出到网页上的错误" },
3 | { "version": "1.9.0", "description": "新增代码标记高亮支持|新增“活动监视器”插件|屏蔽窗口模式下的 command+R 刷新" },
4 | { "version": "1.8.9", "description": "调整插件机制(插件 API 暂未对开发者公开)" },
5 | { "version": "1.8.8", "description": "优化部分业务逻辑|修正代码列表不能正确更新的错误" },
6 | { "version": "1.8.7", "description": "使用代码碎片分组方案优化解析速度|解决 general 插件在 firefox 下的兼容性错误|纠正 proxy.php 的 curl getData 处理错误|修正当代码换换时“代码”和“信息”面板不同步错误|综合结果新增最后更新时间信息" },
7 | { "version": "1.8.6", "description": "修复获取 baseUrl 和 fileName 错误(感谢 QA 大姐)|改正在某些特殊情况下 JS 代码泄露到页面上的错误|收集时间改为按百分比显示|分批异步写入页面优化" },
8 | { "version": "1.8.5", "description": "修复当 tab 不处于“当前网页”时,切换模式和关闭控制台呈现白页的错误" },
9 | { "version": "1.8.4", "description": "优化目标网页带 flash 时的控制台字体样式" },
10 | { "version": "1.8.3", "description": "修复 loading 样式错误|修复 IE 条件注释滤除错误|升级 proxy.php 为 curl 实现|修复了与目标页面在模块化方面发生脚本冲突|“关于”对话框增加“改进历史”链接" },
11 | { "version": "1.8.2", "description": "控制台改为 toolbar 的形式|使用 underscore 前端模板进行改进|改善了禁止 iframe 嵌入的网页的使用" },
12 | { "version": "1.8.1", "description": "修复“推荐给好友”功能不可用问题" },
13 | { "version": "1.8.0", "description": "集成 underscore 的前端模板|新增“综合结果”面板(此为第一个插件应用)" },
14 | { "version": "1.7.9", "description": "修复信息面板不可滚动 bug|调整控制台部分布局" },
15 | { "version": "1.7.8", "description": "修复部分界面 bug|调整部分 API|实现插件雏形(暂未开放)" },
16 | { "version": "1.7.7", "description": "优化更精确的监测 cpu 函数(内部用)|信息面板里补充加载和运行时间|优化性能(空间不大)" },
17 | { "version": "1.7.6", "description": "新增加载耗时和运行耗时统计项|修复 Firefox 下菜单不能用的问题" },
18 | { "version": "1.7.5", "description": "延时超时时间|对于在解析较慢网站比较有利" },
19 | { "version": "1.7.4", "description": "修复新浪首页大量报错问题" },
20 | { "version": "1.7.3", "description": "加了 gzip|并且强缓存" },
21 | { "version": "1.7.2", "description": "修复 undefined label 的问题" },
22 | { "version": "1.7.1", "description": "修复 Firefox 下的一个错误|修复部分”无内容“的错误" },
23 | { "version": "1.7.0", "description": "采用 bootstrap 构建的全新的 UI|增加代码详情页的“信息”面板" },
24 | { "version": "1.6.4", "description": "Feedback 字段增加" },
25 | { "version": "1.6.3", "description": "UI 细微调整" },
26 | { "version": "1.6.2", "description": "UI 调整|优化文件名显示|重写代理 php 文件" },
27 | { "version": "1.6.1", "description": "屏蔽 IE 条件注释|从这个版本开始,使用 3 位版本号" },
28 | { "version": "1.6", "description": "性能优化:分析速度提高至少十倍,JS 代码框显示体验无延迟!500K JS 毫秒级打开" },
29 | { "version": "1.5", "description": "解决 script 标签 src 属性无法正确获取的问题|改进对 seajs/requirejs 等 loader 的兼容" },
30 | { "version": "1.4", "description": "对 JS 代码中包含 Html 注释进行容错|修复目标位于淘宝 cdn 的脚本不能正常解析问题|调整分析进度显示" },
31 | { "version": "1.3", "description": "修复高版本 JS 系统方法与用户实现的版本存在冲突的问题" },
32 | { "version": "1.2", "description": "新增”推荐给好友“|修改反馈机制" },
33 | { "version": "1.1", "description": "重构,基于语法树加钩子,确保插入代码的正确性" },
34 | { "version": "1.0", "description": "初版" }
35 | ]
--------------------------------------------------------------------------------
/docs/js/jquery.lazyload.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Lazy Load - jQuery plugin for lazy loading images
3 | *
4 | * Copyright (c) 2007-2013 Mika Tuupola
5 | *
6 | * Licensed under the MIT license:
7 | * http://www.opensource.org/licenses/mit-license.php
8 | *
9 | * Project home:
10 | * http://www.appelsiini.net/projects/lazyload
11 | *
12 | * Version: 1.8.4
13 | *
14 | */
15 | (function(a,b,c,d){var e=a(b);a.fn.lazyload=function(c){function i(){var b=0;f.each(function(){var c=a(this);if(h.skip_invisible&&!c.is(":visible"))return;if(!a.abovethetop(this,h)&&!a.leftofbegin(this,h))if(!a.belowthefold(this,h)&&!a.rightoffold(this,h))c.trigger("appear"),b=0;else if(++b>h.failure_limit)return!1})}var f=this,g,h={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null};return c&&(d!==c.failurelimit&&(c.failure_limit=c.failurelimit,delete c.failurelimit),d!==c.effectspeed&&(c.effect_speed=c.effectspeed,delete c.effectspeed),a.extend(h,c)),g=h.container===d||h.container===b?e:a(h.container),0===h.event.indexOf("scroll")&&g.bind(h.event,function(a){return i()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,c.one("appear",function(){if(!this.loaded){if(h.appear){var d=f.length;h.appear.call(b,d,h)}a("
").bind("load",function(){c.hide().attr("src",c.data(h.data_attribute))[h.effect](h.effect_speed),b.loaded=!0;var d=a.grep(f,function(a){return!a.loaded});f=a(d);if(h.load){var e=f.length;h.load.call(b,e,h)}}).attr("src",c.data(h.data_attribute))}}),0!==h.event.indexOf("scroll")&&c.bind(h.event,function(a){b.loaded||c.trigger("appear")})}),e.bind("resize",function(a){i()}),/iphone|ipod|ipad.*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent.persisted&&f.each(function(){a(this).trigger("appear")})}),a(b).load(function(){i()}),this},a.belowthefold=function(c,f){var g;return f.container===d||f.container===b?g=e.height()+e.scrollTop():g=a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return f.container===d||f.container===b?g=e.width()+e.scrollLeft():g=a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return f.container===d||f.container===b?g=e.scrollTop():g=a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return f.container===d||f.container===b?g=e.scrollLeft():g=a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!a.rightoffold(b,c)&&!a.leftofbegin(b,c)&&!a.belowthefold(b,c)&&!a.abovethetop(b,c)},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})})(jQuery,window,document)
16 |
--------------------------------------------------------------------------------
/controller-resources/controller.css:
--------------------------------------------------------------------------------
1 | .relative{position:relative}.absolute{position:absolute}.navbar,.table{margin-bottom:0}#top-navbar .navbar-inner{border-radius:0}#code-detail .nav-tabs{margin-bottom:0}#code-detail .nav-tabs li a{color:#555}ul .tab-content,ol .tab-content{margin:0;padding:0}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-thumb{background:#ddd;min-height:50px;outline-offset:-2px;outline:2px solid #fff}::-webkit-scrollbar-thumb:hover{background:#666}::-webkit-scrollbar-track-piece{background:#fafafa;-webkit-border-radius:0}html,body,table{font-family:'Courier New','Heiti SC','Microsoft Yahei'}html,body{width:100%;height:100%;overflow:hidden;background:transparent}.scrollable{overflow:auto}.ellipsisable{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}table.compact-width{border-bottom:1px solid #d5d5d5;position:absolute;left:0;top:0;right:0;z-index:1}table.compact-width th{padding:8px 5px}.tab-content{overflow:hidden;position:absolute}.tab-content>li{display:none;position:absolute;top:0;right:0;bottom:0;left:0}.tab-content>li.tab-content-active{display:block}.target-web-page{background:transparent}#top-navbar .close{padding:7px 18px 0 0}#top-navbar .brand{color:#333}.main{position:absolute;top:43px;right:0;bottom:0;left:0}#pages{top:0;bottom:0;left:0;right:0}#pages>li{background-color:#fff}#pages>li.target-web-page{background-color:transparent}#list-codes{cursor:default;position:absolute;top:36px;right:0;bottom:0;left:0}#list-codes-tbody .none{color:#999}#list-codes-tbody .stress{color:#e5818a}#code-detail{left:200px;right:0;top:0;bottom:0;border-left:1px solid #cacaca;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,0.065);display:none;overflow:hidden;z-index:2}#code-detail ul.code-toolbar-inner{list-style-type:none;height:100%;margin:0;padding:0}#code-detail .code-toolbar{height:42px;background-color:#fafafa;border-bottom:1px solid #d5d5d5}#code-detail .code-toolbar li{float:left;display:block}#code-detail .code-toolbar li.right{float:right}#code-detail .code-toolbar li.close-button-like{padding:8px 12px 0 14px}#code-detail .code-toolbar li.tab-like{padding:5px 0 0 30px}#code-detail .code-toolbar li.label-like{line-height:36px;padding:4px 10px 0;color:#999}#code-detail .code-toolbar li.image-like{padding:12px 0 0 8px}#code-detail .code-toolbar .image{width:16px;height:16px;border:1px solid #ccc}#code-detail .code-toolbar .arrive{background-color:#bddbef}#code-detail .code-toolbar .unarrive{background-color:#fff}#code-detail .code-toolbar .hooking{background-color:#ffba93}#code-detail-body{top:43px;bottom:0;left:0;right:0}#code-content{width:100%;height:100%}#code-content pre{padding:0;margin:0;border:0;font-family:'Courier New','Heiti SC','Microsoft Yahei';border-radius:0;background-color:transparent;white-space:pre}#code-content .gutter{position:absolute;left:0;top:0;width:50px;background-color:#fafafa;text-align:right;padding:5px;z-index:1}#code-content .gutter pre{color:#ccc}#code-content .lines{position:absolute;left:60px;top:0;padding:5px}#code-content .lines .arrive{padding:0 3px;border-radius:2px;margin-left:-3px}#code-content .lines .arrive-1{background-color:#bddbef;color:#000}#code-content .timeout-code,#code-content .empty-code{padding:10px;color:#ccc}#code-info{padding:30px}#code-info .group{margin:0 0 10px}#code-info .group dt{display:block;float:left;width:90px}#code-info .group dd{display:block;margin-left:90px}#loading{text-align:left;display:none;height:42px;overflow:hidden;-webkit-transition:height .5s ease;-moz-transition:height .5s ease;-o-transition:height .5s ease;transition:height .5s ease}#loading .navbar-inner{border-left:0;box-shadow:none}#loading span{color:#000;font-size:14px;line-height:40px;display:inline-block;text-shadow:0 1px 0 white}#loading span#waitTime{padding-left:10px}
--------------------------------------------------------------------------------
/docs/css/docs.css:
--------------------------------------------------------------------------------
1 | html, body, table{
2 | font-family: "Courier New", "Heiti SC", "Microsoft Yahei";
3 | }
4 |
5 | body .popover{
6 | max-width: 28em;
7 | }
8 |
9 | header{
10 | width: auto;
11 | background: black;
12 | }
13 |
14 | header .container{
15 | color: white;
16 | padding: 2.5em;
17 | }
18 |
19 | #main{
20 | padding-top: 1.4em;
21 | }
22 |
23 | .sidebar{
24 | }
25 |
26 | .nav{
27 | width: 14.75em;
28 | }
29 |
30 | .nav.affix{
31 | top: 1.4em;
32 | }
33 | .nav.affix-bottom {
34 | position: absolute;
35 | top: auto;
36 | bottom: 1.25em;
37 | }
38 |
39 | .nav li{
40 | font-size: 1.2em;
41 | line-height: 2.5em;
42 | display: block;
43 | }
44 |
45 | .nav li a{
46 | display: block;
47 | padding-left: .6em;
48 | border-radius: .4em;
49 | }
50 |
51 | .nav li a sup{
52 | padding-left: 0.375em;
53 | font-style: italic;
54 | color: #0c0;
55 | font-size: 0.75em;
56 | }
57 |
58 | .nav li.active a{
59 | color: white;
60 | background-color: #08c;
61 | }
62 |
63 | .nav li a .icon-chevron-right {
64 | float: right;
65 | margin-top: 0.8em;
66 | margin-right: 0.375em;
67 | opacity: .25;
68 | }
69 |
70 | .nav li a:hover {
71 | background-color: #f5f5f5;
72 | }
73 |
74 | .nav li a:hover .icon-chevron-right {
75 | opacity: .5;
76 | }
77 |
78 | .nav li.active .icon-chevron-right,
79 | .nav li.active a:hover .icon-chevron-right {
80 | background-image: url(./bootstrap/img/glyphicons-halflings-white.png);
81 | opacity: 1;
82 | }
83 |
84 | #main .container p{
85 | line-height: 1.6;
86 | font-size: 1.3em;
87 | color: #333;
88 | margin: 0 0 1.3em;
89 | }
90 |
91 | #main .container p code{
92 | font-size: 0.9em;
93 | word-wrap: break-word;
94 | white-space: pre-wrap;
95 | word-spacing: normal;
96 | color: #333;
97 | display: block;
98 | }
99 |
100 | #main .container p .striking{
101 | line-height: 1.875em;
102 | padding: 0 1.25em;
103 | border-radius: 0.2em;
104 | display: inline-block;
105 | text-decoration: none;
106 | font-size: 1em;
107 | color: #fff;
108 | background-color: #08C;
109 | }
110 |
111 | #main .container p .bookmarks{
112 | cursor: move;
113 | }
114 |
115 | #main .container p .recommend{
116 | }
117 |
118 | #main .container p.screenshot{
119 | text-align: center;
120 | }
121 |
122 | #main .container p.screenshot img{
123 | width: 620px;
124 | height: 230px;
125 | }
126 |
127 | #main .container ul.funlist{
128 |
129 | }
130 |
131 | #main .container ul.funlist li{
132 | padding: 0 0 1.25em 0;
133 | }
134 |
135 | #main .container span.screenshot-fl{
136 | /* 图片制作参数:描边 2px #2575bd ,背景亮度 -5%,背景高斯模糊 1.5px,大小 350*100 */
137 | display: block;
138 | width: 21.875em;
139 | height: 6.25em;
140 | padding: 1.25em 0;
141 | }
142 |
143 | #main .container span.screenshot-fl img{
144 | width: 350px;
145 | height: 100px;
146 | }
147 |
148 | #main .container .code-panel img{
149 | width: 600px;
150 | height: 300px;
151 | }
152 |
153 | #main .container .screenful-last{
154 | min-height: 30em;
155 | }
156 |
157 | #changelog-content{
158 | overflow: hidden;
159 | width: auto;
160 | height: 0;
161 | opacity: 0;
162 | -webkit-transition: opacity .5s ease;
163 | -moz-transition: opacity .5s ease;
164 | -o-transition: opacity .5s ease;
165 | }
166 |
167 | #changelog-content.show{
168 | opacity: 1;
169 | height: auto;
170 | padding: 1em 0;
171 | }
172 |
173 | #changelog-content .latest{
174 | color: #090;
175 | }
176 |
177 | footer{
178 | background-color: whiteSmoke;
179 | border-top: 1px solid #e5e5e5;
180 | padding: 1.25em;
181 | }
182 |
183 | footer .container{
184 | color: #777;
185 | }
--------------------------------------------------------------------------------
/docs/js/docs.js:
--------------------------------------------------------------------------------
1 | $( function(){
2 | var randomNumber = function( num ){
3 | return Math.floor( Math.random() * num );
4 | };
5 |
6 | var randomWord = function(){
7 | var cw = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
8 | return function( length ){
9 | var re = [];
10 | for( var i = 0; i < length; i ++ )
11 | re[ i ] = cw.charAt( randomNumber( cw.length ));
12 | return re.join( "" );
13 | }
14 | }();
15 |
16 | var loadChangelog = function(){
17 | var data;
18 |
19 | var formatDescription = function( text ){
20 | text = text.split( "|" );
21 | for( var i = 0, l = text.length; i < l; i ++ )
22 | text[ i ] = "
" + text[ i ] + "";
23 | return "";
24 | };
25 |
26 | return function(){
27 | if( !data ) $.get( "./changelog.json", function( json ){
28 | data = json;
29 | data.forEach( function( item, index ){
30 | $changelogTable.append( " 0 ? "" : " class='latest'" ) + ">| " +
31 | item.version + " | " + formatDescription( item.description ) +
32 | " |
" );
33 | } );
34 | } );
35 | };
36 | }();
37 |
38 | var param = function( url, name, value ){
39 | var spliter, suffix;
40 |
41 | spliter = ~url.indexOf( "?" ) ? "&" : "?";
42 | suffix = name + "=" + value;
43 |
44 | return url + spliter + suffix;
45 | };
46 |
47 | var openShareLink = function(){
48 | var url, left, top;
49 |
50 | url = "http://service.weibo.com/share/share.php";
51 | url = param( url, "title", "%40dron%E5%BE%AE%E5%8D%9A%20%E6%88%91%E6%AD%A3%E5%9C%A8%E4%BD%BF%E7%94%A8%20Tracker%20%E6%8E%92%E6%9F%A5%E7%BD%91%E9%A1%B5%E4%B8%AD%E5%86%97%E4%BD%99%E7%9A%84%E8%84%9A%E6%9C%AC%EF%BC%8C%E6%8C%BA%E7%BB%99%E5%8A%9B%E7%9A%84%EF%BC%8C%E5%85%8D%E5%AE%89%E8%A3%85%EF%BC%8C%E7%9B%B4%E6%8E%A5%E5%9C%A8%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E5%B0%B1%E8%83%BD%E7%94%A8%EF%BC%8C%E6%8E%A8%E8%8D%90%E5%A4%A7%E5%AE%B6%E8%AF%95%E8%AF%95%E3%80%82" );
52 | url = param( url, "url", encodeURIComponent( "http://ucren.com/tracker/" ) );
53 |
54 | left = ( screen.width - 680 ) / 2;
55 | top = ( screen.height - 380 ) / 2;
56 |
57 | window.open( url, "", "width=680, height=380, left=" + left + ", top=" + top +
58 | ", toolbar=no, menubar=no, resizable=yes, status=no, " +
59 | "location=no, scrollbars=yes" );
60 | };
61 |
62 | var $changelog = $( "#changelog-content" );
63 | var $changelogTable = $( "tbody", $changelog );
64 |
65 | var showChangeLog = function( bool ){
66 | var $btn = $( ".expand-changelog" );
67 | if( bool ){
68 | $btn.html( "- 收起" );
69 | $changelog.addClass( "show" );
70 | $btn.data( "expanded", "1" );
71 | loadChangelog();
72 | }else{
73 | $btn.html( "+ 展开" );
74 | $changelog.removeClass( "show" );
75 | $btn.removeData( "expanded" );
76 | }
77 | }
78 |
79 | $( ".expand-changelog" ).click( function(){
80 | showChangeLog( !$( this ).data( "expanded" ) );
81 | } );
82 |
83 | var uid = randomWord( 8 );
84 |
85 | $( ".replace-uid" ).each( function(){
86 | if( this.nodeName == "A" )
87 | $( this ).prop( "href", $( this ).prop( "href" ).replace( "$uid", uid ) );
88 | else
89 | $( this ).html( function( index, html ){
90 | return html.replace( "$uid", uid );
91 | } );
92 | } );
93 |
94 | $( ".bookmarks" ).popover( {
95 | animation: true,
96 | placement: "top",
97 | html: true,
98 | trigger: "hover",
99 | container: "body"
100 | } );
101 |
102 | $( "img" ).lazyload();
103 |
104 | $( ".recommend" ).click( openShareLink );
105 |
106 | $( window ).on( "hashchange", function(){
107 | var fn = function(){
108 | if( location.hash == "#changelog" )
109 | showChangeLog( true );
110 | };
111 | return fn(), fn;
112 | }() );
113 |
114 | $( ".setup-fehelper" ).click( function( e ){
115 | window.open('http://www.baidufe.com/fehelper/install.html',
116 | 'fehelper-install',
117 | 'height=360,width=500,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no');
118 | } );
119 | } );
--------------------------------------------------------------------------------
/proxy.php:
--------------------------------------------------------------------------------
1 | $value)
17 | {
18 | if (substr($name, 0, 5) == 'HTTP_')
19 | {
20 | $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
21 | }
22 | }
23 | return $headers;
24 | }
25 | }
26 |
27 | //Makes an HTTP request via cURL, using request data that was passed directly to this script.
28 | function makeRequest($url) {
29 |
30 | //Tell cURL to make the request using the brower's user-agent if there is one, or a fallback user-agent otherwise.
31 | $user_agent = $_SERVER["HTTP_USER_AGENT"];
32 | if (empty($user_agent)) {
33 | $user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";
34 | }
35 | $ch = curl_init();
36 | curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
37 |
38 | //Proxy the browser's request headers.
39 | $browserRequestHeaders = getallheaders();
40 | //(...but let cURL set some of these headers on its own.)
41 | //TODO: The unset()s below assume that browsers' request headers
42 | //will use casing (capitalizations) that appear within them.
43 | unset($browserRequestHeaders["Host"]);
44 | unset($browserRequestHeaders["Content-Length"]);
45 | //Throw away the browser's Accept-Encoding header if any;
46 | //let cURL make the request using gzip if possible.
47 | unset($browserRequestHeaders["Accept-Encoding"]);
48 | curl_setopt($ch, CURLOPT_ENCODING, "");
49 | //Transform the associative array from getallheaders() into an
50 | //indexed array of header strings to be passed to cURL.
51 | $curlRequestHeaders = array();
52 | foreach ($browserRequestHeaders as $name => $value) {
53 | $curlRequestHeaders[] = $name . ": " . $value;
54 | }
55 | curl_setopt($ch, CURLOPT_HTTPHEADER, $curlRequestHeaders);
56 |
57 | //Proxy any received GET/POST/PUT data.
58 | switch ($_SERVER["REQUEST_METHOD"]) {
59 | case "GET":
60 | // $getData = array();
61 | // foreach ($_GET as $key => $value) {
62 | // $getData[] = urlencode($key) . "=" . urlencode($value);
63 | // }
64 | // if (count($getData) > 0) $url .= "?" . implode("&", $getData);
65 | break;
66 | case "POST":
67 | curl_setopt($ch, CURLOPT_POST, true);
68 | //For some reason, $HTTP_RAW_POST_DATA isn't working as documented at
69 | //http://php.net/manual/en/reserved.variables.httprawpostdata.php
70 | //but the php://input method works. This is likely to be flaky
71 | //across different server environments.
72 | //More info here: http://stackoverflow.com/questions/8899239/http-raw-post-data-not-being-populated-after-upgrade-to-php-5-3
73 | curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents("php://input"));
74 | break;
75 | case "PUT":
76 | curl_setopt($ch, CURLOPT_PUT, true);
77 | curl_setopt($ch, CURLOPT_INFILE, fopen("php://input"));
78 | break;
79 | }
80 |
81 | //Other cURL options.
82 | curl_setopt($ch, CURLOPT_HEADER, true);
83 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
84 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
85 | curl_setopt ($ch, CURLOPT_FAILONERROR, true);
86 |
87 | //Set the request URL.
88 | curl_setopt($ch, CURLOPT_URL, $url);
89 |
90 | //Make the request.
91 | $response = curl_exec($ch);
92 | $responseInfo = curl_getinfo($ch);
93 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
94 | curl_close($ch);
95 |
96 | //Setting CURLOPT_HEADER to true above forces the response headers and body
97 | //to be output together--separate them.
98 | $responseHeaders = substr($response, 0, $headerSize);
99 | $responseBody = substr($response, $headerSize);
100 |
101 | return array("headers" => $responseHeaders, "body" => $responseBody, "responseInfo" => $responseInfo);
102 | }
103 |
104 | function get_url( $url ){
105 | global $timeConsum;
106 | $reg = "/^https?:\/\/[^\/].+$/";
107 | if( !preg_match( $reg, $url ) )
108 | return "";
109 | $startTime = microtime( true );
110 | // $content = file_get_contents( $url );
111 |
112 | $response = makeRequest( $url );
113 | // $rawResponseHeaders = $response[ "headers" ];
114 | $content = $response[ "body" ];
115 |
116 | $timeConsum = (int)( ( microtime( true ) - $startTime ) * 1000 );
117 | return $content;
118 | };
119 |
120 | $content = get_url( $url );
121 | $encode_content = json_encode( $content );
122 |
123 | if ( $content && $encode_content == "null" )
124 | $encode_content = json_encode( iconv( "GBK", "UTF-8", $content ) );
125 |
126 | $data = "{\"url\":\"" . $url . "\",\"content\":" . $encode_content . ",\"consum\":" . $timeConsum . "}";
127 |
128 | $json = "document.$callback(" . $data . ");";
129 |
130 | header( "Content-Type: application/x-javascript" );
131 | echo $json;
--------------------------------------------------------------------------------
/controller-resources/controller.less:
--------------------------------------------------------------------------------
1 | /**
2 | * author dron
3 | * generated by less
4 | */
5 |
6 | // veriables
7 | @font-family: 'Courier New', 'Heiti SC', 'Microsoft Yahei';
8 |
9 | // functions
10 | .full(){ width: 100%; height: 100%; }
11 |
12 | .size( @width, @height ){ width: @width; height: @height; }
13 | .size( @size ){ .size( @size, @size ); }
14 |
15 | .pos( @left, @top ){ left: @left; top: @top; }
16 | .pos( @top, @right, @bottom, @left ){ top: @top; right: @right; bottom: @bottom; left: @left; }
17 |
18 | .transition( @text ){
19 | -webkit-transition: @text;
20 | -moz-transition: @text;
21 | -o-transition: @text;
22 | transition: @text;
23 | }
24 |
25 | .gradient( @color1, @color2 ){
26 | background-image: -webkit-linear-gradient(top, @color1 0%, @color2 100%);
27 | background-image: -moz-linear-gradient(top, @color1 0%, @color2 100%);
28 | background-image: -o-linear-gradient(top, @color1 0%, @color2 100%);
29 | background-image: linear-gradient(top, @color1 0%, @color2 100%);
30 | }
31 |
32 | .shadow( @text ){
33 | -webkit-box-shadow: @text;
34 | -moz-box-shadow: @text;
35 | box-shadow: @text;
36 | }
37 |
38 | .radius( @text ){
39 | -webkit-border-radius: @text;
40 | -moz-border-radius: @text;
41 | border-radius: @text;
42 | }
43 |
44 | .boxes(){
45 | display: -moz-box;
46 | display: -webkit-box;
47 | display: box;
48 | }
49 |
50 | .box( @size: 1 ){
51 | -moz-box-flex: @size;
52 | -webkit-box-flex: @size;
53 | box-flex: @size;
54 | }
55 |
56 | .columns( @count: 2 ){
57 | column-count: @count;
58 | -moz-column-count: @count;
59 | -webkit-column-count: @count;
60 | }
61 |
62 | .column( @width ){
63 | -moz-column-width: @width;
64 | -webkit-column-width: @width;
65 | column-width: @width;
66 | }
67 |
68 | .relative{ position: relative; }
69 | .absolute{ position: absolute; }
70 |
71 |
72 |
73 | .navbar, .table{ margin-bottom: 0; }
74 |
75 | #top-navbar{
76 | .navbar-inner{
77 | border-radius: 0;
78 | }
79 | }
80 |
81 | #code-detail{
82 | .nav-tabs{
83 | margin-bottom: 0;
84 | li{
85 | a{
86 | color: #555;
87 | }
88 | }
89 | }
90 | }
91 |
92 | ul, ol{
93 | .tab-content{
94 | margin: 0; padding: 0;
95 | }
96 | }
97 |
98 | ::-webkit-scrollbar{
99 | .size(12px);
100 | &-thumb{
101 | background: #ddd;
102 | min-height: 50px;
103 | outline-offset: -2px;
104 | outline: 2px solid #fff;
105 | &:hover{
106 | background: #666;
107 | }
108 | }
109 | &-track-piece{
110 | background: #fafafa;
111 | -webkit-border-radius: 0;
112 | }
113 | }
114 |
115 |
116 | html, body, table{
117 | font-family: @font-family;
118 | }
119 |
120 | html, body{
121 | .full;
122 | overflow: hidden;
123 | background: transparent;
124 | }
125 |
126 | .scrollable{
127 | overflow: auto;
128 | }
129 |
130 | .ellipsisable{
131 | white-space: nowrap;
132 | text-overflow: ellipsis;
133 | overflow: hidden;
134 | }
135 |
136 | table.compact-width{
137 | border-bottom: 1px solid #d5d5d5;
138 | .absolute;
139 | .pos(0, 0);
140 | right: 0;
141 | z-index: 1;
142 | th{
143 | padding: 8px 5px;
144 | }
145 | }
146 |
147 | .tab-content{
148 | overflow: hidden;
149 | .absolute;
150 | &>li{
151 | display: none;
152 | .absolute;
153 | .pos(0,0,0,0);
154 | &.tab-content-active{
155 | display: block;
156 | }
157 | }
158 | }
159 |
160 | .target-web-page{
161 | background: transparent;
162 | }
163 |
164 | #top-navbar{
165 | .close{
166 | padding: 7px 18px 0 0;
167 | }
168 | .brand{
169 | color: #333;
170 | }
171 | }
172 |
173 | .main{
174 | .absolute;
175 | .pos(43px,0,0,0);
176 | }
177 |
178 | #pages{
179 | top: 0;
180 | bottom: 0;
181 | left: 0;
182 | right: 0;
183 | &>li{
184 | background-color: #fff;
185 | &.target-web-page{
186 | background-color: transparent;
187 | }
188 | }
189 | }
190 |
191 | #list-codes{
192 | cursor: default;
193 | .absolute;
194 | .pos(36px,0,0,0);
195 | }
196 |
197 | #list-codes-tbody{
198 | .none{
199 | color: #999;
200 | }
201 | .stress{
202 | color: #e5818a;
203 | }
204 | }
205 |
206 |
207 | #code-detail{
208 | left: 200px;
209 | right: 0;
210 | top: 0;
211 | bottom: 0;
212 | border-left: 1px solid #cacaca;
213 | background: #fff;
214 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
215 | display: none;
216 | overflow: hidden; z-index: 2;
217 | ul.code-toolbar-inner{
218 | list-style-type: none;
219 | height: 100%;
220 | margin: 0;
221 | padding: 0;
222 | }
223 | .code-toolbar{
224 | height: 42px;
225 | background-color: #fafafa;
226 | border-bottom: 1px solid #d5d5d5;
227 | li{
228 | float: left;
229 | display: block;
230 | &.right{
231 | float: right;
232 | }
233 | &.close-button-like{
234 | padding: 8px 12px 0 14px;
235 | }
236 | &.tab-like{
237 | padding: 5px 0 0 30px;
238 | }
239 | &.label-like{
240 | line-height: 36px;
241 | padding: 4px 10px 0;
242 | color: #999;
243 | }
244 | &.image-like{
245 | padding: 12px 0 0 8px;
246 | }
247 | }
248 | .image{
249 | .size(16px);
250 | border: 1px solid #ccc;
251 | }
252 | .arrive{
253 | background-color: #bddbef;
254 | }
255 | .unarrive{
256 | background-color: #fff;
257 | }
258 | .hooking{
259 | background-color: #ffba93;
260 | }
261 | }
262 | }
263 |
264 | #code-detail-body{
265 | top: 43px;
266 | bottom: 0;
267 | left: 0;
268 | right: 0;
269 | }
270 |
271 | #code-content{
272 | .full;
273 | pre{
274 | padding: 0;
275 | margin: 0;
276 | border: 0;
277 | font-family: @font-family;
278 | border-radius: 0;
279 | background-color: transparent;
280 | white-space: pre;
281 | }
282 | .gutter{
283 | .absolute;
284 | .pos(0,0);
285 | width: 50px;
286 | background-color: #fafafa;
287 | text-align: right;
288 | padding: 5px;
289 | z-index: 1;
290 | pre{
291 | color: #ccc;
292 | }
293 | }
294 | .lines{
295 | .absolute;
296 | .pos(60px,0);
297 | padding: 5px;
298 | .arrive{
299 | padding: 0 3px;
300 | border-radius: 2px;
301 | margin-left: -3px;
302 | }
303 | .arrive-1{
304 | background-color: #bddbef;
305 | color: #000;
306 | }
307 | }
308 | .timeout-code, .empty-code{
309 | padding: 10px;
310 | color: #ccc;
311 | }
312 | }
313 |
314 | #code-info{
315 | padding: 30px;
316 | .group{
317 | margin: 0 0 10px;
318 | dt{
319 | display: block;
320 | float: left;
321 | width: 90px;
322 | }
323 | dd{
324 | display: block;
325 | margin-left: 90px;
326 | }
327 | }
328 | }
329 |
330 | #loading{
331 | text-align: left;
332 | display: none;
333 | height: 42px;
334 | overflow: hidden;
335 | .transition(height .5s ease);
336 | .navbar-inner{
337 | border-left: 0;
338 | box-shadow: none;
339 | }
340 | span{
341 | color: #000;
342 | font-size: 14px;
343 | line-height: 40px;
344 | display: inline-block;
345 | text-shadow: 0 1px 0 white;
346 | waitTime{
347 | padding-left: 10px;
348 | }
349 | }
350 | }
351 |
352 |
353 |
354 |
355 |
--------------------------------------------------------------------------------
/plugins/watch.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Watch Plugin
3 | * @version 1.0
4 | * @author dron
5 | * @create 2013-05-07
6 | */
7 |
8 | Tracker.Plugins.addOn( "watch", function(){
9 | var util, 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__, StatusPool, showState, arrivedSnippetGroupCache,
13 | buttonStateChange, logHtml;
14 |
15 | util = Tracker.util;
16 | tmpl = util.tmpl;
17 | StatusPool = Tracker.StatusPool;
18 | arrivedSnippetGroupCache = {};
19 |
20 | stateEvent = Tracker.Event.bind( {} );
21 |
22 | time = function( date ){
23 | var t = [ date.getHours(), date.getMinutes(), date.getSeconds() ].join( ":" );
24 | t = t.replace( /\b(\d)\b/g, "0$1" );
25 | return t;
26 | };
27 |
28 | Tracker.Plugins.addStyle( [
29 | ".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; }",
30 | "#code-content .lines .arrive-2{ background-color: #ffba93; color: #000; }",
31 | "#plugin-watch-page{ }",
32 | "#plugin-watch-page .header{ height: 126px; background-color: #fafafa; border-bottom: 1px solid #d5d5d5; }",
33 | "#plugin-watch-page .header .title{ line-height: 42px; padding-left: 30px; }",
34 | "#plugin-watch-page .header .control{ padding-left: 30px; height: 42px; }",
35 | "#plugin-watch-page .header .control .btn{ margin-right: 5px; }",
36 | "#plugin-watch-page .header .state{ padding-left: 30px; line-height: 42px; color: #666; }",
37 | "#plugin-watch-page .header .state .text{ }",
38 | "#plugin-watch-page .body{ position: absolute; left: 0; right: 0; top: 127px; bottom: 0; padding: 10px; background-color: #1d1e1a; }",
39 | "#plugin-watch-page .body .logger{ line-height: 20px; color: #f6f6f6; }",
40 | "#plugin-watch-page .body .logger .line{ }",
41 | "#plugin-watch-page .body .logger .line .time{ display: inline-block; width: 80px; }",
42 | "#plugin-watch-page .body .logger .line .content{ }"
43 | ].join( "" ) );
44 |
45 | template = {
46 | page: tmpl( [
47 | "",
58 | "",
59 | "
",
60 | "
",
61 | "
"
62 | ].join( "" ) ),
63 |
64 | state: tmpl( [
65 | "<%= text %>",
66 | ].join( "" ) ),
67 |
68 | logLine: tmpl( [
69 | "<%= time %>",
70 | "<%= content %>"
71 | ].join( "" ) )
72 | };
73 |
74 | activeCodeCache = function(){
75 | var cache = {};
76 |
77 | return {
78 | add: function( id ){
79 | if( !cache[ id ] )
80 | cache[ id ] = 1;
81 | },
82 |
83 | get: function( id ){
84 | return cache[ id ];
85 | },
86 |
87 | clear: function(){
88 | for( var i in cache )
89 | delete cache[ i ];
90 | }
91 | }
92 | }();
93 |
94 | showState = function( stateText, color ){
95 | color = color || "#999";
96 | document.getElementById( stateId ).innerHTML = template.state( {
97 | text: stateText,
98 | color: color
99 | } );
100 | };
101 |
102 | log = function( c ){
103 | var t = time( new Date ), logerEl;
104 | var line = document.createElement( "div" );
105 | line.className = "line";
106 | line.innerHTML = template.logLine( { time: t, content: c } );
107 | logerEl = document.getElementById( logerId );
108 | logerEl.appendChild( line );
109 | logHtml = logerEl.innerHTML;
110 | };
111 |
112 | buttonEventBind = function( buttonId, buttonHandler ){
113 | Tracker.Event.add( document.getElementById( buttonId ), "click", function(){
114 | if( !util.hasClass( this, "disabled" ) )
115 | buttonHandler.call( null );
116 | } );
117 | };
118 |
119 | buttonEnable = function( buttonId, enable ){
120 | var button = document.getElementById( buttonId );
121 |
122 | if( enable )
123 | util.removeClass( button, "disabled" );
124 | else
125 | util.addClass( button, "disabled" );
126 | };
127 |
128 | new__tracker__ = function( groupId ){
129 | var code;
130 |
131 | StatusPool.arrivedSnippetGroupPut( groupId );
132 |
133 | if( !arrivedSnippetGroupCache[ groupId ] )
134 | arrivedSnippetGroupCache[ groupId ] = 1;
135 |
136 | if( code = StatusPool.snippetGroupToCodeGet( groupId ) ){
137 | if( activeCodeCache.get( code.id ) )
138 | return ;
139 |
140 | activeCodeCache.add( code.id );
141 |
142 | log( "发现新的活动代码在 " + ( code.fullUrl || code.fileName ) +
143 | " 查看" );
145 | }else{
146 | log( "发现新的活动代码在 " + groupId );
147 | }
148 | };
149 |
150 | start = function(){
151 | var pageWindow = Tracker.View.ControlFrame.getWindow( "tracker_page" );
152 | pageWindow.__tracker__ = new__tracker__;
153 | StatusPool.arrivedSnippetGroupFlagSet( 2 );
154 | showState( "监控进行中...", "#c00" );
155 | log( "监控开始" );
156 | hooking = true;
157 | stateEvent.fire( "stateChange", "start" );
158 | };
159 |
160 | stop = function(){
161 | var pageWindow = Tracker.View.ControlFrame.getWindow( "tracker_page" );
162 | pageWindow.__tracker__ = original__tracker__;
163 | StatusPool.arrivedSnippetGroupFlagSet( 1 );
164 | showState( "已停止" );
165 | log( "监控结束" );
166 | activeCodeCache.clear();
167 | hooking = false;
168 | stateEvent.fire( "stateChange", "stop" );
169 | };
170 |
171 | clear = function(){
172 | for( var groupId in arrivedSnippetGroupCache ){
173 | StatusPool.arrivedSnippetGroupDelete( groupId, 2 );
174 | delete arrivedSnippetGroupCache[ groupId ];
175 | }
176 |
177 | document.getElementById( logerId ).innerHTML = logHtml = "";
178 | log( "清除完成" );
179 | buttonEnable( clearBtnId, false );
180 | };
181 |
182 | eventBuild = function(){
183 | var topNav, titleEl;
184 |
185 | Tracker.Event.add( document.getElementById( logerId ), "click", function( e ){
186 | var target, codeId;
187 |
188 | target = e.target;
189 |
190 | if( target.getAttribute( "action" ) == "show-code" ){
191 | codeId = target.getAttribute( "data-code-id" );
192 | Tracker.View.ControlPanel.activeTab( "code-list" );
193 | Tracker.View.ControlPanel.showCodeDetail( codeId, 2 );
194 | }
195 | } );
196 |
197 | topNav = document.getElementById( "top-nav" );
198 |
199 | util.forEach( topNav.childNodes , function( li ){
200 | if( li.getAttribute( "data-name" ) == "watch" ){
201 | titleEl = li;
202 | titleEl.setAttribute( "data-html-backup", li.innerHTML );
203 | }
204 | } );
205 |
206 | topNav.tabEvent.on( "active", function( index, name ){
207 | if( hooking ){
208 | if( name == "watch" ){
209 | titleEl.innerHTML = titleEl.getAttribute( "data-html-backup" );
210 | }else{
211 | titleEl.innerHTML = titleEl.getAttribute( "data-html-backup" )
212 | .replace( /<\/a>/i, " " );
213 | }
214 | }
215 | } );
216 | };
217 |
218 | buttonStateChange = function( state ){
219 | if( state == "start" ){
220 | buttonEnable( startBtnId, false );
221 | buttonEnable( stopBtnId, true );
222 | buttonEnable( clearBtnId, false );
223 | }else if( state == "stop" ){
224 | buttonEnable( startBtnId, true );
225 | buttonEnable( stopBtnId, false );
226 | buttonEnable( clearBtnId, true );
227 | }
228 | };
229 |
230 | this.onStartUp( function( win, doc ){
231 | window = win;
232 | document = doc;
233 |
234 | var pageWindow = Tracker.View.ControlFrame.getWindow( "tracker_page" );
235 | original__tracker__ = pageWindow.__tracker__;
236 |
237 | this.body.innerHTML = template.page( {
238 | stateHtml: template.state( { text: "准备就绪", color: null } ),
239 | startBtnId: startBtnId = util.id(),
240 | stopBtnId: stopBtnId = util.id(),
241 | clearBtnId: clearBtnId = util.id(),
242 | stateId: stateId = util.id(),
243 | logerId: logerId = util.id()
244 | } );
245 |
246 | buttonEventBind( startBtnId, start );
247 | buttonEventBind( stopBtnId, stop );
248 | buttonEventBind( clearBtnId, clear );
249 |
250 | if( !started ){
251 | log( "活动监视器初始化完成" );
252 | log( "准备就绪" );
253 |
254 | stateEvent.on( "stateChange", buttonStateChange );
255 | }else{
256 | if( hooking ){
257 | buttonStateChange( "start" );
258 | showState( "监控进行中...", "#c00" );
259 | }else{
260 | buttonStateChange( "stop" );
261 | }
262 |
263 | if( logHtml )
264 | document.getElementById( logerId ).innerHTML = logHtml;
265 | }
266 |
267 | eventBuild();
268 |
269 | started = true;
270 | } );
271 |
272 | this.onActive( function(){
273 |
274 | } );
275 | } );
--------------------------------------------------------------------------------
/plugins/general.js:
--------------------------------------------------------------------------------
1 | /**
2 | * General Plugin
3 | * @version 1.0
4 | * @author dron
5 | * @create 2013-04-21
6 | */
7 |
8 | // TODO: 需要更新文档
9 |
10 | Tracker.Plugins.addOn( "general", function(){
11 | var CodeList, template, template, data, calculate, render, update, eventDelegate,
12 | i, l, r, q, util, tmpl, now, window, document, mainBody, mainBodyId;
13 |
14 | util = Tracker.util;
15 | tmpl = util.tmpl;
16 | CodeList = Tracker.CodeList;
17 |
18 | now = function( time ){
19 | time = new Date();
20 | time = [ time.getFullYear(), time.getMonth() + 1, time.getDate() ].join( "-" ) + " " +
21 | [ time.getHours(), time.getMinutes(), time.getSeconds() ].join( ":" );
22 | time = time.replace( /\b(\d)\b/g, "0$1" );
23 | return time;
24 | };
25 |
26 | Tracker.Plugins.addStyle( [
27 | "#plugin-general-page .toolbar{ height: 42px; background-color: #fafafa; border-bottom: 1px solid #d5d5d5; }",
28 | "#plugin-general-page .toolbar li{ display: block; float: left; }",
29 | "#plugin-general-page .toolbar li.button-like{ padding: 5px 0 0 5px; }",
30 | "#plugin-general-page .toolbar li.text-like{ padding: 12px 0 0 20px; line-height: 20px; }",
31 | "#plugin-general-page .toolbar li.first{ padding-left: 30px; }",
32 | "#plugin-general-page .body{ position: absolute; top: 43px; bottom: 0; left: 0; right: 0; padding: 10px 30px; }",
33 | "#plugin-general-page .body .table{ margin-bottom: 30px; width: 900px; table-layout:fixed; }",
34 | "#plugin-general-page .body .table td{ }",
35 | "#plugin-general-page .body .table td .ellipsisable{ width: 100%; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }",
36 | "#plugin-general-page .body .unit{ font-style: italic; font-weight: 400; }",
37 | "#plugin-general-page .body .close-up{ position: relative; top: -4px; }",
38 | "#plugin-general-page .body .low{ color: #ff814e; }",
39 | "#plugin-general-page .body .high{ color: #2bb027; }",
40 | "#plugin-general-page .body .close-up b{ font-family: Constantia, Georgia; font-size: 24px; font-weight: 400; position: absolute; }"
41 | ].join( "" ) );
42 |
43 | template = {
44 | page: tmpl( [
45 | "",
51 | "",
52 | "<% if( count > 0 ){ %>",
53 | "
当前网页共包含 <%= count %> 个脚本资源:<%= embedCount %> 个内嵌,<%= linkCount %> 个外链文件,<%= appendCount %> 个动态加载。
",
54 | "
",
55 | "",
56 | "",
57 | "| 使用量 (%) | ",
58 | "冗余量 (%) | ",
59 | "使用行数 | ",
60 | "总行数 | ",
61 | "总大小 (k) | ",
62 | "总加载耗时 (ms) | ",
63 | "总运行耗时 (ms) | ",
64 | "
",
65 | "",
66 | "",
67 | "",
68 | "| '><%= usefulRate %> | ",
69 | "<%= redundancyRate %> | ",
70 | "<%= usefulLines %> | ",
71 | "<%= totalLines %> | ",
72 | "<%= totalSize %> | ",
73 | "<%= totalLoadConsum %> | ",
74 | "<%= totalRunConsum %> | ",
75 | "
",
76 | "",
77 | "
",
78 |
79 | "
冗余量最高 top <%= showCodeCount %> 脚本:
",
80 | "
",
81 | "",
82 | "",
83 | "| 文件名 | ",
84 | "类型 | ",
85 | "冗余量 (%) | ",
86 | " | ",
87 | "
",
88 | "",
89 | "",
90 | "<% for( var i = 0, r; i < redundancyRateTableData.length; i ++ ){ %>",
91 | "<% r = redundancyRateTableData[ i ]; %>",
92 | "",
93 | "<%= r.fullUrl || '-' %> | ",
94 | "",
95 | "<% switch( r.type ){ ",
96 | "case 'embed':",
97 | "print( '内嵌' );",
98 | "break;",
99 | "case 'link':",
100 | "print( '文件链接' );",
101 | "break;",
102 | "case 'append':",
103 | "print( '动态插入' );",
104 | "break;",
105 | "} %>",
106 | " | ",
107 | "<%= Math.round( ( 1 - r.prop( 'usefulRate' ) ) * 1e4 ) / 1e2 %> | ",
108 | " | ",
109 | "
",
110 | "<% } %>",
111 | "",
112 | "
",
113 |
114 | "
体积最大 top <%= showCodeCount %> 脚本:
",
115 | "
",
116 | "",
117 | "",
118 | "| 文件名 | ",
119 | "类型 | ",
120 | "大小 (k) | ",
121 | " | ",
122 | "
",
123 | "",
124 | "",
125 | "<% for( var i = 0, r; i < sizeTableData.length; i ++ ){ %>",
126 | "<% r = sizeTableData[ i ]; %>",
127 | "",
128 | "<%= r.fullUrl || '-' %> | ",
129 | "",
130 | "<% switch( r.type ){ ",
131 | "case 'embed':",
132 | "print( '内嵌' );",
133 | "break;",
134 | "case 'link':",
135 | "print( '文件链接' );",
136 | "break;",
137 | "case 'append':",
138 | "print( '动态插入' );",
139 | "break;",
140 | "} %>",
141 | " | ",
142 | "<%= ( r.size / 1024 ).toFixed( 2 ) %> | ",
143 | " | ",
144 | "
",
145 | "<% } %>",
146 | "",
147 | "
",
148 |
149 | "
运时耗时最高 top <%= showCodeCount %> 脚本:
",
150 | "
",
151 | "",
152 | "",
153 | "| 文件名 | ",
154 | "类型 | ",
155 | "耗时 (ms) | ",
156 | " | ",
157 | "
",
158 | "",
159 | "",
160 | "<% for( var i = 0, r; i < runConsumTableData.length; i ++ ){ %>",
161 | "<% r = runConsumTableData[ i ]; %>",
162 | "",
163 | "<%= r.fullUrl || '-' %> | ",
164 | "",
165 | "<% switch( r.type ){ ",
166 | "case 'embed':",
167 | "print( '内嵌' );",
168 | "break;",
169 | "case 'link':",
170 | "print( '文件链接' );",
171 | "break;",
172 | "case 'append':",
173 | "print( '动态插入' );",
174 | "break;",
175 | "} %>",
176 | " | ",
177 | "<%= r.runConsum %> | ",
178 | " | ",
179 | "
",
180 | "<% } %>",
181 | "",
182 | "
",
183 | "<% } else { %>",
184 | "该网页没有任何 JS 代码。",
185 | "<% } %>",
186 | "
"
187 | ].join( "" ) )
188 | };
189 |
190 | data = function(){};
191 |
192 | data.prototype = {
193 | count: 0,
194 | embedCount: 0,
195 | linkCount: 0,
196 | appendCount: 0,
197 |
198 | usefulRate: 0,
199 | redundancyRate: 100,
200 |
201 | usefulLines: 0,
202 | totalLines: 0,
203 |
204 | totalSize: 0,
205 |
206 | totalLoadConsum: 0,
207 | totalRunConsum: 0,
208 |
209 | now: now
210 | };
211 |
212 | data = new data;
213 |
214 | calculate = function(){
215 | var redundancyRate = function( code1, code2 ){
216 | return code1.prop( "usefulRate" ) - code2.prop( "usefulRate" );
217 | };
218 |
219 | var size = function( code1, code2 ){
220 | return code2.size - code1.size;
221 | };
222 |
223 | var runConsum = function( code1, code2 ){
224 | return code2.runConsum - code1.runConsum;
225 | };
226 |
227 | return function (){
228 | for( i in data )
229 | delete data[ i ];
230 | l = data.count = CodeList.count();
231 |
232 | data.showCodeCount = l > 2 ? 3 : l;
233 |
234 | for( i = 0; i < l; i ++ ){
235 | r = CodeList.get( i );
236 |
237 | if( r.type == "embed" ){
238 | data.embedCount ++;
239 | }else if( r.type == "link" ){
240 | data.linkCount ++;
241 | }else if( r.type == "append" ){
242 | data.appendCount ++;
243 | }
244 |
245 | data.usefulLines += r.arriveRowsCount;
246 | data.totalLines += r.rowsCount;
247 | data.totalSize += r.size;
248 | data.totalLoadConsum += r.loadConsum;
249 | data.totalRunConsum += r.runConsum;
250 |
251 | r.prop( "usefulRate", r.arriveRowsCount / r.rowsCount );
252 | }
253 |
254 | r = data.usefulLines / data.totalLines;
255 |
256 | data.usefulRate = Math.round( ( r ) * 1e4 ) / 1e2;
257 | data.redundancyRate = Math.round( ( 1 - r ) * 1e4 ) / 1e2;
258 | data.totalSize = ( data.totalSize / 1000 ).toFixed( 2 );
259 |
260 | q = CodeList.list().slice( 0 );
261 | q.sort( redundancyRate );
262 | data.redundancyRateTableData = q.slice( 0, data.showCodeCount );
263 |
264 | q = CodeList.list().slice( 0 );
265 | q.sort( size );
266 | data.sizeTableData = q.slice( 0, data.showCodeCount );
267 |
268 | q = CodeList.list().slice( 0 );
269 | q.sort( runConsum );
270 | data.runConsumTableData = q.slice( 0, data.showCodeCount );
271 |
272 | mainBodyId = data.mainBodyId = util.id();
273 | }
274 | }();
275 |
276 | render = util.bind( function( text ){
277 | this.body.innerHTML = text || template.page( data );
278 | }, this );
279 |
280 | update = function(){
281 | calculate();
282 | render();
283 | };
284 |
285 | eventDelegate = function( el ){
286 | Tracker.Event.add( el, "click", function( e ){
287 | var target, action, codeId;
288 |
289 | target = e.target;
290 | action = target.getAttribute( "action" );
291 | codeId = target.getAttribute( "data-code-id" );
292 |
293 | if( action == "show-code" ){
294 | Tracker.View.ControlPanel.activeTab( "code-list" );
295 | Tracker.View.ControlPanel.showCodeDetail( codeId );
296 | }else if( action == "update" ){
297 | document.getElementById( mainBodyId ).innerHTML = "loading...";
298 | window.setTimeout( update, 1e2 );
299 | }
300 | } );
301 | };
302 |
303 | this.onStartUp( function( win, doc ){
304 | window = win;
305 | document = doc;
306 | eventDelegate( this.body );
307 | } );
308 |
309 | this.onActive( update );
310 | } );
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Tracker 项目主页
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Tracker
16 |
别让包袱成为网页运行时的负担
17 |
18 |
19 |
20 |
21 |
22 |
36 |
37 |
38 |
39 |
1 概述
40 |
Tracker 是一个运行于浏览器书签栏的 JavaScript 嗅探工具,她将被启动于其他网页之后,为了协助您了解目标网页中 JavaScript 的运行情况,包括:执行覆盖率、执行行数、是否存在执行或语法错误等信息,当你对一个目标网页使用 Tracker,该网页的上方将加载进来一个 Tracker 导航栏。
41 |

42 |
43 | 不用安装,快速开始
44 | 也欢迎体验桌面客户端版
45 |
46 |
47 |
48 |
49 |
2 应用场景
50 |
51 |
2.1 冗余代码排查
52 |
产品的迭代速度极快,我们把大部分的时间都花在实现需求上,很少能很好地从新产品开始时就好好规划以足够强大地支持将来的功能扩展(当然和个别 PM 天马行空提需求也有一定关系),加之维护人员的轮换,日积月累,很多代码已由于“历史原因”而不敢再轻易碰。此时,Tracker 能在排查冗余代码时起到很大的帮助,当您猜测某一坨恶心代码是干某件事情时,您不妨用 Tracker 验证一下。
53 |
54 |
2.2 模块化辅助分析
55 |
当您的项目代码臃肿到一定程度时,也许您和我一样,会考虑将它们做些合理拆分,以达到最佳按需加载,哪些代码是网页初始化时必须的;哪些代码是辅助功能可要可不要的;哪些代码是后序功能需要拆分成按需加载的;有了 Tracker,您能够非常方便地做这些判断。
56 |
57 |
2.3 测试用例编写参考
58 |
每一个产品,都需要有属于它的完整的测试用例,除非您并不关心它的质量。我们通常认为:完整的测试用例最起码的要求是能覆盖到您所有代码的业务逻辑(当然合理的测试还应包括功能需求以外的一些异常用例考虑),在进行测试用例的同时,配合使用 Tracker,能直观地看出哪一些业务逻辑没有被用例覆盖到。
59 |
60 |
2.4 依赖库辅助定制
61 |
为了更快速地完成开发,您也许会在项目中插入各种各样的 JS 库,然而,项目本身对这些 JS 库的利用率并不高,很多情况下只是用了它个别功能,这样导致项目产生大量的冗余代码,一定程度上影响了网页加载速度。如果您希望对这些库进行瘦身定制,Tracker 能帮到您。
62 |
63 |
2.5 性能分析参考
64 |
65 |
待续...
66 |
67 |
68 |
69 |
3 快速开始
70 |
71 |
3.1 我只想测试一下
72 |
打开某个网页后,在浏览器的地址栏里直接输入以下代码:
73 |
javascript:void function(t,r,a,c,k){t.tracker_uid='$uid';(k=t.TrackerGlobalEvent)?k.f(r):[(k=t[a]('script')).charset='utf-8',k.src='http://www.ucren.com/'+c+'/'+c+'.js?'+Math.random(),t.documentElement.appendChild(k)]}(document,'TrackerJSLoad','createElement','tracker');
74 |
注意! Chrome 用户要先手工敲入“javascript:”,再将以上这段粘贴进去。
75 |
76 |
3.2 我想留着以后用
77 |
我们希望您将以下链接添加到(拖放到)您的书签栏里,这样能方便您今后的使用:打开指定网页后,再点击书签栏里的 “Tracker!” 链接。
78 |
Tracker!
79 |
80 |
3.3 另有 Chrome 插件版本
81 |
82 | 感谢 @Alienfe 提供 FeHelper 的集成,点此安装 FeHelper
83 |
84 |
85 |
86 |
87 |
4 功能说明
88 |
89 |
4.1 代码列表
90 |
在呼出 Tracker 面板后,您将看到一个列表,这个列表显示出当前网页所用到的所有 JS 代码:
91 |
92 |
93 | -
94 | 名称:通常为 JS 文件名,如果没有文件名,显示为中划线 “-” (如内嵌类型的脚本);
95 |
96 |
97 |
98 |
99 | -
100 | 类型:表明当前 JS 资源是内嵌的、外链文件的还是运行时动态插入的;
101 |
102 |
103 |
104 |
105 | -
106 | 执行覆盖率:当前 JS 资源截止现在已执行的比率,计算方法 = 执行行数 / 总行数;
107 |
108 |
109 |
110 |
111 | -
112 | 执行行数:当前 JS 资源截止现在已执行经过的行数;
113 |
114 |
115 |
116 |
117 | -
118 | 总行数:当前 JS 资源解压后得到的总行数(注:不一定等于 JS 在压缩前的行数);
119 |
120 |
121 |
122 |
123 | -
124 | 原始大小:当前 JS 资源所占字节数;
125 |
126 |
127 |
128 |
129 | -
130 | 解压大小:当前 JS 资源解压后所占字节数;
131 |
132 |
133 |
134 |
135 | -
136 | 加载耗时:当前 JS 资源从开始下载到下载完成消耗的时间;
137 |
138 |
139 |
140 |
141 | -
142 | 运时耗时:当前 JS 资源从头到尾顺序执行消耗的时间;
143 |
144 |
145 |
146 |
147 | -
148 | 执行报错:当前 JS 资源截止现在执行中是否出现错误;
149 |
150 |
151 |
152 |
153 | -
154 | 语法错误:当前 JS 资源是否存在语法错误;
155 |
156 |
157 |
158 |
159 | -
160 | 状态:本次分析的结果状态;
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
4.2 代码面板
169 |
当您点击表格中某一行,此时在表格右侧出现一个代码框,用于显示当前 JS 资源解压后的代码,执行经过的语句或表达式用蓝底黑字表示,没有经过的代码为白底。
170 |

171 |
172 |
4.3 综合结果
173 |
待续...
174 |
175 |
176 |
177 |
5 兼容性
178 |
Tracker 在各浏览器中的表现排序为:Chrome, Safari, Firefox,从左到右为最优到最痤。
179 |
为了发布时能给您一个相对完美与正确的体验,直到边写着这段文字,我还一边在调试浏览器兼容性。上面列表中没有伟大的 IE 浏览器有这两方面的原因:1) 为了能用上最新潮的技术;2) 为了拥有更好的性能。上面列表没有 Opera,仅仅只是因为我还没调试通过它,以及我认为调通它的优先级并不高。:)
180 |
我相信每一位前端开发者都应安装 Chrome 浏览器,如果您还没有上述浏览器之一,我建议您立刻就开始下载 Google Chrome,我不确定它是不是前端开发者的最佳浏览器,但至少在我心目中是。
181 |
182 |
183 |
191 |
192 |
193 |
7 版本历史
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | | 版本 |
204 | 说明 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
8 未来的功能
215 |
我们正在认真规划这个工具的未来,但这并不影响您现在就将她收藏进浏览器中,我们将永久为您保留这个链接,以保证它在将来也是可用的,未来的 Tracker 包括以下功能(暂无优先级之分),您也可以通过后面的章节”反馈“向我提出您的想法!
216 |
217 |
218 |
219 |
220 | | # |
221 | 点子 |
222 | 说明 |
223 |
224 |
225 |
226 |
227 | | 1 |
228 | CSS 冗余 |
229 | 计算哪些 CSS 内容是冗余的 |
230 |
231 |
232 | | 2 |
233 | 函数关系图 |
234 | 生成可视化的全局函数或对象调用关系图 |
235 |
236 |
237 | | 3 |
238 | 错误详情 |
239 | 目前的版本只告诉有没有错误,但没有告诉错误是什么 |
240 |
241 |
242 | | 4 |
243 | 当前网页综述 |
244 | 通过科学计算,给出综合结果 |
245 |
246 |
247 | | 5 |
248 | 更多 |
249 | 期待您的参与 |
250 |
251 |
252 |
253 |
254 |
255 |
9 常见问题
256 |
257 | -
258 |
为什么我的网页 JS 覆盖率这么低?
259 | 网页打开后,显示的 JS 覆盖率为初始化覆盖率,也就是说当前网页在渲染完成后,您还未进行网页上的任何功能操作之前时的覆盖率,如果此时显示的覆盖率很低,您可以考虑请 JS 做分模块按需加载处理。
260 |
261 | -
262 |
iframe 的内容是否纳入统计?
263 | 由于受同源策略限制,iframe 他域网页无法进行捕获解析,出于保持相同策略考虑,同域的 iframe 网页也暂不进行统计。
264 |
265 | -
266 |
由 document.write 引入的脚本是否纳入统计?
267 | 目前还没有这部分内容,以后会考虑支持。
268 |
269 | -
270 |
为什么我在某些网页上使用 Tracker,网页会跳走?
271 | Tracker 启动后会将该网页放置到 iframe 中,该网页可能写了防止嵌入的代码,当被 iframe 嵌入时修改 top.location 导致页面跳转,Tracker 也一直在防止地址被跳走,目前已能在大部分禁止 iframe 嵌入的网页当中使用。
272 |
273 |
274 |
275 |
276 |
10 反馈
277 |
278 |
您可以选择一种您喜欢的方法向我反馈:
279 |
280 |
285 |
286 |
287 |
Tracker 需要您帮忙推广,您可通过微博帮我们传播,举手之劳便是对 Tracker 很大的帮忙,点击下面的链接:
288 |
推荐给好友
289 |
290 |
291 |
292 |
293 |
294 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
--------------------------------------------------------------------------------
/bootstrap/js/zepto.min.js:
--------------------------------------------------------------------------------
1 | /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */
2 | (function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>$2>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/