Skip to content

Commit 6d68f19

Browse files
committed
Merge pr/tirrth/2897 into unstable
2 parents b61fa32 + 733a013 commit 6d68f19

File tree

6 files changed

+58
-10
lines changed

6 files changed

+58
-10
lines changed

debug/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ <h2>Element events</h2>
174174
<option value="tapdragout">tapdragout</option>
175175
<option value="tapdrag">tapdrag</option>
176176
<option value="taphold">taphold</option>
177+
<option value="onetap">onetap</option>
178+
<option value="dbltap">dbltap</option>
177179
<option value="cxttapstart">cxttapstart</option>
178180
<option value="cxttapend">cxttapstart</option>
179181
<option value="cxttapend">cxttapend</option>
@@ -239,6 +241,8 @@ <h2>Core events</h2>
239241
<option value="tapdragout">tapdragout</option>
240242
<option value="tapdrag">tapdrag</option>
241243
<option value="taphold">taphold</option>
244+
<option value="onetap">onetap</option>
245+
<option value="dbltap">dbltap</option>
242246
<option value="cxttapstart">cxttapstart</option>
243247
<option value="cxttapend">cxttapstart</option>
244248
<option value="cxttapend">cxttapend</option>

documentation/md/core/init.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ An instance of Cytoscape.js has a number of options that can be set on initialis
5353
<a href="#init-opts/autolock">autolock</a>: false,
5454
<a href="#init-opts/autoungrabify">autoungrabify</a>: false,
5555
<a href="#init-opts/autounselectify">autounselectify</a>: false,
56+
<a href="#init-opts/multiClickDebounceTime">multiClickDebounceTime</a>: 250,
5657

5758
// rendering options:
5859
<a href="#init-opts/headless">headless</a>: false,
@@ -130,6 +131,9 @@ An instance of Cytoscape.js has a number of options that can be set on initialis
130131
<span id="init-opts/autounselectify"></span>
131132
**`autounselectify`** : Whether nodes should be unselectified (immutable selection state) by default (if `true`, overrides individual element state).
132133

134+
<span id="init-opts/multiClickDebounceTime"></span>
135+
**`multiClickDebounceTime`** : Debouce time in milliseconds to check for `dblclick` event before executing the `oneclick` event
136+
133137

134138
### Rendering options
135139

documentation/md/events.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ There are also some higher level events that you can use so you don't have to li
4747
* `tapdragout` : normalised off of element event (either `touchmove` or `mousemove`/`mouseout`)
4848
* `tapend` or `vmouseup` : normalised tap end event (either `mouseup` or `touchend`)
4949
* `tap` or `vclick` : normalised tap event (either `click`, or `touchstart` followed by `touchend` without `touchmove`)
50+
* `onetap` or `voneclick` or `oneclick` : normalised tap event (triggers after a given debouce time to first check for `dblclick` event - `multiClickDebounceTime`: set to 250ms by default)
51+
* `dbltap` or `vdblclick` or `dblclick` : normalised double tap event (either two subsequent `click`, or two subsequent `touchstart` followed by `touchend` without `touchmove`)
5052
* `taphold` : normalised tap hold event
5153
* `cxttapstart` : normalised right-click mousedown or two-finger `tapstart`
5254
* `cxttapend` : normalised right-click `mouseup` or two-finger `tapend`

src/core/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ let Core = function( opts ){
9191
current: [],
9292
queue: []
9393
},
94-
hasCompoundNodes: false
94+
hasCompoundNodes: false,
95+
multiClickDebounceTime: defVal(250, options.multiClickDebounceTime)
9596
};
9697

9798
this.createEmitter();
@@ -422,7 +423,8 @@ util.extend( corefn, {
422423
'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',
423424
'panningEnabled', 'userPanningEnabled',
424425
'boxSelectionEnabled',
425-
'autolock', 'autoungrabify', 'autounselectify'
426+
'autolock', 'autoungrabify', 'autounselectify',
427+
'multiClickDebounceTime'
426428
];
427429

428430
for( let i = 0; i < fields.length; i++ ){
@@ -478,6 +480,7 @@ util.extend( corefn, {
478480
json.textureOnViewport = options.textureOnViewport;
479481
json.wheelSensitivity = options.wheelSensitivity;
480482
json.motionBlur = options.motionBlur;
483+
json.multiClickDebounceTime = options.multiClickDebounceTime;
481484

482485
return json;
483486
}

src/core/viewport.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,12 @@ let corefn = ({
586586
w: width,
587587
h: height
588588
};
589+
},
590+
591+
multiClickDebounceTime: function ( int ){
592+
if( int ) (this._private.multiClickDebounceTime = int);
593+
else return this._private.multiClickDebounceTime;
594+
return this; // chaining
589595
}
590596
});
591597

src/extensions/renderer/base/load-listeners.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ BRp.load = function(){
840840
}
841841
}, false );
842842

