jQuery: Touchmove not working as expected on iOS - javascript

The app works wonderfully on desktop, but not on mobile. When you click DONE, the app will open a new window and show you the output of the drawings, but on iOS, all the coordinates are 0,0... so it looks like the points simply are not being saved in mobile devices.
The problem is most likely either at lines 109 to 111 or lines 171 to 184 of the JS which I am including below:
The section that handles the touch events:
$(trackingLayer).on('mousedown touchstart', function(e) {
e.originalEvent.preventDefault();
isTracking = true;
curMouseX = curMouseY = -1;
if (curTool === "draw") {
var o = {};
o.painLevel = curPainLevel;
o.path = [];
DrawPoints.push(o);
}
}).on('mousemove touchmove', function(e) {
e.originalEvent.preventDefault();
trackMoveMouse($(this), e);
}).on('mouseup mouseleave touchend', function(e) {
e.originalEvent.preventDefault();
isTracking = false;
});
And the area that records the points:
var canvasOffset = ID.offset(); //or $(this).offset(); if you really just want the current element's offset
curMouseX = e.pageX - canvasOffset.left;
curMouseY = e.pageY - canvasOffset.top;
if (curMouseX !== -1 && prevMouseX !== -1) {
var o = {};
o.x = curMouseX / curZoom;
o.y = curMouseY / curZoom;
DrawPoints[DrawPoints.length - 1].path.push(o);
//log("Shapes Recorded: " + DrawPoints.length);
drawImage();
}
I have set up a jsfiddle for this: http://jsfiddle.net/nbernhard/dSED8/
Any help would be appreciated.
Thanks!

Related

moving an img with touch

I'm trying to drag the bucket image (left and right only) with touch.
I'm new to mobile developing so I'm not that acquainted with touch events.
bucket = document.getElementById("bucket");
window.addEventListener('load', function () {
var startx = 0;
var dist = 0;
bucket.addEventListener('touchstart', function (e) {
var touchobj = e.changedTouches[0]; // reference first touch point (ie: first finger)
startx = parseInt(touchobj.clientX); // get x position of touch point relative to left edge of browser
e.preventDefault();
}, false)
bucket.addEventListener('touchstart', function (e) {
var touchobj = e.changedTouches[0]; // reference first touch point for this event
var dist = parseInt(touchobj.clientX) - startx;
bucket.style.left = bucket.offsetLeft + dist;
e.preventDefault();
}, false)
}, false)
Thank you all the helpers.

Handling "mousedown" event on different object

