Fix mouse and touch tracking for embedded Elm programs, #291

This commit is contained in:
Evan Czaplicki 2013-10-13 19:10:02 -04:00
parent ecf5e87dce
commit a29a1fd558
4 changed files with 31 additions and 41 deletions

View file

@ -23,22 +23,6 @@ Elm.Native.Mouse.make = function(elm) {
var isClicked = Signal.constant(false);
var clicks = Signal.constant(Utils.Tuple0);
function getXY(e) {
var posx = 0;
var posy = 0;
if (!e) e = window.event;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
return Utils.Tuple2(posx-elm.node.offsetX, posy-elm.node.offsetY);
}
var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
elm.addListener([isClicked.id, clicks.id], node, 'click', function click() {
@ -53,7 +37,7 @@ Elm.Native.Mouse.make = function(elm) {
elm.notify(isDown.id, false);
});
elm.addListener([position.id], node, 'mousemove', function move(e) {
elm.notify(position.id, getXY(e));
elm.notify(position.id, Utils.getXY(e));
});
return elm.Native.Mouse.values = {

View file

@ -7,7 +7,7 @@ Elm.Native.Touch.make = function(elm) {
var Signal = Elm.Signal.make(elm);
var JS = Elm.JavaScript.make(elm);
var _ = Elm.Native.Utils.make(elm);
var Utils = Elm.Native.Utils.make(elm);
function Dict() {
this.keys = [];
@ -43,10 +43,11 @@ Elm.Native.Touch.make = function(elm) {
function touch(t) {
var r = dict.lookup(t.identifier);
var point = Utils.getXY(t);
return {_ : {},
id: t.identifier,
x : t.pageX - elm.node.offsetX,
y : t.pageY - elm.node.offsetY,
x : point._0,
y : point._1,
x0: r.x,
y0: r.y,
t0: r.t
@ -56,9 +57,10 @@ Elm.Native.Touch.make = function(elm) {
var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
function start(e) {
var point = Utils.getXY(e);
dict.insert(e.identifier,
{x: e.pageX - elm.node.offsetX,
y: e.pageY - elm.node.offsetY,
{x: point._0,
y: point._1,
t: Date.now()});
}
function end(e) {
@ -88,10 +90,11 @@ Elm.Native.Touch.make = function(elm) {
var mouseID = -1;
function move(e) {
var point = Utils.getXY(e);
for (var i = root.value.length; i--; ) {
if (root.value[i].id === mouseID) {
root.value[i].x = e.pageX - elm.node.offsetX;
root.value[i].y = e.pageY - elm.node.offsetY;
root.value[i].x = point._0;
root.value[i].y = point._1;
elm.notify(root.id, root.value);
break;
}

View file

@ -138,21 +138,26 @@ Elm.Native.Utils.make = function(elm) {
return Tuple2(w,h);
}
function adjustOffset() {
var node = elm.node;
var offsetX = 0, offsetY = 0;
if (node.offsetParent) {
do {
offsetX += node.offsetLeft;
offsetY += node.offsetTop;
} while (node = node.offsetParent);
function getXY(e) {
var posx = 0;
var posy = 0;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
elm.node.offsetX = offsetX;
elm.node.offsetY = offsetY;
}
if (elm.display === ElmRuntime.Display.COMPONENT) {
elm.addListener(elm.inputs, elm.node, 'mouseover', adjustOffset);
if (elm.display === ElmRuntime.Display.COMPONENT) {
var rect = elm.node.getBoundingClientRect();
var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft;
var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop;
// TODO: figure out if there is a way to avoid rounding here
posx = posx - Math.round(relx) - elm.node.clientLeft;
posy = posy - Math.round(rely) - elm.node.clientTop;
}
return Tuple2(posx, posy);
}
return elm.Native.Utils.values = {
@ -172,6 +177,7 @@ Elm.Native.Utils.make = function(elm) {
min : F2(min),
mod : F2(mod),
htmlHeight: F2(htmlHeight),
toFloat: function(x){return x}
getXY: getXY,
toFloat: function(x) { return +x; }
};
};

View file

@ -41,9 +41,6 @@ function init(display, container, module, moduleToReplace) {
return changed;
}
container.offsetX = 0;
container.offsetY = 0;
var listeners = [];
function addListener(relevantInputs, domNode, eventName, func) {
domNode.addEventListener(eventName, func);