How to get continuous mousemove event when using android mobile browser? - javascript

using this code:
<h2 id="status">
0, 0
</h2>
<script type="text/javascript">
$('html').mousemove(function(e){
$('#status').html(e.pageX +', '+ e.pageY);
});
</script>
In Windows browser like firefox, It's ok to see the mouse postion when I move mouse, but when I run this page in android(2.1) browser, I can not get the continuous event when I touch the screen, It just trigger the event when I tap the screen, why? and how to get the continuous mousemove event when I touch the screen?

Use the touchmove event instead (works on my Android browser on Froyo), although there are some problems with it -- the browser only updates the div when the touch has been released, however the event is still fired for every touch movement. This can be demonstrated by changing the code to this:
var x = 0;
$('html').bind('touchmove', function(e) {
$('#status').html(x++); // Only updates on touch release
});
This is due to a bug in the Android browser -- you need to call event.preventDefault() to make this work as expected:
var x = 0;
$('html').bind('touchmove', function(e) {
e.preventDefault();
$('#status').html(x++); // Only updates on touch release
});
Official bug details: available here
To detect the current X and Y position you should use the event.touches object:
$(window).bind('touchmove', function(jQueryEvent) {
jQueryEvent.preventDefault();
var event = window.event;
$('#status').html('x='+event.touches[0].pageX + ' y= ' + event.touches[0].pageY);
});
jQuery creates it's own "version" of the event object which doesn't have the native browsers properties such as .touches -- so you need use window.event instead

After reading the accepted answer, perhaps the best way to deal with on-going events for both touch and mouse is something like this?
<div id="status">x, y</div>
<script>
$('html').on("mousemove touchmove", function(e){
$('#status').html(e.pageX +', '+ e.pageY);
e.preventDefault();
});
</script>

Related

Which events are acceptable for starting HTML5 audio play in mobile Chrome

