Equivalent of "hold" and "release" in hammer.js 2.0 - javascript

In hammer.js 1.1.3 version I was able to use the following code perfectly:
var button = Hammer(element, {
hold: true,
release: true
});
button .on('hold', function() {
//Do something when the hold event starts
});
button .on('release', function() {
//Do something when the hold event stops
});
But in hammer.js 2.0 I'm struggling to find an equivalent:
var button = new Hammer.Manager(element);
button.add(new Hammer.Press({
event: 'press',
pointer: 1,
threshold: 5,
time: 500
}));
button.on('press', function(event) {
//Do something when the the element is pressed after 500ms
});
//Possible handler when the element is released?
According to the documentation (http://hammerjs.github.io/getting-started.html) for the new hammer.js 2.0, there are 5 recognizers:
Pan, Pinch, Press, Rotate, Swipe, Tap
I couldn't find a appropriate recognizer that would allow release type functionality. Any thoughts, suggestions or ideas are appreciated. Cheers for reading!

This will be supported in the next release, 2.0.1!
https://github.com/hammerjs/hammer.js/commit/a764fde2e89c3af2575ae02d3af41d7787a60dc5

Managed to achieve this functionality using 'press' (hold) and 'pressup' (release)
var hammer = new Hammer(this);
hammer.on("press pressup", function (ev) {
// Hold gesture start (press)
if (ev.type == "press") {
console.log("Hold active");
}
// Hold gesture stop (pressup)
if (ev.type == "pressup") {
console.log("Hold inactive");
}
});
Tested on Hammer.JS v2.0.8

Using
$(button).on('touchend',function(e){});
Works on jQuery.

Related

HammerJS clicking on Pan

ready = ->
onPan = (ev) ->
console.log(ev)
# ev.target.dataset.object
createHammer = (v) ->
mc = new Hammer.Manager(v, {})
mc.add new Hammer.Pan(
direction: Hammer.DIRECTION_HORIZONTAL
threshold: 20
)
mc.on 'panleft', onPan
mc.on 'panright', onPan
selector = '.foo a'
createHammer(v) for v in document.querySelectorAll(selector)
$(document).ready(ready)
$(document).on('page:load', ready)
I don't know what I'm doing wrong, here... the objects all get a handler, and when I drag 's (mind you, with my mouse on my computer) if I stop on the element, it clicks. The last hammer event's srcEvent.type is mousemove, so it's not hammer firing the event. I tried calling ev.preventDefault(), but didn't seem to have any effect.
I still want to be able to click the ... just not after a drag. What am I missing?
I tried preventDefault: true as an option on the manager...
I tried ev.preventDefault() on the action...
I had the same problem, fixed it by temporarily (200ms) disabling click-handling on the target element. This was done in the panend event by setting a flag and starting a timer to remove that flag
As stated in this comment:
https://github.com/hammerjs/hammer.js/issues/240#issuecomment-16583814
"It's not a Hammer issue really, but rather just the way client events propagate. Hammer isn't replacing all default events but rather augmenting it, so default stuff like Click still fires."
And you can filter such click with a regular flag. E.g. in Angular 7:
#HostListener('click', ['$event'])
onClickBtn(){
if (!this.filterGhostClick) {
this.regularClickHandler();
}
this.filterGhostClick = false;
}
#HostListener('pan', ['$event'])
onPanStart(e){
this.panHandler(e);
}
private filterGhostClick = false;
panHandler(e: Event) {
...
if (e.isFinal) {
this.filterGhostClick = true;
}
}
...

Hammer.js : How to handle / set tap and doubletap on same elements

I'm using jquery.hammer.js, it works quite well and I am able to bind function to a doubletap event. That is working fine.
What I want is to bind two different behaviors. One for the "tap", one for the "doubletap". I use the code below to bind my functions. When I do that, I only get the "tap", the "doubletap" doesn't seem to be triggered.
$("#W0AM").hammer();
$("#W0AM").on('doubletap', function (event) {
alert( 'this was a double tap' );
}).on('tap', function (event) {
alert( 'this was a single tap' );
});
If I remove the .on('tap'... ) binding, then I get the "doubletap" as expected.
$("#W0AM").hammer();
$("#W0AM").on('doubletap', function (event) {
alert( 'this was a double tap' );
});
If I do the following, both events get triggered all the time. I mean, I tap and I see the alert for the tap and the double tap. I doubletap, same thing, I see both alerts.
$("#W0AM").hammer();
$("#W0AM").on('tap doubletap', function (event) {
alert( 'this was a ' + event.type );
});
The question is how can I bind both behavior and distinguish between the two in order to perform different things
Thank you.
Hammer.js now has a requireFailure method to recognize multiple taps.
Because multiple gestures can be recognized simultaneously and a gesture can be recognized based on the failure of other gestures. Multiple taps on the same element can be easily recognized on this way:
var hammer = new Hammer.Manager(el, {});
var singleTap = new Hammer.Tap({ event: 'singletap' });
var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2 });
var tripleTap = new Hammer.Tap({event: 'tripletap', taps: 3 });
hammer.add([tripleTap, doubleTap, singleTap]);
tripleTap.recognizeWith([doubleTap, singleTap]);
doubleTap.recognizeWith(singleTap);
doubleTap.requireFailure(tripleTap);
singleTap.requireFailure([tripleTap, doubleTap]);
When a tap gesture requires a failure to be recognized, its recognizer will wait a short period to check that the other gesture has been failed. In this case, you should not assume that its tap gesture event will be fired immediately.
SOURCE: http://hammerjs.github.io/require-failure/
While there's probably nothing wrong with the accepted answer, I personally had to edit it a little to get it working. Because this all took longer to discover than it should have I'll provide my working solution. But kudos to Josh Unger.
var hammer = new Hammer(document);
var singleTap = new Hammer.Tap({ event: "tap" });
var doubleTap = new Hammer.Tap({ event: "doubletap", taps: 2 });
hammer.add([doubleTap, singleTap]);
singleTap.requireFailure(doubleTap);
doubleTap.recognizeWith(singleTap);
hammer.on("tap", function(e) {console.log("tap");});
hammer.on("doubletap", function(e) {console.log("doubletap");});
My guess is that the alert is preventing doubletap from being triggered in the first code block... it's kinda messy but you could try something like:
var doubleTapped = false;
$("#W0AM").hammer();
$("#W0AM").on('doubletap', function (event) {
doubleTapped = true;
console.log( 'this was a double tap' );
}).on('tap', function (event) {
setTimeout(function() {
if(!doubleTapped) {
console.log( 'this was a single tap' );
}
doubleTapped = false;
}, 500); // This may have to be higher dependant on the speed of the double tap...
});
I'm using jQuery 2.1.0 and Hammer 1.0.10 and Chris's answer almost work but it fires logs tap after logging double tap. I've added a timeout also to the reset of doubleTap back to false and it seems to work out for me.
var doubleTapped = false;
Hammer(document.getElementById("W0AM")).on('doubletap', function (event) {
doubleTapped = true;
console.log( 'this was a double tap' );
}).on('tap', function (event) {
setTimeout(function() {
if(!doubleTapped) {
console.log( 'this was a single tap' );
}
setTimeout(function() {
doubleTapped = false;
}, 500);
}, 500); // This may have to be higher dependant on the speed of the double tap...
});

