├── .idea
├── debug-mobile-page.iml
├── dictionaries
│ └── yuwanli.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── images
├── 1.png
├── 2.png
├── 3.png
├── 4.jpg
├── 5.jpg
└── 6.png
└── vconsole.min.js
/.idea/debug-mobile-page.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/dictionaries/yuwanli.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | false
9 |
10 | false
11 | false
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Assignment issuesJavaScript
22 |
23 |
24 | CSS
25 |
26 |
27 | CoffeeScript
28 |
29 |
30 | General
31 |
32 |
33 | GeneralCoffeeScript
34 |
35 |
36 | GeneralJavaScript
37 |
38 |
39 | JavaScript
40 |
41 |
42 | Potentially confusing code constructsJavaScript
43 |
44 |
45 | Probable bugsCSS
46 |
47 |
48 |
49 |
50 | CoffeeScriptUnusedLocalSymbols
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | true
46 | DEFINITION_ORDER
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | $USER_HOME$/.subversion
129 |
130 |
131 |
132 |
133 | 1498973472878
134 |
135 |
136 | 1498973472878
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | debug 手机端页面
2 | ===================
3 | 手机端网页(h5、小游戏等)开发的过程中常常会遇到以下两个问题:
4 |
5 | 1,页面在真机下运行时,会出现一些兼容性的问题,需要对真机下的页面进行调试
6 |
7 | 2,真机环境下有异常时无法捕捉,需要加console来断点判断错误的源头
8 |
9 | 以下是前端菜鸟在实际开发过程中会用到的两种调试方式
10 |
11 | ### [weinre](http://web.jobbole.com/82967/) remote 真机调试
12 |
13 | 1.npm install weinre -g
14 |
15 | 2.weinre --httpPort 8088 --boundHost -all-
16 |
17 | 3.页面引入
18 | ```html
19 | //10.96.228.9:8088 本机ip:端口号
20 |
21 | ```
22 | 
23 |
24 | 4.电脑访问http://10.96.228.9:8088/client/
25 |
26 | 
27 |
28 | 这样成功以后,你会发现前端都很熟悉的东西,elements、resources、network、console有了这些东西,基本上能满足前端调试的需求
29 |
30 | 
31 | 
32 |
33 | ***
34 | 一般情况下,用前端都喜爱的google浏览器的手机模拟器在pc上进行开发调试即可,但是避免不了有需要在手机端进行调试的情况,这个时候用这个就比较方便。但是有一个不足的地方,这个是本地调试,适合于本地开发过程中的调试。下面将要介绍的这个就是在产品线上版本的适合,需紧急处理的情况下,本菜鸟会使用的一个工具。
35 |
36 |
37 | ### 手机端console输入调试
38 |
39 | 使用方式很简单,在页面底部引入[vconsole.min.js](/vconsole.min.js)即可,若是觉得上传麻烦,可以试用下面我的这个文件。
40 | 要是有小程序开发经验的人,对这个肯定不会陌生,小程序把这个调试工具集成到运行环境中了,这个主要是用来看日志的输出,然后可以在控制台里输入指令进行调试。
41 |
42 | ```html
43 |
44 | ```
45 |
46 | 固定在屏幕右下角,可拖拽移动位置
47 |
48 | 
49 |
50 | 点开展开后,可手动输入指令进行调试
51 |
52 | 
53 |
54 | 正如开头所说,这些调试工具在你不得不在真机上调试的时候才去使用,正常开发过程中用浏览器自带的调试工具即可。
55 |
56 | 以上两个工具,对页面多多少少会有些影响,造成页面卡顿,js运行错误(一般不会)等问题,所以在需要的时候使用即可,调试完毕以后记得删除。
57 |
58 | 在实际调试过程中,往往希望可以打断点进行调试,然后上面说的weinre还有vconsole都没有这个功能,在这个情况下我一般会在关键位置进行console输入,然后用vconsole进行查看。
59 |
60 | 当然,手机端的调试工具肯定还有很多,还有更好的,但是还是本着能用、好用、方便用的原则,把这两个分享给大家,有任何想要吐槽、或者觉得有哪里不对的地方,欢迎大家留言。
61 |
62 |
--------------------------------------------------------------------------------
/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuwanli/debug-mobile-page/00ff7e698f18dd827f8a19769a2d573deb8d58c0/images/1.png
--------------------------------------------------------------------------------
/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuwanli/debug-mobile-page/00ff7e698f18dd827f8a19769a2d573deb8d58c0/images/2.png
--------------------------------------------------------------------------------
/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuwanli/debug-mobile-page/00ff7e698f18dd827f8a19769a2d573deb8d58c0/images/3.png
--------------------------------------------------------------------------------
/images/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuwanli/debug-mobile-page/00ff7e698f18dd827f8a19769a2d573deb8d58c0/images/4.jpg
--------------------------------------------------------------------------------
/images/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuwanli/debug-mobile-page/00ff7e698f18dd827f8a19769a2d573deb8d58c0/images/5.jpg
--------------------------------------------------------------------------------
/images/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yuwanli/debug-mobile-page/00ff7e698f18dd827f8a19769a2d573deb8d58c0/images/6.png
--------------------------------------------------------------------------------
/vconsole.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vconsole v2.5.3-dev (https://github.com/WechatFE/vConsole)
3 | * Copyright 2017, WechatFE Team
4 | * MIT license
5 | */
6 | (function webpackUniversalModuleDefinition(root, factory) {
7 | if(typeof exports === 'object' && typeof module === 'object')
8 | module.exports = factory();
9 | else if(typeof define === 'function' && define.amd)
10 | define([], factory);
11 | else if(typeof exports === 'object')
12 | exports["vConsole"] = factory();
13 | else
14 | root["vConsole"] = factory();
15 | })(this, function() {
16 | return /******/ (function(modules) { // webpackBootstrap
17 | /******/ // The module cache
18 | /******/ var installedModules = {};
19 |
20 | /******/ // The require function
21 | /******/ function __webpack_require__(moduleId) {
22 |
23 | /******/ // Check if module is in cache
24 | /******/ if(installedModules[moduleId])
25 | /******/ return installedModules[moduleId].exports;
26 |
27 | /******/ // Create a new module (and put it into the cache)
28 | /******/ var module = installedModules[moduleId] = {
29 | /******/ exports: {},
30 | /******/ id: moduleId,
31 | /******/ loaded: false
32 | /******/ };
33 |
34 | /******/ // Execute the module function
35 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
36 |
37 | /******/ // Flag the module as loaded
38 | /******/ module.loaded = true;
39 |
40 | /******/ // Return the exports of the module
41 | /******/ return module.exports;
42 | /******/ }
43 |
44 |
45 | /******/ // expose the modules object (__webpack_modules__)
46 | /******/ __webpack_require__.m = modules;
47 |
48 | /******/ // expose the module cache
49 | /******/ __webpack_require__.c = installedModules;
50 |
51 | /******/ // __webpack_public_path__
52 | /******/ __webpack_require__.p = "";
53 |
54 | /******/ // Load entry module and return exports
55 | /******/ return __webpack_require__(0);
56 | /******/ })
57 | /************************************************************************/
58 | /******/ ([
59 | /* 0 */
60 | /***/ function(module, exports, __webpack_require__) {
61 |
62 | 'use strict';
63 |
64 | Object.defineProperty(exports, "__esModule", {
65 | value: true
66 | });
67 |
68 | var _core = __webpack_require__(1);
69 |
70 | var _core2 = _interopRequireDefault(_core);
71 |
72 | var _plugin = __webpack_require__(15);
73 |
74 | var _plugin2 = _interopRequireDefault(_plugin);
75 |
76 | var _default = __webpack_require__(16);
77 |
78 | var _default2 = _interopRequireDefault(_default);
79 |
80 | var _system = __webpack_require__(23);
81 |
82 | var _system2 = _interopRequireDefault(_system);
83 |
84 | var _network = __webpack_require__(25);
85 |
86 | var _network2 = _interopRequireDefault(_network);
87 |
88 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
89 |
90 | // here we go
91 | var vConsole = new _core2.default();
92 | // built-in tabs
93 | /**
94 | * A Front-End Console Panel for Mobile Webpage
95 | *
96 | * @author WechatFE
97 | */
98 |
99 | // classes
100 |
101 |
102 | var defaultTab = new _default2.default('default', 'Log');
103 | vConsole.addPlugin(defaultTab);
104 |
105 | var systemTab = new _system2.default('system', 'System');
106 | vConsole.addPlugin(systemTab);
107 |
108 | var networkTab = new _network2.default('network', 'Network');
109 | vConsole.addPlugin(networkTab);
110 |
111 | // export
112 | vConsole.VConsolePlugin = _plugin2.default;
113 | exports.default = vConsole;
114 | module.exports = exports['default'];
115 |
116 | /***/ },
117 | /* 1 */
118 | /***/ function(module, exports, __webpack_require__) {
119 |
120 | 'use strict';
121 |
122 | Object.defineProperty(exports, "__esModule", {
123 | value: true
124 | });
125 |
126 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
127 | * vConsole core class
128 | *
129 | * @author WechatFE
130 | */
131 |
132 | var _package = __webpack_require__(2);
133 |
134 | var _package2 = _interopRequireDefault(_package);
135 |
136 | var _tool = __webpack_require__(3);
137 |
138 | var tool = _interopRequireWildcard(_tool);
139 |
140 | var _query = __webpack_require__(4);
141 |
142 | var _query2 = _interopRequireDefault(_query);
143 |
144 | __webpack_require__(6);
145 |
146 | var _core = __webpack_require__(10);
147 |
148 | var _core2 = _interopRequireDefault(_core);
149 |
150 | var _tabbar = __webpack_require__(11);
151 |
152 | var _tabbar2 = _interopRequireDefault(_tabbar);
153 |
154 | var _tabbox = __webpack_require__(12);
155 |
156 | var _tabbox2 = _interopRequireDefault(_tabbox);
157 |
158 | var _topbar_item = __webpack_require__(13);
159 |
160 | var _topbar_item2 = _interopRequireDefault(_topbar_item);
161 |
162 | var _tool_item = __webpack_require__(14);
163 |
164 | var _tool_item2 = _interopRequireDefault(_tool_item);
165 |
166 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
167 |
168 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
169 |
170 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
171 |
172 | var VConsole = function () {
173 | function VConsole() {
174 | _classCallCheck(this, VConsole);
175 |
176 | var that = this;
177 |
178 | this.version = _package2.default.version;
179 | this.html = _core2.default;
180 | this.$dom = null;
181 | this.activedTab = '';
182 | this.tabList = [];
183 | this.pluginList = {};
184 | this.isReady = false;
185 | this.switchPos = {
186 | x: 10, // right
187 | y: 10, // bottom
188 | startX: 0,
189 | startY: 0,
190 | endX: 0,
191 | endY: 0
192 | };
193 |
194 | // export helper functions to public
195 | this.tool = tool;
196 | this.$ = _query2.default;
197 |
198 | var _onload = function _onload() {
199 | that._render();
200 | that._mockTap();
201 | that._bindEvent();
202 | that._autoRun();
203 | };
204 | if (document !== undefined) {
205 | if (document.readyState == 'complete') {
206 | _onload();
207 | } else {
208 | _query2.default.bind(window, 'load', _onload);
209 | }
210 | } else {
211 | (function () {
212 | // if document does not exist, wait for it
213 | var _timer = void 0;
214 | var _pollingDocument = function _pollingDocument() {
215 | if (document && document.readyState == 'complete') {
216 | _timer && clearTimeout(_timer);
217 | _onload();
218 | } else {
219 | _timer = setTimeout(_pollingDocument, 1);
220 | }
221 | };
222 | _timer = setTimeout(_pollingDocument, 1);
223 | })();
224 | }
225 | }
226 |
227 | /**
228 | * render panel DOM
229 | * @private
230 | */
231 |
232 |
233 | _createClass(VConsole, [{
234 | key: '_render',
235 | value: function _render() {
236 | var id = '#__vconsole';
237 | if (!_query2.default.one(id)) {
238 | var e = document.createElement('div');
239 | e.innerHTML = this.html;
240 | document.documentElement.insertAdjacentElement('beforeend', e.children[0]);
241 | }
242 | this.$dom = _query2.default.one(id);
243 |
244 | // reposition switch button
245 | var $switch = _query2.default.one('.vc-switch', this.$dom);
246 | var switchX = tool.getStorage('switch_x') * 1,
247 | switchY = tool.getStorage('switch_y') * 1;
248 | if (switchX || switchY) {
249 | // check edge
250 | if (switchX + $switch.offsetWidth > document.documentElement.offsetWidth) {
251 | switchX = document.documentElement.offsetWidth - $switch.offsetWidth;
252 | }
253 | if (switchY + $switch.offsetHeight > document.documentElement.offsetHeight) {
254 | switchY = document.documentElement.offsetHeight - $switch.offsetHeight;
255 | }
256 | if (switchX < 0) {
257 | switchX = 0;
258 | }
259 | if (switchY < 0) {
260 | switchY = 0;
261 | }
262 | this.switchPos.x = switchX;
263 | this.switchPos.y = switchY;
264 | _query2.default.one('.vc-switch').style.right = switchX + 'px';
265 | _query2.default.one('.vc-switch').style.bottom = switchY + 'px';
266 | }
267 |
268 | // remove from less to present transition effect
269 | _query2.default.one('.vc-mask', this.$dom).style.display = 'none';
270 | }
271 | }, {
272 | key: '_mockTap',
273 |
274 |
275 | /**
276 | * simulate tap event by touchstart & touchend
277 | * @private
278 | */
279 | value: function _mockTap() {
280 | var tapTime = 700,
281 | // maximun tap interval
282 | tapBoundary = 10; // max tap move distance
283 |
284 | var lastTouchStartTime = void 0,
285 | touchstartX = void 0,
286 | touchstartY = void 0,
287 | touchHasMoved = false,
288 | targetElem = null;
289 |
290 | this.$dom.addEventListener('touchstart', function (e) {
291 | // todo: if double click
292 | if (lastTouchStartTime === undefined) {
293 | var touch = e.targetTouches[0];
294 | touchstartX = touch.pageX;
295 | touchstartY = touch.pageY;
296 | lastTouchStartTime = e.timeStamp;
297 | targetElem = e.target.nodeType === Node.TEXT_NODE ? e.target.parentNode : e.target;
298 | }
299 | }, false);
300 |
301 | this.$dom.addEventListener('touchmove', function (e) {
302 | var touch = e.changedTouches[0];
303 | if (Math.abs(touch.pageX - touchstartX) > tapBoundary || Math.abs(touch.pageY - touchstartY) > tapBoundary) {
304 | touchHasMoved = true;
305 | }
306 | });
307 |
308 | this.$dom.addEventListener('touchend', function (e) {
309 | // move and time within limits, manually trigger `click` event
310 | if (touchHasMoved === false && e.timeStamp - lastTouchStartTime < tapTime && targetElem != null) {
311 | var tagName = targetElem.tagName.toLowerCase(),
312 | needFocus = false;
313 | switch (tagName) {
314 | case 'textarea':
315 | // focus
316 | needFocus = true;break;
317 | case 'input':
318 | switch (targetElem.type) {
319 | case 'button':
320 | case 'checkbox':
321 | case 'file':
322 | case 'image':
323 | case 'radio':
324 | case 'submit':
325 | needFocus = false;break;
326 | default:
327 | needFocus = !targetElem.disabled && !targetElem.readOnly;
328 | }
329 | default:
330 | break;
331 | }
332 | if (needFocus) {
333 | targetElem.focus();
334 | } else {
335 | e.preventDefault(); // prevent click 300ms later
336 | }
337 | var touch = e.changedTouches[0];
338 | var event = document.createEvent('MouseEvents');
339 | event.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
340 | event.forwardedTouchEvent = true;
341 | event.initEvent('click', true, true);
342 | targetElem.dispatchEvent(event);
343 | }
344 |
345 | // reset values
346 | lastTouchStartTime = undefined;
347 | touchHasMoved = false;
348 | targetElem = null;
349 | }, false);
350 | }
351 | /**
352 | * bind DOM events
353 | * @private
354 | */
355 |
356 | }, {
357 | key: '_bindEvent',
358 | value: function _bindEvent() {
359 | var that = this;
360 |
361 | // drag & drop switch button
362 | var $switch = _query2.default.one('.vc-switch', that.$dom);
363 | _query2.default.bind($switch, 'touchstart', function (e) {
364 | that.switchPos.startX = e.touches[0].pageX;
365 | that.switchPos.startY = e.touches[0].pageY;
366 | });
367 | _query2.default.bind($switch, 'touchend', function (e) {
368 | that.switchPos.x = that.switchPos.endX;
369 | that.switchPos.y = that.switchPos.endY;
370 | that.switchPos.startX = 0;
371 | that.switchPos.startY = 0;
372 | that.switchPos.endX = 0;
373 | that.switchPos.endY = 0;
374 | tool.setStorage('switch_x', that.switchPos.x);
375 | tool.setStorage('switch_y', that.switchPos.y);
376 | });
377 | _query2.default.bind($switch, 'touchmove', function (e) {
378 | if (e.touches.length > 0) {
379 | var offsetX = e.touches[0].pageX - that.switchPos.startX,
380 | offsetY = e.touches[0].pageY - that.switchPos.startY;
381 | var x = that.switchPos.x - offsetX,
382 | y = that.switchPos.y - offsetY;
383 | // check edge
384 | if (x + $switch.offsetWidth > document.documentElement.offsetWidth) {
385 | x = document.documentElement.offsetWidth - $switch.offsetWidth;
386 | }
387 | if (y + $switch.offsetHeight > document.documentElement.offsetHeight) {
388 | y = document.documentElement.offsetHeight - $switch.offsetHeight;
389 | }
390 | if (x < 0) {
391 | x = 0;
392 | }
393 | if (y < 0) {
394 | y = 0;
395 | }
396 | $switch.style.right = x + 'px';
397 | $switch.style.bottom = y + 'px';
398 | that.switchPos.endX = x;
399 | that.switchPos.endY = y;
400 | e.preventDefault();
401 | }
402 | });
403 |
404 | // show console panel
405 | _query2.default.bind(_query2.default.one('.vc-switch', that.$dom), 'click', function () {
406 | that.show();
407 | });
408 |
409 | // hide console panel
410 | _query2.default.bind(_query2.default.one('.vc-hide', that.$dom), 'click', function () {
411 | that.hide();
412 | });
413 |
414 | // hide console panel when tap background mask
415 | _query2.default.bind(_query2.default.one('.vc-mask', that.$dom), 'click', function (e) {
416 | if (e.target != _query2.default.one('.vc-mask')) {
417 | return false;
418 | }
419 | that.hide();
420 | });
421 |
422 | // show tab box
423 | _query2.default.delegate(_query2.default.one('.vc-tabbar', that.$dom), 'click', '.vc-tab', function (e) {
424 | var tabName = this.dataset.tab;
425 | if (tabName == that.activedTab) {
426 | return;
427 | }
428 | that.showTab(tabName);
429 | });
430 |
431 | // after console panel, trigger a transitionend event to make panel's property 'display' change from 'block' to 'none'
432 | _query2.default.bind(_query2.default.one('.vc-panel', that.$dom), 'transitionend webkitTransitionEnd oTransitionEnd otransitionend', function (e) {
433 | if (e.target != _query2.default.one('.vc-panel')) {
434 | return false;
435 | }
436 | if (!_query2.default.hasClass(that.$dom, 'vc-toggle')) {
437 | e.target.style.display = 'none';
438 | }
439 | });
440 |
441 | // disable background scrolling
442 | var $content = _query2.default.one('.vc-content', that.$dom);
443 | var preventMove = false;
444 | _query2.default.bind($content, 'touchstart', function (e) {
445 | var top = $content.scrollTop,
446 | totalScroll = $content.scrollHeight,
447 | currentScroll = top + $content.offsetHeight;
448 | if (top === 0) {
449 | // when content is on the top,
450 | // reset scrollTop to lower position to prevent iOS apply scroll action to background
451 | $content.scrollTop = 1;
452 | // however, when content's height is less than its container's height,
453 | // scrollTop always equals to 0 (it is always on the top),
454 | // so we need to prevent scroll event manually
455 | if ($content.scrollTop === 0) {
456 | if (!_query2.default.hasClass(e.target, 'vc-cmd-input')) {
457 | // skip input
458 | preventMove = true;
459 | }
460 | }
461 | } else if (currentScroll === totalScroll) {
462 | // when content is on the bottom,
463 | // do similar processing
464 | $content.scrollTop = top - 1;
465 | if ($content.scrollTop === top) {
466 | if (!_query2.default.hasClass(e.target, 'vc-cmd-input')) {
467 | preventMove = true;
468 | }
469 | }
470 | }
471 | });
472 |
473 | _query2.default.bind($content, 'touchmove', function (e) {
474 | if (preventMove) {
475 | e.preventDefault();
476 | }
477 | });
478 |
479 | _query2.default.bind($content, 'touchend', function (e) {
480 | preventMove = false;
481 | });
482 | }
483 | }, {
484 | key: '_autoRun',
485 |
486 |
487 | /**
488 | * auto run after initialization
489 | * @private
490 | */
491 | value: function _autoRun() {
492 | this.isReady = true;
493 |
494 | // init plugins
495 | for (var id in this.pluginList) {
496 | this._initPlugin(this.pluginList[id]);
497 | }
498 |
499 | // show first tab
500 | if (this.tabList.length > 0) {
501 | this.showTab(this.tabList[0]);
502 | }
503 | }
504 |
505 | /**
506 | * init a plugin
507 | * @private
508 | */
509 |
510 | }, {
511 | key: '_initPlugin',
512 | value: function _initPlugin(plugin) {
513 | var that = this;
514 | // start init
515 | plugin.trigger('init');
516 | // render tab (if it is a tab plugin then it should has tab-related events)
517 | plugin.trigger('renderTab', function (tabboxHTML) {
518 | // add to tabList
519 | that.tabList.push(plugin.id);
520 | // render tabbar
521 | var $tabbar = _query2.default.render(_tabbar2.default, { id: plugin.id, name: plugin.name });
522 | _query2.default.one('.vc-tabbar', that.$dom).insertAdjacentElement('beforeend', $tabbar);
523 | // render tabbox
524 | var $tabbox = _query2.default.render(_tabbox2.default, { id: plugin.id });
525 | if (!!tabboxHTML) {
526 | if (tool.isString(tabboxHTML)) {
527 | $tabbox.innerHTML += tabboxHTML;
528 | } else if (tool.isFunction(tabboxHTML.appendTo)) {
529 | tabboxHTML.appendTo($tabbox);
530 | } else if (tool.isElement(tabboxHTML)) {
531 | $tabbox.insertAdjacentElement('beforeend', tabboxHTML);
532 | }
533 | }
534 | _query2.default.one('.vc-content', that.$dom).insertAdjacentElement('beforeend', $tabbox);
535 | });
536 | // render top bar
537 | plugin.trigger('addTopBar', function (btnList) {
538 | if (!btnList) {
539 | return;
540 | }
541 | var $topbar = _query2.default.one('.vc-topbar', that.$dom);
542 |
543 | var _loop = function _loop(i) {
544 | var item = btnList[i];
545 | var $item = _query2.default.render(_topbar_item2.default, {
546 | name: item.name || 'Undefined',
547 | className: item.className || '',
548 | pluginID: plugin.id
549 | });
550 | if (item.data) {
551 | for (var k in item.data) {
552 | $item.dataset[k] = item.data[k];
553 | }
554 | }
555 | if (tool.isFunction(item.onClick)) {
556 | _query2.default.bind($item, 'click', function (e) {
557 | var enable = item.onClick.call($item);
558 | if (enable === false) {
559 | // do nothing
560 | } else {
561 | _query2.default.removeClass(_query2.default.all('.vc-topbar-' + plugin.id), 'vc-actived');
562 | _query2.default.addClass($item, 'vc-actived');
563 | }
564 | });
565 | }
566 | $topbar.insertAdjacentElement('beforeend', $item);
567 | };
568 |
569 | for (var i = 0; i < btnList.length; i++) {
570 | _loop(i);
571 | }
572 | });
573 | // render tool bar
574 | plugin.trigger('addTool', function (toolList) {
575 | if (!toolList) {
576 | return;
577 | }
578 | var $defaultBtn = _query2.default.one('.vc-tool-last');
579 |
580 | var _loop2 = function _loop2(i) {
581 | var item = toolList[i];
582 | var $item = _query2.default.render(_tool_item2.default, {
583 | name: item.name || 'Undefined',
584 | pluginID: plugin.id
585 | });
586 | if (item.global == true) {
587 | _query2.default.addClass($item, 'vc-global-tool');
588 | }
589 | if (tool.isFunction(item.onClick)) {
590 | _query2.default.bind($item, 'click', function (e) {
591 | item.onClick.call($item);
592 | });
593 | }
594 | $defaultBtn.parentNode.insertBefore($item, $defaultBtn);
595 | };
596 |
597 | for (var i = 0; i < toolList.length; i++) {
598 | _loop2(i);
599 | }
600 | });
601 | // end init
602 | plugin.trigger('ready');
603 | }
604 |
605 | /**
606 | * trigger an event for each plugin
607 | * @private
608 | */
609 |
610 | }, {
611 | key: '_triggerPluginsEvent',
612 | value: function _triggerPluginsEvent(eventName) {
613 | for (var id in this.pluginList) {
614 | this.pluginList[id].trigger(eventName);
615 | }
616 | }
617 |
618 | /**
619 | * trigger an event by plugin's name
620 | * @private
621 | */
622 |
623 | }, {
624 | key: '_triggerPluginEvent',
625 | value: function _triggerPluginEvent(pluginName, eventName) {
626 | var plugin = this.pluginList[pluginName];
627 | if (plugin) {
628 | plugin.trigger(eventName);
629 | }
630 | }
631 |
632 | /**
633 | * add a new plugin
634 | * @public
635 | * @param object VConsolePlugin object
636 | * @return boolean
637 | */
638 |
639 | }, {
640 | key: 'addPlugin',
641 | value: function addPlugin(plugin) {
642 | // ignore this plugin if it has already been installed
643 | if (this.pluginList[plugin.id] !== undefined) {
644 | console.warn('Plugin ' + plugin.id + ' has already been added.');
645 | return false;
646 | }
647 | this.pluginList[plugin.id] = plugin;
648 | // init plugin only if vConsole is ready
649 | if (this.isReady) {
650 | this._initPlugin(plugin);
651 | // if it's the first plugin, show it by default
652 | if (this.tabList.length == 1) {
653 | this.showTab(this.tabList[0]);
654 | }
655 | }
656 | return true;
657 | }
658 |
659 | /**
660 | * remove a plugin
661 | * @public
662 | * @param string pluginID
663 | * @return boolean
664 | */
665 |
666 | }, {
667 | key: 'removePlugin',
668 | value: function removePlugin(pluginID) {
669 | pluginID = (pluginID + '').toLowerCase();
670 | var plugin = this.pluginList[pluginID];
671 | // skip if is has not been installed
672 | if (plugin === undefined) {
673 | console.warn('Plugin ' + pluginID + ' does not exist.');
674 | return false;
675 | }
676 | // trigger `remove` event before uninstall
677 | plugin.trigger('remove');
678 | // the plugin will not be initialized before vConsole is ready,
679 | // so the plugin does not need to handle DOM-related actions in this case
680 | if (this.isReady) {
681 | var $tabbar = _query2.default.one('#__vc_tab_' + pluginID);
682 | $tabbar && $tabbar.parentNode.removeChild($tabbar);
683 | // remove topbar
684 | var $topbar = _query2.default.all('.vc-topbar-' + pluginID, this.$dom);
685 | for (var i = 0; i < $topbar.length; i++) {
686 | $topbar[i].parentNode.removeChild($topbar[i]);
687 | }
688 | // remove content
689 | var $content = _query2.default.one('#__vc_log_' + pluginID);
690 | $content && $content.parentNode.removeChild($content);
691 | // remove tool bar
692 | var $toolbar = _query2.default.all('.vc-tool-' + pluginID, this.$dom);
693 | for (var _i = 0; _i < $toolbar.length; _i++) {
694 | $toolbar[_i].parentNode.removeChild($toolbar[_i]);
695 | }
696 | }
697 | // remove plugin from list
698 | var index = this.tabList.indexOf(pluginID);
699 | if (index > -1) {
700 | this.tabList.splice(index, 1);
701 | }
702 | try {
703 | delete this.pluginList[pluginID];
704 | } catch (e) {
705 | this.pluginList[pluginID] = undefined;
706 | }
707 | // show the first plugin by default
708 | if (this.activedTab == pluginID) {
709 | if (this.tabList.length > 0) {
710 | this.showTab(this.tabList[0]);
711 | }
712 | }
713 | return true;
714 | }
715 |
716 | /**
717 | * show console panel
718 | * @public
719 | */
720 |
721 | }, {
722 | key: 'show',
723 | value: function show() {
724 | var that = this;
725 | // before show console panel,
726 | // trigger a transitionstart event to make panel's property 'display' change from 'none' to 'block'
727 | var $panel = _query2.default.one('.vc-panel', this.$dom);
728 | $panel.style.display = 'block';
729 |
730 | // set 10ms delay to fix confict between display and transition
731 | setTimeout(function () {
732 | _query2.default.addClass(that.$dom, 'vc-toggle');
733 | that._triggerPluginsEvent('showConsole');
734 | var $mask = _query2.default.one('.vc-mask', that.$dom);
735 | $mask.style.display = 'block';
736 | }, 10);
737 | }
738 |
739 | /**
740 | * hide console paneldocument.body.scrollTop
741 | * @public
742 | */
743 |
744 | }, {
745 | key: 'hide',
746 | value: function hide() {
747 | _query2.default.removeClass(this.$dom, 'vc-toggle');
748 | this._triggerPluginsEvent('hideConsole');
749 |
750 | var $mask = _query2.default.one('.vc-mask', this.$dom),
751 | $panel = _query2.default.one('.vc-panel', this.$dom);
752 | _query2.default.bind($mask, 'transitionend', function (evnet) {
753 | $mask.style.display = 'none';
754 | $panel.style.display = 'none';
755 | });
756 | }
757 |
758 | /**
759 | * show a tab
760 | * @public
761 | */
762 |
763 | }, {
764 | key: 'showTab',
765 | value: function showTab(tabID) {
766 | var $logbox = _query2.default.one('#__vc_log_' + tabID);
767 | // set actived status
768 | _query2.default.removeClass(_query2.default.all('.vc-tab', this.$dom), 'vc-actived');
769 | _query2.default.addClass(_query2.default.one('#__vc_tab_' + tabID), 'vc-actived');
770 | _query2.default.removeClass(_query2.default.all('.vc-logbox', this.$dom), 'vc-actived');
771 | _query2.default.addClass($logbox, 'vc-actived');
772 | // show topbar
773 | var $curTopbar = _query2.default.all('.vc-topbar-' + tabID, this.$dom);
774 | _query2.default.removeClass(_query2.default.all('.vc-toptab', this.$dom), 'vc-toggle');
775 | _query2.default.addClass($curTopbar, 'vc-toggle');
776 | if ($curTopbar.length > 0) {
777 | _query2.default.addClass(_query2.default.one('.vc-content', this.$dom), 'vc-has-topbar');
778 | } else {
779 | _query2.default.removeClass(_query2.default.one('.vc-content', this.$dom), 'vc-has-topbar');
780 | }
781 | // show toolbar
782 | _query2.default.removeClass(_query2.default.all('.vc-tool', this.$dom), 'vc-toggle');
783 | _query2.default.addClass(_query2.default.all('.vc-tool-' + tabID, this.$dom), 'vc-toggle');
784 | // trigger plugin event
785 | this._triggerPluginEvent(this.activedTab, 'hide');
786 | this.activedTab = tabID;
787 | this._triggerPluginEvent(this.activedTab, 'show');
788 | }
789 | }]);
790 |
791 | return VConsole;
792 | }(); // END class
793 |
794 | exports.default = VConsole;
795 | module.exports = exports['default'];
796 |
797 | /***/ },
798 | /* 2 */
799 | /***/ function(module, exports) {
800 |
801 | module.exports = {
802 | "name": "vconsole",
803 | "version": "2.5.3-dev",
804 | "description": "A lightweight, extendable front-end developer tool for mobile web page.",
805 | "homepage": "https://github.com/WechatFE/vConsole",
806 | "main": "dist/vconsole.min.js",
807 | "scripts": {
808 | "test": "mocha",
809 | "dist": "webpack && npm test"
810 | },
811 | "keywords": [
812 | "console",
813 | "debug",
814 | "mobile"
815 | ],
816 | "repository": {
817 | "type": "git",
818 | "url": "git+https://github.com/WechatFE/vConsole.git"
819 | },
820 | "dependencies": {},
821 | "devDependencies": {
822 | "babel-core": "^6.7.7",
823 | "babel-loader": "^6.2.4",
824 | "babel-plugin-add-module-exports": "^0.1.4",
825 | "babel-preset-es2015": "^6.6.0",
826 | "babel-preset-stage-3": "^6.5.0",
827 | "chai": "^3.5.0",
828 | "css-loader": "^0.23.1",
829 | "extract-text-webpack-plugin": "^1.0.1",
830 | "html-loader": "^0.4.3",
831 | "jsdom": "^9.2.1",
832 | "json-loader": "^0.5.4",
833 | "less": "^2.5.3",
834 | "less-loader": "^2.2.3",
835 | "mocha": "^2.5.3",
836 | "style-loader": "^0.13.1",
837 | "webpack": "~1.12.11"
838 | },
839 | "author": "WechatFE Team",
840 | "license": "MIT"
841 | };
842 |
843 | /***/ },
844 | /* 3 */
845 | /***/ function(module, exports) {
846 |
847 | 'use strict';
848 |
849 | Object.defineProperty(exports, "__esModule", {
850 | value: true
851 | });
852 |
853 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
854 |
855 | exports.getDate = getDate;
856 | exports.isNumber = isNumber;
857 | exports.isString = isString;
858 | exports.isArray = isArray;
859 | exports.isBoolean = isBoolean;
860 | exports.isUndefined = isUndefined;
861 | exports.isNull = isNull;
862 | exports.isSymbol = isSymbol;
863 | exports.isObject = isObject;
864 | exports.isFunction = isFunction;
865 | exports.isElement = isElement;
866 | exports.isPlainObject = isPlainObject;
867 | exports.htmlEncode = htmlEncode;
868 | exports.JSONStringify = JSONStringify;
869 | exports.getObjAllKeys = getObjAllKeys;
870 | exports.getObjName = getObjName;
871 | exports.setStorage = setStorage;
872 | exports.getStorage = getStorage;
873 | /**
874 | * Utility Functions
875 | *
876 | * @author WechatFE
877 | */
878 |
879 | /**
880 | * get formatted date by timestamp
881 | * @param int time
882 | * @return object
883 | */
884 | function getDate(time) {
885 | var d = time > 0 ? new Date(time) : new Date();
886 | var day = d.getDate() < 10 ? '0' + d.getDate() : d.getDate(),
887 | month = d.getMonth() < 9 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1,
888 | year = d.getFullYear(),
889 | hour = d.getHours() < 10 ? '0' + d.getHours() : d.getHours(),
890 | minute = d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes(),
891 | second = d.getSeconds() < 10 ? '0' + d.getSeconds() : d.getSeconds(),
892 | millisecond = d.getMilliseconds() < 10 ? '0' + d.getMilliseconds() : d.getMilliseconds();
893 | if (millisecond < 100) {
894 | millisecond = '0' + millisecond;
895 | }
896 | return {
897 | time: +d,
898 | year: year,
899 | month: month,
900 | day: day,
901 | hour: hour,
902 | minute: minute,
903 | second: second,
904 | millisecond: millisecond
905 | };
906 | }
907 |
908 | /**
909 | * determines whether the passed value is a specific type
910 | * @param mixed value
911 | * @return boolean
912 | */
913 | function isNumber(value) {
914 | return Object.prototype.toString.call(value) == '[object Number]';
915 | }
916 | function isString(value) {
917 | return Object.prototype.toString.call(value) == '[object String]';
918 | }
919 | function isArray(value) {
920 | return Object.prototype.toString.call(value) == '[object Array]';
921 | }
922 | function isBoolean(value) {
923 | return Object.prototype.toString.call(value) == '[object Boolean]';
924 | }
925 | function isUndefined(value) {
926 | return Object.prototype.toString.call(value) == '[object Undefined]';
927 | }
928 | function isNull(value) {
929 | return Object.prototype.toString.call(value) == '[object Null]';
930 | }
931 | function isSymbol(value) {
932 | return Object.prototype.toString.call(value) == '[object Symbol]';
933 | }
934 | function isObject(value) {
935 | return Object.prototype.toString.call(value) == '[object Object]' ||
936 | // if it isn't a primitive value, then it is a common object
937 | !isNumber(value) && !isString(value) && !isBoolean(value) && !isArray(value) && !isNull(value) && !isFunction(value) && !isUndefined(value) && !isSymbol(value);
938 | }
939 | function isFunction(value) {
940 | return Object.prototype.toString.call(value) == '[object Function]';
941 | }
942 | function isElement(value) {
943 | return (typeof HTMLElement === 'undefined' ? 'undefined' : _typeof(HTMLElement)) === 'object' ? value instanceof HTMLElement : //DOM2
944 | value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === "object" && value !== null && value.nodeType === 1 && typeof value.nodeName === "string";
945 | }
946 |
947 | /**
948 | * check whether an object is plain (using {})
949 | * @param object obj
950 | * @return boolean
951 | */
952 | function isPlainObject(obj) {
953 | var hasOwn = Object.prototype.hasOwnProperty;
954 | // Must be an Object.
955 | if (!obj || (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || obj.nodeType || isWindow(obj)) {
956 | return false;
957 | }
958 | try {
959 | if (obj.constructor && !hasOwn.call(obj, 'constructor') && !hasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) {
960 | return false;
961 | }
962 | } catch (e) {
963 | return false;
964 | }
965 | var key = void 0;
966 | for (key in obj) {}
967 | return key === undefined || hasOwn.call(obj, key);
968 | }
969 |
970 | /**
971 | * HTML encode a string
972 | * @param string text
973 | * @return string
974 | */
975 | function htmlEncode(text) {
976 | return document.createElement('a').appendChild(document.createTextNode(text)).parentNode.innerHTML;
977 | }
978 |
979 | /**
980 | * JSON stringify, support circular structure
981 | */
982 | function JSONStringify(obj) {
983 | var json = '',
984 | lv = 0;
985 |
986 | // use a map to track parent relationship
987 | var objMap = [];
988 | function _hasSameParentAsChild(child) {
989 | // find upper item which child is equal to this child
990 | for (var i = objMap.length - 1; i >= 0; i--) {
991 | if (objMap[i].child == child) {
992 | return true;
993 | }
994 | }
995 | return false;
996 | }
997 |
998 | function _iterateObj(val) {
999 | if (isObject(val)) {
1000 | // object
1001 | if (_hasSameParentAsChild(val)) {
1002 | // this object is circular, skip it
1003 | json += "CircularObject";
1004 | return;
1005 | }
1006 | objMap.push({ parent: parent, child: val });
1007 |
1008 | var keys = Object.keys(val);
1009 | json += "{";
1010 | lv++;
1011 | for (var i = 0; i < keys.length; i++) {
1012 | var k = keys[i];
1013 | if (val.hasOwnProperty && !val.hasOwnProperty(k)) {
1014 | continue;
1015 | }
1016 | json += k + ': ';
1017 | _iterateObj(val[k], val);
1018 | if (i < keys.length - 1) {
1019 | json += ', ';
1020 | }
1021 | }
1022 | lv--;
1023 | json += '}';
1024 |
1025 | objMap.pop();
1026 | } else if (isArray(val)) {
1027 | // array
1028 | if (_hasSameParentAsChild(val)) {
1029 | // this array is circular, skip it
1030 | json += "CircularArray";
1031 | return;
1032 | }
1033 | objMap.push({ parent: parent, child: val });
1034 |
1035 | json += '[';
1036 | lv++;
1037 | for (var _i = 0; _i < val.length; _i++) {
1038 | _iterateObj(val[_i], val);
1039 | if (_i < val.length - 1) {
1040 | json += ', ';
1041 | }
1042 | }
1043 | lv--;
1044 | json += ']';
1045 |
1046 | objMap.pop();
1047 | } else if (isString(val)) {
1048 | json += '"' + val + '"';
1049 | } else if (isNumber(val)) {
1050 | json += val;
1051 | } else if (isBoolean(val)) {
1052 | json += val;
1053 | } else if (isNull(val)) {
1054 | json += 'null';
1055 | } else if (isUndefined(val)) {
1056 | json += 'undefined';
1057 | } else if (isFunction(val)) {
1058 | json += 'function()';
1059 | } else if (isSymbol(val)) {
1060 | json += 'symbol';
1061 | } else {
1062 | json += 'unknown';
1063 | }
1064 | }
1065 | _iterateObj(obj, null);
1066 |
1067 | return json;
1068 | }
1069 |
1070 | /**
1071 | * get an object's all keys ignore whether they are not enumerable
1072 | */
1073 | function getObjAllKeys(obj) {
1074 | if (!isObject(obj) && !isArray(obj)) {
1075 | return [];
1076 | }
1077 | var dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];
1078 | var keys = [];
1079 | for (var key in obj) {
1080 | if (dontEnums.indexOf(key) < 0) {
1081 | keys.push(key);
1082 | }
1083 | }
1084 | keys = keys.sort();
1085 | return keys;
1086 | }
1087 |
1088 | /**
1089 | * get an object's prototype name
1090 | */
1091 | function getObjName(obj) {
1092 | return Object.prototype.toString.call(obj).replace('[object ', '').replace(']', '');
1093 | }
1094 |
1095 | /**
1096 | * localStorage methods
1097 | */
1098 | function setStorage(key, value) {
1099 | if (!window.localStorage) {
1100 | return;
1101 | }
1102 | key = 'vConsole_' + key;
1103 | localStorage.setItem(key, value);
1104 | }
1105 | function getStorage(key) {
1106 | if (!window.localStorage) {
1107 | return;
1108 | }
1109 | key = 'vConsole_' + key;
1110 | return localStorage.getItem(key);
1111 | }
1112 |
1113 | /***/ },
1114 | /* 4 */
1115 | /***/ function(module, exports, __webpack_require__) {
1116 |
1117 | 'use strict';
1118 |
1119 | Object.defineProperty(exports, "__esModule", {
1120 | value: true
1121 | });
1122 |
1123 | var _tool = __webpack_require__(3);
1124 |
1125 | var _mito = __webpack_require__(5);
1126 |
1127 | var _mito2 = _interopRequireDefault(_mito);
1128 |
1129 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1130 |
1131 | /**
1132 | * DOM related Functions
1133 | *
1134 | * @author WechatFE
1135 | */
1136 |
1137 | var $ = {};
1138 |
1139 | /**
1140 | * get single element
1141 | * @public
1142 | */
1143 | $.one = function (selector, contextElement) {
1144 | if (contextElement) {
1145 | return contextElement.querySelector(selector);
1146 | }
1147 | return document.querySelector(selector);
1148 | };
1149 |
1150 | /**
1151 | * get multiple elements
1152 | * @public
1153 | */
1154 | $.all = function (selector, contextElement) {
1155 | var nodeList = void 0,
1156 | list = [];
1157 | if (contextElement) {
1158 | nodeList = contextElement.querySelectorAll(selector);
1159 | } else {
1160 | nodeList = document.querySelectorAll(selector);
1161 | }
1162 | if (nodeList && nodeList.length > 0) {
1163 | list = Array.prototype.slice.call(nodeList);
1164 | }
1165 | return list;
1166 | };
1167 |
1168 | /**
1169 | * add className to an element
1170 | * @public
1171 | */
1172 | $.addClass = function ($el, className) {
1173 | if (!$el) {
1174 | return;
1175 | }
1176 | if (!(0, _tool.isArray)($el)) {
1177 | $el = [$el];
1178 | }
1179 | for (var i = 0; i < $el.length; i++) {
1180 | var name = $el[i].className || '',
1181 | arr = name.split(' ');
1182 | if (arr.indexOf(className) > -1) {
1183 | continue;
1184 | }
1185 | arr.push(className);
1186 | $el[i].className = arr.join(' ');
1187 | }
1188 | };
1189 |
1190 | /**
1191 | * remove className from an element
1192 | * @public
1193 | */
1194 | $.removeClass = function ($el, className) {
1195 | if (!$el) {
1196 | return;
1197 | }
1198 | if (!(0, _tool.isArray)($el)) {
1199 | $el = [$el];
1200 | }
1201 | for (var i = 0; i < $el.length; i++) {
1202 | var arr = $el[i].className.split(' ');
1203 | for (var j = 0; j < arr.length; j++) {
1204 | if (arr[j] == className) {
1205 | arr[j] = '';
1206 | }
1207 | }
1208 | $el[i].className = arr.join(' ').trim();
1209 | }
1210 | };
1211 |
1212 | /**
1213 | * see whether an element contains a className
1214 | * @public
1215 | */
1216 | $.hasClass = function ($el, className) {
1217 | if (!$el) {
1218 | return false;
1219 | }
1220 | var arr = $el.className.split(' ');
1221 | for (var i = 0; i < arr.length; i++) {
1222 | if (arr[i] == className) {
1223 | return true;
1224 | }
1225 | }
1226 | return false;
1227 | };
1228 |
1229 | /**
1230 | * bind an event to element(s)
1231 | * @public
1232 | * @param array $el element object or array
1233 | * @param string eventType name of the event
1234 | * @param function fn
1235 | * @param boolean useCapture
1236 | */
1237 | $.bind = function ($el, eventType, fn, useCapture) {
1238 | if (!$el) {
1239 | return;
1240 | }
1241 | if (useCapture === undefined) {
1242 | useCapture = false;
1243 | }
1244 | if (!(0, _tool.isArray)($el)) {
1245 | $el = [$el];
1246 | }
1247 | for (var i = 0; i < $el.length; i++) {
1248 | $el[i].addEventListener(eventType, fn, useCapture);
1249 | }
1250 | };
1251 |
1252 | /**
1253 | * delegate an event to a parent element
1254 | * @public
1255 | * @param array $el parent element
1256 | * @param string eventType name of the event
1257 | * @param string selector target's selector
1258 | * @param function fn
1259 | */
1260 | $.delegate = function ($el, eventType, selector, fn) {
1261 | if (!$el) {
1262 | return;
1263 | }
1264 | $el.addEventListener(eventType, function (e) {
1265 | var targets = $.all(selector, $el);
1266 | if (!targets) {
1267 | return;
1268 | }
1269 | findTarget: for (var i = 0; i < targets.length; i++) {
1270 | var $node = e.target;
1271 | while ($node) {
1272 | if ($node == targets[i]) {
1273 | fn.call($node, e);
1274 | break findTarget;
1275 | }
1276 | $node = $node.parentNode;
1277 | if ($node == $el) {
1278 | break;
1279 | }
1280 | }
1281 | }
1282 | }, false);
1283 | };
1284 |
1285 | /**
1286 | * simply render a HTML template
1287 | * @param string tpl
1288 | * @param object key-value data
1289 | * @param boolean whether to conver to HTML string
1290 | * @return object|string
1291 | */
1292 | $.render = _mito2.default;
1293 |
1294 | /**
1295 | * export
1296 | */
1297 | exports.default = $;
1298 | module.exports = exports['default'];
1299 |
1300 | /***/ },
1301 | /* 5 */
1302 | /***/ function(module, exports) {
1303 |
1304 | 'use strict';
1305 |
1306 | Object.defineProperty(exports, "__esModule", {
1307 | value: true
1308 | });
1309 | exports.default = render;
1310 | /**
1311 | * Mito.js
1312 | * A simple template engine
1313 | *
1314 | * @author Maiz
1315 | */
1316 |
1317 | function render(tpl, data, toString) {
1318 | var pattern = /\{\{([^\}]+)\}\}/g,
1319 | code = '',
1320 | codeWrap = '',
1321 | pointer = 0,
1322 | match = [];
1323 | var addCode = function addCode(line, isJS) {
1324 | if (line === '') {
1325 | return;
1326 | }
1327 | // console.log(line)
1328 | if (isJS) {
1329 | if (line.match(/^ ?else/g)) {
1330 | // else --> } else {
1331 | code += '} ' + line + ' {\n';
1332 | } else if (line.match(/\/(if|for|switch)/g)) {
1333 | // /if --> }
1334 | code += '}\n';
1335 | } else if (line.match(/^ ?if|for|switch/g)) {
1336 | // if (age) --> if (this.age) {
1337 | code += line + ' {\n';
1338 | } else if (line.match(/^ ?(break|continue) ?$/g)) {
1339 | // break --> break;
1340 | code += line + ';\n';
1341 | } else if (line.match(/^ ?(case|default)/g)) {
1342 | // case (1) --> case (1):
1343 | code += line + ':\n';
1344 | } else {
1345 | // name --> name
1346 | code += 'arr.push(' + line + ');\n';
1347 | }
1348 | } else {
1349 | // plain text
1350 | code += 'arr.push("' + line.replace(/"/g, '\\"') + '");\n';
1351 | }
1352 | };
1353 | // init global param
1354 | window.__mito_data = data;
1355 | window.__mito_code = "";
1356 | window.__mito_result = "";
1357 | // remove spaces after switch
1358 | tpl = tpl.replace(/(\{\{ ?switch(.+?)\}\})[\r\n\t ]+\{\{/g, '$1{{');
1359 | // line breaks
1360 | tpl = tpl.replace(/^\n/, '').replace(/\n/g, '\\\n');
1361 | // init code
1362 | codeWrap = '(function(){\n';
1363 | code = 'var arr = [];\n';
1364 | while (match = pattern.exec(tpl)) {
1365 | addCode(tpl.slice(pointer, match.index), false);
1366 | addCode(match[1], true);
1367 | pointer = match.index + match[0].length;
1368 | }
1369 | addCode(tpl.substr(pointer, tpl.length - pointer), false);
1370 | code += '__mito_result = arr.join("");';
1371 | code = 'with (__mito_data) {\n' + code + '\n}';
1372 | codeWrap += code;
1373 | codeWrap += '})();';
1374 | // console.log("code:\n"+codeWrap);
1375 | // run code, do NOT use `eval` or `new Function` to avoid `unsafe-eval` CSP rule
1376 | var script = document.createElement('SCRIPT');
1377 | script.innerHTML = codeWrap;
1378 | document.documentElement.appendChild(script);
1379 | var dom = __mito_result;
1380 | document.documentElement.removeChild(script);
1381 | if (!toString) {
1382 | var e = document.createElement('div');
1383 | e.innerHTML = dom;
1384 | dom = e.children[0];
1385 | }
1386 | return dom;
1387 | }
1388 | module.exports = exports['default'];
1389 |
1390 | /***/ },
1391 | /* 6 */
1392 | /***/ function(module, exports, __webpack_require__) {
1393 |
1394 | // style-loader: Adds some css to the DOM by adding a