Custom "swipe" events in Mobile Safari not firing - javascript

I have written a plugin for jQuery which simulates mobile events, but with support for standard web browsers too. Here is the markup for the swipeleft and swiperight events:
(function($) {
var settings = {
swipe_h_threshold : 30,
swipe_v_threshold : 50,
taphold_threshold : 750,
startevent : ('ontouchstart' in document.documentElement) ? 'touchstart' : 'mousedown',
endevent : ('ontouchstart' in document.documentElement) ? 'touchend' : 'mouseup'
};
// swipeleft Event:
$.fn.swipeleft = function(handler) {
return this.each(function() {
$this = $(this);
var start_x = 0;
var end_x = 0;
$this.bind(settings.startevent, function(e) {
e.stopPropagation();
e.preventDefault();
start_x = e.pageX;
$this.one(settings.endevent, function(e) {
end_x = e.pageX;
if(start_x > end_x && (start_x - end_x >= settings.swipe_h_threshold))
{
handler.call(this);
}
});
});
});
};
// swiperight Event:
$.fn.swiperight = function(handler) {
return this.each(function() {
var $this = $(this);
var start_x = 0;
var end_x = 0;
$this.bind(settings.startevent, function(e) {
e.preventDefault();
e.stopPropagation();
start_x = e.pageX;
$this.one(settings.endevent, function(e) {
end_x = e.pageX;
if(start_x < end_x && (end_x - start_x >= settings.swipe_h_threshold))
{
handler.call(this);
}
});
});
});
};
}) (jQuery);
And I then call the events using the following:
$('#my_div').swiperight(function() { self.nextCard('r'); });
$('#my_div').swipeleft(function() { self.nextCard('r'); });
This seems to work fine on a desktop browser (well, Chrome anyway) > http://ben-major.co.uk/labs/carousel.html, but doesn't seem to function in Mobile Safari. The swipeleft executes without problem, but swiperight won't run whatsoever.
Can anyone offer any pointers?

If I'm not completely mistaken e (in the event callback) has an array touches on mobile browsers. It has one element for each touch event.
Here an example:
document.addEventListener('touchmove', function(event) {
event.preventDefault();
var touch = event.touches[0];
console.log("Touch x:" + touch.pageX + ", y:" + touch.pageY);
}, false);

Related

Can I capture the mouse pointer in a Figma plugin window?

I have some code that I've used to create controls for a long time, and it works well, in that it properly captures and releases the mouse (at least in chrome).
function createSlider(slider, width, height)
{
slider.width = width;
slider.height = height;
slider.style.display = 'inline';
//
slider.onchange = new Event('onchange');
//
slider.addEventListener('mousedown', function(e)
{
var e = window.event || e;
if (e.button == 0)
{
e.preventDefault();
if (slider.setCapture)
slider.setCapture();
slider.mouseDown0 = true;
slider.sx = e.clientX;
slider.sv = slider.value;
}
});
slider.addEventListener('losecapture', function()
{
slider.mouseDown0 = false;
});
document.addEventListener('mouseup', function(e)
{
var e = window.event || e;
if (e.button == 0 && slider.mouseDown0)
slider.mouseDown0 = false;
}, true);
(slider.setCapture ? slider : document).addEventListener('mousemove', function(e)
{
if (slider.mouseDown0)
{
var dx = slider.sx - e.clientX;
var adaptive = 10 * Math.pow(Math.abs(dx), slider.acc);
slider.value = Math.min(Math.max(slider.min, slider.sv - dx*slider.scale*adaptive), slider.max);
//TODO: if (log) do log scaling
slider.paint();
slider.dispatchEvent(slider.onchange);
}
}, true);
slider.onmousewheel = function(e)
{
e.preventDefault();
var s = e.target;
s.value = Math.min(Math.max(s.min, s.value + (e.wheelDeltaY > 0 ? 1 : -1) * s.scale), s.max);
s.dispatchEvent(s.onchange);
s.paint();
};
slider.paint = function()
{
//...
};
//
slider.paint();
}
But when I tried using this code inside of a Figma plugin window, it loses mouse capture as soon as the mouse leaves the window. Is there something that I need to adjust for this to work?
Apparently you cannot, but you can use pointer lock to solve the issue for some situations.

Stop scrolling when div reaches fixed position on the page

