mirror of https://github.com/gorhill/uBlock.git
Element picker: cleanup and Firefox improvements (closes #1211)
In Firefox, you can now block an element right from the Web Inspector. This was implemented by @AlexVallat -- thanks to Alex for the awesome feature enhancement.
This commit is contained in:
parent
f961cad0f0
commit
e8572bdc21
|
@ -65,7 +65,7 @@ vAPI.app.restart = function() {
|
||||||
var cleanupTasks = [];
|
var cleanupTasks = [];
|
||||||
|
|
||||||
// This must be updated manually, every time a new task is added/removed
|
// This must be updated manually, every time a new task is added/removed
|
||||||
var expectedNumberOfCleanups = 6; // 7 instances of cleanupTasks.push, but one is unique to fennec, and one to desktop.
|
var expectedNumberOfCleanups = vAPI.fennec ? 7 : 8; // 8 instances of cleanupTasks.push, but one is unique to fennec, and two to desktop.
|
||||||
|
|
||||||
window.addEventListener('unload', function() {
|
window.addEventListener('unload', function() {
|
||||||
for ( var cleanup of cleanupTasks ) {
|
for ( var cleanup of cleanupTasks ) {
|
||||||
|
@ -392,8 +392,9 @@ vAPI.tabs.registerListeners = function() {
|
||||||
cleanupTasks.push(function() {
|
cleanupTasks.push(function() {
|
||||||
Services.ww.unregisterNotification(windowWatcher);
|
Services.ww.unregisterNotification(windowWatcher);
|
||||||
|
|
||||||
|
vAPI.contextMenu.remove();
|
||||||
|
|
||||||
for ( var win of vAPI.tabs.getWindows() ) {
|
for ( var win of vAPI.tabs.getWindows() ) {
|
||||||
vAPI.contextMenu.unregister(win.document);
|
|
||||||
win.removeEventListener('DOMContentLoaded', windowWatcher.onReady);
|
win.removeEventListener('DOMContentLoaded', windowWatcher.onReady);
|
||||||
|
|
||||||
var tabContainer;
|
var tabContainer;
|
||||||
|
@ -1760,6 +1761,15 @@ vAPI.contextMenu.displayMenuItem = function({target}) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
vAPI.contextMenu.createContextMenuItem = function(doc) {
|
||||||
|
var menuitem = doc.createElement('menuitem');
|
||||||
|
menuitem.setAttribute('id', this.menuItemId);
|
||||||
|
menuitem.setAttribute('label', this.menuLabel);
|
||||||
|
menuitem.setAttribute('image', vAPI.getURL('img/browsericons/icon16.svg'));
|
||||||
|
menuitem.setAttribute('class', 'menuitem-iconic');
|
||||||
|
return menuitem;
|
||||||
|
}
|
||||||
|
|
||||||
vAPI.contextMenu.register = function(doc) {
|
vAPI.contextMenu.register = function(doc) {
|
||||||
if ( !this.menuItemId ) {
|
if ( !this.menuItemId ) {
|
||||||
return;
|
return;
|
||||||
|
@ -1777,11 +1787,7 @@ vAPI.contextMenu.register = function(doc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var contextMenu = doc.getElementById('contentAreaContextMenu');
|
var contextMenu = doc.getElementById('contentAreaContextMenu');
|
||||||
var menuitem = doc.createElement('menuitem');
|
var menuitem = this.createContextMenuItem(doc);
|
||||||
menuitem.setAttribute('id', this.menuItemId);
|
|
||||||
menuitem.setAttribute('label', this.menuLabel);
|
|
||||||
menuitem.setAttribute('image', vAPI.getURL('img/browsericons/icon16.svg'));
|
|
||||||
menuitem.setAttribute('class', 'menuitem-iconic');
|
|
||||||
menuitem.addEventListener('command', this.onCommand);
|
menuitem.addEventListener('command', this.onCommand);
|
||||||
contextMenu.addEventListener('popupshowing', this.displayMenuItem);
|
contextMenu.addEventListener('popupshowing', this.displayMenuItem);
|
||||||
contextMenu.insertBefore(menuitem, doc.getElementById('inspect-separator'));
|
contextMenu.insertBefore(menuitem, doc.getElementById('inspect-separator'));
|
||||||
|
@ -1808,6 +1814,36 @@ vAPI.contextMenu.unregister = function(doc) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
vAPI.contextMenu.registerForWebInspector = function(eventName, toolbox, panel) {
|
||||||
|
var menuPopup = panel.panelDoc.getElementById("inspector-node-popup");
|
||||||
|
var deleteMenuItem = panel.panelDoc.getElementById("node-menu-delete");
|
||||||
|
var tiltButton = toolbox.toolboxButtons.filter(tool => tool.id === "command-button-tilt")[0];
|
||||||
|
tiltButton = tiltButton && tiltButton.button;
|
||||||
|
|
||||||
|
if (menuPopup && deleteMenuItem) {
|
||||||
|
var menuitem = vAPI.contextMenu.createContextMenuItem(panel.panelDoc);
|
||||||
|
menuitem.addEventListener('command', function() {
|
||||||
|
var selectedNodeFront = panel.selection.nodeFront;
|
||||||
|
while (selectedNodeFront && selectedNodeFront.baseURI !== panel.walker.rootNode.baseURI) {
|
||||||
|
// This is an iFrame, so we can't select it directly. Walk up the parent stack until we do
|
||||||
|
selectedNodeFront = selectedNodeFront.parentNode();
|
||||||
|
}
|
||||||
|
if (selectedNodeFront) {
|
||||||
|
selectedNodeFront.getUniqueSelector().then(selector => µBlock.elementPickerExec(vAPI.tabs.getTabId(panel.browser), selector));
|
||||||
|
|
||||||
|
// Turn off 3D view, if it's turned on.
|
||||||
|
if (tiltButton && tiltButton.checked) {
|
||||||
|
tiltButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
menuPopup.insertBefore(menuitem, deleteMenuItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.contextMenu.create = function(details, callback) {
|
vAPI.contextMenu.create = function(details, callback) {
|
||||||
this.menuItemId = details.id;
|
this.menuItemId = details.id;
|
||||||
this.menuLabel = details.title;
|
this.menuLabel = details.title;
|
||||||
|
@ -1850,6 +1886,19 @@ vAPI.contextMenu.create = function(details, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Also add a context menu to the web inspector
|
||||||
|
if (!vAPI.fennec) {
|
||||||
|
try {
|
||||||
|
this.gDevTools = Cu.import('resource:///modules/devtools/gDevTools.jsm', null).gDevTools;
|
||||||
|
} catch (ex) {
|
||||||
|
// console.error(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.gDevTools) {
|
||||||
|
this.gDevTools.on("inspector-ready", this.registerForWebInspector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( var win of vAPI.tabs.getWindows() ) {
|
for ( var win of vAPI.tabs.getWindows() ) {
|
||||||
this.register(win.document);
|
this.register(win.document);
|
||||||
}
|
}
|
||||||
|
@ -1862,6 +1911,10 @@ vAPI.contextMenu.remove = function() {
|
||||||
this.unregister(win.document);
|
this.unregister(win.document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vAPI.fennec && this.gDevTools) {
|
||||||
|
this.gDevTools.off("inspector-ready", this.registerForWebInspector);
|
||||||
|
}
|
||||||
|
|
||||||
this.menuItemId = null;
|
this.menuItemId = null;
|
||||||
this.menuLabel = null;
|
this.menuLabel = null;
|
||||||
this.contexts = null;
|
this.contexts = null;
|
||||||
|
|
|
@ -136,11 +136,10 @@ return {
|
||||||
noopFunc: function(){},
|
noopFunc: function(){},
|
||||||
|
|
||||||
apiErrorCount: 0,
|
apiErrorCount: 0,
|
||||||
contextMenuTarget: '',
|
|
||||||
contextMenuClientX: -1,
|
contextMenuClientX: -1,
|
||||||
contextMenuClientY: -1,
|
contextMenuClientY: -1,
|
||||||
|
|
||||||
epickerTarget: '',
|
epickerTargetElementSelector: null,
|
||||||
epickerEprom: null,
|
epickerEprom: null,
|
||||||
|
|
||||||
// so that I don't have to care for last comma
|
// so that I don't have to care for last comma
|
||||||
|
|
|
@ -45,26 +45,8 @@ var onContextMenuClicked = function(details, tab) {
|
||||||
if ( /^https?:\/\//.test(tab.url) === false ) {
|
if ( /^https?:\/\//.test(tab.url) === false ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var tagName = details.tagName || '';
|
|
||||||
var src = details.frameUrl || details.srcUrl || details.linkUrl || '';
|
|
||||||
|
|
||||||
if ( !tagName ) {
|
µb.elementPickerExec(tab.id);
|
||||||
if ( typeof details.frameUrl === 'string' ) {
|
|
||||||
tagName = 'iframe';
|
|
||||||
} else if ( typeof details.srcUrl === 'string' ) {
|
|
||||||
if ( details.mediaType === 'image' ) {
|
|
||||||
tagName = 'img';
|
|
||||||
} else if ( details.mediaType === 'video' ) {
|
|
||||||
tagName = 'video';
|
|
||||||
} else if ( details.mediaType === 'audio' ) {
|
|
||||||
tagName = 'audio';
|
|
||||||
}
|
|
||||||
} else if ( typeof details.linkUrl === 'string' ) {
|
|
||||||
tagName = 'a';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
µb.elementPickerExec(tab.id, tagName + '\t' + src);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -128,7 +128,8 @@ if ( window.top !== window ) {
|
||||||
var pickerRoot = document.getElementById(vAPI.sessionId);
|
var pickerRoot = document.getElementById(vAPI.sessionId);
|
||||||
|
|
||||||
if ( pickerRoot ) {
|
if ( pickerRoot ) {
|
||||||
return;
|
// If it's already running, stop it and then allow it to restart
|
||||||
|
pickerRoot.onload(); // Calls stopPicker
|
||||||
}
|
}
|
||||||
|
|
||||||
var localMessager = vAPI.messaging.channel('element-picker.js');
|
var localMessager = vAPI.messaging.channel('element-picker.js');
|
||||||
|
@ -873,53 +874,21 @@ var startPicker = function(details) {
|
||||||
|
|
||||||
highlightElements([], true);
|
highlightElements([], true);
|
||||||
|
|
||||||
var elem;
|
var elem = null;
|
||||||
|
|
||||||
|
// If a target element was provided, use it
|
||||||
|
if (details.targetElementSelector) {
|
||||||
|
elem = document.querySelector(details.targetElementSelector);
|
||||||
|
}
|
||||||
|
|
||||||
// Try using mouse position
|
// Try using mouse position
|
||||||
if ( details.clientX !== -1 ) {
|
if (!elem && details.clientX !== -1) {
|
||||||
elem = elementFromPoint(details.clientX, details.clientY);
|
elem = elementFromPoint(details.clientX, details.clientY);
|
||||||
|
}
|
||||||
|
|
||||||
if (elem !== null) {
|
if (elem !== null) {
|
||||||
filtersFromElement(elem);
|
filtersFromElement(elem);
|
||||||
showDialog();
|
showDialog();
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No mouse position available, use suggested target
|
|
||||||
var target = details.target || '';
|
|
||||||
var pos = target.indexOf('\t');
|
|
||||||
if ( pos === -1 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var srcAttrMap = {
|
|
||||||
'a': 'href',
|
|
||||||
'img': 'src',
|
|
||||||
'iframe': 'src',
|
|
||||||
'embed': 'src',
|
|
||||||
'video': 'src',
|
|
||||||
'audio': 'src'
|
|
||||||
};
|
|
||||||
var tagName = target.slice(0, pos);
|
|
||||||
var url = target.slice(pos + 1);
|
|
||||||
var attr = srcAttrMap[tagName];
|
|
||||||
if ( attr === undefined ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var elems = document.querySelectorAll(tagName + '[' + attr + ']');
|
|
||||||
var i = elems.length;
|
|
||||||
var src;
|
|
||||||
while ( i-- ) {
|
|
||||||
elem = elems[i];
|
|
||||||
src = elem[attr];
|
|
||||||
if ( typeof src !== 'string' || src === '' ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( src !== url ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
filtersFromElement(elem);
|
|
||||||
showDialog({ modifier: true });
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -574,13 +574,12 @@ var onMessage = function(request, sender, callback) {
|
||||||
|
|
||||||
callback({
|
callback({
|
||||||
frameContent: this.responseText.replace(reStrings, replacer),
|
frameContent: this.responseText.replace(reStrings, replacer),
|
||||||
target: µb.contextMenuTarget,
|
targetElementSelector: µb.epickerTargetElementSelector,
|
||||||
clientX: µb.contextMenuClientX,
|
clientX: µb.contextMenuClientX,
|
||||||
clientY: µb.contextMenuClientY,
|
clientY: µb.contextMenuClientY,
|
||||||
eprom: µb.epickerEprom
|
eprom: µb.epickerEprom
|
||||||
});
|
});
|
||||||
|
|
||||||
µb.contextMenuTarget = '';
|
|
||||||
µb.contextMenuClientX = -1;
|
µb.contextMenuClientX = -1;
|
||||||
µb.contextMenuClientY = -1;
|
µb.contextMenuClientY = -1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -276,8 +276,8 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
µBlock.elementPickerExec = function(tabId, targetElement) {
|
µBlock.elementPickerExec = function(tabId, targetElementSelector) {
|
||||||
this.epickerTarget = targetElement || '';
|
this.epickerTargetElementSelector = targetElementSelector;
|
||||||
vAPI.tabs.injectScript(tabId, { file: 'js/element-picker.js' });
|
vAPI.tabs.injectScript(tabId, { file: 'js/element-picker.js' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue