My iPhone's screen is playing up. I had the idea, since I'm a web developer, to go to a page on my local machine's web server, or on jsfiddle, using my phone, and have some jquery running on that page which gives me some simple feedback about every touch event. (I have a feeling that I will see lots of spurious swipe events firing off even when i'm not touching the screen, for example).
So, something like this:
<div id="feedback">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
function feedback(msg){
$("#feedback").append("<div class=\"line\">"+msg+"</div");
}
$(function() {
feedback("in $(function) block");
$(document).on("click", function(event){
feedback("clicked at "+event.pageX+","+event.pageY);
});
//can you replace the below with working code?
$(document).on("all events", function(event){
var msg = "Some basic info about this event: if it's a swipe, which direction. if it's a keypress, which character? etc"
feedback(msg);
});
});
</script>
I've set this up in a jsfiddle here: https://jsfiddle.net/sxqjp9xe/
Do I need to write a handler for every event i'm interested in, like I've done with the click handler? Or is there some more generic solution? Thanks, Max
EDIT: changed my "feedback" function to use prepend() instead of append() as it's easier to see once you get a lot of lines on there.
You can include more than one event in the handler:
function feedback(msg){
$("#feedback").append("<div class=\"line\">"+msg+"</div");
}
$(document).on("blur touchstart touchmove touchend touchcancel focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error", function(event) {
var msg = event.type
feedback(msg);
}
https://jsfiddle.net/e9e0ehyc/
Related
I'm trying to handle touch/mouse events. So, I created this code:
myObject.addEventListener("touchstart", function(e){
e.stopPropagation();
e.preventDefault();
console.log("Touched");
mouseTouchDown(e);
});
myObject.addEventListener("mousedown", function(e){
console.log("Clicked");
mouseTouchDown(e);
});
function mouseTouchDown(e){
console.log("Some function.");};
I want to stop bubbling of touch event, so click won't be fired afterwards. It works on Chrome, but on Firefox I get in console:
Touched
Clicked
How can I stop mouse click firing after touch event?
I tried returning false, but it doesn't work.
This looks like a bug in the browser, your code looks fine.
See: https://bugzilla.mozilla.org/show_bug.cgi?id=977226.
What OS/version of Firefox are you testing this with?
Have u attached both events with same element?
If that is the case the error is not because of bubbling happening.while mouse click several events will happen like mousedown, touchstart ..etc.so if you want to avoid mouse click event occuring add preventDefault() in the mouse down.This will disable default mouse click event happening on that element.
my idea is a script that auto click the picture when user moves mouse pointer over the picture. Please guide me how to make it. Thank you in advanced.
Not that I support such a thing. but...
el = document.getElementById('lol');
el.onmouseover = function(){el.click();}
el.onclick = function(){
//your code for having clicked the element
}
Here is a jsfiddle: http://jsfiddle.net/Rap6M/
But!, why not just put your code in the onmouseover listener? Especially seeing that (though widely acceptable) not all browsers suppoer the el.click()
Here is what MDN has to say about click(): https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.click
Noting that they say:
However, bubbling of a click event will not cause an <a> element to
initiate navigation as if a real mouse-click had been received.
It sounds like you want to trigger a DOM mouse onclick event but during mouse overs on certain elements (in this case a picture).
My suggestion would be to just trigger the event (mouse onclick) whenever you hover over the image. Just have an event listener on your object listening for a onmouseover event, once you detect it, fire off a click event on whatever element you need to.
Take a look at this:
<img id="my_image" src="myimage.png"></img>
<div id="my_clicky_div">My click event will be triggered</div>
<script type="text/javascript">
$("#my_clicky_div").on("click", function() {
console.log("My click event has been triggered!")
})
$("#my_image").on("mouseover", function() {
$("#my_clicky_div").trigger('click');
});
</script>
You create an image tag and a div. Whenever you hover (mouseover) this image, the div's onclick event is triggered.
To make it easier, you should just bind whatever event you need triggered onto the onmouseover event, you essentially bypass a step as so:
<img id="my_image" src="myimage.png"></img>
<script type="text/javascript">
$("#my_image").on("mouseover", function() {
// Instead of issuing another event, run the code that happens during the click event
});
</script>
Let me know if this helps!
References:
http://api.jquery.com/mouseover/, http://api.jquery.com/trigger/, http://api.jquery.com/on
In a mousedown event-handler of a div another new div is created and appended to the body.
This new div has position:fixed (can also be position:absolute) and has 100% width and 100% height. Therefore it immediately covers the source div which triggered the mouse down event.
Now with the latest Google Chrome (v30), latest Firefox (v24), Opera v12.16 and even with a older Safari v5.1.1 (on Windows) after the mousedown event no click event gets fired on an event listener attached to the body.
Only Internet Explorer (both 9 and 10) does fire the click event on the body afterwards! Why? And how can this be prevented? Is this actually a bug in IE?
The HTML:
<div class="clickme">Click me</div>
The CSS:
.clickme {
background-color: #BBB;
}
.overlay {
position: fixed; /* or absolute */
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: #000;
}
The JavaScript:
$(document).on('click', function(event) {
console.log('body click');
});
$('.clickme').on('mousedown', function(event) {
console.log('div mousedown');
var mask = $('<div></div>');
mask.attr('class', 'overlay');
mask.appendTo('body');
});
Here is a the example with some additional comments: http://jsfiddle.net/Fh4sK/5/
After clicking the "Click me" div, only
div mousedown
should be written to the console, but in Internet Explorer it actually is
div mousedown
body click
I appreciate any help!
EDIT 1:
I found some resources describing the conditions when to trigger a click event:
http://www.quirksmode.org/dom/events/click.html:
"click - Fires when a mousedown and mouseup event occur on the same element."
http://www.w3.org/TR/DOM-Level-3-Events/#events-mouseevent-event-order
"...in general should fire click and dblclick events when the event target of the associated mousedown and mouseup events is the same element with no mouseout or mouseleave events intervening, and should fire click and dblclick events on the nearest common ancestor when the event targets of the associated mousedown and mouseup events are different."
I'm not 100% sure what the "correct" behaviour now actually should be (maybe IE is the only browser which handles it right?). From the last sentence, it seems that it is correct to fire the click event on the body, because the body is the "nearest common ancestor" of both div elements. There are some other statements on the referenced w3.org page above, which describe the behaviour if an element gets removed, but again I'm not sure if this applies here, as no element gets removed, but covered by an other element.
EDIT 2:
#Evan opened a bug report asking Microsoft to drop the described behaviour: https://connect.microsoft.com/IE/feedback/details/809003/unexpected-click-event-triggered-when-the-elements-below-cursor-at-mousedown-and-mouseup-events-are-different
EDIT 3:
In addition to Internet Explorer, Google Chrome recently started to have the same behaviour: https://code.google.com/p/chromium/issues/detail?id=484655
I bumped into this issue too. I decided I'd make a jQuery plugin to solve this issue and put it on GitHub.
It's all here, feedback is welcome : https://github.com/louisameline/XClick
#mkurz : thanks for finding that W3 directive, you saved me a lot of time.
#vitalets : I solved this issue because I use select2 like you (you led me to this topic). I'll fork the select2 repo and leave a message for the people interested in this.
I'll see if I can ask the Microsoft people to take a look at it and hopefully change that annoying click behavior.
I also struggled with such behavior. I've modified your fiddle to find out how all mouse events are triggered with dynamically created overlay:
http://jsfiddle.net/Fh4sK/9/
So, when mousedown handler of some element shows overlay on the same place where mousedown occured:
Chrome, FF:
mousedown triggered on element
mouseup triggered on overlay
click does not trigger
IE:
mousedown triggered on element
mouseup triggered on overlay
click triggered on BODY(!)
The same behavior if you hide mask in mousedown.
This issue can lead to weird things in IE with modals, masks, overlays etc..
Intresting thing: if you show overlay in mouseup instead of mousedown - everything works
The solution I found is to use mouseup instead of mousedown.
It can't be explained normally because both these events are triggered before click.
In that case all mouse events are triggered on element:
http://jsfiddle.net/Fh4sK/11/
mousedown triggered on element
mouseup triggered on element
click triggered on element
Hope this helps.
You could filter the document click by the target to exclude clicks on that div:
$(document).on('click', function(event) {
if(!$(event.target).hasClass('clickme')) {
console.log('body click');
}
});
If you want to stop bubbling of the click event, try this : (I don't have IE to test)
$(document).on('click', function(event) {
console.log('body click');
});
$('.clickme').on('mousedown', function(event) {
console.log('div mousedown');
});
$('.clickme').on('click', function(event) {
event.stopPropagation();
});
Click, mousedown and mouseup are differents events, independant.
here is a similar question
I've built a webapp, and for a little bit of polish, I wanted to add mousedown and mouseup handlers to swap out images (in this case, to make a button look like it's being pressed).
my code is something like this:
window.onload = function() {
//preload mouse down image here via Image()
$("#button_img").mousedown(function(){$("#button_img").attr("src","button_on.png");});
$("#button_img").mouseup(function(){$("#button_img").attr("src","button_off.png")});
}
This works swimmingly on the desktop, but on mobile (testing in iOS Safari), the mousedown and mouseup events happen at the same time, so effectively nothing happens.
I tried to use the vmousedown and vmouseup events in jQueryMobile, however this code:
//include jquerymobile.js and jquerymobile.css
window.onload = function() {
//preload mouse down image here via Image()
$("#button_img").vmousedown(function(){$("#button_img").attr("src","button_on.png");});
$("#button_img").vmouseup(function(){$("#button_img").attr("src","button_off.png")});
}
Just gave me the errors that vmousedown and vmouseup don't exist. Also, jQueryMobile overrides the CSS I've already written for the page.
So is there a way to get vmousedown and vmouseup to work, and to do so without jQuery Mobile's CSS?
You're looking for touchstart and touchend. They are the events that vmousedown and vmouseup attempt to mimic.
Here's an example:
window.onload = function() {
//preload mouse down image here via Image()
$("#button_img").bind('touchstart', function(){
$("#button_img").attr("src","button_on.png");
}).bind('touchend', function(){
$("#button_img").attr("src","button_off.png");
});
}
This will work without any framework on any device that supports touch events. You could use something like Modernizr to do this test and if the device does not support touch events, bind to the regular desktop events.
When you use touchstart/touchend/touchmove you get some interesting information, for instance how many touches are occurring at once, so you can detect if the user is scrolling or attempting to zoom.
UPDATE
Since the event object inside an event handler differs for touch events and mouse events, if you want to know the coordinates of the event either way, you can do something like this (the example below assumes Modernizr has been loaded):
//determine which events to use
var startEventType = 'mousedown',
endEventType = 'mouseup';
if (Modernizr.touch === true) {
startEventType = 'touchstart';
endEventType = 'touchend';
}
//bind to determined event(s)
$("#button_img").bind(startEventType, function(event) {
//determine where to look for pageX by the event type
var pageX = (startEventType === 'mousedown')
? event.pageX
: event.originalEvent.touches[0].pageX;
...
})...
UPDATE
I was looking this over and it seems like you don't need to detect the event type before binding the event handler:
//bind to determined event(s)
$("#button_img").bind('mousedown touchstart', function(event) {
//determine where to look for pageX by the event type
var pageX = (event.type.toLowerCase() === 'mousedown')
? event.pageX
: event.originalEvent.touches[0].pageX;
...
})...
If you are worried about receiving both events in quick succession you could use a timeout to throttle the event handler:
//create timer
var timer = null;
//bind to determined event(s)
$("#button_img").bind('mousedown touchstart', function(event) {
//clear timer
clearTimeout(timer);
//set timer
timer = setTimeout(function () {
//determine where to look for pageX by the event type
var pageX = (event.type.toLowerCase() === 'mousedown')
? event.pageX
: event.originalEvent.touches[0].pageX;
...
}, 50);
})...
Note: You can force mousedown and touchstart events in quick succession with developer tools but I'm not sure about the real world use case here.
Have you considered styling your buttons using CSS instead? the :active state will be triggered when a user is clicking/touching the element. Here is an example:
/* Default state */
#button_img {
background-image: url('button_off.png');
}
/* Clicked/touched state */
#button_img:active {
background-image: url('button_on.png');
}
CSS will be much more performant and you will also be able to better separate concerns (display vs logic, etc).
JSBin: http://jsbin.com/beyin/1/
There is a way to get the vmouseup, vmousedown, vmousemove, vclick, etc. functionality of jQueryMobile without getting all the rest (and especially the side effects) of jquerymobile (i.e. enhancement, extra css, and the like)
Go to http://jquerymobile.com/download-builder/ (a tool for downloading a custom build of jquerymobile with only the components you need)
select ONLY "Virtual Mouse (vmouse) Bindings"
download it.
The download will contain only a single .js files (in both minimized and uncompressed version). No css.
Link this script in the head of your html after plain jquery, and use it like this:
<head>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
<script src="whatever/path/jquery.mobile.custom.min.js"></script>
<script>
$(function(){ // or replace this with window.onload for that matter
// Your code here, e.g.
$("#button_img").on("vmousedown", function() {
/*whatever*/
});
// CAUTION: this won't work (see note below):
// $("#button_img").vmousedown(function(){/*whatever*/}); // WON'T WORK
});
</script>
</head>
NOTE: the methods .vmousedown(), .vmouseup(), etc. won't work. You have to bind the event listener with .on("vmousedown", ...).
Not sure why: I guess this is because the part of jquerymobile that creates shortcut methods with the same name as the events is in some other module. Maybe it is possible to figure out which module it is and include it in the download, but I think it would force you to include other undesired dependencies.
Use touchstart or touchend for touch devices.
Most times you want to catch touchstart as well as mousedown. You need to make sure though that the handler is only triggered once. The simplest way to do this is to catch them both and call e.preventDefault().
$("#button_img").on('touchstart mousedown', function(e) {
//your code...
e.preventDefault(); //prevents further events from being dispatched
}
Source: developer.mozilla.org:
If the browser fires both touch and mouse events because of a single user input, the browser must fire a touchstart before any mouse events. Consequently, if an application does not want mouse events fired on a specific touch target element, the element's touch event handlers should call preventDefault() and no additional mouse events will be dispatched.
Is it possible to trigger a mouseout event on a link element using jQuery ?
I.e. Something of the sort
$(linkEle).mouseout()
I want this to work on an iPad, which even though does not have any mouse cursor, does actually have the event...
Yes, jquery has a mouseout event handler - http://api.jquery.com/mouseout/
$('some_selector_here').mouseout(function() {
// Do some stuff
}
$('some_selector_here').trigger('mouseout');
You might be able to use:
.trigger('mouseleave');
In the form of:
$('#elementToTriggerMouseLeaveOn').trigger('mouseleave');
References:
trigger().
I don't know about the ipad, but it works as you posted. http://jsfiddle.net/tESUc/
$(linkEle).mouseout();
or
$(linkEle).trigger('mouseout');
or
$(linkEle).trigger($.Event('mouseout'));
Try with tap event
tap - triggered after a tapping an pnscreen element.
http://www.roccles.com/?p=134
$('.link').live('tap',function(event) {
//TODO
});
mouse hover state does not exist on touchscreens
Mouse over/out events do not work as required on ipad. Take a look at touchstart/touchmove and touchend events which are specially for touch devices.
Something like this http://jsfiddle.net/hTYKQ/ Will work in ipad but in this fashion:
1st click to the element triggers the mouseenter function.
2nd click triggers stuff.. if it has stuff... like a link (
http://jsfiddle.net/qxM33/1/ i screwed the <a> href but you get
the point.)
Click outside the element triggers the mouseleave function.
What this story teaches is: jquery mouse over and mouse out functions work much like click functions in ipad.