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
}
});
Related
I have a situation in which i have to prevent all MouseClick events until the page loads.
i have 1 javascript function defined on page load like
onload="init();"
Now in function init(), we are showing tree and select a particular node of it.
function init() {
ExpandAncestors(node);
ExpandNode(node);
setTimeout("treeScrollToView()", 1000);
}
Now i want to prevent all the mouse click event on tree/page until whole tree is not fully shown.
I have searched through some of the posts related to my question but that uses event.preventDefault() but i dont have Event object here.
Any help is greatly appreciated.
You can use:
CSS
body {
pointer-events:none;
}
and then on page load reactivate them
$(document).ready(() => {
$('body').css('pointer-events', 'all') //activate all pointer-events on body
})
Explanation
pointer-events:none; blocks all mouse interaction with the elements it's applied to - Since the body is usually the parent of all the elements in your page, it would case them not to react to any mouse interaction at all.
Keep in mind that all mouse interaction would be blocked this way, not only mouse clicks but mouse hover, mouse up's etc etc..
I think the basic need is to prevent user from clicking the tree area. I would prefer to display an overlay div rather than playing with the tree mouse click events.
You can show a loading overlay on the tree part until it is loaded. once done, you can hide the loading and show your original tree.
Ref: How to completely DISABLE any MOUSE CLICK
JavaScript Only
You can have an event listener along with a boolean. onclick disables a click. oncontextmenu disables right clicks.
(function(){window.onload = function () {
var allowClicks = false;
document.onclick = function (e) { !allowClicks&&e.preventDefault(); }
document.oncontextmenu = function (e) { !allowClicks&&e.preventDefault(); }
document.getElementById('myElement').onload = function () { allowClicks = true; }
}());
myElement is your element which you can replace with whatever
Use this with one element
If you want to disable mouse clicks for just one element, do:
(function(){window.onload = function () {
var allowClicks = false,
elem = document.getElementById('myElement');
elem.onclick = function (e) { !allowClicks&&e.preventDefault(); }
elem.oncontextmenu = function (e) { !allowClicks&&e.preventDefault(); }
elem.onload = function () { allowClicks = true; }
}());
onload="init();" here you can have event object.
pass event as argument.
onload="init(event);"
now you can use that in init() function.
Try utilizing $.holdReady()
$.holdReady(true);
$(window).off("click");
$("*").each(function(i, el) {
this.onclick = function(e) {
e.preventDefault();
}
});
function init() {
$("div").on("click", function() {
alert($.now())
})
}
setTimeout(function() {
$.holdReady(false);
}, 7000)
$(function() {
init()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<body>
<div>click</div>
click
</body>
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...
});
I have this 'template' code (just for example):
$(document).on("<EVENT>", "form", function() {
$(this).find(".input input").each(function() {
var required = $(this).attr("required");
var checkField = $(this).closest("tr").children(".check");
var errorField = $(this).closest("tr").children(".errormessage");
if (required != undefined) {
$(checkField).css("color", "#FFFF00");
$(checkField).html("✘");
$(errorField).css("color", "#FFFF00");
$(errorField).html("(Required)");
}
else {
$(checkField).css("color", "#FFFF00");
$(checkField).html("✔");
$(errorField).css("color", "#000000");
$(errorField).html("");
}
});
});
When <EVENT> is for example click or mouseover, it just works as expected.
However it refuses to work on an ready or load event, any clue why?
From http://api.jquery.com/on/
In all browsers, the load, scroll, and error events (e.g., on an element) do not bubble. In Internet Explorer 8 and lower, the paste and reset events do not bubble. Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event.
I have read about 15 different stack overflow questions on Firefox having problems with event. Not of them closely pertained to my function but I figured it was a straight forward problem. I have tried everything that seemed to have worked for their problems and they all fail.
My problem is in Firefox, nothing happens and this is caused by the order I have my code. The order is very important or I'll cause unwanted appending of multiple buttons. I at least understand why it isn't adding and removing a class based on a click function. What I don't understand is I added var event = event || window.event; and tried if(!event) event = window.event;. They all seem to do nothing so I even tried just putting window.event anywhere I had just event at and this also did not work.
My problem in IE, This one at least allows me to click and expand the article which is great but it doesn't append my button once clicked. This one isn't major since the close article button isn't life or death.
My jQuery
function newsArticle() { // Articles Functionality
$('.article').on('click', function() {
var self = this;
var button = $('<span />', {
'class': 'close',
text: 'Click to minimize article',
on: {
click: function (e) {
e.stopPropagation();
$(self).stop(true).toggleClass('fullArticle article');
$(this).remove();
}
}
});
if(!event) event = window.event;
if($(event.target).is('.article')) {
$(this).append(button);
}
else if($(event.target).parents().is('.article')) {
$(this).append(button);
}
$(this).removeClass('article').addClass('fullArticle');
});
}
newsArticle();
Answer
function newsArticle() { // Articles Functionality
$('.article').on('click', function(e) {
var self = this;
var button = $('<span />', {
'class': 'close',
text: 'Click to minimize article',
on: {
click: function (e) {
e.stopPropagation();
$(self).stop(true).toggleClass('fullArticle article');
$(this).remove();
}
}
});
if($(e.target).is('.article')) {
$(this).append(button);
}
else if($(e.target).parents().is('.article')) {
$(this).append(button);
}
$(this).removeClass('article').addClass('fullArticle');
});
}
newsArticle();
jsfiddle
If jsfiddle doesn't show problem then view on live site --> site
Just scroll all the way down and above footer there is 4 tabs, click on "In the News".
If you need anything else then let me know and sorry for asking this question but I have not been able to find an answer that works.
When you use jQuery, you don't need to do the cross-browser checks (if(!event) event = window.event; etc) since jQuery does that for you. You should, however, accept the event as a parameter in your event handler:
$('.article').on('click', function(event) {
I like to use e as a convention, to avoid confusion:
$('.article').on('click', function(e) {
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.