@@ -13,14 +13,12 @@ Elm.fullscreen = function(module) {
13 return init(ElmRuntime.Display.FULLSCREEN, container, module);
13 return init(ElmRuntime.Display.FULLSCREEN, container, module);
16−Elm.byId = function(id, module) {
16+Elm.domNode = function(container, module) {
17− var container = document.getElementById(id);
18 var tag = container.tagName;
17 var tag = container.tagName;
19 if (tag !== 'DIV') {
18 if (tag !== 'DIV') {
20− throw new Error('Elm.byId must be given a div, not a ' + tag + '.');
19+ throw new Error('Elm.node must be given a DIV, not a ' + tag + '.');
22− while (container.hasChildNodes()) {
20+ } else if (container.hasChildNodes()) {
23− container.removeChild(container.lastChild);
21+ throw new Error('Elm.node must be given an empty DIV. No children allowed!');
25 return init(ElmRuntime.Display.COMPONENT, container, module);
23 return init(ElmRuntime.Display.COMPONENT, container, module);
@@ -34,26 +32,36 @@ function init(display, container, module, moduleToReplace) {
34 var inputs = [];
32 var inputs = [];
36 function notify(id, v) {
34 function notify(id, v) {
37− var timestep = Date.now();
35+ var timestep = Date.now();
38− var hasListener = false;
39− for (var i = inputs.length; i--; ) {
36+ for (var i = inputs.length; i--; ) {
40− // must maintain the order of this stmt to avoid having the ||
41− // short-circuiting the necessary work of recv
42− hasListener = inputs[i].recv(timestep, id, v) || hasListener;
37+ inputs[i].recv(timestep, id, v);
47 container.offsetX = 0;
41 container.offsetX = 0;
48 container.offsetY = 0;
42 container.offsetY = 0;
45+ function addListener(relevantInputs, domNode, eventName, func) {
46+ domNode.addEventListener(eventName, func);
48+ relevantInputs: relevantInputs,
50+ eventName: eventName,
53+ listeners.push(listener);
50 // create the actual RTS. Any impure modules will attach themselves to this
56 // create the actual RTS. Any impure modules will attach themselves to this
51 // object. This permits many Elm programs to be embedded per document.
57 // object. This permits many Elm programs to be embedded per document.
52− var elm = { notify:notify,
59+ notify:notify,
53− node:container,
60+ node:container,
54− display:display,
61+ display:display,
55− id:ElmRuntime.guid(),
62+ id:ElmRuntime.guid(),
63+ addListener:addListener,
56− inputs:inputs
64+ inputs:inputs
59 // Set up methods to communicate with Elm program from JS.
67 // Set up methods to communicate with Elm program from JS.
@@ -75,8 +83,8 @@ function init(display, container, module, moduleToReplace) {
77 function swap(newModule) {
85 function swap(newModule) {
86+ removeListeners(listeners);
78 var div = document.createElement('div');
87 var div = document.createElement('div');
79− if (container.id) { div.id = container.id; }
80 var newElm = init(display, div, newModule, elm);
88 var newElm = init(display, div, newModule, elm);
81 // elm.send = newElm.send;
89 // elm.send = newElm.send;
82 // elm.recv = newElm.recv;
90 // elm.recv = newElm.recv;
@@ -86,6 +94,7 @@ function init(display, container, module, moduleToReplace) {
87 var Module = module(elm);
95 var Module = module(elm);
88 inputs = ElmRuntime.filterDeadInputs(inputs);
96 inputs = ElmRuntime.filterDeadInputs(inputs);
97+ filterListeners(inputs, listeners);
89 if (display !== ElmRuntime.Display.NONE) {
98 if (display !== ElmRuntime.Display.NONE) {
90 var graphicsNode = initGraphics(elm, Module);
99 var graphicsNode = initGraphics(elm, Module);
@@ -102,6 +111,26 @@ function init(display, container, module, moduleToReplace) {
102 return { send:send, recv:recv, swap:swap };
111 return { send:send, recv:recv, swap:swap };
114+function filterListeners(inputs, listeners) {
116+ for (var i = listeners.length; i--; ) {
117+ var listener = listeners[i];
118+ for (var j = inputs.length; j--; ) {
119+ if (listener.relevantInputs.indexOf(inputs[j].id) >= 0) {
123+ listener.domNode.removeEventListener(listener.eventName, listener.func);
127+function removeListeners(listeners) {
128+ for (var i = listeners.length; i--; ) {
129+ var listener = listeners[i];
130+ listener.domNode.removeEventListener(listener.eventName, listener.func);
105function initGraphics(elm, Module) {
134function initGraphics(elm, Module) {
106 if (!('main' in Module))
135 if (!('main' in Module))
107 throw new Error("'main' is missing! What do I display?!");
136 throw new Error("'main' is missing! What do I display?!");