843+
let clickTimeout, didDoubleClick, prevClickTimeStamp;
843844
r.registerBinding( window, 'mouseup', function mouseupHandler( e ){ // eslint-disable-line no-undef
844845
var capture = r.hoverData.capture;
845846
if( !capture ){ return; }
@@ -897,13 +898,27 @@ BRp.load = function(){
897898

898899
triggerEvents( near, [ 'mouseup', 'tapend', 'vmouseup' ], e, { x: pos[0], y: pos[1] } );
899900

900-
if(
901-
!r.dragData.didDrag // didn't move a node around
902-
&& !r.hoverData.dragged // didn't pan
903-
&& !r.hoverData.selecting // not box selection
904-
&& !r.hoverData.isOverThresholdDrag // didn't move too much
905-
){
906-
triggerEvents( down, ['click', 'tap', 'vclick'], e, { x: pos[0], y: pos[1] } );
901+
if (
902+
!r.dragData.didDrag && // didn't move a node around
903+
!r.hoverData.dragged && // didn't pan
904+
!r.hoverData.selecting && // not box selection
905+
!r.hoverData.isOverThresholdDrag // didn't move too much
906+
) {
907+
triggerEvents(down, ["click", "tap", "vclick"], e, { x: pos[0], y: pos[1] });
908+
909+
didDoubleClick = false;
910+
if (e.timeStamp - prevClickTimeStamp <= cy.multiClickDebounceTime()) {
911+
clickTimeout && clearTimeout(clickTimeout);
912+
didDoubleClick = true;
913+
prevClickTimeStamp = null;
914+
triggerEvents(down, ["dblclick", "dbltap", "vdblclick"], e, { x: pos[0], y: pos[1] });
915+
} else {
916+
clickTimeout = setTimeout(() => {
917+
if (didDoubleClick) return;
918+
triggerEvents(down, ["oneclick", "onetap", "voneclick"], e, { x: pos[0], y: pos[1] });
919+
}, cy.multiClickDebounceTime());
920+
prevClickTimeStamp = e.timeStamp;
921+
}
907922
}
908923

909924
// Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something
@@ -1795,7 +1810,7 @@ BRp.load = function(){
17951810
}
17961811
} );
17971812

1798-
var touchendHandler;
1813+
var touchendHandler, didDoubleTouch, touchTimeout, prevTouchTimeStamp;
17991814
r.registerBinding( window, 'touchend', touchendHandler = function( e ){ // eslint-disable-line no-unused-vars
18001815
var start = r.touchData.start;
18011816

@@ -1967,6 +1982,20 @@ BRp.load = function(){
19671982
}
19681983

19691984
triggerEvents( start, [ 'tap', 'vclick' ], e, { x: now[0], y: now[1] } );
1985+
1986+
didDoubleTouch = false;
1987+
if (e.timeStamp - prevTouchTimeStamp <= cy.multiClickDebounceTime()) {
1988+
touchTimeout && clearTimeout(touchTimeout);
1989+
didDoubleTouch = true;
1990+
prevTouchTimeStamp = null;
1991+
triggerEvents( start, [ 'dbltap', 'vdblclick' ], e, { x: now[0], y: now[1] } );
1992+
} else {
1993+
touchTimeout = setTimeout(() => {
1994+
if (didDoubleTouch) return;
1995+
triggerEvents( start, [ 'onetap', 'voneclick' ], e, { x: now[0], y: now[1] } );
1996+
}, cy.multiClickDebounceTime());
1997+
prevTouchTimeStamp = e.timeStamp;
1998+
}
19701999
}
19712000

19722001
// Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance

0 commit comments

Comments
 (0)