Mobile Phone Touch Event - javascript

I want to create a slider. Here is my javascript code:
<div id="ghgh" style='width:50px;height:50px;position:absolute;top:0;left:0;background:#000'>
</div>
<script type="text/javascript">
$(document).bind('mousemove',function(ev){
$('#ghgh').offset({left:(ev.pageX-25)});});
</script>
This, however, only works in computers but not touch screen. I have tried to use events like touchmove,slide,scroll,etc. yet none of them works. What events should I use in order to make it work in touch screens?

First of all: put your styles and scripts in separate files.
For touch events, you may have a look at hammer.js
Example from their website:
Hammer(el).on("swipeleft", function() {
alert('you swiped left!');
});
EDIT: more specific example:
Hammer(document.body).on('drag', function (event) {
var gesture = event.gesture,
pageX = gesture.center.pageX,
pageY = gesture.center.pageY,
deltaX = gesture.deltaX,
deltaY = gesture.deltaY;
// console.log(event); Uncomment this to see all properties of the event object in your webinspector console
});

Related

mouseover event and click event on same element conflicts on mobile

I'm using angular.js to build my website, and I have an element that MOUSEOVER event is supposed to show the navbar, and on mobile, clicking on that element, supposed to show the navbar + the menu.
These two events conflict.
Any ideas?
//navbar fade in by mouse over menu button
angular.element('.picture_hamburger>.text').on('mouseover', function() {
angular.element('#navbar').stop().fadeIn();
btnState.setPosition(1);
// navbar fade out by mouse out of button
angular.element('.menu_hamburger').one('mouseout', function() {
btnState.setPosition(0);
});
});
//menu open by click
angular.element('.picture_hamburger>.text').click(function () {
angular.element('#navbar').finish().slideDown();
btnState.openMenu();
});
i finally used this:
var isTouchDevice = 'ontouchstart' in document.documentElement;
and i had a variable that checks for touch screen ability, without adding Modernizr.
If you are able to use Modernizr (js library for checking HTML5 stuff), then it provides the best method for checking if a client is mobile or not. You can do this in pure javascript too I think, but after countless tries I gave it up:
By using Modernizr.touch, you can see if the device is touch capable or not. Touch screens are quite unique to phones and pads, but unfortunately also laptops which have touchscreens (not many of these thank God).
So then the code would be like this:
//navbar fade in by mouse over menu button
angular.element('.picture_hamburger>.text').on('mouseover', function() {
if(Modernizr.touch) {
return;
}
angular.element('#navbar').stop().fadeIn();
btnState.setPosition(1);
// navbar fade out by mouse out of button
angular.element('.menu_hamburger').one('mouseout', function() {
if(Modernizr.touch) {
return;
}
btnState.setPosition(0);
});
});
//menu open by click
angular.element('.picture_hamburger>.text').click(function () {
angular.element('#navbar').finish().slideDown();
btnState.openMenu();
});
So, if its mobile and the mouseover and mouseout fires, then it just returns before executing anything - just the way you want.
Modernizr can be found at http://www.modernizr.com/

JavaScript: translate long tap events to right click events

How can one automatically translate long tap events to right click events? Since many touch devices like the iPad don't provide a way to do a right click on a website this would be very handy because a website's code doesn't need to be adjusted.
For example this code is designed for desktop browser having mouse support:
<html>
<head><title>Long tap to right click test</title></head>
<body>
<img src="dummy.png" oncontextmenu="alert('Hi!'); return false;" width="20" height="20" />
</body>
</html>
The goal is to translate a long tap event to the right click event without modifying the code. (Just loading some JavaScript, of course.)
If've seen that https://github.com/furf/jquery-ui-touch-punch/ does something similar for drag'n'drop support on jQuery widgets. However this plugin doesn't support the long tap.
Also http://code.google.com/p/jquery-ui-for-ipad-and-iphone/ does actually perform the desired translation but it brakes scrolling, thus making it useless for regular websites with the need of scroll support.
Any help is appreciated - thanks!
You can write simple plugin to handle this type of events. Lets call it longTap event. Example:
$.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);
});
});
};
Obviously you want to change mousedown and mouseup to touchstart and touchend in case of iPad.
Usage: http://jsfiddle.net/dfsq/RZgxT/1/
You can use a timeout for that:
var timeoutLongTouch;
var $mydiv = $j('#myDiv');
// Listen to mousedown event
$mydiv.on('mousedown.LongTouch', function () {
timeoutLongTouch = setTimeout(function () {
$mydiv.trigger('contextmenu');
}, 1000);
})
// Listen to mouseup event
.on('mouseup.LongTouch', function () {
// Prevent long touch
clearTimeout(timeoutLongTouch);
});
All solutions not work in desktop browsers.
You should also tune up 'click' handler behaviour, cause all 'longtap' events should also be followed by 'click' event.
In this case something code like this:
itemEl.click(function(event){
if ($(this).data('itemlongtouch')){
$(this).data('itemlongtouch', false);
}else{
//some work
}
});
itemEl.longTap(function(event){
$(this).data('itemlongtouch', true);
//some work
});

