jQuery Mobile: Taps won't register with `vclick` or `touchend` - jquery-mobile

I have this mobile touch indicator, but in Chrome's mobile emulator, how come taps only get registered using mouseup but not touchend orvclick` (http://api.jquerymobile.com/vclick/)?
With vclick (taps don't register): http://jsfiddle.net/frank_o/LnhrF/14/embedded/result/
With mouseup (taps register): http://jsfiddle.net/frank_o/LnhrF/9/embedded/result/
$(document).on('pagecreate', function () {
$('button').on('vclick', function (event) {
showActionIndicator(event, event.pageX - 30, event.pageY - 30);
});
function showActionIndicator(event, pageX, pageY) {
var touchIndicator = $("#touchIndicatorDiv");
touchIndicator.html($("#touchIndicatorTemplate").html());
touchIndicator.css("left", pageX);
touchIndicator.css("top", pageY);
event.preventDefault();
}
});

Related

swipe-right triggered twice in jQuery Mobile

I'm trying to integrate this plug-in into my site so I can swipe to delete. The problem however is that this plugin is triggered with a 'swiperight', the same swipe event is used to reveal my panel. I managed to separate the events using event.target.tagName. When it's a A(link), I want to activate the swipe to delete button and otherwise I want my panel to slide in.
With other words the pageinit event is triggered twice so the swipe to delete button starts to appear then the same event is triggered again. I want to somehow cancel one action but i can't make it work. I already tried:
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
I also tried to use some solutions given here but with no luck:
jQuery Mobile: document ready vs page events
A demo of my problem can be found snip and my current pageinit function is this:
$(document).on('pageinit', function() {
//Activate horizontal swipe after x px.
$.event.special.swipe.horizontalDistanceThreshold = 80;
$('div[data-role="content"]').on("swiperight", function(event) {
//If tagname is 'A' you probably want slide to delete not the panel
if(event.target.tagName != 'A') {
$.mobile.activePage.find("#menu").panel("open");
} else {
//Cancel swipe
event.stopImmediatePropagation();
}
});
//Swipe to delete
$("#swipe li").swiper( {
corners: false,
label: "Verwijder",
swipe: function(event, ui) {
alert('trigger');
},
click: function(event, ui) {
var $item = $(this);
//console.log($(this));
$item.fadeOut(250, function() {
$item.remove();
});
}
});
});
Fixed issue using the following plugin: TouchSwipe which has the ability to simple exclude elements from the events.

Change and Slide called together jqueryui slider

I am trying to create a jquery handle that when you slide it it moves another div inside a container. Following is my js
function handleSliderChange(e, ui)
{
console.log('1');
var maxScroll = $(".content-item").width()*$(".content-item").length - $("#content-scroll").width();
$("#content-scroll").animate({scrollLeft: ui.value * (maxScroll / 100) },1000);
}
function handleSliderSlide(e, ui)
{
console.log('2');
var maxScroll = $(".content-item").width()*$(".content-item").length - $("#content-scroll").width();
$("#content-scroll").animate({scrollLeft: ui.value * (maxScroll / 100) }, 10);
}
$("#content-slider").slider({
animate: true,
slide: handleSliderSlide,
change: handleSliderChange
});
So when I click on the bar both handleSliderChange and handleSliderSlide are called, but when i drag the slider it works fine any solution ? I don't mind cancelling the click function from the slider i only need the drag anyways
I found the solution to that, the trick is to check prior to running the methods for what type of event is triggered. This is how i did it
sliderBar.slider({
start: checkType,
animate: options.animateSpeed,
slide: handleSliderSlide,
step: options.step,
change: handleSliderChange,
});
function checkType(e){
_isSlide = $(e.originalEvent.target).hasClass("ui-slider-handle");
}

Cordova/Phonegap backbutton handler not working

I am using Phonegap and jQuery Mobile. This is my code:
function onDeviceReady() {
// Register the event listener
document.addEventListener("backbutton", onBackKeyDown, false);
setPage();
}
function setPage(){
//All pages at least 100% of viewport height
var viewPortHeight = $(window).height();
//alert(viewPortHeight );
var headerHeight = $('div[data-role="header"]').height();
var footerHeight = $('div[data-role="footer"]').height();
var contentHeight = viewPortHeight - headerHeight - footerHeight-120;
// Set all pages with class="page-content" to be at least contentHeight
$('div[class="page-content"]').css({'min-height': contentHeight + 'px'});
}
function confirmExit(){
alert("exit...");
}
// Call onDeviceReady when Cordova is loaded.
// At this point, the document has loaded but cordova-2.2.0.js has not.
// When Cordova is loaded and talking with the native device,
// it will call the event `deviceready`.
//
function onLoad() { alert("onload");
document.addEventListener("deviceready", onDeviceReady, false);
}
// Handle the back button
function onBackKeyDown() {
alert("onbackkeydown");
console.log("back clicked");
confirmExit();
}
$(document).ready(function(){});
And in the body tag:
<body onload="onLoad();">
But when I load the app I only get the alert in the onLoad method.
What I am doing wrong?
Thanks a lot.

jQuery mobile image gallery default vertical scroll issue

I have an image gallery with a series of thumbs. Both are loaded dynamically depending on how many images are associated with a product. You can click on a thumb to get that series of images. On a mobile device you can swipe left and right to see all the images. That all works fine.
Here's my issue: When you try to scroll down the page and you happen to be touching one of the main images you get stuck and the page doesn't move. For the life of me I cannot figure out a work around for this. I am wondering if anyone has ever encountered this and figured out a solution. I think there could be a way to control this via the touch-punch.js but cannot figure it out. Thank you.
Here is my simplified gallery HTML:
<ul id="Gallery" class="gallery productGalleryInner">
<li>
<a href="#"><img src="img.jpg" />/a>
<a href="#"><img src="img.jpg" />/a>
<a href="#"><img src="img.jpg" />/a>
<a href="#"><img src="img.jpg" />/a>
<a href="#"><img src="img.jpg" />/a>
</li>
</ul>
</div>
css:
#productGalleryWrap {
overflow: hidden;
margin: 7px 10px 0;
}
#productGalleryWrap .productGalleryInner {
white-space: nowrap;
}
#productGalleryWrap .productGalleryInner li {
display: inline;
}
#productGalleryWrap .productGalleryInner img {
display: inline;
width: 50%;
}
I am using touch-punch.js to control the horizontal drag. Here is the code:
(function ($) {
// Detect touch support
$.support.touch = 'ontouchend' in document;
// Ignore browsers without touch support
if (!$.support.touch) {
return;
}
var mouseProto = $.ui.mouse.prototype,
_mouseInit = mouseProto._mouseInit,
touchHandled;
/**
* Simulate a mouse event based on a corresponding touch event
* #param {Object} event A touch event
* #param {String} simulatedType The corresponding mouse event
*/
function simulateMouseEvent (event, simulatedType) {
// Ignore multi-touch events
if (event.originalEvent.touches.length > 1) {
return;
}
event.preventDefault();
var touch = event.originalEvent.changedTouches[0],
simulatedEvent = document.createEvent('MouseEvents');
// Initialize the simulated mouse event using the touch event's coordinates
simulatedEvent.initMouseEvent(
simulatedType, // type
true, // bubbles
true, // cancelable
window, // view
1, // detail
touch.screenX, // screenX
touch.screenY, // screenY
touch.clientX, // clientX
touch.clientY, // clientY
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
0, // button
null // relatedTarget
);
// Dispatch the simulated event to the target element
event.target.dispatchEvent(simulatedEvent);
}
/**
* Handle the jQuery UI widget's touchstart events
* #param {Object} event The widget element's touchstart event
*/
mouseProto._touchStart = function (event) {
var self = this;
// Ignore the event if another widget is already being handled
if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
return;
}
// Set the flag to prevent other widgets from inheriting the touch event
touchHandled = true;
// Track movement to determine if interaction was a click
self._touchMoved = false;
// Simulate the mouseover event
simulateMouseEvent(event, 'mouseup');
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
// Simulate the mousedown event
simulateMouseEvent(event, 'mousedown');
};
mouseProto._touchMove = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Interaction was not a click
this._touchMoved = true;
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
};
/**
* Handle the jQuery UI widget's touchend events
* #param {Object} event The document's touchend event
*/
mouseProto._touchEnd = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Simulate the mouseup event
simulateMouseEvent(event, 'mouseup');
// Simulate the mouseout event
simulateMouseEvent(event, 'mouseout');
// If the touch interaction did not move, it should trigger a click
if (!this._touchMoved) {
// Simulate the click event
simulateMouseEvent(event, 'click');
}
// Unset the flag to allow other widgets to inherit the touch event
touchHandled = false;
};
/**
* A duck punch of the $.ui.mouse _mouseInit method to support touch events.
* This method extends the widget with bound touch event handlers that
* translate touch events to mouse events and pass them to the widget's
* original mouse event handling methods.
*/
mouseProto._mouseInit = function () {
var self = this;
// Delegate the touch handlers to the widget's element
self.element
.bind('touchstart', $.proxy(self, '_touchStart'))
.bind('touchmove', $.proxy(self, '_touchMove'))
.bind('touchend', $.proxy(self, '_touchEnd'));
// Call the original $.ui.mouse init method
_mouseInit.call(self);
};
})(jQuery);
Please let me know if more info is needed. Thanks.
Kind of late answer but I had this same problem on a current project I'm working on.
Comment out:
event.preventDefault();
Add this after:
document.ontouchmove = function(e) {
var target = e.currentTarget;
while(target) {
if(checkIfElementShouldScroll(target))
return;
target = target.parentNode;
}
e.preventDefault();
};
Dolla dolla bills y'all.
Code taken from this thread: document.ontouchmove and scrolling on iOS 5