I am trying to stop scrolling when a DIV is in view and centered in the viewport as the user scrolls down the page.
When the page is stopped and the user scrolls I need the content of the DIV to scroll horizontally and then allow the user to continue scrolling.
function pauseScroll() {
// $(document).bind('mousewheel DOMMouseScroll', function() {
disableScroll();
console.log('trying to scroll Card: ' + selCard);
setTimeout(pauseStop(), 500);
slideCard(selCard);
// });
}
function pauseStop() {
console.log('Pause Stop');
}
function unpauseScroll() {
// $(document).unbind('mousewheel DOMMouseScroll');
enableScroll();
document.getElementById("status").innerHTML = "enabled";
document.getElementById("status").className = "enabled";
}
// left: 37, up: 38, right: 39, down: 40,
// spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
var keys = {
37: 1,
38: 1,
39: 1,
40: 1
};
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
}
function preventDefaultForScrollKeys(e) {
if (keys[e.keyCode]) {
preventDefault(e);
return false;
}
}
function disableScroll() {
if (window.addEventListener) // older FF
window.addEventListener('DOMMouseScroll', preventDefault, false);
window.onwheel = preventDefault; // modern standard
window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
window.ontouchmove = preventDefault; // mobile
document.onkeydown = preventDefaultForScrollKeys;
}
function enableScroll() {
if (window.removeEventListener)
window.removeEventListener('DOMMouseScroll', preventDefault, false);
window.onmousewheel = document.onmousewheel = null;
window.onwheel = null;
window.ontouchmove = null;
document.onkeydown = null;
}
$(window).scroll(function() {
if ($("div").hasClass("cardstop")) {
var top_of_element = $(".cardstop").offset().top;
var bottom_of_element = $(".cardstop").offset().top + $(".cardstop").outerHeight();
var bottom_of_screen = $(window).height()
var top_of_screen = $(window).scrollTop();
var elHeight = bottom_of_element - top_of_element;
var topSpace = ((($(window).height()) - elHeight) / 2);
var scrollFix = top_of_screen + topSpace;
//top_of_screen
var st = $(this).scrollTop();
if (st > lastScrollTop) {
// downscroll code
console.log('Top of el: ' + top_of_element);
console.log('TopScreen: ' + top_of_screen);
console.log('Space: ' + topSpace);
console.log('Bot of el: ' + bottom_of_element);
console.log('BotScreen: ' + bottom_of_screen);;
if (top_of_element < scrollFix) {
if (selCard = 1) {
console.log('One to Two');
pauseScroll();
selCard = 2;
} else if (selCard = 2) {
pauseScroll();
selCard = 1;
}
unpauseScroll();
}
} else {
// upscroll code
console.log('Scroll Up: ');
if (selCard = 3) {
console.log('3 to 2');
pauseScroll();
selCard = 4;
}
if (selCard = 4) {
pauseScroll();
unpauseScroll();
}
}
lastScrollTop = st;
// if (bottom_of_screen > top_of_element) {
// The element is visible, do something
}
});
The process is kind of working apart it's scrolling the card content too quickly and then moving on.
Any pointers on where I am going wrong would be great.
Regards
I've added a mockup on [jsfiddle]:https://jsfiddle.net/stato74/sjtp9wv3/2/
I would admit you to use this JS tool: Waypoints
http://imakewebthings.com/waypoints/
If you prefer the hard way, then you can set "html, body{overflow-y=hidden}" and set your Div {overflow-y=scroll}
This will let you scroll the div instead of the whole page.
If I will find some time later, I can provide code for this (if needed)
the maximum value of scrollTop is not scrollHeight, it's scrollHeight - outerHeight.
This will give you the correct value:
var elem = $("body");
var maxScrollTop = elem[0].scrollHeight - elem.outerHeight();
$(document).scroll(function(){
if(e.target.scrollTop > maxScrollTop ){
e.target.scrollTop = maxScrollTop ;
}
});

"tap" for mobile adding to "keydown" event jquery

var gameLink = $("#theGame");
$(window).keydown(function (e) {
if (e.which === 32) {
window.location.href = "thegame.html;
}
});
I am very new to jQuery and I can't seem to figure out where to add the "tap" event for mobile to this code.
This is pretty much all you need: http://jsfiddle.net/gianlucaguarini/56Szw/
*code from fiddle
var getPointerEvent = function(event) {
return event.originalEvent.targetTouches ? event.originalEvent.targetTouches[0] : event;
};
var $touchArea = $('#touchArea'),
touchStarted = false, // detect if a touch event is sarted
currX = 0,
currY = 0,
cachedX = 0,
cachedY = 0;
//setting the events listeners
$touchArea.on('touchstart mousedown',function (e){
e.preventDefault();
var pointer = getPointerEvent(e);
// caching the current x
cachedX = currX = pointer.pageX;
// caching the current y
cachedY = currY = pointer.pageY;
// a touch event is detected
touchStarted = true;
$touchArea.text('Touchstarted');
// detecting if after 200ms the finger is still in the same position
setTimeout(function (){
if ((cachedX === currX) && !touchStarted && (cachedY === currY)) {
// Here you get the Tap event
$touchArea.text('Tap');
}
},200);
});
$touchArea.on('touchend mouseup touchcancel',function (e){
e.preventDefault();
// here we can consider finished the touch event
touchStarted = false;
$touchArea.text('Touchended');
});
$touchArea.on('touchmove mousemove',function (e){
e.preventDefault();
var pointer = getPointerEvent(e);
currX = pointer.pageX;
currY = pointer.pageY;
if(touchStarted) {
// here you are swiping
$touchArea.text('Swiping');
}
});

