mirror of https://github.com/gorhill/uBlock.git
functional DOM inspector
This commit is contained in:
parent
8305b8990a
commit
9becb466d4
|
@ -75,7 +75,7 @@ li.listEntry > a:nth-of-type(3) {
|
|||
}
|
||||
/* I designed the button with: http://charliepark.org/bootstrap_buttons/ */
|
||||
button.custom {
|
||||
padding: 5px;
|
||||
padding: 0.6em 1em;
|
||||
border: 1px solid transparent;
|
||||
border-color: #80b3ff #80b3ff hsl(216, 100%, 75%);
|
||||
border-radius: 3px;
|
||||
|
@ -98,7 +98,6 @@ button.custom:hover {
|
|||
#buttonApply {
|
||||
display: initial;
|
||||
margin: 1em 0;
|
||||
padding: 1em;
|
||||
position: fixed;
|
||||
right: 1em;
|
||||
top: 0;
|
||||
|
|
|
@ -18,7 +18,7 @@ body {
|
|||
font: 14px/1.3 sans-serif;
|
||||
}
|
||||
button.important {
|
||||
padding: 5px;
|
||||
padding: 0.6em 1em;
|
||||
border: 1px solid transparent;
|
||||
border-color: #ffcc7f #ffcc7f hsl(36, 100%, 73%);
|
||||
border-radius: 3px;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#domInspector {
|
||||
border-top: 1px solid #ccc;
|
||||
display: none;
|
||||
max-height: 40%;
|
||||
min-height: 40%;
|
||||
max-height: 70%;
|
||||
min-height: 70%;
|
||||
overflow: auto;
|
||||
}
|
||||
#domInspector.enabled {
|
||||
|
@ -83,6 +83,11 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
#cosmeticFilteringDialog .dialog {
|
||||
text-align: center;
|
||||
}
|
||||
#cosmeticFilteringDialog .dialog textarea {
|
||||
height: 40vh;
|
||||
}
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ var logger = self.logger;
|
|||
var messager = logger.messager;
|
||||
|
||||
var inspectedTabId = '';
|
||||
var inspectedURL = '';
|
||||
var inspectedHostname = '';
|
||||
var pollTimer = null;
|
||||
var fingerprint = null;
|
||||
|
@ -282,7 +283,48 @@ var nidFromNode = function(node) {
|
|||
|
||||
var startDialog = (function() {
|
||||
var dialog = uDom.nodeFromId('cosmeticFilteringDialog');
|
||||
var candidateFilters = [];
|
||||
var textarea = dialog.querySelector('textarea');
|
||||
var hideSelectors = [];
|
||||
var unhideSelectors = [];
|
||||
var inputTimer = null;
|
||||
|
||||
var onInputChanged = (function() {
|
||||
var parse = function() {
|
||||
inputTimer = null;
|
||||
hideSelectors = [];
|
||||
unhideSelectors = [];
|
||||
|
||||
var line, matches;
|
||||
var re = /^([^#]*)(#@?#)(.+)$/;
|
||||
var lines = textarea.value.split(/\s*\n\s*/);
|
||||
for ( var i = 0; i < lines.length; i++ ) {
|
||||
line = lines[i].trim();
|
||||
if ( line === '' || line.charAt(0) === '!' ) {
|
||||
continue;
|
||||
}
|
||||
matches = re.exec(line);
|
||||
if ( matches === null || matches.length !== 4 ) {
|
||||
continue;
|
||||
}
|
||||
if ( inspectedHostname.lastIndexOf(matches[1]) === -1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( matches[2] === '##' ) {
|
||||
hideSelectors.push(matches[3]);
|
||||
} else {
|
||||
unhideSelectors.push(matches[3]);
|
||||
}
|
||||
}
|
||||
|
||||
showCommitted();
|
||||
};
|
||||
|
||||
return function parseAsync() {
|
||||
if ( inputTimer === null ) {
|
||||
inputTimer = vAPI.setTimeout(parse, 743);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
var onClick = function(ev) {
|
||||
var target = ev.target;
|
||||
|
@ -292,45 +334,94 @@ var startDialog = (function() {
|
|||
return stop();
|
||||
}
|
||||
ev.stopPropagation();
|
||||
|
||||
if ( target.id === 'createCosmeticFilters' ) {
|
||||
messager.send({ what: 'createUserFilter', filters: textarea.value });
|
||||
// Force a reload for the new cosmetic filter(s) to take effect
|
||||
messager.send({ what: 'reloadTab', tabId: inspectedTabId });
|
||||
return stop();
|
||||
}
|
||||
};
|
||||
|
||||
var stop = function() {
|
||||
dialog.removeEventListener('click', onClick, true);
|
||||
document.body.removeChild(dialog);
|
||||
var onCooked = function(entries) {
|
||||
if ( Array.isArray(entries) === false ) {
|
||||
return;
|
||||
}
|
||||
hideSelectors = entries;
|
||||
var taValue = [], i, node;
|
||||
var d = new Date();
|
||||
taValue.push('! ' + d.toLocaleString() + ' ' + inspectedURL);
|
||||
for ( i = 0; i < entries.length; i++ ) {
|
||||
taValue.push(inspectedHostname + '##' + entries[i]);
|
||||
}
|
||||
var nodes = domTree.querySelectorAll('code.filter.off');
|
||||
for ( i = 0; i < nodes.length; i++ ) {
|
||||
node = nodes[i];
|
||||
unhideSelectors.push(node.textContent);
|
||||
taValue.push(inspectedHostname + '#@#' + node.textContent);
|
||||
}
|
||||
textarea.value = taValue.join('\n');
|
||||
document.body.appendChild(dialog);
|
||||
dialog.addEventListener('click', onClick, true);
|
||||
showCommitted();
|
||||
};
|
||||
|
||||
var showCommitted = function() {
|
||||
messager.sendTo(
|
||||
{
|
||||
what: 'showCommitted',
|
||||
hide: hideSelectors.join(',\n'),
|
||||
unhide: unhideSelectors.join(',\n')
|
||||
},
|
||||
inspectedTabId,
|
||||
'dom-inspector.js'
|
||||
);
|
||||
};
|
||||
|
||||
var showInteractive = function() {
|
||||
messager.sendTo(
|
||||
{
|
||||
what: 'showInteractive',
|
||||
hide: hideSelectors.join(',\n'),
|
||||
unhide: unhideSelectors.join(',\n')
|
||||
},
|
||||
inspectedTabId,
|
||||
'dom-inspector.js'
|
||||
);
|
||||
};
|
||||
|
||||
var start = function() {
|
||||
// Collect all selectors which are currently toggled
|
||||
var node, filters = [];
|
||||
textarea.addEventListener('input', onInputChanged);
|
||||
var node, entries = [];
|
||||
var nodes = domTree.querySelectorAll('code.off');
|
||||
for ( var i = 0; i < nodes.length; i++ ) {
|
||||
node = nodes[i];
|
||||
if ( node.classList.contains('filter') ) {
|
||||
filters.push({
|
||||
prefix: '#@#',
|
||||
nid: '',
|
||||
selector: node.textContent
|
||||
});
|
||||
} else {
|
||||
filters.push({
|
||||
prefix: '##',
|
||||
if ( node.classList.contains('filter') === false ) {
|
||||
entries.push({
|
||||
nid: nidFromNode(node),
|
||||
selector: node.textContent
|
||||
selector: selectorFromNode(node)
|
||||
});
|
||||
}
|
||||
}
|
||||
messager.sendTo(
|
||||
{ what: 'cookFilters', entries: entries },
|
||||
inspectedTabId,
|
||||
'dom-inspector.js',
|
||||
onCooked
|
||||
);
|
||||
};
|
||||
|
||||
// TODO: Send filters through dom-inspector.js for further processing.
|
||||
|
||||
candidateFilters = filters;
|
||||
var taValue = [], filter;
|
||||
for ( i = 0; i < filters.length; i++ ) {
|
||||
filter = filters[i];
|
||||
taValue.push(inspectedHostname + filter.prefix + filter.selector);
|
||||
var stop = function() {
|
||||
if ( inputTimer !== null ) {
|
||||
clearTimeout(inputTimer);
|
||||
inputTimer = null;
|
||||
}
|
||||
dialog.querySelector('textarea').value = taValue.join('\n');
|
||||
document.body.appendChild(dialog);
|
||||
dialog.addEventListener('click', onClick, true);
|
||||
showInteractive();
|
||||
hideSelectors = [];
|
||||
unhideSelectors = [];
|
||||
textarea.removeEventListener('input', onInputChanged);
|
||||
dialog.removeEventListener('click', onClick, true);
|
||||
document.body.removeChild(dialog);
|
||||
};
|
||||
|
||||
return start;
|
||||
|
@ -404,7 +495,10 @@ var onMouseOver = (function() {
|
|||
if ( inspectedTabId === '' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convenience: skip real-time highlighting if shift key is pressed.
|
||||
if ( ev.shiftKey ) {
|
||||
return;
|
||||
}
|
||||
// Find closest `li`
|
||||
var target = ev.target;
|
||||
while ( target !== null ) {
|
||||
|
@ -447,6 +541,7 @@ var fetchDOMAsync = (function() {
|
|||
case 'full':
|
||||
renderDOMFull(response);
|
||||
fingerprint = response.fingerprint;
|
||||
inspectedURL = response.url;
|
||||
inspectedHostname = response.hostname;
|
||||
break;
|
||||
|
||||
|
|
|
@ -140,11 +140,9 @@ var cssEscape = (function(root) {
|
|||
var localMessager = vAPI.messaging.channel('dom-inspector.js');
|
||||
|
||||
// Highlighter-related
|
||||
var svgOcean = null;
|
||||
var svgIslands = null;
|
||||
var svgRoot = null;
|
||||
var pickerRoot = null;
|
||||
var highlightedElements = [];
|
||||
var highlightedElementLists = [ [], [], [] ];
|
||||
|
||||
var nodeToIdMap = new WeakMap(); // No need to iterate
|
||||
var toggledNodes = new Map();
|
||||
|
@ -209,20 +207,7 @@ var domLayout = (function() {
|
|||
}
|
||||
return out;
|
||||
})();
|
||||
/*
|
||||
var matchesSelector = (function() {
|
||||
if ( typeof Element.prototype.matches === 'function' ) {
|
||||
return 'matches';
|
||||
}
|
||||
if ( typeof Element.prototype.mozMatchesSelector === 'function' ) {
|
||||
return 'mozMatchesSelector';
|
||||
}
|
||||
if ( typeof Element.prototype.webkitMatchesSelector === 'function' ) {
|
||||
return 'webkitMatchesSelector';
|
||||
}
|
||||
return '';
|
||||
})();
|
||||
*/
|
||||
|
||||
var selectorFromNode = function(node) {
|
||||
var str, attr, pos, sw, i;
|
||||
var tag = node.localName;
|
||||
|
@ -362,13 +347,12 @@ var domLayout = (function() {
|
|||
|
||||
// Track and report mutations to the DOM
|
||||
|
||||
var journalEntries = [];
|
||||
var journalNodes = Object.create(null);
|
||||
|
||||
var mutationObserver = null;
|
||||
var mutationTimer = null;
|
||||
var addedNodelists = [];
|
||||
var removedNodelist = [];
|
||||
var journalEntries = [];
|
||||
var journalNodes = Object.create(null);
|
||||
|
||||
var previousElementSiblingId = function(node) {
|
||||
var sibling = node;
|
||||
|
@ -499,20 +483,14 @@ var domLayout = (function() {
|
|||
// API
|
||||
|
||||
var getLayout = function(fingerprint) {
|
||||
if ( fingerprint !== domFingerprint() && mutationObserver !== null ) {
|
||||
if ( mutationTimer !== null ) {
|
||||
clearTimeout(mutationTimer);
|
||||
mutationTimer = null;
|
||||
}
|
||||
mutationObserver.disconnect();
|
||||
mutationObserver = null;
|
||||
journalEntries = [];
|
||||
journalNodes = Object.create(null);
|
||||
if ( fingerprint !== domFingerprint() ) {
|
||||
reset();
|
||||
}
|
||||
|
||||
var response = {
|
||||
what: 'domLayout',
|
||||
fingerprint: domFingerprint(),
|
||||
url: window.location.href,
|
||||
hostname: window.location.hostname
|
||||
};
|
||||
|
||||
|
@ -542,6 +520,10 @@ var domLayout = (function() {
|
|||
return response;
|
||||
};
|
||||
|
||||
var reset = function() {
|
||||
shutdown();
|
||||
};
|
||||
|
||||
var shutdown = function() {
|
||||
if ( mutationTimer !== null ) {
|
||||
clearTimeout(mutationTimer);
|
||||
|
@ -551,32 +533,195 @@ var domLayout = (function() {
|
|||
mutationObserver.disconnect();
|
||||
mutationObserver = null;
|
||||
}
|
||||
addedNodelists = [];
|
||||
removedNodelist = [];
|
||||
journalEntries = [];
|
||||
journalNodes = Object.create(null);
|
||||
nodeToIdMap = new WeakMap();
|
||||
};
|
||||
|
||||
return {
|
||||
get: getLayout,
|
||||
reset: reset,
|
||||
shutdown: shutdown
|
||||
};
|
||||
})();
|
||||
|
||||
// https://www.youtube.com/watch?v=qo8zKhd4Cf0
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// For browsers not supporting `:scope`, it's not the end of the world: the
|
||||
// suggested CSS selectors may just end up being more verbose.
|
||||
|
||||
var cssScope = ':scope > ';
|
||||
try {
|
||||
document.querySelector(':scope *');
|
||||
} catch (e) {
|
||||
cssScope = '';
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var cosmeticFilterFromEntries = function(entries) {
|
||||
var out = [];
|
||||
var entry, i = entries.length;
|
||||
while ( i-- ) {
|
||||
entry = entries[i];
|
||||
out.push(cosmeticFilterFromTarget(entry.nid, entry.selector));
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Extract the best possible cosmetic filter, i.e. as specific as possible.
|
||||
|
||||
var cosmeticFilterFromNode = function(elem) {
|
||||
var tagName = elem.localName;
|
||||
var prefix = '';
|
||||
var suffix = [];
|
||||
var v, i;
|
||||
|
||||
// Id
|
||||
v = typeof elem.id === 'string' && cssEscape(elem.id);
|
||||
if ( v ) {
|
||||
suffix.push('#', v);
|
||||
}
|
||||
|
||||
// Class(es)
|
||||
if ( suffix.length === 0 ) {
|
||||
v = elem.classList;
|
||||
if ( v ) {
|
||||
i = v.length || 0;
|
||||
while ( i-- ) {
|
||||
suffix.push('.' + cssEscape(v.item(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tag name
|
||||
if ( suffix.length === 0 ) {
|
||||
prefix = tagName;
|
||||
}
|
||||
|
||||
// Attributes (depends on tag name)
|
||||
var attributes = [], attr;
|
||||
switch ( tagName ) {
|
||||
case 'a':
|
||||
v = elem.getAttribute('href');
|
||||
if ( v ) {
|
||||
v = v.replace(/\?.*$/, '');
|
||||
if ( v.length ) {
|
||||
attributes.push({ k: 'href', v: v });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'img':
|
||||
v = elem.getAttribute('alt');
|
||||
if ( v && v.length !== 0 ) {
|
||||
attributes.push({ k: 'alt', v: v });
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while ( attr = attributes.pop() ) {
|
||||
if ( attr.v.length === 0 ) {
|
||||
continue;
|
||||
}
|
||||
suffix.push('[', attr.k, '="', attr.v, '"]');
|
||||
}
|
||||
|
||||
var selector = prefix + suffix.join('');
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/637
|
||||
// If the selector is still ambiguous at this point, further narrow using
|
||||
// `nth-of-type`. It is preferable to use `nth-of-type` as opposed to
|
||||
// `nth-child`, as `nth-of-type` is less volatile.
|
||||
var parent = elem.parentElement;
|
||||
if ( elementsFromSelector(cssScope + selector, parent).length > 1 ) {
|
||||
i = 1;
|
||||
while ( elem.previousElementSibling !== null ) {
|
||||
elem = elem.previousElementSibling;
|
||||
if ( elem.localName !== tagName ) {
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
selector += ':nth-of-type(' + i + ')';
|
||||
}
|
||||
|
||||
return selector;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var cosmeticFilterFromTarget = function(nid, coarseSelector) {
|
||||
var elems = elementsFromSelector(coarseSelector);
|
||||
var target = null;
|
||||
var i = elems.length;
|
||||
while ( i-- ) {
|
||||
if ( nodeToIdMap.get(elems[i]) === nid ) {
|
||||
target = elems[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( target === null ) {
|
||||
return coarseSelector;
|
||||
}
|
||||
// Find the most concise selector from the target node
|
||||
var segments = [], segment;
|
||||
var node = target;
|
||||
while ( node !== document.body ) {
|
||||
segment = cosmeticFilterFromNode(node);
|
||||
segments.unshift(segment);
|
||||
if ( segment.charAt(0) === '#' ) {
|
||||
break;
|
||||
}
|
||||
node = node.parentElement;
|
||||
}
|
||||
var fineSelector = segments.join(' > ');
|
||||
if ( fineSelector.charAt(0) === '#' ) {
|
||||
return fineSelector;
|
||||
}
|
||||
if ( fineSelector.charAt(0) === '.' && elementsFromSelector(fineSelector).length === 1 ) {
|
||||
return fineSelector;
|
||||
}
|
||||
return 'body > ' + fineSelector;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var elementsFromSelector = function(selector, context) {
|
||||
if ( !context ) {
|
||||
context = document;
|
||||
}
|
||||
var out = [];
|
||||
try {
|
||||
out = context.querySelectorAll(selector);
|
||||
} catch (ex) {
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var highlightElements = function(scrollTo) {
|
||||
var elems = highlightedElements;
|
||||
var wv = pickerRoot.contentWindow.innerWidth;
|
||||
var hv = pickerRoot.contentWindow.innerHeight;
|
||||
var ocean = ['M0 0h' + wv + 'v' + hv + 'h-' + wv, 'z'];
|
||||
var islands = [];
|
||||
var elem, rect, poly;
|
||||
var ocean = ['M0 0h' + wv + 'v' + hv + 'h-' + wv, 'z'], islands;
|
||||
var elems, elem, rect, poly;
|
||||
var xl, xr, yt, yb, w, h, ws;
|
||||
var xlu = Number.MAX_VALUE, xru = 0, ytu = Number.MAX_VALUE, ybu = 0;
|
||||
var lists = highlightedElementLists;
|
||||
|
||||
for ( var i = 0; i < elems.length; i++ ) {
|
||||
elem = elems[i];
|
||||
for ( var i = 0; i < lists.length; i++ ) {
|
||||
elems = lists[i];
|
||||
islands = [];
|
||||
for ( var j = 0; j < elems.length; j++ ) {
|
||||
elem = elems[j];
|
||||
if ( elem === pickerRoot ) {
|
||||
continue;
|
||||
}
|
||||
|
@ -610,8 +755,10 @@ var highlightElements = function(scrollTo) {
|
|||
if ( yt < ytu ) { ytu = yt; }
|
||||
if ( yb > ybu ) { ybu = yb; }
|
||||
}
|
||||
svgOcean.setAttribute('d', ocean.join(''));
|
||||
svgIslands.setAttribute('d', islands.join('') || 'M0 0');
|
||||
svgRoot.children[i+1].setAttribute('d', islands.join('') || 'M0 0');
|
||||
}
|
||||
|
||||
svgRoot.children[0].setAttribute('d', ocean.join(''));
|
||||
|
||||
if ( !scrollTo ) {
|
||||
return;
|
||||
|
@ -646,13 +793,30 @@ var highlightElements = function(scrollTo) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var elementsFromSelector = function(filter) {
|
||||
var out = [];
|
||||
try {
|
||||
out = document.querySelectorAll(filter);
|
||||
} catch (ex) {
|
||||
var onScrolled = function() {
|
||||
highlightElements();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var resetToggledNodes = function() {
|
||||
var value;
|
||||
// Chromium does not support destructuring as of v43.
|
||||
for ( var node of toggledNodes.keys() ) {
|
||||
value = toggledNodes.get(node);
|
||||
if ( value !== null ) {
|
||||
node.style.removeProperty('display');
|
||||
} else {
|
||||
node.style.setProperty('display', value);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
toggledNodes.clear();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var forgetToggledNodes = function() {
|
||||
toggledNodes.clear();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -673,15 +837,16 @@ var selectNodes = function(selector, nid) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var hightlightNodes = function(selector, nid, scrollTo) {
|
||||
highlightedElements = selectNodes(selector, nid);
|
||||
highlightElements(scrollTo);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onScrolled = function() {
|
||||
highlightElements();
|
||||
var shutdown = function() {
|
||||
resetToggledNodes();
|
||||
domLayout.shutdown();
|
||||
localMessager.removeAllListeners();
|
||||
localMessager.close();
|
||||
localMessager = null;
|
||||
window.removeEventListener('scroll', onScrolled, true);
|
||||
document.documentElement.removeChild(pickerRoot);
|
||||
pickerRoot = svgRoot = null;
|
||||
highlightedElementLists = [ [], [], [] ];
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -718,8 +883,10 @@ var toggleNodes = function(nodes, originalState, targetState) {
|
|||
}
|
||||
} else { // hidden, ?
|
||||
if ( targetState ) { // hidden, any
|
||||
toggledNodes.set(node, 'none');
|
||||
node.style.setProperty('display', 'initial', 'important');
|
||||
} else { // hidden, hidden
|
||||
toggledNodes.delete(node);
|
||||
node.style.setProperty('display', 'none', 'important');
|
||||
}
|
||||
}
|
||||
|
@ -729,41 +896,25 @@ var toggleNodes = function(nodes, originalState, targetState) {
|
|||
// https://www.youtube.com/watch?v=L5jRewnxSBY
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var resetToggledNodes = function() {
|
||||
var value;
|
||||
// Chromium does not support destructuring as of v43.
|
||||
for ( var node of toggledNodes.keys() ) {
|
||||
value = toggledNodes.get(node);
|
||||
if ( value !== null ) {
|
||||
node.style.removeProperty('display');
|
||||
} else {
|
||||
node.style.setProperty('display', value);
|
||||
}
|
||||
}
|
||||
toggledNodes.clear();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var shutdown = function() {
|
||||
resetToggledNodes();
|
||||
domLayout.shutdown();
|
||||
localMessager.removeAllListeners();
|
||||
localMessager.close();
|
||||
localMessager = null;
|
||||
window.removeEventListener('scroll', onScrolled, true);
|
||||
document.documentElement.removeChild(pickerRoot);
|
||||
pickerRoot = svgRoot = svgOcean = svgIslands = null;
|
||||
highlightedElements = [];
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request) {
|
||||
var response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'commitFilters':
|
||||
resetToggledNodes();
|
||||
toggleNodes(selectNodes(request.hide, ''), true, false);
|
||||
toggleNodes(selectNodes(request.unhide, ''), false, true);
|
||||
forgetToggledNodes();
|
||||
highlightedElementLists = [ [], [], [] ];
|
||||
highlightElements();
|
||||
break;
|
||||
|
||||
case 'cookFilters':
|
||||
response = cosmeticFilterFromEntries(request.entries);
|
||||
break;
|
||||
|
||||
case 'domLayout':
|
||||
response = domLayout.get(request.fingerprint);
|
||||
break;
|
||||
|
@ -773,16 +924,34 @@ var onMessage = function(request) {
|
|||
break;
|
||||
|
||||
case 'highlightOne':
|
||||
hightlightNodes(request.selector, request.nid, request.scrollTo);
|
||||
highlightedElementLists[0] = selectNodes(request.selector, request.nid);
|
||||
highlightElements(request.scrollTo);
|
||||
break;
|
||||
|
||||
case 'resetToggledNodes':
|
||||
resetToggledNodes();
|
||||
break;
|
||||
|
||||
case 'showCommitted':
|
||||
resetToggledNodes();
|
||||
highlightedElementLists[0] = [];
|
||||
highlightedElementLists[1] = selectNodes(request.hide, '');
|
||||
highlightedElementLists[2] = selectNodes(request.unhide, '');
|
||||
toggleNodes(highlightedElementLists[2], false, true);
|
||||
highlightElements(true);
|
||||
break;
|
||||
|
||||
case 'showInteractive':
|
||||
resetToggledNodes();
|
||||
toggleNodes(selectNodes(request.hide, ''), true, false);
|
||||
toggleNodes(selectNodes(request.unhide, ''), false, true);
|
||||
highlightedElementLists = [ [], [], [] ];
|
||||
highlightElements();
|
||||
break;
|
||||
|
||||
case 'toggleNodes':
|
||||
highlightedElements = selectNodes(request.selector, request.nid);
|
||||
toggleNodes(highlightedElements, request.original, request.target);
|
||||
highlightedElementLists[0] = selectNodes(request.selector, request.nid);
|
||||
toggleNodes(highlightedElementLists[0], request.original, request.target);
|
||||
highlightElements(true);
|
||||
break;
|
||||
|
||||
|
@ -845,27 +1014,28 @@ pickerRoot.onload = function() {
|
|||
'fill: rgba(0,0,0,0.75);',
|
||||
'fill-rule: evenodd;',
|
||||
'}',
|
||||
'svg > path + path {',
|
||||
'svg > path:nth-of-type(2) {',
|
||||
'fill: rgba(0,0,255,0.1);',
|
||||
'stroke: #FFF;',
|
||||
'stroke-width: 0.5px;',
|
||||
'}',
|
||||
'svg.invert > path:first-child {',
|
||||
'fill: rgba(0,0,255,0.1);',
|
||||
'svg > path:nth-of-type(3) {',
|
||||
'fill: rgba(255,0,0,0.2);',
|
||||
'stroke: #F00;',
|
||||
'}',
|
||||
'svg.invert > path + path {',
|
||||
'fill: rgba(0,0,0,0.75);',
|
||||
'stroke: #000;',
|
||||
'svg > path:nth-of-type(4) {',
|
||||
'fill: rgba(0,255,0,0.2);',
|
||||
'stroke: #0F0;',
|
||||
'}',
|
||||
''
|
||||
].join('\n');
|
||||
pickerDoc.body.appendChild(style);
|
||||
|
||||
svgRoot = pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
svgOcean = pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
svgRoot.appendChild(svgOcean);
|
||||
svgIslands = pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
svgRoot.appendChild(svgIslands);
|
||||
svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
|
||||
svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
|
||||
svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
|
||||
svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
|
||||
pickerDoc.body.appendChild(svgRoot);
|
||||
|
||||
window.addEventListener('scroll', onScrolled, true);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<div id="domInspector">
|
||||
<div class="permatoolbar">
|
||||
<div>
|
||||
<span class="button fa highlightMode"></span>
|
||||
<span class="button fa highlightMode" style="display: none"></span>
|
||||
<span class="button fa revert disabled"></span>
|
||||
<span class="button fa commit disabled"></span>
|
||||
</div>
|
||||
|
@ -98,7 +98,8 @@
|
|||
</div>
|
||||
<div id="cosmeticFilteringDialog" class="modalDialog">
|
||||
<div class="dialog">
|
||||
<p><textarea class="cosmeticFilters" value=""></textarea>
|
||||
<textarea class="cosmeticFilters" value=""></textarea>
|
||||
<button id="createCosmeticFilters" class="important" type="button" data-i18n="pickerCreate"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="filterFinderDialogSentence1"><span><span></span><code></code><span></span></span></div>
|
||||
|
|
Loading…
Reference in New Issue