chore: small changes

This commit is contained in:
redhoodsu
2022-12-17 13:37:08 +08:00
parent 025c8cea6e
commit 586e81c009
5 changed files with 189 additions and 213 deletions

View File

@@ -120,7 +120,6 @@ LocalStorage, sessionStorage, cookies, scripts, styleSheets and images.
|Name |Type |Desc | |Name |Type |Desc |
|----------------|-------|---------------------| |----------------|-------|---------------------|
|hideErudaSetting|boolean|Hide Eruda Setting | |hideErudaSetting|boolean|Hide Eruda Setting |
|observeElement |boolean|Auto Refresh Elements|
## Sources ## Sources

View File

@@ -3,6 +3,7 @@ import lowerCase from 'licia/lowerCase'
import pick from 'licia/pick' import pick from 'licia/pick'
import toStr from 'licia/toStr' import toStr from 'licia/toStr'
import map from 'licia/map' import map from 'licia/map'
import isEl from 'licia/isEl'
import escape from 'licia/escape' import escape from 'licia/escape'
import startWith from 'licia/startWith' import startWith from 'licia/startWith'
import contain from 'licia/contain' import contain from 'licia/contain'
@@ -14,23 +15,63 @@ import each from 'licia/each'
import keys from 'licia/keys' import keys from 'licia/keys'
import isNull from 'licia/isNull' import isNull from 'licia/isNull'
import trim from 'licia/trim' import trim from 'licia/trim'
import isFn from 'licia/isFn'
import isBool from 'licia/isBool'
import safeGet from 'licia/safeGet'
import $ from 'licia/$'
import MutationObserver from 'licia/MutationObserver'
import CssStore from './CssStore' import CssStore from './CssStore'
import Settings from '../Settings/Settings'
import LunaModal from 'luna-modal' import LunaModal from 'luna-modal'
import { formatNodeName } from './util' import { formatNodeName } from './util'
import { pxToNum, classPrefix as c } from '../lib/util' import { pxToNum, isErudaEl, classPrefix as c } from '../lib/util'
export default class Detail { export default class Detail {
constructor($container) { constructor($container, devtools) {
this._$container = $container this._$container = $container
this._devtools = devtools
this._curEl = document.documentElement this._curEl = document.documentElement
this._bindEvent() this._bindEvent()
this._initObserver()
this._initCfg()
} }
show(el) { show(el) {
this._curEl = el this._curEl = el
this._rmDefComputedStyle = true this._rmDefComputedStyle = true
this._computedStyleSearchKeyword = '' this._computedStyleSearchKeyword = ''
this._enableObserver()
this._render() this._render()
} }
hide() {
this._disableObserver()
}
destroy() {
this._disableObserver()
this.restoreEventTarget()
this._rmCfg()
}
overrideEventTarget() {
const winEventProto = getWinEventProto()
const origAddEvent = (this._origAddEvent = winEventProto.addEventListener)
const origRmEvent = (this._origRmEvent = winEventProto.removeEventListener)
winEventProto.addEventListener = function (type, listener, useCapture) {
addEvent(this, type, listener, useCapture)
origAddEvent.apply(this, arguments)
}
winEventProto.removeEventListener = function (type, listener, useCapture) {
rmEvent(this, type, listener, useCapture)
origRmEvent.apply(this, arguments)
}
}
restoreEventTarget() {
const winEventProto = getWinEventProto()
if (this._origAddEvent) winEventProto.addEventListener = this._origAddEvent
if (this._origRmEvent) winEventProto.removeEventListener = this._origRmEvent
}
_toggleAllComputedStyle() { _toggleAllComputedStyle() {
this._rmDefComputedStyle = !this._rmDefComputedStyle this._rmDefComputedStyle = !this._rmDefComputedStyle
@@ -250,6 +291,8 @@ export default class Detail {
return ret return ret
} }
_bindEvent() { _bindEvent() {
const devtools = this._devtools
this._$container this._$container
.on('click', c('.toggle-all-computed-style'), () => .on('click', c('.toggle-all-computed-style'), () =>
this._toggleAllComputedStyle() this._toggleAllComputedStyle()
@@ -262,6 +305,81 @@ export default class Detail {
this._render() this._render()
}) })
}) })
.on('click', '.eruda-listener-content', function () {
const text = $(this).text()
const sources = devtools.get('sources')
if (sources) {
sources.set('js', text)
devtools.showTool('sources')
}
})
.on('click', '.eruda-breadcrumb', () => {
const sources = devtools.get('sources')
if (sources) {
sources.set('object', this._curEl)
devtools.showTool('sources')
}
})
}
_initObserver() {
this._observer = new MutationObserver((mutations) => {
each(mutations, (mutation) => this._handleMutation(mutation))
})
}
_enableObserver() {
this._observer.observe(document.documentElement, {
attributes: true,
childList: true,
subtree: true,
})
}
_disableObserver() {
this._observer.disconnect()
}
_handleMutation(mutation) {
if (isErudaEl(mutation.target)) return
if (mutation.type === 'attributes') {
if (mutation.target !== this._curEl) return
this._render()
}
}
_rmCfg() {
const cfg = this.config
const settings = this._container.get('settings')
if (!settings) return
settings
.remove(cfg, 'overrideEventTarget')
.remove(cfg, 'observeElement')
.remove('Elements')
}
_initCfg() {
const cfg = (this.config = Settings.createCfg('elements', {
overrideEventTarget: true,
}))
if (cfg.get('overrideEventTarget')) this.overrideEventTarget()
cfg.on('change', (key, val) => {
switch (key) {
case 'overrideEventTarget':
return val ? this.overrideEventTarget() : this.restoreEventTarget()
}
})
const settings = this._devtools.get('settings')
if (!settings) return
settings
.text('Elements')
.switch(cfg, 'overrideEventTarget', 'Catch Event Listeners')
settings.separator()
} }
} }
@@ -350,3 +468,40 @@ function boxModelValue(val, type) {
return ret === 0 ? '' : ret return ret === 0 ? '' : ret
} }
function addEvent(el, type, listener, useCapture = false) {
if (!isEl(el) || !isFn(listener) || !isBool(useCapture)) return
const events = (el.erudaEvents = el.erudaEvents || {})
events[type] = events[type] || []
events[type].push({
listener: listener,
listenerStr: listener.toString(),
useCapture: useCapture,
})
}
function rmEvent(el, type, listener, useCapture = false) {
if (!isEl(el) || !isFn(listener) || !isBool(useCapture)) return
const events = el.erudaEvents
if (!(events && events[type])) return
const listeners = events[type]
for (let i = 0, len = listeners.length; i < len; i++) {
if (listeners[i].listener === listener) {
listeners.splice(i, 1)
break
}
}
if (listeners.length === 0) delete events[type]
if (keys(events).length === 0) delete el.erudaEvents
}
const getWinEventProto = () => {
return safeGet(window, 'EventTarget.prototype') || window.Node.prototype
}

