on 475bc10 help sign in
elk/runtime/Init.js
94 lines 3.2 kB history raw
2Elm.init = function(module, baseNode) {
3 'use strict';
5 // defining state needed for an instance of the Elm RTS
6 var signalGraph = null;
7 var inputs = [];
8 var visualModel = null;
9
10 function notify(id, v) {
11 var timestep = Date.now();
12 var hasListener = false;
13 for (var i = inputs.length; i--; ) {
14 // must maintain the order of this stmt to avoid having the ||
15 // short-circuiting the necessary work of recv
16 hasListener = inputs[i].recv(timestep, id, v) || hasListener;
17 }
18 return hasListener;
19 }
21 // ensure that baseNode exists and is properly formatted.
22 if (typeof baseNode === 'undefined') {
23 var newElement = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
24 baseNode = newElement('div');
25 document.body.appendChild(baseNode);
26 baseNode.style.width = window.innerWidth + 'px';
27 baseNode.style.height = window.innerHeight + 'px';
28 window.addEventListener('resize', function() {
29 console.log('resize the base node');
30 baseNode.style.width = window.innerWidth + 'px';
31 baseNode.style.height = window.innerHeight + 'px';
32 }, true);
34 var style = newElement('style');
35 style.type = 'text/css';
36 style.innerHTML = "html,head,body { padding:0; margin:0; }" +
37 "body { font-family: calibri, helvetica, arial, sans-serif; }";
38 document.head.appendChild(style);
39 }
41 // create the actuall RTS. Any impure modules will attach themselves to this
42 // object. This permits many Elm programs to be embedded per document.
43 var elm = {notify: notify, node: baseNode, id: ElmRuntime.guid(), inputs: inputs};
45 // Set up methods to communicate with Elm program from JS.
46 function send(name, value) {
47 var e = document.createEvent('Event');
48 e.initEvent(name + '_' + elm.id, true, true);
49 e.value = value;
50 document.dispatchEvent(e);
51 }
52 function recv(name, handler) {
53 document.addEventListener(name + '_' + elm.id, handler);
54 }
56 // If graphics are not enabled, escape early, skip over setting up DOM stuff.
57 if (baseNode === null) return { send : send, recv : recv };
60 var Render = ElmRuntime.use(ElmRuntime.Render.Element);
62 // evaluate the given module and extract its 'main' value.
63 signalGraph = module(elm).main;
65 // make sure the signal graph is actually a signal, extract the visual model,
66 // and filter out any unused inputs.
67 var Signal = Elm.Signal(elm);
68 if (!('recv' in signalGraph)) signalGraph = Signal.constant(signalGraph);
69 visualModel = signalGraph.value;
70 inputs = ElmRuntime.filterDeadInputs(inputs);
72 // Add the visualModel to the DOM
73 baseNode.appendChild(Render.render(visualModel));
75 if ('Window' in elm) {
76 var w = baseNode.clientWidth;
77 if (w !== elm.Window.dimensions.value._0) {
78 notify(elm.Window.dimensions.id,
79 Elm.Native.Utils(elm).Tuple2(w, baseNode.clientHeight));
80 }
81 }
83 // set up updates so that the DOM is adjusted as necessary.
84 var update = Render.update;
85 function domUpdate(value) {
86 update(baseNode.firstChild, visualModel, value);
87 visualModel = value;
88 return value;
89 }
91 signalGraph = A2(Signal.lift, domUpdate, signalGraph);
93 return { send : send, recv : recv };
94};