diff --git a/src/epicker.html b/src/epicker.html
index a1c676d97..b9e1adc10 100644
--- a/src/epicker.html
+++ b/src/epicker.html
@@ -20,6 +20,14 @@ html#ublock0-epicker,
#ublock0-epicker div {
display: block !important;
}
+#ublock0-epicker #toolbar {
+ cursor: grab;
+ display: flex !important;
+ justify-content: space-between;
+}
+#ublock0-epicker aside.moving #toolbar {
+ cursor: grabbing;
+}
#ublock0-epicker ul {
margin: 0.25em 0 0 0 !important;
}
@@ -31,13 +39,9 @@ html#ublock0-epicker,
box-shadow: none !important;
color: #000 !important;
cursor: pointer !important;
- margin: 0 0 0 2px !important;
opacity: 0.7 !important;
padding: 4px 6px !important;
}
-#ublock0-epicker button:first-of-type {
- margin-left: 0 !important;
-}
#ublock0-epicker button:disabled {
color: #999 !important;
background-color: #ccc !important;
@@ -218,12 +222,16 @@ html#ublock0-epicker,
-
+
-
diff --git a/src/js/scriptlets/element-picker.js b/src/js/scriptlets/element-picker.js
index 5f3e6ee84..59160f72e 100644
--- a/src/js/scriptlets/element-picker.js
+++ b/src/js/scriptlets/element-picker.js
@@ -126,26 +126,26 @@ if (
return;
}
-var pickerRoot = document.getElementById(vAPI.sessionId);
+let pickerRoot = document.getElementById(vAPI.sessionId);
if ( pickerRoot ) { return; }
-var pickerBody = null;
-var svgOcean = null;
-var svgIslands = null;
-var svgRoot = null;
-var dialog = null;
-var taCandidate = null;
+let pickerBody = null;
+let svgOcean = null;
+let svgIslands = null;
+let svgRoot = null;
+let dialog = null;
+let taCandidate = null;
-var netFilterCandidates = [];
-var cosmeticFilterCandidates = [];
+const netFilterCandidates = [];
+const cosmeticFilterCandidates = [];
-var targetElements = [];
-var candidateElements = [];
-var bestCandidateFilter = null;
+let targetElements = [];
+let candidateElements = [];
+let bestCandidateFilter = null;
-var lastNetFilterSession = window.location.host + window.location.pathname;
-var lastNetFilterHostname = '';
-var lastNetFilterUnion = '';
+const lastNetFilterSession = window.location.host + window.location.pathname;
+let lastNetFilterHostname = '';
+let lastNetFilterUnion = '';
/******************************************************************************/
@@ -1517,6 +1517,55 @@ const onScrolled = function() {
/******************************************************************************/
+const onStartMoving = (( ) => {
+ let mx0 = 0, my0 = 0;
+ let r0 = 0, b0 = 0;
+ let rMax = 0, bMax = 0;
+
+ const move = ev => {
+ if ( ev.isTrusted === false ) { return; }
+ let r1 = Math.min(Math.max(r0 - ev.pageX + mx0, 4), rMax);
+ let b1 = Math.min(Math.max(b0 - ev.pageY + my0, 4), bMax);
+ dialog.style.setProperty('right', `${r1}px`, 'important');
+ dialog.style.setProperty('bottom', `${b1}px`, 'important');
+ ev.preventDefault();
+ ev.stopPropagation();
+ };
+
+ const stop = ev => {
+ if ( ev.isTrusted === false ) { return; }
+ if ( dialog.classList.contains('moving') === false ) { return; }
+ dialog.classList.remove('moving');
+ const pickerWin = pickerRoot.contentWindow;
+ pickerWin.removeEventListener('mousemove', move, { capture: true });
+ pickerWin.removeEventListener('mouseup', stop, { capture: true, once: true });
+ ev.preventDefault();
+ ev.stopPropagation();
+ };
+
+ return function(ev) {
+ if ( ev.isTrusted === false ) { return; }
+ const target = dialog.querySelector('#toolbar');
+ if ( ev.target !== target ) { return; }
+ if ( dialog.classList.contains('moving') ) { return; }
+ mx0 = ev.pageX; my0 = ev.pageY;
+ const pickerWin = pickerRoot.contentWindow;
+ const style = pickerWin.getComputedStyle(dialog);
+ r0 = parseInt(style.right, 10);
+ b0 = parseInt(style.bottom, 10);
+ const rect = dialog.getBoundingClientRect();
+ rMax = pickerBody.clientWidth - 4 - rect.width ;
+ bMax = pickerBody.clientHeight - 4 - rect.height;
+ dialog.classList.add('moving');
+ pickerWin.addEventListener('mousemove', move, { capture: true });
+ pickerWin.addEventListener('mouseup', stop, { capture: true, once: true });
+ ev.preventDefault();
+ ev.stopPropagation();
+ };
+})();
+
+/******************************************************************************/
+
const pausePicker = function() {
pickerBody.classList.add('paused');
svgListening(false);
@@ -1553,20 +1602,11 @@ const stopPicker = function() {
vAPI.domFilterer.unexcludeNode(pickerRoot);
window.removeEventListener('scroll', onScrolled, true);
- pickerRoot.contentWindow.removeEventListener('keydown', onKeyPressed, true);
- taCandidate.removeEventListener('input', onCandidateChanged);
- dialog.removeEventListener('click', onDialogClicked);
svgListening(false);
- svgRoot.removeEventListener('click', onSvgClicked);
- svgRoot.removeEventListener('touchstart', onSvgTouchStartStop);
- svgRoot.removeEventListener('touchend', onSvgTouchStartStop);
pickerRoot.parentNode.removeChild(pickerRoot);
- pickerRoot.removeEventListener('load', stopPicker);
- pickerRoot =
- pickerBody =
- dialog =
- svgRoot = svgOcean = svgIslands =
- taCandidate = null;
+ pickerRoot = pickerBody =
+ svgRoot = svgOcean = svgIslands =
+ dialog = taCandidate = null;
window.focus();
};
@@ -1612,6 +1652,8 @@ const startPicker = function(details) {
taCandidate = dialog.querySelector('textarea');
taCandidate.addEventListener('input', onCandidateChanged);
+ dialog.querySelector('#toolbar').addEventListener('mousedown', onStartMoving);
+
svgRoot = pickerBody.querySelector('svg');
svgOcean = svgRoot.firstChild;
svgIslands = svgRoot.lastChild;