on master help sign in
Fix mouse and touch tracking for embedded Elm programs, #291
commita29a1fd5581446530b721e54cc1c19d45e85aa70 authorEvan Czaplicki <info@elm-lang.org> dateSun 13 Oct 2013, 19:10 (13 years ago) parentecf5e87
4 files changed+31−41
libraries/Native/Signal/Mouse.js+1−17 libraries/Native/Signal/Touch.js+10−7 libraries/Native/Utils.js+20−14 runtime/Init.js−3
libraries/Native/Signal/Mouse.js+1−17
@@ -23,22 +23,6 @@ Elm.Native.Mouse.make = function(elm) {
2323 var isClicked = Signal.constant(false);
2424 var clicks = Signal.constant(Utils.Tuple0);
2525
26− function getXY(e) {
27− var posx = 0;
28− var posy = 0;
29− if (!e) e = window.event;
30− if (e.pageX || e.pageY) {
31− posx = e.pageX;
32− posy = e.pageY;
33− } else if (e.clientX || e.clientY) {
34− posx = e.clientX + document.body.scrollLeft +
35− document.documentElement.scrollLeft;
36− posy = e.clientY + document.body.scrollTop +
37− document.documentElement.scrollTop;
38− }
39− return Utils.Tuple2(posx-elm.node.offsetX, posy-elm.node.offsetY);
40− }
41−
4226 var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
4327
4428 elm.addListener([isClicked.id, clicks.id], node, 'click', function click() {
@@ -53,7 +37,7 @@ Elm.Native.Mouse.make = function(elm) {
5337 elm.notify(isDown.id, false);
5438 });
5539 elm.addListener([position.id], node, 'mousemove', function move(e) {
56− elm.notify(position.id, getXY(e));
40+ elm.notify(position.id, Utils.getXY(e));
5741 });
5842
5943 return elm.Native.Mouse.values = {
libraries/Native/Signal/Touch.js+10−7
@@ -7,7 +7,7 @@ Elm.Native.Touch.make = function(elm) {
77
88 var Signal = Elm.Signal.make(elm);
99 var JS = Elm.JavaScript.make(elm);
10− var _ = Elm.Native.Utils.make(elm);
10+ var Utils = Elm.Native.Utils.make(elm);
1111
1212 function Dict() {
1313 this.keys = [];
@@ -43,10 +43,11 @@ Elm.Native.Touch.make = function(elm) {
4343
4444 function touch(t) {
4545 var r = dict.lookup(t.identifier);
46+ var point = Utils.getXY(t);
4647 return {_ : {},
4748 id: t.identifier,
48− x : t.pageX - elm.node.offsetX,
49− y : t.pageY - elm.node.offsetY,
49+ x : point._0,
50+ y : point._1,
5051 x0: r.x,
5152 y0: r.y,
5253 t0: r.t
@@ -56,9 +57,10 @@ Elm.Native.Touch.make = function(elm) {
5657 var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
5758
5859 function start(e) {
60+ var point = Utils.getXY(e);
5961 dict.insert(e.identifier,
60− {x: e.pageX - elm.node.offsetX,
61− y: e.pageY - elm.node.offsetY,
62+ {x: point._0,
63+ y: point._1,
6264 t: Date.now()});
6365 }
6466 function end(e) {
@@ -88,10 +90,11 @@ Elm.Native.Touch.make = function(elm) {
8890
8991 var mouseID = -1;
9092 function move(e) {
93+ var point = Utils.getXY(e);
9194 for (var i = root.value.length; i--; ) {
9295 if (root.value[i].id === mouseID) {
93− root.value[i].x = e.pageX - elm.node.offsetX;
94− root.value[i].y = e.pageY - elm.node.offsetY;
96+ root.value[i].x = point._0;
97+ root.value[i].y = point._1;
9598 elm.notify(root.id, root.value);
9699 break;
97100 }
libraries/Native/Utils.js+20−14
@@ -138,21 +138,26 @@ Elm.Native.Utils.make = function(elm) {
138138 return Tuple2(w,h);
139139 }
140140
141− function adjustOffset() {
142− var node = elm.node;
143− var offsetX = 0, offsetY = 0;
144− if (node.offsetParent) {
145− do {
146− offsetX += node.offsetLeft;
147− offsetY += node.offsetTop;
148− } while (node = node.offsetParent);
141+ function getXY(e) {
142+ var posx = 0;
143+ var posy = 0;
144+ if (e.pageX || e.pageY) {
145+ posx = e.pageX;
146+ posy = e.pageY;
147+ } else if (e.clientX || e.clientY) {
148+ posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
149+ posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
149150 }
150− elm.node.offsetX = offsetX;
151− elm.node.offsetY = offsetY;
152− }
153151
154− if (elm.display === ElmRuntime.Display.COMPONENT) {
155− elm.addListener(elm.inputs, elm.node, 'mouseover', adjustOffset);
152+ if (elm.display === ElmRuntime.Display.COMPONENT) {
153+ var rect = elm.node.getBoundingClientRect();
154+ var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft;
155+ var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop;
156+ // TODO: figure out if there is a way to avoid rounding here
157+ posx = posx - Math.round(relx) - elm.node.clientLeft;
158+ posy = posy - Math.round(rely) - elm.node.clientTop;
159+ }
160+ return Tuple2(posx, posy);
156161 }
157162
158163 return elm.Native.Utils.values = {
@@ -172,6 +177,7 @@ Elm.Native.Utils.make = function(elm) {
172177 min : F2(min),
173178 mod : F2(mod),
174179 htmlHeight: F2(htmlHeight),
175− toFloat: function(x){return x}
180+ getXY: getXY,
181+ toFloat: function(x) { return +x; }
176182 };
177183};
runtime/Init.js−3
@@ -41,9 +41,6 @@ function init(display, container, module, moduleToReplace) {
4141 return changed;
4242 }
4343
44− container.offsetX = 0;
45− container.offsetY = 0;
46−
4744 var listeners = [];
4845 function addListener(relevantInputs, domNode, eventName, func) {
4946 domNode.addEventListener(eventName, func);