diff --git a/eustia/evalCss.js b/eustia/evalCss.js index d0afc10..7723e5a 100644 --- a/eustia/evalCss.js +++ b/eustia/evalCss.js @@ -1,23 +1,51 @@ -var mark = []; +_('toStr each filter'); + +var styleList = [], + scale = 1; function exports(css) { - for (var i = 0, len = mark.length; i < len; i++) + css = toStr(css); + + for (var i = 0, len = styleList.length; i < len; i++) { - if (mark[i] === css) return; + if (styleList[i].css === css) return; } - mark.push(css); - var container = exports.container || document.head, - style = document.createElement('style'); + let container = exports.container || document.head, + el = document.createElement('style'); - style.type = 'text/css'; - style.textContent = css; + el.type = 'text/css'; + container.appendChild(el); + + let style = {css, el, container}; + resetStyle(style); + styleList.push(style); - container.appendChild(style); + return style; } -exports.reset = function () +exports.setScale = function (s) { - mark = []; -}; \ No newline at end of file + scale = s; + each(styleList, style => resetStyle(style)); +}; + +exports.clear = function () +{ + each(styleList, ({container, el}) => container.removeChild(el)); + styleList = []; +}; + +exports.remove = function (style) +{ + console.log(style); + styleList = filter(styleList, s => s !== style); + + style.container.removeChild(style.el); +}; + +function resetStyle({css, el}) +{ + el.innerText = css.replace(/(\d+)px/g, ($0, $1) => (+$1 * scale) + 'px'); +} diff --git a/src/Console/Console.js b/src/Console/Console.js index 4549b8d..0f633e0 100644 --- a/src/Console/Console.js +++ b/src/Console/Console.js @@ -1,6 +1,7 @@ import Logger from './Logger' import Tool from '../DevTools/Tool' import util from '../lib/util' +import emitter from '../lib/emitter' export default class Console extends Tool { @@ -9,6 +10,9 @@ export default class Console extends Tool super(); this.name = 'console'; + this._scale = 1; + + this._registerListener(); } init($el, parent) { @@ -80,16 +84,29 @@ export default class Console extends Tool } destroy() { + this._logger.destroy(); super.destroy(); + util.evalCss.remove(this._style); this.ignoreGlobalErr(); this.restoreConsole(); + this._unregisterListener(); + } + _registerListener() + { + this._scaleListener = scale => this._scale = scale; + + emitter.on(emitter.SCALE, this._scaleListener); + } + _unregisterListener() + { + emitter.off(emitter.SCALE, this._scaleListener); } _appendTpl() { let $el = this._$el; - util.evalCss(require('./Console.scss')); + this._style = util.evalCss(require('./Console.scss')); $el.append(require('./Console.hbs')()); let _$inputContainer = $el.find('.eruda-js-input'), @@ -174,7 +191,7 @@ export default class Console extends Tool { this._$inputContainer.css({ paddingTop: 0, - height: 40 + height: 40 * this._scale }); this._$inputBtns.hide(); @@ -182,7 +199,7 @@ export default class Console extends Tool _showInput() { this._$inputContainer.css({ - paddingTop: 40, + paddingTop: 40 * this._scale, height: '100%' }); diff --git a/src/Console/Logger.js b/src/Console/Logger.js index 3749e98..7ed2291 100644 --- a/src/Console/Logger.js +++ b/src/Console/Logger.js @@ -6,7 +6,7 @@ export default class Logger extends util.Emitter constructor($el, parent) { super(); - util.evalCss(require('./Logger.scss')); + this._style = util.evalCss(require('./Logger.scss')); this._$el = $el; this._parent = parent; @@ -47,6 +47,10 @@ export default class Logger extends util.Emitter { Log.showSrcInSources = flag; } + destroy() + { + util.evalCss.remove(this._style); + } filter(val) { this._filter = val; diff --git a/src/DevTools/DevTools.js b/src/DevTools/DevTools.js index ea6192f..a9ce673 100644 --- a/src/DevTools/DevTools.js +++ b/src/DevTools/DevTools.js @@ -2,6 +2,7 @@ import NavBar from './NavBar' import util from '../lib/util' import logger from '../lib/logger' import Tool from './Tool' +import emitter from '../lib/emitter' export default class DevTools extends util.Emitter { @@ -10,15 +11,17 @@ export default class DevTools extends util.Emitter super(); if (!util.isMobile()) util.evalCss(require('../style/scrollbar.css')); - util.evalCss(require('./DevTools.scss')); + this._style = util.evalCss(require('./DevTools.scss')); this.$parent = $parent; this._isShow = false; this._opacity = 1; + this._scale = 1; this._tools = {}; this._appendTpl(); this._initNavBar(); + this._registerListener(); } show() { @@ -168,15 +171,32 @@ export default class DevTools extends util.Emitter } setNavBarHeight(height) { - this._$el.css('paddingTop', height); - this._navBar.setHeight(height); + this._navBarHeight = height; + this._$el.css('paddingTop', height * this._scale); + this._navBar.setHeight(height * this._scale); } destroy() { + util.evalCss.remove(this._style); + this._unregisterListener(); this.removeAll(); this._navBar.destroy(); this._$el.remove(); } + _registerListener() + { + this._scaleListener = scale => + { + this._scale = scale; + this.setNavBarHeight(this._navBarHeight); + } + + emitter.on(emitter.SCALE, this._scaleListener); + } + _unregisterListener() + { + emitter.off(emitter.SCALE, this._scaleListener); + } _setTransparency(opacity) { if (!util.isNum(opacity)) return; diff --git a/src/DevTools/NavBar.js b/src/DevTools/NavBar.js index ac4d66a..01e0cbe 100644 --- a/src/DevTools/NavBar.js +++ b/src/DevTools/NavBar.js @@ -6,7 +6,7 @@ export default class NavBar extends util.Emitter { super(); - util.evalCss(require('./NavBar.scss')); + this._style = util.evalCss(require('./NavBar.scss')); this._$el = $el; $el.html('
'); @@ -60,6 +60,7 @@ export default class NavBar extends util.Emitter } destroy() { + util.evalCss.remove(this._style); this._$el.remove(); } _resetBottomBar() @@ -82,7 +83,6 @@ export default class NavBar extends util.Emitter this._$el.css('height', height); let $el = this._$el; - this._resetBottomBar(); $el.css({ height: height @@ -91,6 +91,8 @@ export default class NavBar extends util.Emitter 'height': height, 'lineHeight': height }); + + this._resetBottomBar(); } _bindEvent() { diff --git a/src/Elements/Elements.js b/src/Elements/Elements.js index 1012c02..aef7647 100644 --- a/src/Elements/Elements.js +++ b/src/Elements/Elements.js @@ -11,7 +11,7 @@ export default class Elements extends Tool { super(); - util.evalCss(require('./Elements.scss')); + this._style = util.evalCss(require('./Elements.scss')); this.name = 'elements'; this._tpl = require('./Elements.hbs'); @@ -87,7 +87,9 @@ export default class Elements extends Tool { super.destroy(); + util.evalCss.remove(this._style); this._select.disable(); + this._highlight.destroy(); this.restoreEventTarget(); } _back() diff --git a/src/Elements/Highlight.js b/src/Elements/Highlight.js index 5417c90..770a8cb 100644 --- a/src/Elements/Highlight.js +++ b/src/Elements/Highlight.js @@ -4,7 +4,7 @@ export default class Highlight { constructor($parent) { - util.evalCss(require('./Highlight.scss')); + this._style = util.evalCss(require('./Highlight.scss')); this._isShow = false; @@ -22,6 +22,10 @@ export default class Highlight this.render(); this._$el.show(); } + destroy() + { + util.evalCss.remove(this._style); + } hide() { this._isShow = false; diff --git a/src/EntryBtn/EntryBtn.js b/src/EntryBtn/EntryBtn.js index 8c9202d..188f8fc 100644 --- a/src/EntryBtn/EntryBtn.js +++ b/src/EntryBtn/EntryBtn.js @@ -1,5 +1,6 @@ import util from '../lib/util' import Draggabilly from 'draggabilly' +import emitter from '../lib/emitter' export default class EntryBtn extends util.Emitter { @@ -7,12 +8,13 @@ export default class EntryBtn extends util.Emitter { super(); - util.evalCss(require('./EntryBtn.scss')); + this._style = util.evalCss(require('./EntryBtn.scss')); this._$parent = $parent; this._appendTpl(); this._makeDraggable(); this._bindEvent(); + this._registerListener(); } hide() { @@ -24,8 +26,33 @@ export default class EntryBtn extends util.Emitter } destroy() { + util.evalCss.remove(this._style); + this._unregisterListener(); this._$el.remove(); } + _isOutOfRange() + { + let cfg = this.config, + pos = cfg.get('pos'), + defPos = this._getDefPos(); + + return pos.x > defPos.x + 10 || + pos.x < 0 || + pos.y < 0 || + pos.y > defPos.y + 10; + } + _registerListener() + { + this._scaleListener = () => util.nextTick(() => + { + if (this._isOutOfRange()) this._setPos(); + }); + emitter.on(emitter.SCALE, this._scaleListener) + } + _unregisterListener() + { + emitter.off(emitter.SCALE, this._scaleListener); + } _appendTpl() { let $parent = this._$parent; @@ -39,12 +66,7 @@ export default class EntryBtn extends util.Emitter pos = cfg.get('pos'), defPos = this._getDefPos(); - let outOfRange = pos.x > defPos.x + 10 || - pos.x < 0 || - pos.y < 0 || - pos.y > defPos.y + 10; - - if (outOfRange || + if (this._isOutOfRange() || !cfg.get('rememberPos') || orientationChanged) pos = defPos; diff --git a/src/Features/Features.js b/src/Features/Features.js index d9bda23..6e021cf 100644 --- a/src/Features/Features.js +++ b/src/Features/Features.js @@ -13,7 +13,7 @@ export default class Features extends Tool { super(); - util.evalCss(require('./Features.scss')); + this._style = util.evalCss(require('./Features.scss')); this.name = 'features'; this._tpl = require('./Features.hbs'); @@ -26,6 +26,12 @@ export default class Features extends Tool if (!this._isInit) this._initFeatures(); } + destroy() + { + super.destroy(); + + util.evalCss.remove(this._style); + } _initFeatures() { this._isInit = true; diff --git a/src/Info/Info.js b/src/Info/Info.js index da8165f..ab825da 100644 --- a/src/Info/Info.js +++ b/src/Info/Info.js @@ -8,7 +8,7 @@ export default class Info extends Tool { super(); - util.evalCss(require('./Info.scss')); + this._style = util.evalCss(require('./Info.scss')); this.name = 'info'; this._tpl = require('./Info.hbs'); @@ -20,6 +20,12 @@ export default class Info extends Tool this._addDefInfo(); } + destroy() + { + super.destroy(); + + util.evalCss.remove(this._style); + } add(name, val) { this._msgs.push({name, val}); diff --git a/src/Network/Network.js b/src/Network/Network.js index c63b24a..a711ba2 100644 --- a/src/Network/Network.js +++ b/src/Network/Network.js @@ -8,7 +8,7 @@ export default class Network extends Tool { super(); - util.evalCss(require('./Network.scss')); + this._style = util.evalCss(require('./Network.scss')); this.name = 'network'; this._performanceTimingData = []; @@ -264,6 +264,7 @@ export default class Network extends Tool { super.destroy(); + util.evalCss.remove(this._style); this.restoreXhr(); } _getResourceTimingData() diff --git a/src/Resources/Resources.js b/src/Resources/Resources.js index fb5f38a..2247d30 100644 --- a/src/Resources/Resources.js +++ b/src/Resources/Resources.js @@ -7,7 +7,7 @@ export default class Resources extends Tool { super(); - util.evalCss(require('./Resources.scss')); + this._style = util.evalCss(require('./Resources.scss')); this.name = 'resources'; this._localStoreData = []; @@ -38,6 +38,12 @@ export default class Resources extends Tool .refreshStylesheet() .refreshImage()._render(); } + destroy() + { + super.destroy(); + + util.evalCss.remove(this._style); + } refreshScript() { let scriptData = []; diff --git a/src/Settings/Settings.js b/src/Settings/Settings.js index 69a1760..9ed4a60 100644 --- a/src/Settings/Settings.js +++ b/src/Settings/Settings.js @@ -7,7 +7,7 @@ export default class Settings extends Tool { super(); - util.evalCss(require('./Settings.scss')); + this._style = util.evalCss(require('./Settings.scss')); this.name = 'settings'; this._switchTpl = require('./switch.hbs'); @@ -22,6 +22,12 @@ export default class Settings extends Tool this._bindEvent(); } + destroy() + { + super.destroy(); + + util.evalCss.remove(this._style); + } clear() { this._settings = []; diff --git a/src/Snippets/Snippets.js b/src/Snippets/Snippets.js index d7d5734..5b9353e 100644 --- a/src/Snippets/Snippets.js +++ b/src/Snippets/Snippets.js @@ -8,7 +8,7 @@ export default class Snippets extends Tool { super(); - util.evalCss(require('./Snippets.scss')); + this._style = util.evalCss(require('./Snippets.scss')); this.name = 'snippets'; @@ -22,6 +22,12 @@ export default class Snippets extends Tool this._bindEvent(); this._addDefSnippets(); } + destroy() + { + super.destroy(); + + util.evalCss.remove(this._style); + } add(name, fn, desc) { this._snippets.push({name, fn, desc}); diff --git a/src/Sources/Sources.js b/src/Sources/Sources.js index 98b1bb4..ffecf7a 100644 --- a/src/Sources/Sources.js +++ b/src/Sources/Sources.js @@ -10,7 +10,7 @@ export default class Sources extends Tool { super(); - util.evalCss(require('./Sources.scss')); + this._style = util.evalCss(require('./Sources.scss')); this.name = 'sources'; this._showLineNum = true; @@ -26,6 +26,12 @@ export default class Sources extends Tool this._bindEvent(); this._initCfg(); } + destroy() + { + super.destroy(); + + util.evalCss.remove(this._style); + } set(type, val) { if (type === 'img') diff --git a/src/index.js b/src/index.js index 8be4404..a2f7c97 100644 --- a/src/index.js +++ b/src/index.js @@ -16,7 +16,7 @@ import logger from './lib/logger' import extraUtil from './lib/extraUtil' module.exports = { - init({el, tool} = {}) + init({el, tool, autoScale = true} = {}) { this._isInit = true; @@ -27,6 +27,8 @@ module.exports = { this._initSettings(); this._initTools(tool); this._registerListener(); + + if (autoScale) this._autoScale(); }, _isInit: false, version: VERSION, @@ -82,7 +84,17 @@ module.exports = { delete this.entryBtn; this._unregisterListener(); this._$el.remove(); - util.evalCss.reset(); + util.evalCss.clear(); + }, + setScale(scale) + { + emitter.emit(emitter.SCALE, scale); + }, + _autoScale() + { + if (!util.isMobile()) return; + + this.setScale(window.innerWidth / screen.width); }, _registerListener() { @@ -91,11 +103,13 @@ module.exports = { emitter.on(emitter.ADD, this._addListener); emitter.on(emitter.SHOW, this._showListener); + emitter.on(emitter.SCALE, util.evalCss.setScale); }, _unregisterListener() { emitter.off(emitter.ADD, this._addListener); emitter.off(emitter.SHOW, this._showListener); + emitter.off(emitter.SCALE, util.evalCss.setScale); }, _checkInit() { diff --git a/src/lib/emitter.js b/src/lib/emitter.js index 772c629..6b1d217 100644 --- a/src/lib/emitter.js +++ b/src/lib/emitter.js @@ -3,5 +3,6 @@ import util from './util' let emitter = new util.Emitter(); emitter.ADD = 'ADD'; emitter.SHOW = 'SHOW'; +emitter.SCALE = 'SCALE'; module.exports = emitter; \ No newline at end of file diff --git a/src/lib/util.js b/src/lib/util.js index ff876d2..f5409e0 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -735,37 +735,6 @@ module.exports = (function () return exports; })(); - /* ------------------------------ evalCss ------------------------------ */ - - _.evalCss = (function () - { - var mark = []; - - function exports(css) - { - for (var i = 0, len = mark.length; i < len; i++) - { - if (mark[i] === css) return; - } - mark.push(css); - - var container = exports.container || document.head, - style = document.createElement('style'); - - style.type = 'text/css'; - style.textContent = css; - - container.appendChild(style); - } - - exports.reset = function () - { - mark = []; - }; - - return exports; - })(); - /* ------------------------------ fileSize ------------------------------ */ _.fileSize = (function () @@ -2348,6 +2317,67 @@ module.exports = (function () return exports; })(); + /* ------------------------------ evalCss ------------------------------ */ + + _.evalCss = (function () + { + /* dependencies + * toStr each filter + */ + + var styleList = [], + scale = 1; + + function exports(css) + { + css = toStr(css); + + for (var i = 0, len = styleList.length; i < len; i++) + { + if (styleList[i].css === css) return; + } + + let container = exports.container || document.head, + el = document.createElement('style'); + + el.type = 'text/css'; + container.appendChild(el); + + let style = {css, el, container}; + resetStyle(style); + styleList.push(style); + + return style; + } + + exports.setScale = function (s) + { + scale = s; + each(styleList, style => resetStyle(style)); + }; + + exports.clear = function () + { + each(styleList, ({container, el}) => container.removeChild(el)); + styleList = []; + }; + + exports.remove = function (style) + { + console.log(style); + styleList = filter(styleList, s => s !== style); + + style.container.removeChild(style.el); + }; + + function resetStyle({css, el}) + { + el.innerText = css.replace(/(\d+)px/g, ($0, $1) => (+$1 * scale) + 'px'); + } + + return exports; + })(); + /* ------------------------------ map ------------------------------ */ var map = _.map = (function () @@ -3902,6 +3932,49 @@ module.exports = (function () return exports; })({}); + /* ------------------------------ nextTick ------------------------------ */ + + _.nextTick = (function (exports) + { + /* Next tick for both node and browser. + * + * |Name|Type |Desc | + * |----|--------|----------------| + * |cb |function|Function to call| + * + * Use process.nextTick if available. + * + * Otherwise setImmediate or setTimeout is used as fallback. + * + * ```javascript + * nextTick(function () + * { + * // Do something... + * }); + * ``` + */ + + if (typeof process === 'object' && process.nextTick) + { + exports = process.nextTick; + } else if (typeof setImmediate === 'function') + { + exports = function (cb) { setImmediate(ensureCallable(cb)) } + } else + { + exports = function (cb) { setTimeout(ensureCallable(cb), 0) }; + } + + function ensureCallable(fn) + { + if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function'); + + return fn; + } + + return exports; + })({}); + /* ------------------------------ now ------------------------------ */ _.now = (function (exports) diff --git a/test/boot.js b/test/boot.js index c3d570c..4a4acc6 100644 --- a/test/boot.js +++ b/test/boot.js @@ -3,9 +3,13 @@ function boot(name, cb) // Need a little delay to make sure width and height of webpack dev server iframe are initialized. setTimeout(function () { - eruda.init({ - tool: name === 'settings' ? [] : name - }); + var options = {}; + if (name) + { + options.tool = name === 'settings' ? [] : name; + } + + eruda.init(options); eruda.show().get().config.set('displaySize', 50); cb && cb();