jQuery trigger draggable start and stop by touchmove event - javascript

Please correct me if I am wrong!
https://codepen.io/MrHill/pen/kLvcw
The above url shows functional combination number lock using jQuery draggable.
I want to use this in touch devices (touchmove event in js). I try to google it but I found following code
jQuery(".lock-dial ul").draggable();
jQuery.fn.draggable = function() {
var offset = null;
var start = function(e) {
var orig = e.originalEvent;
var pos = jQuery(this).position();
offset = {
y: orig.changedTouches[0].pageY - pos.top
};
};
var moveMe = function(e) {
e.preventDefault();
var orig = e.originalEvent;
jQuery(this).css({
top: orig.changedTouches[0].pageY - offset.y,
});
};
this.bind("touchstart", start);
this.bind("touchmove", moveMe);
};
In the above code touchmove is working. but not properly. while dragging in touch devices repeatable numbers are not working and y axis scrolling position not equal with jQuery draggable (scrolling in draggable function y axis increment/decrement by 35px).
I think I didn't explain correctly. Actually https://codepen.io/MrHill/pen/kLvcw combination number lock functionality work with touch devices.
This code is needed for my brother college mini project in login module. Could anyone please help me? Thanks in advance.

This code perfectly work for me. i found this from Javascript Drag and drop for touch devices
function touchHandler(event) {
var touch = event.changedTouches[0];
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent({
touchstart: "mousedown",
touchmove: "mousemove",
touchend: "mouseup"
}[event.type], true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
touch.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init() {
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
}

Related

Detect the mousemove inside the broswer

Question:
i would like to detect the mousemove inside the browser. When the mouse stop for 60seconds, the user will log out.
However, i would like to have a iframe (inside the login system) , but it cannot click or mousemove inside the iframe. I don't know what is the problems of iframe. Can any tell me any way to find out the mousemove action? Thank you very much.
<iframe id=iframe src=""></iframe>
http://jsfiddle.net/keshann/oqjgzsm0/518/
Check this fiddle
You can have mouse stop delay detection function as below
(function(mouseStopDelay) {
var timeout;
document.addEventListener('mousemove', function(e) {
clearTimeout(timeout);
timeout = setTimeout(function() {
var event = new CustomEvent("mousestop", {
detail: {
clientX: e.clientX,
clientY: e.clientY
},
bubbles: true,
cancelable: true
});
e.target.dispatchEvent(event);
}, mouseStopDelay);
});
}(1000));
Iframes capture mouse events, but you can transfer the events to the parent scope if the cross-domain policy is satisfied. Here's how:
// This example assumes execution from the parent of the the iframe
function bubbleIframeMouseMove(iframe) {
// Save any previous onmousemove handler
var existingOnMouseMove = iframe.contentWindow.onmousemove;
// Attach a new onmousemove listener
iframe.contentWindow.onmousemove = function(e) {
// Fire any existing onmousemove listener
if (existingOnMouseMove) existingOnMouseMove(e);
// Create a new event for the this window
var evt = document.createEvent("MouseEvents");
// We'll need this to offset the mouse move appropriately
var boundingClientRect = iframe.getBoundingClientRect();
// Initialize the event, copying exiting event values
// for the most part
evt.initMouseEvent(
"mousemove",
true, // bubbles
false, // not cancelable
window,
e.detail,
e.screenX,
e.screenY,
e.clientX + boundingClientRect.left,
e.clientY + boundingClientRect.top,
e.ctrlKey,
e.altKey,
e.shiftKey,
e.metaKey,
e.button,
null // no related element
);
// Dispatch the mousemove event on the iframe element
iframe.dispatchEvent(evt);
};
}
// Get the iframe element we want to track mouse movements on
var myIframe = document.getElementById("iframe");
// Run it through the function to setup bubbling
bubbleIframeMouseMove(myIframe);
At last have a listener
// Example use
document.getElementById('iframe').addEventListener('mousestop', function(e) {
console.log('Mouse coordinates are: ', e.detail.clientX, e.detail.clientY);
document.getElementById("message").innerHTML = 'Mouse coordinates are: ' + e.detail.clientX + ' ' + e.detail.clientY;
// The event will bubble up to parent elements.
});
and your html will be
<iframe id="iframe"></iframe>
<div id="message"></div>
function over() {
console.log("over");
}
<iframe width="300" height="300" src="http://google.com" onMouseOver="over()" />
Well here's some piece of code that does just that,
var logOut = function() {
(timeOut !== undefined)? window.clearTimeout(timeOut): null;
isLoggedIn = false;
document.removeEventListener("mousemove", setTime);
alert("Oops Logged you out");
};
var setTime = function() {
window.clearTimeout(timeOut);
timeOut = window.setTimeout(logOut, maxOut);
};
var timeOut,
isLoggedIn = true,
maxOut = 10000;
if (isLoggedIn === true) {
setTime();
document.addEventListener("mousemove", setTime);
}
Edit:
If you add this then, even if the user moves on Iframe it doesn't matter any more.
document.getElementById("myFrame").addEventListener("mousemove", function(evt) {
evt.preventDefault();
});
and here's the codepen link http://codepen.io/ram333/pen/ygLNQG
Cheers,
Rj

Tracking swipe events with Google Tag Manager

I have a client who wishes to track swipe events (swipe left, swipe right) on a FlexSlider photo gallery. I am using a small script to detect swipe events, and it works quite well to send an alert() or console.log() for testing purposes. However, when I tried to instead push an event to Google Tag Manager it doesn't appear to be sent.
Here is how I am attempting to track the events:
// Previous Photo
jQuery('#photo_gallery').on('swiperight', 'img', function() {
dataLayer.push({'category': 'photo-gallery', 'action' : 'photo-gallery-previous', 'label' : 'previous'});
});
// Next Photo
jQuery('#photo_gallery').on('swipeleft', 'img', function() {
dataLayer.push({'category': 'photo-gallery', 'action' : 'photo-gallery-next', 'label' : 'next'});
});
Where #photo_gallery is the ID of the standard <div class="flexslider"> container.
Here is the script I am using to create the swipeleft swiperight events:
(function($) {
$.detectSwipe = {
enabled: 'ontouchstart' in document.documentElement,
preventDefault: true,
threshold: 20
};
var startX,
startY,
isMoving = false;
function onTouchEnd() {
this.removeEventListener('touchmove', onTouchMove);
this.removeEventListener('touchend', onTouchEnd);
isMoving = false;
}
function onTouchMove(e) {
if ($.detectSwipe.preventDefault) { e.preventDefault(); }
if(isMoving) {
var x = e.touches[0].pageX;
var y = e.touches[0].pageY;
var dx = startX - x;
var dy = startY - y;
var dir;
if(Math.abs(dx) >= $.detectSwipe.threshold) {
dir = dx > 0 ? 'left' : 'right'
} else if(Math.abs(dy) >= $.detectSwipe.threshold) {
dir = dy > 0 ? 'down' : 'up'
}
if(dir) {
onTouchEnd.call(this);
$(this).trigger('swipe', dir).trigger('swipe' + dir);
}
}
}
function onTouchStart(e) {
if (e.touches.length == 1) {
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
isMoving = true;
this.addEventListener('touchmove', onTouchMove, false);
this.addEventListener('touchend', onTouchEnd, false);
}
}
function setup() {
this.addEventListener && this.addEventListener('touchstart', onTouchStart, false);
}
function teardown() {
this.removeEventListener('touchstart', onTouchStart);
}
$.event.special.swipe = { setup: setup };
$.each(['left', 'up', 'down', 'right'], function () {
$.event.special['swipe' + this] = { setup: function(){
$(this).on('swipe', $.noop);
} };
});
})(jQuery);
Note: The above script works for console logs and alerts
Does anyone have any experience tracking swipe events in Google Analytics/Tag Manager? It would be nice to tap into the FlexSlider built in swipe functionality, but I wouldn't want to modify any of the plugin code.
You should also include an "event" parameter (of, say, "swipe") to use in your GTM trigger:
dataLayer.push({
'event': 'swipe',
// your other parameters
})
Quoting from this: https://developers.google.com/tag-manager/devguide?hl=en
Google Tag Manager provides a special data layer variable called an
event that is used within JavaScript event listeners to initiate tag
firing when a user interacts with website elements such as a button.
You could then use the 'swipe' event to fire your tags.
Not sure if it is still of interest, but as an alternative to dataLayer (best option imho) you may create a "History Change" Trigger.
"Triggers based on the History Change event will fire a tag when the URL fragment (hash) changes or when a site is using the HTML5 pushstate APIs. This trigger is useful to fire tags tracking virtual pageview in an Ajax application, for instance."
https://support.google.com/tagmanager/answer/6106961?hl=en
trigger screenshot

Zoom and pinch events not fired in Desktop using javascript

Im trying to create a function for app idle timeout. I registered all touch events using Gesture object. Doing these static events are fired. But zoom, pinch and cursor move are not fired. Any sussestions?
var count = 0;
var max = 15;
var myGesture = new MSGesture();
myGesture.target = document.body;
document.body.addEventListener("pointerdown", function (evt) {
// adds the current mouse, pen, or touch contact for gesture recognition
myGesture.addPointer(evt.pointerId);
});
document.body.addEventListener("MSGestureStart", eventListener, false);
document.body.addEventListener("MSGestureEnd", eventListener, false);
document.body.addEventListener("MSGestureChange", eventListener, false);
document.body.addEventListener("MSInertiaStart", eventListener, false);
document.body.addEventListener("MSGestureTap", eventListener, false);
document.body.addEventListener("MSGestureHold", eventListener, false);
setTimer();
function setTimer() {
if (count == max)
window.close();
else {
count = count + 1;
t = setTimeout(setTimer, 1000);
}
}
function eventListener(evt) {
clearTimeout(t);
count = 0;
setTimer();
}
}
In your pointerdown handler you need to add code to reflect when two (or more) fingers are down.
There you will be able to multi touch gestures like zoom or pinch
edit: not mine, but take a look at this code http://pastebin.com/frAqdhGj

RactiveJS draggable utilizing mouseevent

I am trying to achieve a simple draggable DIV with RactiveJS utilizing proxy events (on-mousedown,up,move,out)
Following JSFiddle works just fine, however when the user moves the mouse too fast the dragging stops. This is simply because the mouseevent handlers in my case are on the DIV tag instead of the body or document elements. The final idea I have is to create a slider component, however I am seeking to provide the best user experience and make this work more like JQuery's draggable.
Template:
<div class="rect {{drag ? 'dragging' : ''}}"
on-mousedown="startDrag"
on-mouseup="stopDrag"
on-mouseout="stopDrag"
on-mousemove="drag"
style="top:{{top}}px; left:{{left}}px;">
</div>
Ractive instance:
var ractive = new Ractive({
el: "#content",
template: "#template",
data: {left:20,top:80}
});
ractive.on({
startDrag : function (event) {
this.set({
'drag': true,
'mouseX': event.original.clientX - this.get('left'),
'mouseY': event.original.clientY - this.get('top')
});
},
stopDrag : function (event) {
this.set('drag', false);
},
drag : function (event) {
if(this.get('drag')) {
var x = event.original.clientX,
y = event.original.clientY;
this.set({
top: y - this.get('mouseY') ,
left: x - this.get('mouseX')
});
event.original.stopPropagation();
}
}
})
How can I improve the above code?
Usually mousemove and mouseend need to be on the document. I find that with Ractive a decorator usually works better for dragging. Here's one example to get you going (http://jsfiddle.net/h9j2hdyj/1/):
<div class="rect noSelect {{ dragging ? 'dragging' : ''}}"
decorator='drag:"position"'
style="{{#position}}top:{{top}}px;left:{{left}}px{{/}}">
</div>
decorator:
Ractive.decorators.drag = function(node, keypath){
var ractive = this, initial, begin, startPos;
node.addEventListener('mousedown', start, false)
function listenOnDocument(){
document.addEventListener('mousemove', move, false)
document.addEventListener('mouseup', unlistenOnDocument, false)
}
function unlistenOnDocument(){
document.removeEventListener('mousemove', move, false)
document.removeEventListener('mouseup', end, false)
}
function start(e){
begin = { x: e.x, y: e.y }
startPos = ractive.get(keypath)
startPos = { x: startPos.left, y: startPos.top }
ractive.set('dragging', true)
listenOnDocument()
e.preventDefault()
e.stopPropagation()
}
function move(e){
ractive.set(keypath, {
left: startPos.x + (e.x - begin.x),
top: startPos.y + (e.y - begin.y)
})
e.preventDefault()
e.stopPropagation()
}
function end(){
unlistenOnDocument()
ractive.set('dragging', false)
}
return {
update: function(pos){
console.log(pos)
position = pos
},
teardown: function(){
node.removeEventListener('mousedown', start, false)
end()
}
}
}
Another option is to use the ractive-touch plugin's pan events - they use Hammer.js under the hood so they're mouse- and touch-friendly.

Simulate scroll event using Javascript

I am trying to Simulate a scroll event using Javascript for Mobile Safari.
I am using the following code
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("scroll", true, true, window,0, 0, 0, 0, 0, false, false, false, false, 0, null);
The above code is part of a jQuery plugin jQuery.UI.Ipad which basically maps touch events like touchstart, touchmove, touchend to mouse events like mouseover, mousedown, etc
However for some reasons the code for simulating a scroll event is not working... Please help me. So essentially my question is how do I simulate the scroll event.
I think people are confused as to why you would overide the scroll control. I can see why you want to imitate mouse events, but scroll maybe should not be one of them.
Usually for scroll changes you can just get the scroll with:
var top = document.body.scrollTop;
And set with:
document.body.scrollLeft = sX;
document.body.scrollTop = sY;
So, I know I' need to simulate it too. for me it's when you have a lightbox with a overflow box that you would need it. Just one case of many I can think of. looking to for an answer. Just thought I'd share where I'm at, thou not with the jQuery.Ui.Ipad I will Google that.. but here is what I got so far and does work but not perfectly.
var inTouch=false;
var timers_arr = new Array();
var c=0;
var t;
var timer_is_on=0;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
// jeremy's timer functions
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
function clearCount(timer){
/// clear the time from timer
clearTimeout(timers_arr[timer]);
/// Make sure it's clear
timers_arr[''+timer+'']=0;
delete timers_arr[''+timer+''];
}
function setCount(timer,time,func){
clearCount(timer);
if(timers_arr[timer]==0||typeof(timers_arr[timer]) === 'undefined'){
timers_arr[timer]=setTimeout(function(){
func();
},time);
}
}
function updatePos(evt,startY){
setCount('touchmove',1,function(){
var orig = evt.originalEvent;
var curY = orig.changedTouches[0].pageY;
var y = curY - startY;
var sliderVal = $("#slider-vertical").slider("value");
sliderVal += (y*.008);
$("#slider-vertical").slider("value", sliderVal);
updatePos(evt,startY);
});
setCount('touchmove_anitMotion',200,function(){
clearCount('touchmove');
clearCount('touchmove_anitMotion');
});
}
var startX=0;
var startY=0;
var x=0;
var y=0;
var direction='';
$('body').bind("onorientationchange", updateOrientation, false);
$('#scroll-pane').live("touchstart", function(evt){
inTouch=true;
startX = event.targetTouches[0].pageX;
startY = event.targetTouches[0].pageY;
});
$('#scroll-pane').live("touchmove", function(evt){
evt.stopPropagation();
evt.preventDefault();
updatePos(evt,startY);
});
$('#scroll-pane').live("touchend", function(evt){
startX=0;
startY=0;
clearCount('touchmove');
inTouch=false;
});
$('#scroll-pane').live("touchcancel", function(evt){
startX=0;
startY=0;
clearCount('touchmove');
inTouch=false;
});
Again not perfect and looking to fix it.. but it's at the least working. Now note, this is a div that is using the jQuery UI slider for a scroll bar as (thou in mine it's vertical) shown in
http://jqueryui.com/demos/slider/#side-scroll
Hope that spurs some ideas. If I get a super stable answer I'll get back.
Cheers -Jeremy
I needed this to write a unit test , for which i need to simulate a scroll event
function dispatchScroll(target,newScrollTop) {
target.scrollTop = newScrollTop;
var e = document.createEvent("UIEvents");
// creates a scroll event that bubbles, can be cancelled,
// and with its view and detail property initialized to window and 1,
// respectively
e.initUIEvent("scroll", true, true, window, 1);
target.dispatchEvent(e);
}
For more details : https://developer.mozilla.org/en-US/docs/Web/API/event.initUIEvent
The event that worked for me was mousewheel, and the 5th parameter needs to be positive for scrolldown and negative for scrollup.
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("mousewheel", true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
Note that the event type is DOMMouseScroll for FireFox.
Events should now be created with CustomEvent as such new CustomEvent("wheel", { detail: { deltaY: 1 } }). document.createEvent is deprecated
https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
I built this utility function that scrolls by 1 pixel every frame
const startFakeScrolling = (container: HTMLDivElement) => {
const cb = () => {
container.dispatchEvent(
new CustomEvent("wheel", { detail: { deltaY: 1 } })
);
window.requestAnimationFrame(cb);
};
window.requestAnimationFrame(cb);
};
You will also need to modify the event listener to use detail, as deltaY will be undefined
const delta = e.deltaY != null ? e.deltaY : (e.detail as any).deltaY;

Categories