@@ -8,6 +8,8 @@ Elm.Native.Graphics.Input.make = function(elm) {
88 var Render = ElmRuntime.use(ElmRuntime.Render.Element);
99 var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
1010
11+ var toCss = Elm.Native.Color.make(elm).toCss;
12+ var Text = Elm.Native.Text.make(elm);
1113 var Signal = Elm.Signal.make(elm);
1214 var newElement = Elm.Graphics.Element.make(elm).newElement;
1315 var JS = Elm.Native.JavaScript.make(elm);
@@ -78,7 +80,7 @@ Elm.Native.Graphics.Input.make = function(elm) {
7880
7981 function updateButton(node, oldModel, newModel) {
8082 node.elm_signal = newModel.signal;
81− node.elm_value = nemModel.value;
83+ node.elm_value = newModel.value;
8284 var txt = newModel.text;
8385 if (oldModel.text !== txt) node.innerHTML = txt;
8486 }
@@ -215,72 +217,149 @@ Elm.Native.Graphics.Input.make = function(elm) {
215217 }
216218 }
217219
220+ function updateIfNeeded(css, attribute, latestAttribute) {
221+ if (css[attribute] !== latestAttribute) {
222+ css[attribute] = latestAttribute;
223+ }
224+ }
225+ function cssDimensions(dimensions) {
226+ return dimensions.top + 'px ' +
227+ dimensions.right + 'px ' +
228+ dimensions.bottom + 'px ' +
229+ dimensions.left + 'px';
230+ }
231+ function updateFieldStyle(css, style) {
232+ updateIfNeeded(css, 'padding', cssDimensions(style.padding));
233+
234+ var outline = style.outline;
235+ updateIfNeeded(css, 'border-width', cssDimensions(outline.width));
236+ updateIfNeeded(css, 'border-color', toCss(outline.color));
237+ updateIfNeeded(css, 'border-radius', outline.radius + 'px');
238+
239+ var highlight = style.highlight;
240+ if (highlight.width === 0) {
241+ css.outline = 'none';
242+ } else {
243+ updateIfNeeded(css, 'outline-width', highlight.width + 'px');
244+ updateIfNeeded(css, 'outline-color', toCss(highlight.color));
245+ }
246+
247+ var textStyle = style.style;
248+ updateIfNeeded(css, 'color', toCss(textStyle.color));
249+ if (textStyle.typeface.ctor !== '[]') {
250+ updateIfNeeded(css, 'font-family', Text.toTypefaces(textStyle.typeface));
251+ }
252+ if (textStyle.height.ctor !== "Nothing") {
253+ updateIfNeeded(css, 'font-size', textStyle.height._0 + 'px');
254+ }
255+ updateIfNeeded(css, 'font-weight', textStyle.bold ? 'bold' : 'normal');
256+ updateIfNeeded(css, 'font-style', textStyle.italic ? 'italic' : 'normal');
257+ if (textStyle.line.ctor !== 'Nothing') {
258+ updateIfNeeded(css, 'text-decoration', Text.toLine(textStyle.line._0));
259+ }
260+ }
261+
218262 function renderField(model) {
219263 var field = newNode('input');
264+ updateFieldStyle(field.style, model.style);
265+ field.style.borderStyle = 'solid';
220266 field.style.pointerEvents = 'auto';
221− field.elm_signal = model.signal;
222− field.elm_handler = model.handler;
223267
224268 field.type = model.type;
225269 field.placeholder = JS.fromString(model.placeHolder);
226270 field.value = JS.fromString(model.content.string);
227− var selection = model.content.selection;
228− var direction = selection.direction.ctor === 'Forward' ? 'forward' : 'backward';
229− setRange(field, selection.start, selection.end, direction);
230− field.style.border = 'none';
231271
232− function update() {
233− var direction = field.selectionDirection === 'backward' ? 'Backward' : 'Forward';
272+ field.elm_signal = model.signal;
273+ field.elm_handler = model.handler;
274+ field.elm_old_value = field.value;
275+
276+ function inputUpdate(event) {
277+ var curr = field.elm_old_value;
278+ var next = field.value;
279+ if (curr === next) {
280+ return;
281+ }
282+
283+ var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
284+ var start = field.selectionStart;
285+ var end = field.selectionEnd;
286+ field.value = field.elm_old_value;
287+
234288 elm.notify(field.elm_signal.id, field.elm_handler({
235289 _:{},
236− string:JS.toString(field.value),
290+ string: JS.toString(next),
237291 selection: {
238− start:field.selectionStart,
239− end:field.selectionEnd,
240− direction: { ctor:direction }
292+ _:{},
293+ start: start,
294+ end: end,
295+ direction: { ctor: direction }
241296 },
242297 }));
243298 }
244− function mousedown() {
245− update();
299+
300+ function mouseUpdate(event) {
301+ var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
302+ elm.notify(field.elm_signal.id, field.elm_handler({
303+ _:{},
304+ string: field.value,
305+ selection: {
306+ _:{},
307+ start: field.selectionStart,
308+ end: field.selectionEnd,
309+ direction: { ctor: direction }
310+ },
311+ }));
312+ }
313+ function mousedown(event) {
314+ mouseUpdate(event);
246315 elm.node.addEventListener('mouseup', mouseup);
247316 }
248− function mouseup() {
249− update();
317+ function mouseup(event) {
318+ mouseUpdate(event);
250319 elm.node.removeEventListener('mouseup', mouseup)
251320 }
252− field.addEventListener('keyup', update);
321+ field.addEventListener('input', inputUpdate);
253322 field.addEventListener('mousedown', mousedown);
323+ field.addEventListener('focus', function() {
324+ field.elm_hasFocus = true;
325+ });
326+ field.addEventListener('blur', function() {
327+ field.elm_hasFocus = false;
328+ });
254329
255330 return field;
256331 }
257332
258− function updateField(node, oldModel, newModel) {
259− node.elmHandler = newModel.handler;
260− var newStr = JS.fromString(newModel.content.string);
261− if (node.value !== newStr) node.value = newStr;
262−
263− var selection = newModel.content.selection;
264− var start = selection.start;
265− var end = selection.end;
266− var direction = selection.direction.ctor === 'Forward' ? 'forward' : 'backward';
267− if (end < start) {
268− start = end;
269− end = selection.start;
333+ function updateField(field, oldModel, newModel) {
334+ if (oldModel.style !== newModel.style) {
335+ updateFieldStyle(field.style, newModel.style);
270336 }
271−
272− if (node.selectionStart !== start
273− || node.selectionEnd !== end
274− || node.selectionDirection !== direction) {
275− setRange(node, start, end, direction);
337+ field.elm_signal = newModel.signal;
338+ field.elm_handler = newModel.handler;
339+
340+ field.type = newModel.type;
341+ field.placeholder = JS.fromString(newModel.placeHolder);
342+ var value = JS.fromString(newModel.content.string);
343+ field.value = value;
344+ field.elm_old_value = value;
345+ if (field.elm_hasFocus) {
346+ var selection = newModel.content.selection;
347+ var direction = selection.direction.ctor === 'Forward' ? 'forward' : 'backward';
348+ setRange(field, selection.start, selection.end, direction);
276349 }
277350 }
278351
279352 function mkField(type) {
280− function field(signal, handler, placeHolder, content) {
353+ function field(style, signal, handler, placeHolder, content) {
354+ var padding = style.padding;
355+ var outline = style.outline.width;
356+ var adjustWidth = padding.left + padding.right + outline.left + outline.right;
357+ var adjustHeight = padding.top + padding.bottom + outline.top + outline.bottom;
281358 return A3(newElement, 200, 30, {
282359 ctor: 'Custom',
283− type: type + 'Input',
360+ type: type + 'Field',
361+ adjustWidth: adjustWidth,
362+ adjustHeight: adjustHeight,
284363 render: renderField,
285364 update: updateField,
286365 model: {
@@ -288,14 +367,14 @@ Elm.Native.Graphics.Input.make = function(elm) {
288367 handler:handler,
289368 placeHolder:placeHolder,
290369 content:content,
370+ style:style,
291371 type:type
292372 }
293373 });
294374 }
295− return F4(field);
375+ return F5(field);
296376 }
297377
298−
299378 function hoverable(signal, handler, elem) {
300379 function onHover(bool) {
301380 elm.notify(signal.id, handler(bool));