Mobile browsers require user action to start play on Audio elements. The click event satisfies the requirement, but it appears that touchstart is not an acceptable initiating event in Chrome on Android or iOS. (See below)
Does anyone know where to find a precise definition of the event context required to start play.
(I was attempting to solve a UX problem using the ideas in How to prevent doubletap zoom in iOS and Android. Since posting my original question, I've found a solution that solves the UX problem without using touchstart, but I think the essential question about which events are considered to be user action is still valid.)
Addendum:
It has been suggested that I am mistaken about touchstart events, so for the record, I am providing a trivial test program. Since it requires a real music file and a mobile device, JSFiddle isn't a suitable platform (unless somebody knows how to simulate a touchstart event in a fiddle). To reproduce my observations, edit the javascript to load your own audio file.
<!DOCTYPE html>
<html>
<body>
<br>
<button type="button" id="but1">click</button>
<button type="button" id="but2">touch</button>
<br>
<br>
<span id="message"></span>
<script>
var e;
e = document.getElementById('but1');
e.onclick = click;
e = document.getElementById('but2');
e.ontouchstart = touchstart;
function click() {
alert('caught click');
play();
event.preventDefault();
}
function touchstart() {
alert('caught touchstart');
play();
event.preventDefault();
}
var p;
var t;
function play() {
p = new Audio();
p.src = '/k487.mp3'; // CHANGE THIS
p.preload = 'auto';
p.play();
t = setInterval(report,1000);
}
function report() {
var s = 'Player readyState='+p.readyState+', currentTime='+p.currentTime;
var e = document.getElementById('message');
e.innerHTML = s;
}
</script>
</body>
</html>
When I load this page in Chrome 58 on Android 6.0.1 the Click button works as expected, producing a popup, playing some music and updating the play time.
If I reload the page and touch the Touch button instead, I get the popup, but no music plays. The status display shows a readyState of 4 and a currentTime of 0. In other words, the touchstart event is permitted to load the audio but not to initiate play.
Since I can find no documentation on what events are meant to work, I don't know whether to consider this a Chrome bug, or intended behaviour.
When the play() method on a media element is invoked, the user agent must run the following steps https://html.spec.whatwg.org/multipage/media.html#dom-media-play
step1: if the media element is not allowed to play...
then I wonder the condition that allowed to play, it jump to here https://html.spec.whatwg.org/multipage/media.html#allowed-to-play
it says:
For example, a user agent could require that playback is triggered by user activation, but an exception could be made to allow playback while mute
then came to 'triggered-by-user-activation' here
I think that's the reason:
An algorithm is triggered by user activation if any of the following conditions is true:
The task in which the algorithm is running is currently processing an activation behavior whose click event's isTrusted attribute is true.
change
click
contextmenu
dblclick
mouseup
pointerup
reset
submit
touchend
'touchstart' is not mentioned there.
hope that helps you.
In this page you will found answer on this question .
Use some popup or any animation nice for eye to attract user for tap .
in my memory ... android and iOS have no same behavior it is about max number of audios that we can start buffer with this trick .
var EXE_JUST_ONE_TIME = false;
document.addEventListener("touchstart" , function(e) {
if (EXE_JUST_ONE_TIME == false){
EXE_JUST_ONE_TIME = true;
document.getElementById("LaserShot").play(); // need for play pause just for buffering start
document.getElementById("LaserShot").pause();
// now you can play programmability from js
document.getElementById("LaserShot_CLONE").play();
document.getElementById("LaserShot_CLONE").pause();
}
else if(EXE_JUST_ONE_TIME = true){
document.getElementById("MakeReadyotherAudio1").play();
document.getElementById("MakeReadyotherAudio1").pause();
EXE_JUST_ONE_TIME = 'NOMORE'
}
}
If you have problems i can make you code snippet with working example !
I put in 90% in mobile web dev in event function on begin :
document.getElementById("myAnchor").addEventListener("click", function(event){
event.preventDefault()
});
//Sometimes even if you dont use some event its good to override :
window.addEventListener('touchstart', function(e){
e.preventDefault()
}, false)
window.addEventListener('touchmove', function(e){
e.preventDefault()
}, false)
window.addEventListener('touchend', function(e){
e.preventDefault()
}, false)
window.addEventListener('touchleave', function(e){
e.preventDefault()
}, false)
window.addEventListener('touchcancel', function(e){
e.preventDefault()
}, false)
window.addEventListener('touchenter', function(e){
e.preventDefault()
}, false)
If you wanna you can use this library :
desktop/mobile event optimise for canvas

Touch Screen Preventing Scroll

I have a Lenovo touch screen desktop where I am running a touch based website. The problem is that browsers (Chrome) seem to freeze when I click with eight fingers and try to scroll around. The browser locks up. So I'm attempting to create a function with jQuery that will only register one single touch event.
Here is what I have now:
var isTouched = false;
var $document = $(document);
$document.on('touchstart', function (e) {
if (!isTouched) {
isTouched = true;
console.log('start: ' + isTouched);
$document.on('touchend', function() {
if (isTouched) {
isTouched = false;
console.log('end: ' + isTouched);
}
});
}
});
Which works ok, but it prevents me from scrolling, and the touchend seems to be firing when I lift the first finger off the screen. The expected behavior would be for touchend only to fire when I lift the finger off the screen that caused the touchstart. Any suggestions for creating a function which will only register one touchstart at a time and allow scrolling (i.e. not ignore the touchmove).

Prevent page scroll on drag in IOS and Android

I'm working on a html5 canvas game, but I don't know how to handle touch events. When a user touch the screen, and drag, then the browser will scroll the page. I would like to prevent it, and get the touch start, and touch end position. Is it possible?
Thanks in advance
You need to override the default touch behaviour to stop touchevents dragging the page. Clearly, you'll need to handle them again if your page becomes larger than the available area, but as you're making a game, going to assume you're doing 100%/100% layout.
function preventBehavior(e) {
e.preventDefault();
};
document.addEventListener("touchmove", preventBehavior, {passive: false});
Edit: here's the W3C recommendation talking about touch events, which might be handy for you.
Due to breaking changes made in recent versions of Chrome, the above answers are no longer correct. Attaching a touch event listener to the document or body elements will cause the event listener to be registered in "passive" mode, which causes calls to preventDefault to be ignored.
There are two solutions:
The preferred solution is to use the CSS style touch-action to specify that no scrolling should happen (e.g. with the value "none")
In cases where this is not appropriate (e.g. if the type of interaction should change dynamically in a way that cannot be determined before the gesture begins) then the event listener must be registered with the third parameter set to { passive: false } (you should perform browser detection to ensure that this style is supported first, though).
If you don't want to use jQuery mobile or any other library then you can try this.
var startX, startY, endX, endY;
document.addEventListener("touchstart", function(e){
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
e.preventDefault();//Stops the default behavior
}, false);
document.addEventListener("touchend", function(e){
endX = e.touches[0].pageX;
endY = e.touches[0].pageY;
e.preventDefault();//Stops the default behavior
}, false);
canvas.addEventListener('touchstart', function(e)
{
alert(e.changedTouches[0].pageX + " " + e.changedTouches[0].pageY);
}
canvas.addEventListener('touchend', function(e)
{
alert(e.changedTouches[0].pageX + " " + e.changedTouches[0].pageY);
}
Here's a good article about touching and gesturing on mobile phones:
http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
Following solution preventing scroll when dragging AND at the same time usual scroll is working (when not dragging)
var scrollable = true;
var listener = function(e) {
if (! scrollable) {
e.preventDefault();
}
}
document.addEventListener('touchmove', listener, { passive:false });
onDragstartHandler() {
scrollable = false;
}
onDragendHandler(} {
scrollable = true;
}
Don't forget to bind onDragstartHandler and onDragendHandler to related elements

Safari iPad 1: how to disable zoom/centering on double-tap, but keep pinch zoom

I wonder if its possible to prevent double-tap-to-zoom and double-tap-to-center on a specific HTML element in Safari iOS (iPad 1) ?
Because my small HTML5 game forces users to make fast clicks (or taps), which are interpreted as double clicks, and when it happens - the page changes zoom and centers itself.
Detecting double clicks (like in this answer - Safari iPad : prevent zoom on double-tap) smells bad..
Wrong answer #1:
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> - does not suit my purposes, because it will block any zoom.
Wrong answer #2: maybe would .preventDefault() on click event alone be enough for that ? - Does not have any effect.
There's no other way than catching the events you want to prevent, and call preventDefault() on them, as you had already more or less figured out.
Indeed, some particular CSS properties / values may change the global site behavior (fixed width or fixed, for example), but you're not safe from changes to the OS (see fixedhandling change in iOS5), nor do these changes necessarily prevent all behavior (pinch might be off, but not double-tapping).
So, the best way to disable default behavior only for double-tapping is to take advantage of the count of touches iOS provides: if we have only one contact, then we're tapping. Two, this means we're pinching.
The following setup code provides that functionality:
var elm = document.body; // or some selection of the element you want to disable
var catcher = function(evt) {
if (evt.touches.length < 2)
evt.preventDefault();
};
elm.addEventListener('touchstart', catcher, true);
Demo on jsFiddle.
Note: the third parameter (true) to addEventListener means that we want to capture events, that is catch them all, even for our descendant children.
I am preventing doubletaps like this:
var doubleTouchStartTimestamp = 0;
$(document).bind("touchstart", function (event) {
var now = +(new Date());
if (doubleTouchStartTimestamp + 500 > now) {
event.preventDefault();
}
doubleTouchStartTimestamp = now;
});
The elegance lies within the fact, that no timeouts are needed. I only update a timestamp. It only gets compared on the next touchstart. Works for me on iOS 6.
Doubletaps further down the dom are not affected.
The same works without jQuery, as well:
var doubleTouchStartTimestamp = 0;
document.addEventListener("touchstart", function (event) {
var now = +(new Date());
if (doubleTouchStartTimestamp + 500 > now) {
event.preventDefault();
}
doubleTouchStartTimestamp = now;
});
I wrote a jQuery plugin for the same purpose - selectively disabling double-tap zoom on given page elements (in my case, navigation buttons to flip pages) I want to respond to every tap (including double-tap) as a normal click event, with no iOS "touch magic", no matter how fast the user clicks it.
To use it, just run something like $('.prev,.next').nodoubletapzoom(); on the elements you care for. The principle it uses is to listen for consecutive touchstart events on a node within 500ms, and running event.preventDefault() on the second, unless other touches are active at the same time. As that preventDefault consumes both touches, we also synthesize the two "missed" click events for the node, so your intended touch action happens as many times as the user intended.
Apple has a lot of tips with specialized tags for webkit (Safari). View Official Docs
What iOS version/Safari browser are you using? That site most definitely does not let you double-tap. I found some CSS but haven't had time to try it as I'm about to step out:
body {
-webkit-text-size-adjust:none;
margin:0px;
}
div{
clear:both!important;
display:block!important;
width:100%!important;
float:none!important;
margin:0!important;
padding:0!important;
}
You will need to implement a double tap function and preventDefault on the second tap. Here is some tested code that uses global variables that should get you started:
<button id="test1">Double Tap Me!</button>
<div id="test2">EMPTY</div>
var elm1 = document.getElementById('test1');
var elm2 = document.getElementById('test2');
var timeout;
var lastTap = 0;
elm1.addEventListener('touchend', function(event) {
var currentTime = new Date().getTime();
var tapLength = currentTime - lastTap;
clearTimeout(timeout);
if (tapLength < 500 && tapLength > 0) {
elm2.innerHTML = 'Double Tap';
event.preventDefault();
} else {
elm2.innerHTML = 'Single Tap';
timeout = setTimeout(function() {
elm2.innerHTML = 'Single Tap (timeout)';
clearTimeout(timeout);
}, 500);
}
lastTap = currentTime;
});
And a fiddle: http://jsfiddle.net/brettwp/J4djY/
JQuery approach to disable Double Tap Zoom in MVC4
To Disable the double tap (double mouse down) functionality on iOS 1+ you need to catch the touchStart Event and create an override to prevent the zoom.
// Using Single script.js and JQuery.Mobile-1.2.0 UI each page in MVC gets assigned JQuery through delegates so you don't have to do a full refresh of the page allowing you to take advantage of the data-prefetch which loads the page in the DOM when the app loads for the first time
$(document).delegate("#CashRegister", "pageinit", function () {
// To Disable 'Pinch to Zoom' Note: don't implement gester event handlers if you want to
//keep pinch to zoom functionality NOTE: i use this as my pageinit is a delegate of a page
this.addEventListener("gesturestart", gestureStart, false);
this.addEventListener("gesturechange", gestureChange, false);
this.addEventListener("gestureend", gestureEnd, false);
//handle each event by disabling the defaults
function gestureStart(event) {
event.preventDefault();
}
function gestureChange(event) {
event.preventDefault();
}
function gestureEnd(event) {
event.preventDefault();
}
//Recreate Double Tap and preventDefault on it
$(this).bind('touchstart', function preventZoom(e) {
// recreate the double tab functionality
var t2 = e.timeStamp
, t1 = $(this).data('lastTouch') || t2
, dt = t2 - t1
, fingers = e.originalEvent.touches.length;
$(this).data('lastTouch', t2);
if (!dt || dt > 500 || fingers > 1) return; // not double-tap
e.preventDefault(); // double tap - prevent the zoom
// also synthesize click events we just swallowed up
$(this).trigger('click').trigger('click');
});
Actually, .preventDefault() definitely does work... using jQuery:
var InputHandler = {
startEventType : isTouch ? "touchstart" : "mousedown"
}
$(selector).bind(InputHandler.startEventType, function(evnt) {
evnt.preventDefault();
});
Your problem with trying to prevent on .click() is that the browser isn't throwing a "click" element. Safari only fires a click to help simulate a click... But when there's a double tab, Safair doesn't through a "click" element. Your event handler for .click() doesn't ever fire, and therefore the .preventDefault() doesn't fire either.

How to detect mouseup on a scrollbar? (or "scrollEnd" event)

Anyone have any idea how to detect a mouseup event on a scrollbar? It works in FF, but not in Chrome or IE9.
I set up a quick demo: http://jsfiddle.net/2EE3P/
The overall idea is that I want to detect a scrollEnd event. There is obviously no such thing so I was going with a combination of mouseUp and timers, but mouseUp isn't firing in most browsers! The div contains a grid of items so when the user stops scrolling I want to adjust the scroll position to the nearest point that makes sense, e.g. the edge of the nearest cell. I don't, however, want to automatically adjust the position if they're in the middle of scrolling.
I'll also happily accept any answer that gives me the equivalent of scrollEnd
found a solution that works without timers but only if you are scrolling the complete window.
switch(event.type){
case 'mousedown':
_btnDown = true;
//THIS IS ONLY CAUSE MOUSEUP ON SCROLLBAR IS BUGGY
$(document).bind('mousemove',function(event){
if(event.pageX < ($(window).width() - 30)){
//mouse is off scrollbar
$(this).unbind(event);
$(this).trigger('mouseup');
}
});
break:
case 'mouseup':
//do whatever
_btnDown = false;
break;
}
pretty dirty .. but works.
Using jquery there is a .scroll event you can use. Maybe use a global variable to keep track of when .scrollTop() (it returns the number of pixels there are above the screen) has stopped changing? Still creates a race condition, but it should work.
Answering my own question so I can close it -- there is no good solution to this, so timers it is...
I was handling the same problem. For me IE9 don't emit mouseup event for scrollbars. So, I checked and on IE9 when you "mouseup" it emits a mousemove event. So what I did was monitor scrolling, and monitor mousemove. When user is scrolling, and a mousemove event happens, then I understand it as a mouseup event. Only do this check for IE9, cheching the proto property availability. The code will also run for Opera, but Opera has the mouseup and then no problem for me when both events happens. Here is the code, I write AngularJS + ZEPTO code, so get the idea and write your own code, don't expect to copy&paste this code directly:
// Global for scrolling timeout
var q;
// Action to do when stop scrolling
var updatePosition = function() {
// Put the code for stop scrolling action here
}
$(document).on('mousemove', function(e) {
console.log('MOUSE MOVE ' + e.pageX + ',' + e.pageY);
if(!('__proto__' in {})) {
// for IE only, because it dont have mouseup
if($scope.scrolling && $scope.mouse_down) {
console.log('FAKE MOUSE UP FOR IE');
// Only simulate the mouseup if mouse is down and scrolling
$scope.scrolling = false;
$scope.mouse_down = false;
// Update Position is the action i do when mouseup, stop scrolling
updatePostition();
}
}
});
$(window).on('scroll', function(){
console.log('SCROLLING');
// Set the scrolling flag to true
if(!$scope.scrolling) {
$scope.scrolling = true;
}
// Stop if for some reason you disabled the scrolling monitor
if(!$scope.monitor_scrolling) return;
// Monitor scroll with a timeout
// Update Position is the action i do when stop scrolling
var speed = 200;
$timeout.cancel(q);
q = $timeout(updatePostition, speed);
});
$(window).on('mousedown', function() {
console.log('MOUSE DOWN');
// Stop monitor scrolling
$scope.monitor_scroll = false;
// Set that user is mouse down
$scope.mouse_down = true;
});
$(window).on('mouseup', function() {
console.log('MOUSE UP');
// Enable scrolling monitor
$scope.monitor_scroll = true;
// Change mouse state
$scope.mouse_down = false;
// Action when stop scrolling
updatePostition();
});
Was fighting with this problem. My system also runs for mobile and I have a large horizontal scrolling, that always when user stop scrolling, it need to find the actual item the used is viewing and centralize this item on screen (updatePosition). Hope this can help you. This is to support IE9+, FF, Chorme and Opera, I'm not worrying with old browsers.
Best Regards
Is very late but.... there are solution with any scroll in any part of your page.... I do it with the next code...
onScroll = function(){
$(window).unbind("mouseup").one('mouseup',function(e) {
alert("scroll up")
});
};
$(window).bind("scroll", onScroll);
body{
height:5000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Categories