Windows "disallowed" icon appears when dragging element

I am creating a fairly simple slider using jQuery. To do this i am using the mousedown, mousemove and mouseup events.
var pageX;
$handle.bind('mousedown',function(a){
pageX = a.pageX;
$handle.bind('mousemove',function(e){
e.preventDefault();
var delta = pageX - e.pageX;
pageX = e.pageX;
var left = $handle.position().left;
$handle.css({left:(left-delta)+'px'});
});
});
$handle.bind('mouseup',function(){
$handle.unbind('mousemove');
});
Now, this actually works great, except for that when i drag the handle to fast, the "block" icon appears (you know, the circle with a cross over it). How can i prevent that from happening?
i was able to fix it by preventing default behavior of the mousedown event
$handle.bind('mousedown', function(a) {
a.preventDefault()
// ...
}
You can just manually set the cursor to anything: http://www.echoecho.com/csscursors.htm
In this example you would use:
.css('cursor','default');
Hope that helps.

Route events from one dom node to another WITHOUT JQUERY

My question is totally like: How do I pass javascript events from one element to another? except for the fact that I need a raw JS solution.
I've got a webos app whose UI features a layering of elements that scroll in conjunction with eachother on a page. Basically I have what amounts to an iframe (not quite, but in principle), and a floating header that lives in a z-layer above it. When I scroll the elements in the iframe, it also moves the floating header up.
However, I also need to scroll the underlying doc when the header is dragged.
This is a touchscreen interface, so I'm trying onmousemove and ontouchmove events.
I've got the following code, but it doesn't seem to do anything:
setupScrollFromHeader: function setupScrollFromHeader() {
// webos enyo stuff. Don't worry about it. just know that I get the
// raw dom elements through the this.$.elem.node syntax
var body = this.$.body, header = this.$.mailHeaderUnit;
if (!header.hasNode() && !body.hasNode()) {
return;
}
body = body.node;
// end enyo specific stuff
header.node.addEventListener('touchmove', function(event) {
console.log("### touch move");
event.preventDefault();
body.dispatchEvent(event);
var touch = event.touches[0];
console.log("Touch x:" + touch.pageX + ", y:" + touch.pageY);
}, true);
console.log("### set this stuff up");
}
I'm using dispatchEvent to forward the event, per:
https://developer.mozilla.org/en/DOM/element.dispatchEvent
I've tried this with either touchmove and mousemove events by themselves, toggling prevent default, and also changing the bubbling behavior with the true/false flags.
In all cases I see the log print out, but the events are never passed to the underlying element. What am I doing wrong? Is it even possible to pass the events around this way?
So this is the right way to route events. Looks like the widget I'm talking to needed a mousedown event before receiving the touchmove events. For maximum compatibility, I added listeners for both mouse and touch, for testing in browser and on device.
I came up with the following:
setupScrollFromHeader: function setupScrollFromHeader() {
if (setupScrollFromHeader.complete) {
return;
}
var body = this.$.body, header = this.$.mailHeaderUnit;
if (!header.hasNode() && !body.hasNode()) {
return;
}
var header = header.node;
var forwarder = function forwarder(event) {
body.$.view.node.dispatchEvent(event);
};
['mousedown', 'mousemove', 'touchstart', 'touchmove', 'touchend'].forEach(function(key) {
header.addEventListener(key, forwarder, true);
});
setupScrollFromHeader.complete = true;
},
In the general browser case, you can test such forwarding with with two buttons, routing the click event from one to the other works as expected through dispatchEvent(...).
ie:
var button1 = document.getElementById('button1');
var button2 = document.getElementById('button2');
button1.addEventListener('click', function(event) {
button2.dispatchEvent(event);
}, true);
button2.addEventListener('click', function(event) {
alert("Magnets. How do they work?");
}, true);
clicking button1 will fire the handler of button2.

iOS Web App touch gestures

I've searched all across the web to find a simple way of adding touch gestures to a simple button. Basically I'm trying to find a simple way of getting the back button (which you usually see on the task-bar at the top of an iOS device) to change CSS classes from 'normal' state to 'pressed' state when pressed.
Although I'm very new to Javascript, I would prefer to use standard DOM methods rather than jQuery (or any other library). Would anyone have some complete code and explain how the JavaScript code reads an ontouchstart and ontouchend event and how these functions could be used to change CSS classes?
Any help would be greatly appreciated!
TC
ontouchstart, ontouchmove and ontouchend are managed the same as onclick, onmousemove and so.
You can apply the listeners in a <script> tag or directly in the html element.
Using JavaScript only
var back = document.getElementById("back-button-id");
back.ontouchstart = function( event ) {
// using the target property of the event
// you can reach the hitted html element
event.target.className = 'css-href-selected-class-name';
}
back.ontouchend = function( event ) {
event.target.className = 'css-href-normal-class-name';
}
Using HTML tag and callbacks
1) Declare your Javascript callbacks to swap a css class for any state
function onclickCallback( event ) {
// do something
}
function ontouchstartCallback( event ) {
event.target.className = 'selected';
}
function ontouchendCallback( event ) {
event.target.className = 'normal';
}
2) Put the callbacks into the anchor tag (I suggest to use DIV instead of A)
<div class="normal" onclick="onclickCallback( event );" ontouchstart="ontouchstartCallback( event );" ontouchend="ontouchendCallback( event );">Back</div>
Edit 1: to prevent hilight freezing during scrolling
Try to add the ontouchmove handler
ontouchmove="ontouchmoveCallback( event );"
Then declare the handler function that swap the css class
function ontouchmoveCallback( event ) {
event.target.className = 'normal';
}
Hope this helps!
Ciao.
This should get you started:
HTML:
<input type="button" id="thebutton" value="Do Stuff!" />
Javascript:
var thebutton = document.getElementById("thebutton");
thebutton.ontouchstart = function(e)
{
this.setAttribute('class', 'pressed');
var touches = e.touches; // array of all touch data
var target = touches[0].target; // what DOM element was touched
var pageX = touches[0].pageX; // coords relative to site
var pageY = touches[0].pageY;
var clientX = touches[0].clientX; // coords relative to screen
var clientY = touches[0].clientY;
};
thebutton.ontouchmove = function(e)
{
var touches = e.touches; // same fields as above
var changedTouches = e.changedTouches; // only touches which have changed
};
thebutton.ontouchend = function(e)
{
this.setAttribute('class', '');
// cleanup, if needed
};
For more details, see: http://sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
It's worth noting that MobileSafari sometimes does wonky things with touch events and form elements (input boxes in particular). You may find it's better to use a styled div than an actual input button.
EDIT: For what you're trying to do, I think you might be better served with simple click events, which generally work fine for things like button presses. Touch events are more for drag and drop, precise finger tracking etc. Try this:
thebutton.onclick = function(e) { this.setAttribute('class', 'your_class'); };
EDIT2: Now I see what you're asking for. Easiest way is this:
thebutton.ontouchstart = function(e) { this.setAttribute('class', 'pressed'); };
thebutton.ontouchend = function(e) { this.setAttribute('class', ''); };
There are a couple of libraries already for jQuery
http://plugins.jquery.com/project/multiswipe
And you also can check this demo from
http://taitems.github.com/Mobile-Web-based-Gesture-Recognition/
And you can fork the example and start working with it.
There are some options but everything its quite new.

Categories