Add onRightClick to JavaScript lib Hypertree

I'm currently working (a repo is here) on a Hypertree graph, which I want to use from the JavaScript InfoVis Toolkit. The issue is as follows: I added the specific events to the Hypertree, which are onClick and onRightClick.
Events: {
enable: true,
onClick: function(node, eventInfo, e) {
ht.controller.onComplete();
},
onRightClick: function(node, eventInfo, e) {
ht.controller.onComplete();
},
},
Then I simply attached the veent handlers to the Hypertree labels, just modifying demo-code a little:
//Attach event handlers and add text to the
//labels. This method is only triggered on label
//creation
onCreateLabel: function(domElement, node){
domElement.innerHTML = node.name;
$jit.util.addEvent(domElement, 'click', function () {
ht.onRightClick(node.id, {
onComplete: function() {
ht.controller.onComplete();
}
});
});
$jit.util.addEvent(domElement, 'rclick', function () {
ht.onClick(node.id, {
onComplete: function() {
ht.controller.onComplete();
}
});
});
},
That's pretty straight forward. The documentation for Hypertree events is in Options.Events.js. Now I load the page... and I have the left.clicks. But no right clicks... I want the RightClicks to move the graph and the onClicks to open a link from the DOM Element node. Can someone please give me a pointer here?
Best,
Marius
$jit.util.addEvent(obj, type, fn) is a shortcut for obj.addEventListener(type, fn, false). So you are trying to bind to 'onrclick' event. But there is no such event in javascript. For detecting right click you just need to replace your 'rclick' to 'mouseup', and in callback you should check for button to be the right one. Here is the code:
$jit.util.addEvent(domElement, 'mouseup', function (event) {
// detecting right button
if (event.button != 2) {
return;
}
ht.onClick(node.id, {
onComplete: function() {
ht.controller.onComplete();
}
});
});
Also you don't need to use Options.Events.js for this purpose, so you can remove that code
The only fault I can see in the "Events"-section, is a trailing comma behind onRightClick. It really shouldn't affect the code if you use IE>8, but it's worth a try.
Ok, this is an answer on why I think your solution is not working.
$jit.util.addEvent(domElement, 'rclick', function ()
There is no such jquery event as 'rclick'.
Typically using jquery you would detect a right-click using the following:
$('#element').mousedown(function(event) {
if (event.which === 3) {
alert('Right mouse button pressed');
}
});
Hence in your example you would use 'mousedown' instead of 'rclick'. However, looking at the documentation for addEvent:
$jit.util.addEvent(elem, 'click', function(){ alert('hello'); });
The example seems to suggest that the event object can not be passed in to addEvent's function parameter, meaning that it won't be possible to detect that the right mouse button has been clicked.
Might be worth posting your question directly to InfoVis' author, as I too will be interested to see whether it is possible to hook-up the right mouse button.

How do I disable vertical scrolling in iOS using Hammer.js?

I'm trying to disable vertical scrolling in iOS with Hammer.js (jQuery version) in a horizontally scrolling list. I've tried this:
$(document).hammer().on('swipe,drag', 'body',
function(event)
{
if (event.direction == Hammer.DIRECTION_UP || event.direction == Hammer.DIRECTION_DOWN)
{
event.preventDefault();
}
}
);
But it doesn't work. So, how do I disable the scroll vertically while still being able to scroll horizontally?
I did it using the event.gesture.preventDefault:
$('#horizontalCarousel').hammer({ drag_lock_to_axis: true }).on("swipe drag", function(event) {
event.gesture.preventDefault();
if(event.type == "swipe"){
swipeAction(event);
} else {
dragAction(event);
}
});
Here is the given documentation
[EDIT]
My answer was only to let you know you were using the wrong event.preventDefault(). In fact you also used the wrong syntax to check the event direction. You should be able to manage it in this way, though I haven't tested it:
$(document).hammer({ drag_lock_to_axis: true }).on("swipe drag", function(event) {
if (event.gesture.direction == Hammer.DIRECTION_UP || event.gesture.direction == Hammer.DIRECTION_DOWN){
event.gesture.preventDefault();
}
});
2 things are changed: event.gesture.direction and event.gesture.preventDefault(); The event.direction was the way to do it on older versions of hammer js.
Note: if you want to do something with the swipe event, for instance: jump a bigger amount horizontally when swiping, you can combine my answers.
You can use the drag_block_vertical option to disable vertical scrolling:
$(document).hammer({drag_block_vertical: true}).on('swipe,drag', 'body', function(event){
// etc
});
Also, you're calling it on the body element, which should always exist. For that reason, you could probably simplify to:
$('body').hammer({drag_block_vertical: true}).on('swipe,drag', function(event){
// etc
});
Check out this page:
https://github.com/EightMedia/hammer.js/wiki/Event-delegation-and-how-to-stopPropagation---preventDefaults#evgesturestoppropagation
Try this assuming your $ is jQuery and you are using the jQuery version of hammer.js
$('body').hammer().on('touch', function(ev){
var $t = $(ev.target); //let's you know the exact element you touched.
if(ev.gesture.direction === 'left' || ev.gesture.direction ==='right'){
} else {
ev.gesture.preventDefault();
}
});
Hammer(document.body, { prevent_defaults: true });

Capture "tap" event with pure JavaScript

How can I capture a user's "tap" event with pure JS? I cannot use any libraries, unfortunately.
The click event is triggered on mouse click as well as on a touch click.
The touchstart event is triggered when the screen is touched.
The touchend event is triggered when the touch ends. If the default action is prevented, a click event will not trigger.
http://www.w3.org/TR/touch-events/
There are touchstart, touchend and other events. You can add event listeners for them in this way:
var el = document.getElementById('test');
el.addEventListener('touchstart', touchHandler);
More information about native DOM events you can find on MDN webstite.
This is not my code but I can't remember where I got it from, used successfully. It uses jQuery but no extra libraries or plugins for the tap handling itself.
$.event.special.tap = {
setup: function(data, namespaces) {
var $elem = $(this);
$elem.bind('touchstart', $.event.special.tap.handler)
.bind('touchmove', $.event.special.tap.handler)
.bind('touchend', $.event.special.tap.handler);
},
teardown: function(namespaces) {
var $elem = $(this);
$elem.unbind('touchstart', $.event.special.tap.handler)
.unbind('touchmove', $.event.special.tap.handler)
.unbind('touchend', $.event.special.tap.handler);
},
handler: function(event) {
event.preventDefault();
var $elem = $(this);
$elem.data(event.type, 1);
if (event.type === 'touchend' && !$elem.data('touchmove')) {
event.type = 'tap';
$.event.handle.apply(this, arguments);
} else if ($elem.data('touchend')) {
$elem.removeData('touchstart touchmove touchend');
}
}
};
$('.thumb img').bind('tap', function() {
//bind tap event to an img tag with the class thumb
}
I used this for a project exclusively for iPad, so might need tweaking to work for desktop and tablet together.
I wrote a little script myself. It's not in pure-JS, but works fine for me.
It prevents executing the script on scrolling, meaning the script only fires on a 'tap'-event.
$(element)
.on('touchstart', function () {
$(this).data('moved', '0');
})
.on('touchmove', function () {
$(this).data('moved', '1');
})
.on('touchend', function () {
if($(this).data('moved') == 0){
// HERE YOUR CODE TO EXECUTE ON TAP-EVENT
}
});

Categories

Resources