I have a question.
Is there a possibility to bind a double click Mouse Event to a node?
In the documentation, there is only 'click'.
Thanks for your help!
I have a question.
Is there a possibility to bind a double click Mouse Event to a node?
In the documentation, there is only 'click'.
Thanks for your help!
You can add a custom doubleTap
event for Cytoscape like this:
var cy = $('#cy').cytoscape('get');
var tappedBefore;
var tappedTimeout;
cy.on('tap', function(event) {
var tappedNow = event.cyTarget;
if (tappedTimeout && tappedBefore) {
clearTimeout(tappedTimeout);
}
if(tappedBefore === tappedNow) {
tappedNow.trigger('doubleTap');
tappedBefore = null;
} else {
tappedTimeout = setTimeout(function(){ tappedBefore = null; }, 300);
tappedBefore = tappedNow;
}
});
Then, you can subscribe for the new event. For example, if you need to detect double tab on nodes, do:
cy.on('doubleTap', 'node', function(event) { /* ... */ });
Nevertheless, I understant @maxkfranz point of view that this is not mobile-friendly solution.
One of the core requirements of cy.js is that it should work equally well and as-consistently-as-possible across devices. Double click is a carry over from PC days: It often results in poor UI, and it is completely foreign to touch-based devices. Therefore, we do not support it currently. -M
There is also a way to achieve this without setTimeout
. The event has a timeStamp
property with the values of UNIX time stamp when the event got triggered. So, here is the approach:
var doubleClickDelayMs = 350;
var previousTapStamp;
cy.on('tap', function(e) {
var currentTapStamp = e.timeStamp;
var msFromLastTap = currentTapStamp - previousTapStamp;
if (msFromLastTap < doubleClickDelayMs) {
e.target.trigger('doubleTap', e);
}
previousTapStamp = currentTapStamp;
});
cy.on('doubleTap', function(event, originalTapEvent) {
...
});
Here is a working fiddle: https://jsfiddle.net/scebotari66/84x7hxd0/4/
thanks @fracz for the solution. In my case I needed the tap position. If metadata from the original tap event are needed, don't forget passing and replacing the event, as the doubletap event doesn't contain all metadata.
var tappedBefore;
var tappedTimeout;
cy.on('tap', function(event) {
var tappedNow = event.target;
if (tappedTimeout && tappedBefore) {
clearTimeout(tappedTimeout);
}
if(tappedBefore === tappedNow) {
tappedNow.trigger('doubleTap', event);
tappedBefore = null;
originalTapEvent = null;
} else {
tappedTimeout = setTimeout(function(){ tappedBefore = null; }, 300);
tappedBefore = tappedNow;
}
});
and to use it:
cy.on('doubleTap', function (event, originalTapEvent) {
event = originalTapEvent;
...
Besides, did someone do experiments with a combination of tapstart (index finger, use this event location) + tap(middle finger, location irrelevant only as selection confirmation) as an alternative? Would that work?
This is not a strict double tap but works like it. It relies on node.selected()
When user taps/click once on a node it gets a state selected
.
When user clicks again and the node is selected from before it works as a double click.
There is no need to track another state and use timeouts with this solution.
cy.on('tap', 'node', function(evt){
let node = evt.target;
console.log('tapped ' + node.id());
if (node.selected()) {
console.log('selected ' + node.id());
}
});
console log will then be
tapped <nodeId>
tapped <nodeId>
selected <nodeId>
See fixpoint/cytoscape-dblclick (MIT License) for a 3rd-party solution that is ready to use.