iOS/WebKit: touchmove/touchstart not working on input & textarea

I have an IOS Web App that can't be scrolled. For that reason I want to deactivate scrolling. To do this, I use an element's ontouchmove attribute and have it call a function that uses element.preventDefault.
However, I am unable to detect any touching event when it starts on a textarea or input element, even when the element is disabled! I have also tried binding the touchmove or touchstart event to these elements via JavaScript's addEventlistener, without success!
And here's my JavaScript:
function onBodyLoad() {
document.addEventListener( "touchstart", doNotScroll, true );
document.addEventListener( "touchmove", doNotScroll, true );
}
function doNotScroll( event ) {
event.preventDefault();
event.stopPropagation();
}
Thanks for any help!
I think I've found a great workaround for this issue using the "pointer-events" CSS property:
function setTextareaPointerEvents(value) {
var nodes = document.getElementsByTagName('textarea');
for(var i = 0; i < nodes.length; i++) {
nodes[i].style.pointerEvents = value;
}
}
document.addEventListener('DOMContentLoaded', function() {
setTextareaPointerEvents('none');
});
document.addEventListener('touchstart', function() {
setTextareaPointerEvents('auto');
});
document.addEventListener('touchmove', function(e) {
e.preventDefault();
setTextareaPointerEvents('none');
});
document.addEventListener('touchend', function() {
setTimeout(function() {
setTextareaPointerEvents('none');
}, 0);
});
This will make Mobile Safari on iOS (others not tested so far) ignore the textareas for scrolling but allows to set focus etc. as usual.
the Thomas Bachem answer is the one!
I rewrote it in jQuery. Just add a class scrollFix to your desired inputs and you are ready to go. Or attach the event handlers to all inputs and textareas using $('input, textarea').
Now when you touch and scroll on an input on iOS 8+, the input get all its pointer-events disabled (including the problematic behavior). Those pointer-events are enabled when we detect a simple touch.
$('.scrollFix').css("pointer-events","none");
$('body').on('touchstart', function(e) {
$('.scrollFix').css("pointer-events","auto");
});
$('body').on('touchmove', function(e) {
$('.scrollFix').css("pointer-events","none");
});
$('body').on('touchend', function(e) {
setTimeout(function() {
$('.scrollFix').css("pointer-events", "none");
},0);
});

Resources