Detect when touch event is over in Hammer.js and jQuery - javascript

In Hammer.js 2.02, how do you detect when a press gesture has ended?
I have a 'press' recognizer on an element with a time of 1 which prints a message as soon as the press event starts. But how do I check when the user has lifted their finger? Right now I'm using the 'pressup' recognizer which nearly works, except that it only triggers if the user has held their finger down for >500ms. How can I check when shorter presses end?
var pressOptions = {
event: 'press',
pointer: 1,
threshold: 5,
time: 1
};
var trackpadRight = $('#trackpad-right').hammer();
trackpadRight.data("hammer").get('press').set(pressOptions);
trackpadRight.bind('press', function(ev) {
console.log("PRESSS DOWN");
});
trackpadRight.bind('pressup', function(ev) {
console.log("PRESS UP");
});

Just use Hammer without jQuery.
var pressOptions = {
// event: 'press', //no need to pass defaults
// pointer: 1,
// threshold: 5,
time: 1
};
var trackpadRightTouch = new Hammer(document.getElementById('trackpad-right'));
trackpadRightTouch.get('press').set(pressOptions);
trackpadRightTouch.on('press', function(ev) {
console.log("PRESSS DOWN");
});
trackpadRightTouch.on('pressup', function(ev) {
console.log("PRESS UP");
});
this should work.

From your comment, I thought you need to detect the touch release. If yes then you can use the default "touchend" event by directly bind to the element, like below:
$('#trackpad-right').bind('touchend', function(ev) {
console.log("PRESS UP");
});

Related

jQuery: Prevent Click Event from being fired after long tap (mobile)

