1Elm.Native.Graphics.Input = {};
2Elm.Native.Graphics.Input.make = function(elm) {
4 elm.Native = elm.Native || {};
5 elm.Native.Graphics = elm.Native.Graphics || {};
6 elm.Native.Graphics.Input = elm.Native.Graphics.Input || {};
7 if (elm.Native.Graphics.Input.values) return elm.Native.Graphics.Input.values;
9 var Render = ElmRuntime.use(ElmRuntime.Render.Element);
10 var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
12 var Signal = Elm.Signal.make(elm);
13 var newElement = Elm.Graphics.Element.make(elm).newElement;
14 var JS = Elm.Native.JavaScript.make(elm);
15 var Utils = Elm.Native.Utils.make(elm);
16 var Tuple2 = Utils.Tuple2;
18 function dropDown(values) {
19 var entries = JS.fromList(values);
20 var events = Signal.constant(entries[0]._1);
22 var drop = newNode('select');
23 drop.style.pointerEvents = 'auto';
24 drop.style.border = '0 solid';
25 for (var i = 0; i < entries.length; ++i) {
26 var option = newNode('option');
27 var name = JS.fromString(entries[i]._0);
29 option.innerHTML = name;
30 drop.appendChild(option);
32 drop.addEventListener('change', function() {
33 elm.notify(events.id, entries[drop.selectedIndex]._1);
36 var t = drop.cloneNode(true);
37 t.style.visibility = "hidden";
39 elm.node.appendChild(t);
40 var style = window.getComputedStyle(t, null);
41 var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
42 var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
43 elm.node.removeChild(t);
45 var element = A3(newElement, w, h, {
48 render: function render(model) { return drop; },
49 update: function update(node, oldModel, newModel) {},
53 return Tuple2(Signal.constant(element), events);
56 function buttons(defaultValue) {
57 var events = Signal.constant(defaultValue);
59 function render(model) {
60 var b = newNode('button');
61 b.style.pointerEvents = 'auto';
62 b.style.display = 'block';
63 b.elmEvent = model.event;
64 function click() { elm.notify(events.id, b.elmEvent); }
65 b.addEventListener('click', click);
66 b.innerHTML = model.text;
70 function update(node, oldModel, newModel) {
71 node.elmEvent = newModel.event;
72 var txt = newModel.text;
73 if (oldModel.text !== txt) node.innerHTML = txt;
76 function button(evnt, txt) {
77 return A3(newElement, 100, 40, {
82 model: { event:evnt, text:JS.fromString(txt) }
86 return { _:{}, button:F2(button), events:events };
89 function customButtons(defaultValue) {
90 var events = Signal.constant(defaultValue);
92 function render(model) {
93 var btn = newNode('div');
94 btn.style.pointerEvents = 'auto';
95 btn.elmEvent = model.event;
97 btn.elmUp = Render.render(model.up);
98 btn.elmHover = Render.render(model.hover);
99 btn.elmDown = Render.render(model.down);
101 function replace(node) {
102 if (node !== btn.firstChild) btn.replaceChild(node, btn.firstChild);
106 if (overCount++ > 0) return;
107 replace(btn.elmHover);
110 if (btn.contains(e.toElement || e.relatedTarget)) return;
115 replace(btn.elmHover);
116 elm.notify(events.id, btn.elmEvent);
118 function down() { replace(btn.elmDown); }
119 btn.addEventListener('mouseover', over);
120 btn.addEventListener('mouseout' , out);
121 btn.addEventListener('mousedown', down);
122 btn.addEventListener('mouseup' , up);
124 btn.appendChild(btn.elmUp);
126 var clicker = newNode('div');
127 clicker.style.width = btn.elmUp.style.width;
128 clicker.style.height = btn.elmUp.style.height;
129 clicker.style.position = 'absolute';
130 clicker.style.top = 0;
131 btn.appendChild(clicker);
136 function update(node, oldModel, newModel) {
137 node.elmEvent = newModel.event;
138 Render.update(node.elmUp, oldModel.up, newModel.up)
139 Render.update(node.elmHover, oldModel.hover, newModel.hover)
140 Render.update(node.elmDown, oldModel.down, newModel.down)
143 function button(evnt, up, hover, down) {
144 return A3(newElement,
145 Math.max(up.props.width, hover.props.width, down.props.width),
146 Math.max(up.props.height, hover.props.height, down.props.height),
148 type: 'CustomButton',
151 model: { event:evnt, up:up, hover:hover, down:down }
155 return { _:{}, customButton:F4(button), events:events };
159 function hoverables(defaultValue) {
160 var events = Signal.constant(defaultValue);
161 function hoverable(handler, elem) {
162 function onHover(bool) {
163 elm.notify(events.id, handler(bool));
165 var props = Utils.replace([['hover',onHover]], elem.props);
166 return { props:props, element:elem.element };
168 return { _:{}, hoverable:F2(hoverable), events:events };
172 function checkboxes(defaultValue) {
173 var events = Signal.constant(defaultValue);
175 function render(model) {
176 var b = newNode('input');
177 b.style.pointerEvents = 'auto';
180 b.checked = model.checked;
181 b.style.display = 'block';
182 b.elmHandler = model.handler;
183 function change() { elm.notify(events.id, b.elmHandler(b.checked)); }
184 b.addEventListener('change', change);
188 function update(node, oldModel, newModel) {
189 node.elmHandler = newModel.handler;
190 node.checked = newModel.checked;
194 function box(handler, checked) {
195 return A3(newElement, 13, 13, {
200 model: { checked:checked, handler:handler }
204 return { _:{}, checkbox:F2(box), events:events };
207 function setRange(node, start, end, dir) {
208 if (node.parentNode) {
209 node.setSelectionRange(start, end, dir);
211 setTimeout(function(){node.setSelectionRange(start, end, dir);}, 0);
215 function mkTextPool(type) { return function fields(defaultValue) {
216 var events = Signal.constant(defaultValue);
220 function render(model) {
221 var field = newNode('input');
222 field.style.pointerEvents = 'auto';
223 field.elmHandler = model.handler;
227 field.placeholder = JS.fromString(model.placeHolder);
228 field.value = JS.fromString(model.state.string);
229 setRange(field, model.state.selectionStart, model.state.selectionEnd, 'forward');
230 field.style.border = 'none';
234 var start = field.selectionStart,
235 end = field.selectionEnd;
236 if (field.selectionDirection === 'backward') {
238 end = field.selectionStart;
241 string:JS.toString(field.value),
242 selectionStart:start,
244 elm.notify(events.id, field.elmHandler(state));
246 function mousedown() {
248 elm.node.addEventListener('mouseup', mouseup);
252 elm.node.removeEventListener('mouseup', mouseup)
254 field.addEventListener('keyup', update);
255 field.addEventListener('mousedown', mousedown);
260 function update(node, oldModel, newModel) {
261 node.elmHandler = newModel.handler;
262 if (state === newModel.state) return;
263 var newStr = JS.fromString(newModel.state.string);
264 if (node.value !== newStr) node.value = newStr;
266 var start = newModel.state.selectionStart;
267 var end = newModel.state.selectionEnd;
268 var direction = 'forward';
271 end = newModel.state.selectionStart;
272 direction = 'backward';
275 if (node.selectionStart !== start
276 || node.selectionEnd !== end
277 || node.selectionDirection !== direction) {
278 setRange(node, start, end, direction);
282 function field(handler, placeHolder, state) {
283 return A3(newElement, 200, 30,
285 type: type + 'Input',
288 model: { handler:handler,
289 placeHolder:placeHolder,
294 return { _:{}, field:F3(field), events:events };
298 return elm.Native.Graphics.Input.values = {
300 customButtons:customButtons,
301 hoverables:hoverables,
302 checkboxes:checkboxes,
303 fields:mkTextPool('text'),
304 emails:mkTextPool('email'),
305 passwords:mkTextPool('password'),
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list