Try to resize image by HammerJS in iOS not work

I try to make image resizable on iOS by Hammer.js gesture.
This jsfiddle code work OK on desktop, and this is my converted code (run on iOS safari)
var startX,startY,startW,startH;
var canResize = false;
$('img').hammer().on("touch", function(events) {
canResize = true;
var e = events[0];
startX = e.pageX;
startY = e.pageY;
startW = $(this).innerWidth();
startH = $(this).innerHeight();
return false;
});
$('img').hammer().on("release", function(events) {
canResize = false;
return false;
});
$('img').hammer().on("drag", function(events) {
var e = events[0];
if (canResize == true) {
$(this).innerWidth(startW + e.pageX-startX);
$(this).innerHeight(startH + e.pageY-startY);
}
});
Another try code:
var canResize = false;
$('img').hammer().on("touch", function(events) {
canResize = true;
return false;
});
$('img').hammer().on("release", function(events) {
canResize = false;
return false;
});
$('img').hammer().on("drag", function(events) {
if (canResize == true) {
$(this).innerWidth += deltaX;
$(this).innerHeight += deltaY;
}
});
Events are fired but resize not work.
What am I doing wrong? Please help!
After some days, I realize that Hammer JS is not good in compatible with iOS. I use jQuery touch instead
$("document").ready(function() {
var imgArray = $('img');
for (var i = 0; i < imgArray.length; i++) {
var startX,startY,startW,startH;
var canResize = false;
var image = imgArray[i];
image.addEventListener('touchstart', function(e) {
e.preventDefault();
canResize = true;
var touch = e.touches[0];
startX = touch.pageX;
startY = touch.pageY;
startW = $(this).innerWidth();
startH = $(this).innerHeight();
}, false);
image.addEventListener('touchend', function(e) {
e.preventDefault();
canResize = false;
}, false);
image.addEventListener('touchmove', function(e) {
e.preventDefault();
var touch = e.touches[0];
if (canResize == true) {
$(this).innerWidth(startW + touch.pageX-startX);
$(this).innerHeight(startH + touch.pageY-startY);
}
}, false);
}
});

Dragging div selects text on page (some browsers)

Im using the following function to drag a div with a handle.
Problem is that in some browsers when i drag at the same time text is selected and highlighted on the page..
Any ideas how to fix it?
function enableDragging (ele) {
var dragging = dragging || false,
x, y, Ox, Oy,
current;
enableDragging.z = enableDragging.z || 1;
var grabber = document.getElementById("myHandle");
grabber.onmousedown = function (ev) {
ev = ev || window.event;
var target = ev.target || ev.srcElement;
current = target.parentElement;
dragging = true;
x = ev.clientX;
y = ev.clientY;
Ox = current.offsetLeft;
Oy = current.offsetTop;
current.style.zIndex = ++enableDragging.z;
console.log(dragging);
document.onmousemove = function(ev) {
ev = ev || window.event;
//pauseEvent(ev);
if (dragging == true) {
var Sx = ev.clientX - x + Ox,
Sy = ev.clientY - y + Oy;
current.style.top = Sy + "px";
current.style.left = Sx + "px";
document.body.focus();
// prevent text selection in IE
document.onselectstart = function () { return false; };
// prevent IE from trying to drag an image
ev.ondragstart = function() { return false; };
return false;
}
}
document.onmouseup = function(ev) {
//alert("stop");
dragging && (dragging = false);
}
};
}
function pauseEvent(e){
if(e.stopPropagation) e.stopPropagation();
if(e.preventDefault) e.preventDefault();
e.cancelBubble=true;
e.returnValue=false;
return false;
}
Drag is started by:
var ele = document.getElementById("divWrapper");
enableDragging(ele);
I'm sorry, I forget the second question in your previous post. However, you need to prevent default from onmouseup too:
document.onmouseup = function(ev) {
ev = ev || window.event;
dragging && (dragging = false);
if (ev.preventDefault) {
ev.preventDefault();
} else {
ev.cancelBubble=true;
ev.returnValue=false;
}
return false;
}
EDIT
Or simply use your pauseEvent() function. Notice, that in your code there's this: ev.ondragstart = function () {...};. It's no use to assign the eventhandler to the Event object, rather assign that to the document or document.body. And also use that pauseEvent() in every eventhandler function too.
It looks like it's better to move document.onselectstart and document.ondragstart to the onmousedown handler, since those events have already fired when execution moves to onmousemove().

Categories

Resources