For mobile devices there is not action like right-clicking - so I want to handle a long press for this.
I also need a normal "click" event.
For the long-press handling I found a solution, but when I add an onClick-listener, the onClick gets fired even if I only want the long-press event to be fired.
How can I prevent the Click Event when the longTap event fires?
Here is the Code + example:
var c = console.log.bind(console);
(function() {
$.fn.longTap = function(options) {
options = $.extend({
delay: 1000,
onRelease: null
}, options);
var eventType = {
mousedown: 'ontouchstart' in window ? 'touchstart' : 'mousedown',
mouseup: 'ontouchend' in window ? 'touchend' : 'mouseup'
};
return this.each(function() {
$(this).on(eventType.mousedown + '.longtap', function() {
$(this).data('touchstart', +new Date);
})
.on(eventType.mouseup + '.longtap', function(e) {
var now = +new Date,
than = $(this).data('touchstart');
now - than >= options.delay && options.onRelease && options.onRelease.call(this, e);
});
});
};
})(jQuery);
$('.long-tap').longTap({
delay: 1000, // really long tap
onRelease: function(e) {
c($(this).position(), e);
e.stopImmediatePropagation();
e.preventDefault();
alert('show context menu or something else:');
}
});
$('.long-tap').click(function(){
alert("click");
})
.test {
width: 200px;
height: 100px;
background-color: #DDD;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test long-tap"></div>
You can use contextmenu for right click event:
$(document).on("contextmenu",function(e){
e.preventDefault();
// do the stuff
});
When you long press with the finger in your mobile device then the context menu will appear.
There is really no good way to do such thing, what you can do is test if longtap event is registered on event target for click event handler:
$('.long-tap').click(function(){
if ($(this).data('touchstart')) {
return;
}
...
});
In general, I think your general approach to implement context menu for touch screen devices should be reconsidered.
Best of luck!

Creating an event that triggers a second event

I'm trying to create a jQuery event that triggers a second event. The first event is clicking on the emoji id which refers to an image. The second is a mousemove event which moves the image around the page. The third event stops this event when the mouse click happens again anywhere in the body of the page and places the image at that absolute position. I was able to get the second and the third events to work but I can't get the first event to work with the second. Here is what I have so far for my jQuery:
var mouseTracker = function(event) {
console.log(event.pageX, event.pageY, !!event.which)
$('#emoji').css('top', event.pageY);
$('#emoji').css('bottom', event.pageY);
$('#emoji').css('left', event.pageX);
$('#emoji').css('right', event.pageX);
}
var begin = function() {
$('body').on('mousemove', mouseTracker);
$('body').css('cursor', 'none');
}
var stop = function() {
$('body').off('mousemove', mouseTracker);
$('#emoji').css('postion', 'absolute')
$('body').css('cursor', 'default');
}
$('#emoji').on('click', begin);
$('body').on('click', stop);`
Initialize the event from within the first event call.
$('#emoji').on('click', function() {
begin();
$('body').on('click', stop);
});
During the click on #emoji the body click even is also triggered.
That leads to calling stop(). The propagation of that event to body can be blocked by event.stopPropagation() (or equivalent return false from begin()). The propagation should be manually stopped even if body on click handler is attached in begin().
You may want one-time usage of some events. That can be done by binding using .one(). In that case the handler is detached after the first usage without manual .off():
var begin = function (event) {
$('body').on('mousemove', mouseTracker);
$('body').one('click', stop);
$('body').css('cursor', 'none');
return false; // event.stopPropagation();
}
var stop = function () {
$('#emoji').one('click', begin);
$('body').off('mousemove', mouseTracker);
$('#emoji').css('postion', 'absolute')
$('body').css('cursor', 'default');
}
$('#emoji').one('click', begin);

Javascript buttons, prevent mouse double click

I have two buttons that use Javascript to call their function which controls a carousel and some other actions.
I'd simply like to disable the ability of the user to doubleclick the button.
Here is my code:
var onRightArrow = function(e) {
//alert("Right");
if (unitCtr<=unitTotal) {
unitCtr++;
TweenLite.to(productTxt, 0.2, {y: "-="+unitHeight });
TweenLite.to(productImg, 0.2, {y: "-="+unitHeight });
}
hideArrows();
}, onLeftArrow = function(e) {
//alert("Left");
if (unitCtr>1) {
unitCtr--;
TweenLite.to(productTxt, 0.2, {y: "+="+unitHeight });
TweenLite.to(productImg, 0.2, {y: "+="+unitHeight });
}
hideArrows();
}
arrowRight.addEventListener('click', onRightArrow, false);
arrowLeft.addEventListener('click', onLeftArrow, false);
I'm aware of the dblclick line of code but not exactly sure how to apply to disable the double click action from the mouse.
When the user doubleclicks now, it misplaces the positioning of the elements in the carousel which is why I want to remove the ability of the dblclick to affect the button.
Thanks in advance for any advice. Please avoid providing answers in JQuery.
More code:
http://codepen.io/anon/pen/QjGydw
I solved this myself, while the answer is more complex, is anyone is looking to apply listeners to disable the ability to doubleclick, it's here:
(arrowRight and arrowLeft are variables that have been defined by ID)
arrowRight.addEventListener('dblclick', function(e){
e.preventDefault();
});
arrowLeft.addEventListener('dblclick', function(e){
e.preventDefault();
});
I also created functions that disable the arrow while animation is happening to prevent errors. Reenables after animation completes. Functions look like this:
function disableArrows() { //ADDED NEW FUNCTION TO DISABLE ARROWS
arrowRight.removeEventListener('click', onTopArrow, false);
arrowLeft.removeEventListener('click', onBottomArrow, false);
}
function enableArrows() { //ADDED NEW FUNCTION TO RE-ENABLE ARROWS
arrowRight.addEventListener('click', onTopArrow, false);
arrowLeft.addEventListener('click', onBottomArrow, false);
}

Prevent click event after drag in jQuery

I have a draggable <div> with a click event and without any event for drag,
but after I drag <div> the click event is apply to <div>.
How can prevent of click event after drag?
$(function(){
$('div').bind('click', function(){
$(this).toggleClass('orange');
});
$('div').draggable();
});
http://jsfiddle.net/prince4prodigy/aG72R/
FIRST attach the draggable event, THEN the click event:
$(function(){
$('div').draggable();
$('div').click(function(){
$(this).toggleClass('orange');
});
});
Try it here:
http://jsfiddle.net/aG72R/55/
With an ES6 class (No jQuery)
To achieve this in javascript without the help of jQuery you can add and remove an event handler.
First create functions that will be added and removed form event listeners
flagged () {
this.isScrolled = true;
}
and this to stop all events on an event
preventClick (event) {
event.preventDefault();
event.stopImmediatePropagation();
}
Then add the flag when the mousedown and mousemove events are triggered one after the other.
element.addEventListener('mousedown', () => {
element.addEventListener('mousemove', flagged);
});
Remember to remove this on a mouse up so we don't get a huge stack of events repeated on this element.
element.addEventListener('mouseup', () => {
element.removeEventListener('mousemove', flagged);
});
Finally inside the mouseup event on our element we can use the flag logic to add and remove the click.
element.addEventListener('mouseup', (e) => {
if (this.isScrolled) {
e.target.addEventListener('click', preventClick);
} else {
e.target.removeEventListener('click', preventClick);
}
this.isScrolled = false;
element.removeEventListener('mousemove', flagged);
});
In the above example above I am targeting the real target that is clicked, so if this were a slider I would be targeting the image and not the main gallery element. to target the main element just change the add/remove event listeners like this.
element.addEventListener('mouseup', (e) => {
if (this.isScrolled) {
element.addEventListener('click', preventClick);
} else {
element.removeEventListener('click', preventClick);
}
this.isScrolled = false;
element.removeEventListener('mousemove', flagged);
});
Conclusion
By setting anonymous functions to const we don't have to bind them. Also this way they kind of have a "handle" allowing s to remove the specific function from the event instead of the entire set of functions on the event.
I made a solution with data and setTimeout. Maybe better than helper classes.
<div id="dragbox"></div>
and
$(function(){
$('#dragbox').bind('click', function(){
if($(this).data('dragging')) return;
$(this).toggleClass('orange');
});
$('#dragbox').draggable({
start: function(event, ui){
$(this).data('dragging', true);
},
stop: function(event, ui){
setTimeout(function(){
$(event.target).data('dragging', false);
}, 1);
}
});
});
Check the fiddle.
This should work:
$(function(){
$('div').draggable({
start: function(event, ui) {
$(this).addClass('noclick');
}
});
$('div').click(function(event) {
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');
}
else {
$(this).toggleClass('orange');
}
});
});
DEMO
You can do it without jQuery UI draggable. Just using common 'click' and 'dragstart' events:
$('div').on('dragstart', function (e) {
e.preventDefault();
$(this).data('dragging', true);
}).on('click', function (e) {
if ($(this).data('dragging')) {
e.preventDefault();
$(this).data('dragging', false);
}
});
You can just check for jQuery UI's ui-draggable-dragging class on the draggable. If it's there, don't continue the click event, else, do. jQuery UI handles the setting and removal of this class, so you don't have to. :)
Code:
$(function(){
$('div').bind('click', function(){
if( $(this).hasClass('ui-draggable-dragging') ) { return false; }
$(this).toggleClass('orange');
});
$('div').draggable();
});
With React
This code is for React users, checked the draggedRef when mouse up.
I didn`t use click event. The click event checked by the mouse up event.
const draggedRef = useRef(false);
...
<button
type="button"
onMouseDown={() => (draggedRef.current = false)}
onMouseMove={() => (draggedRef.current = true)}
onMouseUp={() => {
if (draggedRef.current) return;
setLayerOpened(!layerOpened);
}}
>
BTN
</button>
I had the same problem (tho with p5.js) and I solved it by having a global lastDraggedAt variable, which was updated when the drag event ran. In the click event, I just checked if the last drag was less than 0.1 seconds ago.
function mouseDragged() {
// other code
lastDraggedAt = Date.now();
}
function mouseClicked() {
if (Date.now() - lastDraggedAt < 100)
return; // its just firing due to a drag so ignore
// other code
}

setInterval cannot clear with mouseup

I am using mousedown and mouseup to trigger a setInterval function like so:
$("#rotateRight").mousedown(function() {
intervalIRight = setInterval(rotateRight, 0);
}).mouseup(function() {
clearInterval(intervalIRight);
});
This works great, however, if I release the mouse (mouseup) when I am not hovering over $("#rotateRight") then there is technically no 'mouseup' so the interval goes on forever and is never cleared.
I cannot use hover because I want the even to be when a user clicks and holds a mouse. But at the same time, I need to fix this 'mouseup bug.' Any ideas?
UPDATE: New code is as follows, but still does not clear interval because mouseup happens on an iframe, not the DOM.
var intervalIRight;
var intervalILeft;
$("#rotateRight").on('mousedown', function() {
intervalIRight = setInterval(rotateRight, 0);
});
$("#rotateLeft").on('mousedown', function() {
intervalILeft = setInterval(rotateLeft, 0);
});
$(document).on('mouseup', function() {
clearInterval(intervalIRight);
clearInterval(intervalILeft);
});
clear the interval on any mouseup by attaching the event handler to the document.
var intervalIRight;
$("#rotateRight").on('mousedown', function() {
intervalIRight = setInterval(rotateRight, 0);
});
$(document).on('mouseup', function() {
clearInterval(intervalIRight);
});
FIDDLE

Categories