View File

@@ -1,15 +1,8 @@
import Tool from '../DevTools/Tool' import Tool from '../DevTools/Tool'
import Highlight from './Highlight' import Highlight from './Highlight'
import Select from './Select' import Select from './Select'
import Settings from '../Settings/Settings'
import $ from 'licia/$' import $ from 'licia/$'
import keys from 'licia/keys'
import MutationObserver from 'licia/MutationObserver'
import each from 'licia/each'
import isEl from 'licia/isEl' import isEl from 'licia/isEl'
import isFn from 'licia/isFn'
import isBool from 'licia/isBool'
import safeGet from 'licia/safeGet'
import nextTick from 'licia/nextTick' import nextTick from 'licia/nextTick'
import Emitter from 'licia/Emitter' import Emitter from 'licia/Emitter'
import map from 'licia/map' import map from 'licia/map'
@@ -42,7 +35,8 @@ export default class Elements extends Tool {
this._initTpl() this._initTpl()
this._htmlEl = document.documentElement this._htmlEl = document.documentElement
this._detail = new Detail(this._$detail) this._detail = new Detail(this._$detail, container)
this.config = this._detail.config
this._domViewer = new LunaDomViewer(this._$domViewer.get(0), { this._domViewer = new LunaDomViewer(this._$domViewer.get(0), {
node: this._htmlEl, node: this._htmlEl,
ignore: (node) => isErudaEl(node), ignore: (node) => isErudaEl(node),
@@ -51,62 +45,32 @@ export default class Elements extends Tool {
this._highlight = new Highlight(this._container.$container) this._highlight = new Highlight(this._container.$container)
this._select = new Select() this._select = new Select()
this._bindEvent() this._bindEvent()
this._initObserver()
this._initCfg()
nextTick(() => this._updateHistory()) nextTick(() => this._updateHistory())
} }
show() { show() {
super.show() super.show()
if (this._observeElement) this._enableObserver() if (!this._curNode) {
if (!this._curEl) this._setEl(this._htmlEl) this._setNode(document.body)
} }
hide() {
this._disableObserver()
return super.hide()
} }
// To be removed in 3.0.0 // To be removed in 3.0.0
set(node) { set(node) {
return this.select(node) return this.select(node)
} }
select(node) { select(node) {
this._setEl(node) this._setNode(node)
this.emit('change', node) this.emit('change', node)
return this return this
} }
overrideEventTarget() {
const winEventProto = getWinEventProto()
const origAddEvent = (this._origAddEvent = winEventProto.addEventListener)
const origRmEvent = (this._origRmEvent = winEventProto.removeEventListener)
winEventProto.addEventListener = function (type, listener, useCapture) {
addEvent(this, type, listener, useCapture)
origAddEvent.apply(this, arguments)
}
winEventProto.removeEventListener = function (type, listener, useCapture) {
rmEvent(this, type, listener, useCapture)
origRmEvent.apply(this, arguments)
}
}
restoreEventTarget() {
const winEventProto = getWinEventProto()
if (this._origAddEvent) winEventProto.addEventListener = this._origAddEvent
if (this._origRmEvent) winEventProto.removeEventListener = this._origRmEvent
}
destroy() { destroy() {
super.destroy() super.destroy()
evalCss.remove(this._style) evalCss.remove(this._style)
this._detail.destroy()
this._select.disable() this._select.disable()
this._highlight.destroy() this._highlight.destroy()
this._disableObserver()
this.restoreEventTarget()
this._rmCfg()
} }
_initTpl() { _initTpl() {
const $el = this._$el const $el = this._$el
@@ -129,7 +93,7 @@ export default class Elements extends Tool {
this._$crumbs = $el.find(c('.crumbs')) this._$crumbs = $el.find(c('.crumbs'))
} }
_renderCrumbs() { _renderCrumbs() {
const crumbs = getCrumbs(this._curEl) const crumbs = getCrumbs(this._curNode)
let html = '' let html = ''
if (!isEmpty(crumbs)) { if (!isEmpty(crumbs)) {
html = map(crumbs, ({ text, idx }) => { html = map(crumbs, ({ text, idx }) => {
@@ -139,7 +103,7 @@ export default class Elements extends Tool {
this._$crumbs.html(html) this._$crumbs.html(html)
} }
_back() { _back() {
if (this._curEl === this._htmlEl) return if (this._curNode === this._htmlEl) return
const parentQueue = this._curParentQueue const parentQueue = this._curParentQueue
let parent = parentQueue.shift() let parent = parentQueue.shift()
@@ -150,57 +114,28 @@ export default class Elements extends Tool {
} }
_bindEvent() { _bindEvent() {
const self = this const self = this
const container = this._container
const select = this._select const select = this._select
this._$el this._$el.on('click', c('.crumb'), function () {
.on('click', '.eruda-listener-content', function () { let idx = toNum($(this).data('idx'))
const text = $(this).text() let el = self._curNode
const sources = container.get('sources')
if (sources) { while (idx-- && el.parentElement) {
sources.set('js', text) el = el.parentElement
container.showTool('sources') }
}
})
.on('click', '.eruda-breadcrumb', () => {
const sources = container.get('sources')
if (sources) { if (isElExist(el)) {
sources.set('object', this._curEl) self.set(el)
container.showTool('sources') }
} })
})
.on('click', c('.crumb'), function () {
let idx = toNum($(this).data('idx'))
let el = self._curEl
while (idx-- && el.parentElement) {
el = el.parentElement
}
if (isElExist(el)) {
self.set(el)
}
})
this._$control this._$control
.on('click', c('.select'), () => this._toggleSelect()) .on('click', c('.select'), () => this._toggleSelect())
.on('click', c('.show'), () => this._detail.show(this._curEl)) .on('click', c('.show'), () => this._detail.show(this._curNode))
select.on('select', (target) => this.set(target)) select.on('select', (target) => this.set(target))
this._domViewer.on('select', this._setEl) this._domViewer.on('select', this._setNode)
}
_enableObserver() {
this._observer.observe(this._htmlEl, {
attributes: true,
childList: true,
subtree: true,
})
}
_disableObserver() {
this._observer.disconnect()
} }
_toggleHighlight() { _toggleHighlight() {
if (this._selectElement) return if (this._selectElement) return
@@ -225,18 +160,18 @@ export default class Elements extends Tool {
select.disable() select.disable()
} }
} }
_setEl = (el) => { _setNode = (node) => {
if (el === this._curEl) return if (node === this._curNode) return
this._curEl = el this._curNode = node
this._domViewer.select(el) this._domViewer.select(node)
this._renderCrumbs() this._renderCrumbs()
this._highlight.setEl(el) this._highlight.setEl(node)
const parentQueue = [] const parentQueue = []
let parent = el.parentNode let parent = node.parentNode
while (parent) { while (parent) {
parentQueue.push(parent) parentQueue.push(parent)
parent = parent.parentNode parent = parent.parentNode
@@ -250,122 +185,12 @@ export default class Elements extends Tool {
if (!console) return if (!console) return
const history = this._history const history = this._history
history.unshift(this._curEl) history.unshift(this._curNode)
if (history.length > 5) history.pop() if (history.length > 5) history.pop()
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
console.setGlobal(`$${i}`, history[i]) console.setGlobal(`$${i}`, history[i])
} }
} }
_initObserver() {
this._observer = new MutationObserver((mutations) => {
each(mutations, (mutation) => this._handleMutation(mutation))
})
}
_handleMutation(mutation) {
let i, len, node
if (isErudaEl(mutation.target)) return
if (mutation.type === 'attributes') {
if (mutation.target !== this._curEl) return
this._render()
} else if (mutation.type === 'childList') {
if (mutation.target === this._curEl) return this._render()
const addedNodes = mutation.addedNodes
for (i = 0, len = addedNodes.length; i < len; i++) {
node = addedNodes[i]
if (node.parentNode === this._curEl) return this._render()
}
const removedNodes = mutation.removedNodes
for (i = 0, len = removedNodes.length; i < len; i++) {
if (removedNodes[i] === this._curEl) return this.set(this._htmlEl)
}
}
}
_rmCfg() {
const cfg = this.config
const settings = this._container.get('settings')
if (!settings) return
settings
.remove(cfg, 'overrideEventTarget')
.remove(cfg, 'observeElement')
.remove('Elements')
}
_initCfg() {
const cfg = (this.config = Settings.createCfg('elements', {
overrideEventTarget: true,
observeElement: true,
}))
if (cfg.get('overrideEventTarget')) this.overrideEventTarget()
if (cfg.get('observeElement')) this._observeElement = false
cfg.on('change', (key, val) => {
switch (key) {
case 'overrideEventTarget':
return val ? this.overrideEventTarget() : this.restoreEventTarget()
case 'observeElement':
this._observeElement = val
return val ? this._enableObserver() : this._disableObserver()
}
})
const settings = this._container.get('settings')
if (!settings) return
settings
.text('Elements')
.switch(cfg, 'overrideEventTarget', 'Catch Event Listeners')
if (this._observer) settings.switch(cfg, 'observeElement', 'Auto Refresh')
settings.separator()
}
}
function addEvent(el, type, listener, useCapture = false) {
if (!isEl(el) || !isFn(listener) || !isBool(useCapture)) return
const events = (el.erudaEvents = el.erudaEvents || {})
events[type] = events[type] || []
events[type].push({
listener: listener,
listenerStr: listener.toString(),
useCapture: useCapture,
})
}
function rmEvent(el, type, listener, useCapture = false) {
if (!isEl(el) || !isFn(listener) || !isBool(useCapture)) return
const events = el.erudaEvents
if (!(events && events[type])) return
const listeners = events[type]
for (let i = 0, len = listeners.length; i < len; i++) {
if (listeners[i].listener === listener) {
listeners.splice(i, 1)
break
}
}
if (listeners.length === 0) delete events[type]
if (keys(events).length === 0) delete el.erudaEvents
}
const getWinEventProto = () => {
return safeGet(window, 'EventTarget.prototype') || window.Node.prototype
} }
const isElExist = (val) => isEl(val) && val.parentNode const isElExist = (val) => isEl(val) && val.parentNode

View File

@@ -28,6 +28,7 @@
font-size: $font-size-s; font-size: $font-size-s;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis;
li { li {
cursor: pointer; cursor: pointer;
padding: 0 7px; padding: 0 7px;

View File

@@ -203,13 +203,9 @@ export function pxToNum(str) {
} }
export function isErudaEl(el) { export function isErudaEl(el) {
let parentNode = el.parentNode while (el) {
if (el.id === 'eruda') return true
if (!parentNode) return false el = el.parentNode
while (parentNode) {
if (parentNode.id === 'eruda') return true
parentNode = parentNode.parentNode
} }
return false return false