on 505b1e3 help sign in
elk/runtime/Init.js
92 lines 3.0 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 var Render = ElmRuntime.Render;
23 if (typeof baseNode === 'undefined') {
24 baseNode = Render.newElement('div');
25 document.appendChild(baseNode);
26 window.addEventListener('resize', function() {
27 console.log('resize the base node');
28 baseNode.style.width = document.documentElement.clientWidth + 'px';
29 baseNode.style.height = document.documentElement.clientHeight + 'px';
30 }, true);
31 }
32 baseNode.style.overflow = 'scroll';
34 // create the actuall RTS. Any impure modules will attach themselves to this
35 // object. This permits many Elm programs to be embedded per document.
36 var elm = { notify: notify, node: baseNode };
38 // evaluate the given module and extract its 'main' value.
39 signalGraph = module(elm).main;
41 // make sure the signal graph is actually a signal, extract the visual model,
42 // and filter out any unused inputs.
43 var Signal = Elm.Signal(elm);
44 if (!('recv' in signalGraph)) signalGraph = Signal.constant(signalGraph);
45 visualModel = signalGraph.value;
46 inputs = ElmRuntime.filterDeadInputs(inputs);
48 // Add the visualModel to the DOM
49 baseNode.appendChild(Render.render(visualModel));
51 if (p'Window' in elm) {
52 var w = baseNode.clientWidth;
53 if (w !== elm.Window.dimensions.value._0) {
54 notify(elm.Window.dimensions.id,
55 Elm.Native.Utils(elm).Tuple2(w, baseNode.clientHeight));
56 }
57 }
59 // set up updates so that the DOM is adjusted as necessary.
60 var update = Render.update;
61 function domUpdate(value) {
62 update(baseNode.firstChild, visualModel, value);
63 visualModel = value;
64 return value;
65 }
67 signalGraph = A2(Signal.lift, domUpdate, signalGraph);
68};
70// Helper function to filter dead inputs. Not specific to initialization.
71ElmRuntime = ElmRuntime || {};
72ElmRuntime.filterDeadInputs = function() {
73 'use strict';
74 function isAlive(input) {
75 if (!('defaultNumberOfKids' in input)) return true;
76 var len = input.kids.length;
77 if (len == 0) return false;
78 if (len > input.defaultNumberOfKids) return true;
79 var alive = false;
80 for (var i = len; i--; ) {
81 alive = alive || isAlive(input.kids[i]);
82 }
83 return alive;
84 }
85 return function filterDeadInputs(inputs) {
86 var temp = [];
87 for (var i = inputs.length; i--; ) {
88 if (isAlive(inputs[i])) temp.push(inputs[i]);
89 }
90 return temp;
91 };
92}();