Skip to content

Commit 005c659

Browse files
committed
code review: improve element picker for touch-only devices
1 parent bbda2a9 commit 005c659

2 files changed

Lines changed: 66 additions & 15 deletions

File tree

src/epicker.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
height: 8em;
7575
margin: 0;
7676
overflow: hidden;
77+
overflow-y: auto;
7778
padding: 2px;
7879
resize: none;
7980
width: 100%;
@@ -165,10 +166,11 @@
165166
border: 1px solid #aaa;
166167
bottom: 4px;
167168
box-sizing: border-box;
168-
visibility: hidden;
169+
min-width: 24em;
169170
padding: 4px;
170171
position: fixed;
171172
right: 4px;
173+
visibility: hidden;
172174
width: calc(40% - 4px);
173175
}
174176
body.paused > aside {
@@ -179,6 +181,12 @@
179181
body.paused > aside:hover {
180182
opacity: 1;
181183
}
184+
body.paused > aside.show {
185+
opacity: 1;
186+
}
187+
body.paused > aside.hide {
188+
opacity: 0.1;
189+
}
182190
</style>
183191
</head>
184192

src/js/scriptlets/element-picker.js

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*******************************************************************************
22
33
uBlock Origin - a browser extension to block requests.
4-
Copyright (C) 2014-2016 Raymond Hill
4+
Copyright (C) 2014-2017 Raymond Hill
55
66
This program is free software: you can redistribute it and/or modify
77
it under the terms of the GNU General Public License as published by
@@ -1092,7 +1092,14 @@ var filterChoiceFromEvent = function(ev) {
10921092
/******************************************************************************/
10931093

10941094
var onDialogClicked = function(ev) {
1095-
if ( ev.target === null ) {
1095+
1096+
// If the dialog is hidden, clicking on it force it to become visible.
1097+
if ( dialog.classList.contains('hide') ) {
1098+
dialog.classList.add('show');
1099+
dialog.classList.remove('hide');
1100+
}
1101+
1102+
else if ( ev.target === null ) {
10961103
/* do nothing */
10971104
}
10981105

@@ -1161,6 +1168,11 @@ var showDialog = function(options) {
11611168

11621169
options = options || {};
11631170

1171+
// Typically the dialog will be forced to be visible when using a
1172+
// touch-aware device.
1173+
dialog.classList.toggle('show', options.show === true);
1174+
dialog.classList.remove('hide');
1175+
11641176
// Create lists of candidate filters
11651177
var populate = function(src, des) {
11661178
var root = dialog.querySelector(des);
@@ -1262,7 +1274,17 @@ var onSvgHovered = (function() {
12621274
};
12631275
})();
12641276

1265-
/******************************************************************************/
1277+
/*******************************************************************************
1278+
1279+
Swipe right:
1280+
If picker not paused: quit picker
1281+
If picker paused and dialog visible: hide dialog
1282+
If picker paused and dialog not visible: quit picker
1283+
1284+
Swipe left:
1285+
If picker paused and dialog not visible: show dialog
1286+
1287+
*/
12661288

12671289
var onSvgTouchStartStop = (function() {
12681290
var startX,
@@ -1277,22 +1299,43 @@ var onSvgTouchStartStop = (function() {
12771299
if ( startX === undefined ) { return; }
12781300
var stopX = ev.changedTouches[0].pageX,
12791301
stopY = ev.changedTouches[0].pageY,
1302+
angle = Math.abs(Math.atan2(stopY - startY, stopX - startX)),
12801303
distance = Math.sqrt(
12811304
Math.pow(stopX - startX, 2),
12821305
Math.pow(stopY - startY, 2)
12831306
);
1284-
// Swipe = exit element zapper/picker.
1285-
if ( distance > 32 ) {
1286-
stopPicker();
1307+
var angleUpperBound = Math.PI * 0.25 * 0.5,
1308+
swipeRight = angle < angleUpperBound,
1309+
swipeInvalid = swipeRight === false &&
1310+
angle < Math.PI - angleUpperBound;
1311+
// Interpret touch events as a click events if swipe is not valid.
1312+
if ( distance < 64 || swipeInvalid ) {
1313+
onSvgClicked({
1314+
type: 'touch',
1315+
target: ev.target,
1316+
clientX: startX,
1317+
clientY: startY
1318+
});
12871319
return;
12881320
}
1289-
// Interpret touch event as a click.
1290-
onSvgClicked({
1291-
type: 'click',
1292-
target: ev.target,
1293-
clientX: startX,
1294-
clientY: startY
1295-
});
1321+
// Swipe left.
1322+
if ( swipeRight === false ) {
1323+
if ( pickerBody.classList.contains('paused') ) {
1324+
dialog.classList.remove('hide');
1325+
dialog.classList.add('show');
1326+
}
1327+
return;
1328+
}
1329+
// Swipe right.
1330+
if (
1331+
pickerBody.classList.contains('paused') &&
1332+
dialog.classList.contains('show')
1333+
) {
1334+
dialog.classList.remove('show');
1335+
dialog.classList.add('hide');
1336+
return;
1337+
}
1338+
stopPicker();
12961339
};
12971340
})();
12981341

@@ -1329,7 +1372,7 @@ var onSvgClicked = function(ev) {
13291372
if ( filtersFrom(ev.clientX, ev.clientY) === 0 ) {
13301373
return;
13311374
}
1332-
showDialog();
1375+
showDialog({ show: ev.type === 'touch' });
13331376
};
13341377

13351378
/******************************************************************************/

0 commit comments

Comments
 (0)