on master help sign in
Move to initializing with three different functions: fullscreen, node, and worker.
7ce5509evancz
compiler/Gen/GenerateHtml.hs+1−1
@@ -71,5 +71,5 @@ createHtml jsStyle libLoc title js noscript moduleToLoad =
71 makeScript Readable (Left libLoc)
71 makeScript Readable (Left libLoc)
72 makeScript jsStyle js
72 makeScript jsStyle js
73 H.body $ do
73 H.body $ do
74− H.script ! A.type_ "text/javascript" $ preEscapedToMarkup ("Elm.init(Elm." ++ moduleToLoad ++ ")" :: String)
74+ H.script ! A.type_ "text/javascript" $ preEscapedToMarkup ("Elm.fullscreen(Elm." ++ moduleToLoad ++ ")" :: String)
75 H.noscript $ preEscapedToMarkup noscript
75 H.noscript $ preEscapedToMarkup noscript
libraries/Native/Show.js−18
@@ -13,24 +13,6 @@ Elm.Native.Show = function(elm) {
13 var Json = Elm.Json(elm);
13 var Json = Elm.Json(elm);
14 var Tuple2 = Elm.Native.Utils(elm).Tuple2;
14 var Tuple2 = Elm.Native.Utils(elm).Tuple2;
15
15
16− elm.node.addEventListener('log', function(e) { console.log(e.value); });
17− elm.node.addEventListener('title', function(e) {document.title = e.value;});
18− elm.node.addEventListener('redirect', function(e) {
19− if (e.value.length > 0) { window.location = e.value; }
20− });
21− elm.node.addEventListener('viewport', function(e) {
22− var node = document.getElementById('elm_viewport');
23− if (!node) {
24− node = document.createElement('meta');
25− node.id = 'elm_viewport';
26− node.name = 'viewport';
27− document.head.appendChild(node);
28− }
29− node.content = e.value;
30− Dispatcher.notify(elm.Window.dimensions.id,
31− Tuple2(elm.node.clientWidth, elm.node.clientHeight));
32− });
33−
34 var toString = function(v) {
16 var toString = function(v) {
35 if (typeof v === "function") {
17 if (typeof v === "function") {
36 var name = v.func ? v.func.name : v.name;
18 var name = v.func ? v.func.name : v.name;
libraries/Native/Signal/Keyboard.js+8−8
@@ -14,27 +14,27 @@ Elm.Native.Keyboard = function(elm) {
14 if (NList.member(e.keyCode)(keysDown.value)) return;
14 if (NList.member(e.keyCode)(keysDown.value)) return;
15 var list = NList.Cons(e.keyCode, keysDown.value);
15 var list = NList.Cons(e.keyCode, keysDown.value);
16 var hasListener = elm.notify(keysDown.id, list);
16 var hasListener = elm.notify(keysDown.id, list);
17− if (!hasListener) elm.node.removeEventListener('keydown', down);
17+ if (!hasListener) document.removeEventListener('keydown', down);
18 }
18 }
19 function up(e) {
19 function up(e) {
20 function notEq(kc) { return kc !== e.keyCode; }
20 function notEq(kc) { return kc !== e.keyCode; }
21 var codes = NList.filter(notEq)(keysDown.value);
21 var codes = NList.filter(notEq)(keysDown.value);
22 var hasListener = elm.notify(keysDown.id, codes);
22 var hasListener = elm.notify(keysDown.id, codes);
23− if (!hasListener) elm.node.removeEventListener('keyup', up);
23+ if (!hasListener) document.removeEventListener('keyup', up);
24 }
24 }
25 function blur(e) {
25 function blur(e) {
26 var hasListener = elm.notify(keysDown.id, NList.Nil);
26 var hasListener = elm.notify(keysDown.id, NList.Nil);
27− if (!hasListener) elm.node.removeEventListener('blur', blur);
27+ if (!hasListener) document.removeEventListener('blur', blur);
28 }
28 }
29 function press(e) {
29 function press(e) {
30 var hasListener = elm.notify(lastKey.id, e.charCode || e.keyCode);
30 var hasListener = elm.notify(lastKey.id, e.charCode || e.keyCode);
31− if (!hasListener) elm.node.removeEventListener('keypress', press);
31+ if (!hasListener) document.removeEventListener('keypress', press);
32 }
32 }
33
33
34− elm.node.addEventListener('keydown' , down );
34+ document.addEventListener('keydown' , down );
35− elm.node.addEventListener('keyup' , up );
35+ document.addEventListener('keyup' , up );
36− elm.node.addEventListener('blur' , blur );
36+ document.addEventListener('blur' , blur );
37− elm.node.addEventListener('keypress', press);
37+ document.addEventListener('keypress', press);
38
38
39 function keySignal(f) {
39 function keySignal(f) {
40 var signal = A2( Signal.lift, f, keysDown );
40 var signal = A2( Signal.lift, f, keysDown );
libraries/Native/Signal/Mouse.js+3−3
@@ -21,7 +21,7 @@ Elm.Native.Mouse = function(elm) {
21 var isDown = Signal.constant(false);
21 var isDown = Signal.constant(false);
22 var isClicked = Signal.constant(false);
22 var isClicked = Signal.constant(false);
23 var clicks = Signal.constant(Utils.Tuple0);
23 var clicks = Signal.constant(Utils.Tuple0);
24−
24+
25 function getXY(e) {
25 function getXY(e) {
26 var posx = 0;
26 var posx = 0;
27 var posy = 0;
27 var posy = 0;
@@ -35,10 +35,10 @@ Elm.Native.Mouse = function(elm) {
35 posy = e.clientY + document.body.scrollTop +
35 posy = e.clientY + document.body.scrollTop +
36 document.documentElement.scrollTop;
36 document.documentElement.scrollTop;
37 }
37 }
38− return Utils.Tuple2(posx, posy);
38+ return Utils.Tuple2(posx-elm.node.offsetX, posy-elm.node.offsetY);
39 }
39 }
40
40
41− var node = elm.node.tagName === "BODY" ? document : elm.node;
41+ var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
42
42
43 function click(e) {
43 function click(e) {
44 var hasListener1 = elm.notify(isClicked.id, true);
44 var hasListener1 = elm.notify(isClicked.id, true);
libraries/Native/Signal/Touch.js+12−8
@@ -7,6 +7,7 @@ Elm.Native.Touch = function(elm) {
7
7
8 var Signal = Elm.Signal(elm);
8 var Signal = Elm.Signal(elm);
9 var JS = Elm.JavaScript(elm);
9 var JS = Elm.JavaScript(elm);
10+ var _ = Elm.Native.Utils(elm);
10
11
11 function Dict() {
12 function Dict() {
12 this.keys = [];
13 this.keys = [];
@@ -44,24 +45,27 @@ Elm.Native.Touch = function(elm) {
44 var r = dict.lookup(t.identifier);
45 var r = dict.lookup(t.identifier);
45 return {_ : {},
46 return {_ : {},
46 id: t.identifier,
47 id: t.identifier,
47− x : t.pageX,
48+ x : t.pageX - elm.node.offsetX,
48− y : t.pageY,
49+ y : t.pageY - elm.node.offsetY,
49 x0: r.x,
50 x0: r.x,
50 y0: r.y,
51 y0: r.y,
51 t0: r.t
52 t0: r.t
52 };
53 };
53 }
54 }
54
55
55− var node = elm.node === document.body ? document : elm.node;
56+ var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
56
57
57 function start(e) {
58 function start(e) {
58− dict.insert(e.identifier,{x:e.pageX,y:e.pageY,t:Date.now()});
59+ dict.insert(e.identifier,
60+ {x: e.pageX - elm.node.offsetX,
61+ y: e.pageY - elm.node.offsetY,
62+ t: Date.now()});
59 }
63 }
60 function end(e) {
64 function end(e) {
61 var t = dict.remove(e.identifier);
65 var t = dict.remove(e.identifier);
62 if (Date.now() - t.t < tapTime) {
66 if (Date.now() - t.t < tapTime) {
63− hasTap = true;
67+ hasTap = true;
64− tap = {_:{}, x:t.x, y:t.y};
68+ tap = {_:{}, x:t.x, y:t.y};
65 }
69 }
66 }
70 }
67
71
@@ -87,8 +91,8 @@ Elm.Native.Touch = function(elm) {
87 function move(e) {
91 function move(e) {
88 for (var i = root.value.length; i--; ) {
92 for (var i = root.value.length; i--; ) {
89 if (root.value[i].id === mouseID) {
93 if (root.value[i].id === mouseID) {
90− root.value[i].x = e.pageX;
94+ root.value[i].x = e.pageX - elm.node.offsetX;
91− root.value[i].y = e.pageY;
95+ root.value[i].y = e.pageY - elm.node.offsetY;
92 elm.notify(root.id, root.value);
96 elm.notify(root.id, root.value);
93 break;
97 break;
94 }
98 }
libraries/Native/Signal/Window.js+9−5
@@ -10,7 +10,10 @@ Elm.Native.Window = function(elm) {
10
10
11 function getWidth() { return elm.node.clientWidth; }
11 function getWidth() { return elm.node.clientWidth; }
12 function getHeight() {
12 function getHeight() {
13+ if (elm.display === ElmRuntime.Display.FULLSCREEN) {
14+ return window.innerHeight;
15+ }
13− return document.body === elm.node ? window.innerHeight : elm.node.clientHeight;
16+ return elm.node.clientHeight;
14 }
17 }
15
18
16 var dimensions = Signal.constant(Tuple2(getWidth(), getHeight()));
19 var dimensions = Signal.constant(Tuple2(getWidth(), getHeight()));
@@ -24,19 +27,20 @@ Elm.Native.Window = function(elm) {
24 var height = A2(Signal.lift, function(p){return p._1}, dimensions);
27 var height = A2(Signal.lift, function(p){return p._1}, dimensions);
25 height.defaultNumberOfKids = 0;
28 height.defaultNumberOfKids = 0;
26
29
27− function resize(e) {
30+ function resizeIfNeeded() {
28 var w = getWidth();
31 var w = getWidth();
29 var h = getHeight();
32 var h = getHeight();
30 if (dimensions.value._0 === w && dimensions.value._1 === h) return;
33 if (dimensions.value._0 === w && dimensions.value._1 === h) return;
31 var hasListener = elm.notify(dimensions.id, Tuple2(w,h));
34 var hasListener = elm.notify(dimensions.id, Tuple2(w,h));
32− if (!hasListener) window.removeEventListener('resize', resize);
35+ if (!hasListener) window.removeEventListener('resize', resizeIfNeeded);
33 }
36 }
34− window.addEventListener('resize', resize);
37+ window.addEventListener('resize', resizeIfNeeded);
35
38
36 return elm.Native.Window = {
39 return elm.Native.Window = {
37 dimensions:dimensions,
40 dimensions:dimensions,
38 width:width,
41 width:width,
39− height:height
42+ height:height,
43+ resizeIfNeeded:resizeIfNeeded
40 };
44 };
41
45
42};
46};
libraries/Native/Utils.js+17
@@ -111,6 +111,23 @@ Elm.Native.Utils = function(elm) {
111 return Tuple2(w,h);
111 return Tuple2(w,h);
112 }
112 }
113
113
114+ function adjustOffset() {
115+ var node = elm.node;
116+ var offsetX = offsetY = 0;
117+ if (node.offsetParent) {
118+ do {
119+ offsetX += node.offsetLeft;
120+ offsetY += node.offsetTop;
121+ } while (node = node.offsetParent);
122+ }
123+ node.offsetX = offsetX;
124+ node.offsetY = offsetY;
125+ }
126+
127+ if (elm.display === ElmRuntime.Display.COMPONENT) {
128+ elm.node.addEventListener('mouseover', adjustOffset);
129+ }
130+
114 return elm.Native.Utils = {
131 return elm.Native.Utils = {
115 eq:eq,
132 eq:eq,
116 cmp:compare,
133 cmp:compare,
runtime/Init.js+44−34
@@ -1,7 +1,28 @@
1
1
2−Elm.init = function(module, baseNode) {
2+(function() {
3− 'use strict';
3+'use strict';
4
4
5+Elm.fullscreen = function(module) {
6+ var style = document.createElement('style');
7+ style.type = 'text/css';
8+ style.innerHTML = "html,head,body { padding:0; margin:0; }" +
9+ "body { font-family: calibri, helvetica, arial, sans-serif; }";
10+ document.head.appendChild(style);
11+ return init(ElmRuntime.Display.FULLSCREEN, document.body, module);
12+};
13+
14+Elm.node = function(width, height, module) {
15+ var container = document.createElement('div');
16+ container.style.width = width + 'px';
17+ container.style.height = height + 'px';
18+ return init(ElmRuntime.Display.COMPONENT, container, module);
19+};
20+
21+Elm.worker = function(module) {
22+ return init(ElmRuntime.Display.NONE, {}, module);
23+};
24+
25+function init(display, container, module) {
5 // defining state needed for an instance of the Elm RTS
26 // defining state needed for an instance of the Elm RTS
6 var signalGraph = null;
27 var signalGraph = null;
7 var inputs = [];
28 var inputs = [];
@@ -18,19 +39,17 @@ Elm.init = function(module, baseNode) {
18 return hasListener;
39 return hasListener;
19 }
40 }
20
41
21− // ensure that baseNode exists and is properly formatted.
42+ container.offsetX = 0;
22− if (typeof baseNode === 'undefined') {
43+ container.offsetY = 0;
23− baseNode = document.body;
24− var style = document.createElement('style');
25− style.type = 'text/css';
26− style.innerHTML = "html,head,body { padding:0; margin:0; }" +
27− "body { font-family: calibri, helvetica, arial, sans-serif; }";
28− document.head.appendChild(style);
29− }
30
44
31 // create the actuall RTS. Any impure modules will attach themselves to this
45 // create the actuall RTS. Any impure modules will attach themselves to this
32 // object. This permits many Elm programs to be embedded per document.
46 // object. This permits many Elm programs to be embedded per document.
33− var elm = {notify: notify, node: baseNode, id: ElmRuntime.guid(), inputs: inputs};
47+ var elm = { notify:notify,
48+ node:container,
49+ display:display,
50+ id:ElmRuntime.guid(),
51+ inputs:inputs
52+ };
34
53
35 // Set up methods to communicate with Elm program from JS.
54 // Set up methods to communicate with Elm program from JS.
36 function send(name, value) {
55 function send(name, value) {
@@ -44,15 +63,16 @@ Elm.init = function(module, baseNode) {
44 document.addEventListener(name + '_' + elm.id, handler);
63 document.addEventListener(name + '_' + elm.id, handler);
45 }
64 }
46
65
47− recv('elm_log', function(e) {console.log(e.value)});
66+ recv('log', function(e) {console.log(e.value)});
48− recv('elm_title', function(e) {document.title = e.value});
67+ recv('title', function(e) {document.title = e.value});
49− recv('elm_redirect', function(e) {
68+ recv('redirect', function(e) {
50 if (e.value.length > 0) { window.location = e.value; }
69 if (e.value.length > 0) { window.location = e.value; }
51 });
70 });
52
71
53 // If graphics are not enabled, escape early, skip over setting up DOM stuff.
72 // If graphics are not enabled, escape early, skip over setting up DOM stuff.
73+ if (display === ElmRuntime.Display.NONE) {
54− if (baseNode === null) return { send : send, recv : recv };
74+ return { send : send, recv : recv };
55−
75+ }
56
76
57 var Render = ElmRuntime.use(ElmRuntime.Render.Element);
77 var Render = ElmRuntime.use(ElmRuntime.Render.Element);
58
78
@@ -66,22 +86,10 @@ Elm.init = function(module, baseNode) {
66 visualModel = signalGraph.value;
86 visualModel = signalGraph.value;
67 inputs = ElmRuntime.filterDeadInputs(inputs);
87 inputs = ElmRuntime.filterDeadInputs(inputs);
68
88
69− var tuple2 = Elm.Native.Utils(elm).Tuple2;
70− function adjustWindow() {
71− if ('Window' in elm) {
72− var w = baseNode.clientWidth;
73− if (w !== elm.Window.dimensions.value._0) {
74− notify(elm.Window.dimensions.id,
75− tuple2(w, document.body === baseNode ?
76− window.innerHeight : baseNode.clientHeight));
77− }
78− }
79− }
80−
81− // Add the visualModel to the DOM
89+ // Add the visualModel to the DOM
82 var renderNode = Render.render(visualModel)
90 var renderNode = Render.render(visualModel)
83− baseNode.appendChild(renderNode);
91+ container.appendChild(renderNode);
84− adjustWindow();
92+ elm.Native.Window.resizeIfNeeded();
85
93
86 // set up updates so that the DOM is adjusted as necessary.
94 // set up updates so that the DOM is adjusted as necessary.
87 var update = Render.update;
95 var update = Render.update;
@@ -89,12 +97,14 @@ Elm.init = function(module, baseNode) {
89 ElmRuntime.draw(function(_) {
97 ElmRuntime.draw(function(_) {
90 update(renderNode, visualModel, value);
98 update(renderNode, visualModel, value);
91 visualModel = value;
99 visualModel = value;
92− adjustWindow();
100+ elm.Native.Window.resizeIfNeeded();
93 });
101 });
94 return value;
102 return value;
95 }
103 }
96
104
97 signalGraph = A2(Signal.lift, domUpdate, signalGraph);
105 signalGraph = A2(Signal.lift, domUpdate, signalGraph);
98
106
99− return { send : send, recv : recv };
107+ return { send : send, recv : recv, node : container };
100};
108};
109+
110+}());
runtime/Utils.js+2
@@ -2,6 +2,8 @@
2(function() {
2(function() {
3'use strict';
3'use strict';
4
4
5+ElmRuntime.Display = { FULLSCREEN: 0, COMPONENT: 1, NONE: 2 };
6+
5ElmRuntime.counter = 0;
7ElmRuntime.counter = 0;
6ElmRuntime.guid = function() { return ElmRuntime.counter++; }
8ElmRuntime.guid = function() { return ElmRuntime.counter++; }
7
9