I am trying to change the length of two bars (div) by mouse dragging (extending one example in eloquetjavascript book chapter 14, which involves changing the length of one bar by dragging the mouse.) The intended behavior is clicking on any bar, moving the mouse when holding the left mouse key would change the length of that bar.
Here is my implementation (also available on JSfiddle)
<script>
var lastX; // Tracks the last observed mouse X position
var rect1 = document.getElementById("bar1");
var rect2 = document.getElementById("bar2");
rect1.addEventListener("mousedown", function(){watchmousedown(rect1)});
rect2.addEventListener("mousedown", function(){watchmousedown(rect2)});
function watchmousedown(rec) {
if (event.which == 1) {
lastX = event.pageX;
addEventListener("mousemove",function(){moved(rec)});
event.preventDefault(); // Prevent selection
} else {
removeEventListener("mousedown", watchmousedown)}
}
function moved(rec) {
if (event.which != 1) {
removeEventListener("mousemove", moved);
} else {
var dist = event.pageX - lastX;
var newWidth = Math.max(10, rec.offsetWidth + dist);
rec.style.width = newWidth + "px";
lastX = event.pageX;
}
}
</script>
The problem is I can only change the length of the bar where the first mouse click event happened. I assume I didn't handle the mousedown event correctly (probably need a reset some how).
I am new to javascript, help on programming style is also appreciated.
Thanks!
Add rec. to addEventListener("mousemove", function () { so that the event listener is bound to the rec you clicked on instead of to the window.
function watchmousedown(rec) {
if (event.which == 1) {
lastX = event.pageX;
rec.addEventListener("mousemove", function () {
moved(rec)
});
event.preventDefault(); // Prevent selection
} else {
rec.removeEventListener("mousedown", watchmousedown)
}
}
Edit: I there are some event handlers not being cleaned up properly. I don't know if this would be my final code, but this is closer to how I would do it:
var lastX; // Tracks the last observed mouse X position
var rect1 = document.getElementById("bar1");
var rect2 = document.getElementById("bar2");
var moveRect1 = function () {
console.log(arguments);
moved(rect1)
};
var moveRect2 = function() {
console.log(arguments);
moved(rect2);
}
var watchRect1 = function () {
console.log(arguments);
watchmousedown(moveRect1)
};
var watchRect2 = function () {
console.log(arguments);
watchmousedown(moveRect2)
};
rect1.addEventListener("mousedown", watchRect1);
rect2.addEventListener("mousedown", watchRect2);
window.addEventListener("mouseup", function() {
removeEventListener("mousemove", moveRect1);
removeEventListener("mousemove", moveRect2);
});
function watchmousedown(moverec) {
if (event.which == 1) {
lastX = event.pageX;
addEventListener("mousemove", moverec);
event.preventDefault(); // Prevent selection
}
}
function moved(rec) {
if (event.which == 1) {
var dist = event.pageX - lastX;
var newWidth = Math.max(10, rec.offsetWidth + dist);
rec.style.width = newWidth + "px";
lastX = event.pageX;
}
}
Edit: removed a line that didn't do anything

Dragging div does not work in IE 7 & 8

I am using the following function to drag a div by a handle:
function enableDragging(ele) {
var dragging = dragging || false,
x, y, Ox, Oy,
current;
enableDragging.z = enableDragging.z || 1;
var grabber = document.getElementById("myHandelDiv");
grabber.onmousedown = function(ev) {
current = ev.target.parentNode;
dragging = true;
x = ev.clientX;
y = ev.clientY;
Ox = current.offsetLeft;
Oy = current.offsetTop;
current.style.zIndex = ++enableDragging.z;
console.log(dragging);
window.onmousemove = function(ev) {
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;
}
};
window.onmouseup = function(ev) {
dragging && (dragging = false);
}
};
}
function pauseEvent(e){
if(e.stopPropagation) e.stopPropagation();
if(e.preventDefault) e.preventDefault();
e.cancelBubble=true;
e.returnValue=false;
return false;
}
I have two problems:
Does not work in IE 7 & 8, for some reason i get no errors whatsoever.
Text is selected on some browsers while dragging causing the drag to appear laggy
I initiate the drag like this:
var ele = document.getElementById("divDragWrapper");
enableDragging(ele);
Update, am now getting this error in IE:
SCRIPT5007: Unable to get value of the property 'target': object is
null or undefined
On this line: current = ev.target.parentNode;
You need to add ev = ev || window.event to all eventhander functions. Older IEs don't pass the event object within arguments. Also target is rather srcElement in those browsers.
For example:
grabber.onmousedown = function(ev) {
ev = ev || window.event;
var target = ev.target || ev.srcElement;
current = target.parentNode;
...
}
Another thing is, that older IEs can't attach onmousemove to the window. You can use document or document.body instead.
See the code in action at jsFiddle.

How do I get the mouse position in FireFox?

This code works in Google Chrome and IE but not in FireFox.
function drawChildren(names) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var ctxcolor = "#000000";
if(listeners < 1){
c.addEventListener("click", getPosition, false);
listeners = 1;
} // At the click function "getPosition" is executed
}
function getPosition(event) {
if ( event.offsetX == null ) { // Firefox
clickedX = event.layerX;
clickedY = event.layerY;
} else { // Other browsers
clickedX = event.offsetX;
clickedY = event.offsetY;
}
checkCoordinates(clickedX, clickedY);
}
To answer your question posted in the above comment, your function getPosition() will be called whenever myCanvas is clicked. (Because your code says c.addEventListener("click", getPosition, false);)
Using your mouse position detection code, I'm not sure how the offset and layering works either, but if you use the following code, then I know you will always get x and y coordinates starting from the edge of the browser, rather than starting in any elements of your site:
if(evt.pageX){
var xPos = evt.pageX;
var yPos = evt.pageY;
}else if(evt.clientX){
var xPos = evt.clientX + ((document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft);
var yPos = evt.clientY + ((document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop);
}
Your code may do the same thing as this, but I just wanted to provide what works for me also :)

Javascript iPhone Scroll Effect in an iFrame / Javascript Mouse Acceleration

I'm trying to recreate the iPhone flick / scroll event in a window using JavaScript.
Starting with JQuery, I'm measuring the mouse's acceleration and offset during click - drag - release events using a timer:
var MouseY = {
init: function(context) {
var self = this;
self._context = context || window
self._down = false;
self._now = 0;
self._last = 0;
self._offset = 0;
self._timer = 0;
self._acceleration = 0;
$(self._context).mousedown(function() {self._down = true;});
$(self._context).mouseup(function() {self._down = false;});
$(self._context).mousemove(function(e) {self.move(e);});
},
move: function(e) {
var self = this;
self._timer++;
self._last = self._now;
self._now = e.clientY + window.document.body.scrollTop;
self._offset = self._now - self._last;
self._acceleration = self._offset / self._timer;
},
reset: function() {
this._offset = 0;
this._acceleration = 0;
this._timer = 0;
}
};
$(function() {
MouseY.init();
setInterval(function() {
$('#info').html(
'_acceleration:' + MouseY._acceleration + '<br />' +
'_now:' + MouseY._now + '<br />' +
'_offset:' + MouseY._offset + '<br />' +
'_timer:' + MouseY._timer + '<br />'
);
MouseY.reset();
}, 10);
});
Now the problem is translating that acceleration into screen movement - are there any algorithms (easing?) or animation libraries that could help me out on this? (I've looked into JQuery's .animate() but I'm unsure of how to apply it continuously during the drag events!
Update - final solution here:
http://johnboxall.github.com/iphone.html
Here's what I found when looking for kinetic/momentum scrolling libraries:
iScroll
Zynga Scroller
Overscroll
TouchScroll
jScrollTouch
Hit up this link for the full explanation of one approach that seems to be what you're looking for.
http://www.faqts.com/knowledge_base/view.phtml/aid/14742/fid/53
Here's an excerpt:
This handler then sets up event
capture for mouse movement and stores
mouse cursor positions in variables
mouseX and mouseY. It then starts the
timer monitorMouse() which measures
mouse cursor speed by sampling the
values in these variables at regular
intervals. The variables mouseLeft
and mouseTop hold each samplings mouse
positions and the sampling rate is
set to 100 milliseconds in the
variable monitor.timerDelay.
And some of the author's code:
nn4 = (document.layers)? true:false;
mouseLeft = mouseTop = mouseX = mouseY = 0;
monitor = {
timerDelay:100,
moveLimit:2,
sampleLimit:10
};
function startMonitor(thisText) {
if (!tip) return;
toolTipText = thisText;
writeTooltip(toolTipText);
document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = function (evt) {
mouseX = evt.pageX;
mouseY = evt.pageY;
return true;
}
monitorMouse();
}
function stopMonitor() {
if (!tip) return;
hideTooltip();
if (monitor.timer) {
clearTimeout(monitor.timer);
monitor.timer = null;
}
document.releaseEvents(Event.MOUSEMOVE);
document.onmousemove = null;
monitor.slowSamples = 0;
}
function monitorMouse() {
if (Math.abs(mouseX - mouseLeft) > monitor.moveLimit
|| Math.abs(mouseY - mouseTop) > monitor.moveLimit)
{
monitor.slowSamples = 0;
}
else if (++monitor.slowSamples > monitor.sampleLimit) {
showTooltip();
return;
}
mouseLeft = mouseX;
mouseTop = mouseY;
monitor.timer = setTimeout("monitorMouse()",monitor.timerDelay);
}
You might be interested in the jQuery plugin named overscroll:
http://www.azoffdesign.com/overscroll (GitHub page)

Categories