@@ -107,27 +107,66 @@ Elm.Native.Graphics.Input = function(elm) {
107107 return { _:{}, button:F4(button), events:events };
108108 }
109109
110− function textFields(defaultValue) {
110+
111+ function checkBoxes(defaultValue) {
112+ var events = Signal.constant(defaultValue);
113+
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+ }
124+
125+ function update(node, oldModel, newModel) {
126+ node.elmHandler = newModel.handler;
127+ node.checked = newModel.checked;
128+ return true;
129+ }
130+
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+ }
140+
141+ return { _:{}, box:F2(box), events:events };
142+ }
143+
144+ function mkTextPool(type) { return function textFields(defaultValue) {
111145 var events = Signal.constant(defaultValue);
112146
113147 function render(model) {
114148 var field = newNode('input');
115149 field.elmHandler = model.handler;
116150
117− field.id = 'test'
151+ field.id = 'test';
152+ field.type = type;
118153 field.placeholder = fromString(model.placeHolder);
119− field.elmValue = fromString(model.state.input);
120− field.value = field.elmValue;
154+ field.value = fromString(model.state.input);
121155 field.setSelectionRange(model.state.start, model.state.end);
122156 field.style.border = 'none';
123157
124158 function update() {
159+ var start = field.selectionStart,
160+ end = field.selectionEnd;
161+ if (field.selectionDirection === 'backward') {
162+ start = end;
163+ end = field.selectionStart;
164+ }
125165 var state = { _:{},
126166 input:toString(field.value),
127− start:field.selectionStart,
128− end:field.selectionEnd };
129− field.value = field.elmValue;
130− elm.notify(events.id, state);
167+ start:start,
168+ end:end };
169+ elm.notify(events.id, field.elmHandler(state));
131170 }
132171 function mousedown() {
133172 update();
@@ -144,16 +183,20 @@ Elm.Native.Graphics.Input = function(elm) {
144183 }
145184
146185 function update(node, oldModel, newModel) {
147− node.elmEvent = newModel.handler;
148− node.elmValue = fromString(newModel.state.input);
149− node.value = node.elmValue;
150− node.setSelectionRange(newModel.state.start, newModel.state.end);
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+ }
151194 }
152195
153196 function field(handler, placeHolder, state) {
154197 return A3(newElement, 200, 30,
155198 { ctor: 'Custom',
156− type: 'TextField',
199+ type: type + 'Input',
157200 render: render,
158201 update: update,
159202 model: { handler:handler,
@@ -163,12 +206,15 @@ Elm.Native.Graphics.Input = function(elm) {
163206 }
164207
165208 return { _:{}, field:F3(field), events:events };
209+ }
166210 }
167211
168212 return elm.Native.Graphics.Input = {
169213 buttons:buttons,
170214 customButtons:customButtons,
171− textFields:textFields
215+ textFields:mkTextPool('text'),
216+ emails:mkTextPool('email'),
217+ passwords:mkTextPool('password')
172218 };
173219
174220};