on be72e86 help sign in
220 lines 6.0 kB history raw
2Elm.Native.Graphics.Input = function(elm) {
3 "use strict";
5 elm.Native = elm.Native || {};
6 elm.Native.Graphics = elm.Native.Graphics || {};
7 if (elm.Native.Graphics.Input) return elm.Native.Graphics.Input;
9 var Render = ElmRuntime.use(ElmRuntime.Render.Element);
10 var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
11 var newNode = Utils.newElement, fromString = Utils.fromString,
12 toString = Utils.toString;
14 var Signal = Elm.Signal(elm);
15 var newElement = Elm.Graphics.Element(elm).newElement;
17 function buttons(defaultValue) {
18 var events = Signal.constant(defaultValue);
20 function render(model) {
21 var b = newNode('button');
22 b.style.display = 'block';
23 b.elmEvent = model.event;
24 function click() { elm.notify(events.id, b.elmEvent); }
25 b.addEventListener('click', click);
26 b.innerHTML = model.text;
27 return b;
28 }
30 function update(node, oldModel, newModel) {
31 node.elmEvent = newModel.event;
32 var txt = newModel.text;
33 if (oldModel.text !== txt) node.innerHTML = txt;
34 return true;
35 }
37 function button(evnt, txt) {
38 return A3(newElement, 100, 40, {
39 ctor: 'Custom',
40 type: 'Button',
41 render: render,
42 update: update,
43 model: { event:evnt, text:fromString(txt) }
44 });
45 }
47 return { _:{}, button:F2(button), events:events };
48 }
50 function customButtons(defaultValue) {
51 var events = Signal.constant(defaultValue);
53 function render(model) {
54 var btn = newNode('div');
55 btn.elmEvent = model.event;
57 btn.elmUp = Render.render(model.up);
58 btn.elmHover = Render.render(model.hover);
59 btn.elmDown = Render.render(model.down);
61 function replace(node) {
62 if (node !== btn.firstChild) btn.replaceChild(node, btn.firstChild);
63 }
64 var overCount = 0;
65 function over(e) {
66 if (overCount++ > 0) return;
67 replace(btn.elmHover);
68 }
69 function out(e) {
70 if (btn.contains(e.toElement || e.relatedTarget)) return;
71 overCount = 0;
72 replace(btn.elmUp);
73 }
74 function up() {
75 replace(btn.elmHover);
76 elm.notify(events.id, btn.elmEvent);
77 }
78 function down() { replace(btn.elmDown); }
79 btn.addEventListener('mouseover', over);
80 btn.addEventListener('mouseout' , out);
81 btn.addEventListener('mousedown', down);
82 btn.addEventListener('mouseup' , up);
84 btn.appendChild(btn.elmUp);
85 return btn;
86 }
88 function update(node, oldModel, newModel) {
89 node.elmEvent = newModel.event;
90 Render.update(node.elmUp, oldModel.up, newModel.up)
91 Render.update(node.elmHover, oldModel.hover, newModel.hover)
92 Render.update(node.elmDown, oldModel.down, newModel.down)
93 }
95 function button(evnt, up, hover, down) {
96 return A3(newElement,
97 Math.max(up.props.width, hover.props.width, down.props.width),
98 Math.max(up.props.height, hover.props.height, down.props.height),
99 { ctor: 'Custom',
100 type: 'CustomButton',
101 render: render,
102 update: update,
103 model: { event:evnt, up:up, hover:hover, down:down }
104 });
105 }
107 return { _:{}, button:F4(button), events:events };
108 }
111 function checkBoxes(defaultValue) {
112 var events = Signal.constant(defaultValue);
114 function render(model) {
115 var b = newNode('input');
116 b.type = 'checkbox';
117 b.checked = model.checked;
118 b.style.display = 'block';
119 b.elmHandler = model.handler;
120 function change() { elm.notify(events.id, b.elmHandler(b.checked)); }
121 b.addEventListener('change', change);
122 return b;
123 }
125 function update(node, oldModel, newModel) {
126 node.elmHandler = newModel.handler;
127 node.checked = newModel.checked;
128 return true;
129 }
131 function box(handler, checked) {
132 return A3(newElement, 13, 13, {
133 ctor: 'Custom',
134 type: 'CheckBox',
135 render: render,
136 update: update,
137 model: { checked:checked, handler:handler }
138 });
139 }
141 return { _:{}, box:F2(box), events:events };
142 }
144 function mkTextPool(type) { return function textFields(defaultValue) {
145 var events = Signal.constant(defaultValue);
147 function render(model) {
148 var field = newNode('input');
149 field.elmHandler = model.handler;
151 field.id = 'test';
152 field.type = type;
153 field.placeholder = fromString(model.placeHolder);
154 field.value = fromString(model.state.input);
155 field.setSelectionRange(model.state.start, model.state.end);
156 field.style.border = 'none';
158 function update() {
159 var start = field.selectionStart,
160 end = field.selectionEnd;
161 if (field.selectionDirection === 'backward') {
162 start = end;
163 end = field.selectionStart;
164 }
165 var state = { _:{},
166 input:toString(field.value),
167 start:start,
168 end:end };
169 elm.notify(events.id, field.elmHandler(state));
170 }
171 function mousedown() {
172 update();
173 elm.node.addEventListener('mouseup', mouseup);
174 }
175 function mouseup() {
176 update();
177 elm.node.removeEventListener('mouseup', mouseup)
178 }
179 field.addEventListener('keyup', update);
180 field.addEventListener('mousedown', mousedown);
182 return field;
183 }
185 function update(node, oldModel, newModel) {
186 node.elmHandler = newModel.handler;
187 node.value = fromString(newModel.state.input);
188 if (newModel.state.start <= newModel.state.end) {
189 node.setSelectionRange(newModel.state.start, newModel.state.end);
190 } else {
191 node.setSelectionRange(newModel.state.end,
192 newModel.state.start, 'backward');
193 }
194 }
196 function field(handler, placeHolder, state) {
197 return A3(newElement, 200, 30,
198 { ctor: 'Custom',
199 type: type + 'Input',
200 render: render,
201 update: update,
202 model: { handler:handler,
203 placeHolder:placeHolder,
204 state:state }
205 });
206 }
208 return { _:{}, field:F3(field), events:events };
209 }
210 }
212 return elm.Native.Graphics.Input = {
213 buttons:buttons,
214 customButtons:customButtons,
215 textFields:mkTextPool('text'),
216 emails:mkTextPool('email'),
217 passwords:mkTextPool('password')
218 };
220};