Revert "Get rid of Selection, simplifying the field API"
This reverts commit 8e2c6989b4
.
This commit is contained in:
parent
8e2c6989b4
commit
cbf7a8633b
2 changed files with 96 additions and 10 deletions
|
@ -6,6 +6,9 @@ approach as the [`Graphics.Input`](Graphics-Input) module for describing an
|
|||
# Create Fields
|
||||
@docs field, password, email
|
||||
|
||||
# Field Content
|
||||
@docs Content, Selection, Direction, noContent
|
||||
|
||||
# Field Style
|
||||
@docs Style, Outline, noOutline, Highlight, noHighlight, Dimensions, uniformly
|
||||
-}
|
||||
|
@ -72,29 +75,56 @@ defaultStyle =
|
|||
, style = Text.defaultStyle
|
||||
}
|
||||
|
||||
{-| Represents the current content of a text field. For example:
|
||||
|
||||
Content "She sells sea shells" (Selection 0 3 Backward)
|
||||
|
||||
This means the user highlighted the substring `"She"` backwards.
|
||||
-}
|
||||
type Content = { string:String, selection:Selection }
|
||||
|
||||
{-| The selection within a text field. `start` is never greater than `end`:
|
||||
|
||||
Selection 0 0 Forward -- cursor precedes all characters
|
||||
|
||||
Selection 5 9 Backward -- highlighting characters starting after
|
||||
-- the 5th and ending after the 9th
|
||||
-}
|
||||
type Selection = { start:Int, end:Int, direction:Direction }
|
||||
|
||||
{-| The direction of selection.-}
|
||||
data Direction = Forward | Backward
|
||||
|
||||
{-| A field with no content:
|
||||
|
||||
Content "" (Selection 0 0 Forward)
|
||||
-}
|
||||
noContent : Content
|
||||
noContent = Content "" (Selection 0 0 Forward)
|
||||
|
||||
{-| Create a text field. The following example creates a time-varying element
|
||||
called `nameField`. As the user types their name, the field will be updated
|
||||
to match what they have entered.
|
||||
|
||||
name : Input String
|
||||
name = input ""
|
||||
name : Input Content
|
||||
name = input noContent
|
||||
|
||||
nameField : Signal Element
|
||||
nameField = field name.handle id defaultStyle "Name" <~ name.signal
|
||||
-}
|
||||
field : Handle a -> (String -> a) -> Style -> String -> String -> Element
|
||||
field : Handle a -> (Content -> a) -> Style -> String -> Content -> Element
|
||||
field = Native.Graphics.Input.field
|
||||
|
||||
{-| Same as `field` but the UI element blocks out each characters. -}
|
||||
password : Handle a -> (String -> a) -> Style -> String -> String -> Element
|
||||
password : Handle a -> (Content -> a) -> Style -> String -> Content -> Element
|
||||
password = Native.Graphics.Input.password
|
||||
|
||||
{-| Same as `field` but it adds an annotation that this field is for email
|
||||
addresses. This is helpful for auto-complete and for mobile users who may
|
||||
get a custom keyboard with an `@` and `.com` button.
|
||||
-}
|
||||
email : Handle a -> (String -> a) -> Style -> String -> String -> Element
|
||||
email : Handle a -> (Content -> a) -> Style -> String -> Content -> Element
|
||||
email = Native.Graphics.Input.email
|
||||
|
||||
-- area : Handle a -> (String -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> String -> Element
|
||||
-- area : Handle a -> (Content -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> Content -> Element
|
||||
-- area = Native.Graphics.Input.area
|
||||
|
|
|
@ -209,6 +209,14 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
});
|
||||
}
|
||||
|
||||
function setRange(node, start, end, dir) {
|
||||
if (node.parentNode) {
|
||||
node.setSelectionRange(start, end, dir);
|
||||
} else {
|
||||
setTimeout(function(){node.setSelectionRange(start, end, dir);}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function updateIfNeeded(css, attribute, latestAttribute) {
|
||||
if (css[attribute] !== latestAttribute) {
|
||||
css[attribute] = latestAttribute;
|
||||
|
@ -259,7 +267,10 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
|
||||
field.type = model.type;
|
||||
field.placeholder = JS.fromString(model.placeHolder);
|
||||
field.value = JS.fromString(model.content);
|
||||
field.value = JS.fromString(model.content.string);
|
||||
var selection = model.content.selection;
|
||||
var direction = selection.direction.ctor === 'Forward' ? 'forward' : 'backward';
|
||||
setRange(field, selection.start, selection.end, direction);
|
||||
|
||||
field.elm_signal = model.signal;
|
||||
field.elm_handler = model.handler;
|
||||
|
@ -271,7 +282,15 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
String.fromCharCode(event.keyCode) +
|
||||
curr.slice(field.selectionEnd));
|
||||
var pos = field.selectionEnd + 1;
|
||||
elm.notify(field.elm_signal.id, field.elm_handler(JS.toString(next)));
|
||||
elm.notify(field.elm_signal.id, field.elm_handler({
|
||||
_:{},
|
||||
string: JS.toString(next),
|
||||
selection: {
|
||||
start: pos,
|
||||
end: pos,
|
||||
direction: { ctor:'Forward' }
|
||||
},
|
||||
}));
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
|
@ -281,12 +300,46 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
if (curr === next) {
|
||||
return;
|
||||
}
|
||||
|
||||
var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
|
||||
var start = field.selectionStart;
|
||||
var end = field.selectionEnd;
|
||||
field.value = field.elm_old_value;
|
||||
elm.notify(field.elm_signal.id, field.elm_handler(JS.toString(next)));
|
||||
|
||||
elm.notify(field.elm_signal.id, field.elm_handler({
|
||||
_:{},
|
||||
string: JS.toString(next),
|
||||
selection: {
|
||||
start: start,
|
||||
end: end,
|
||||
direction: { ctor: direction }
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
function mouseUpdate(event) {
|
||||
var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
|
||||
elm.notify(field.elm_signal.id, field.elm_handler({
|
||||
_:{},
|
||||
string: field.value,
|
||||
selection: {
|
||||
start: field.selectionStart,
|
||||
end: field.selectionEnd,
|
||||
direction: { ctor: direction }
|
||||
},
|
||||
}));
|
||||
}
|
||||
function mousedown(event) {
|
||||
mouseUpdate(event);
|
||||
elm.node.addEventListener('mouseup', mouseup);
|
||||
}
|
||||
function mouseup(event) {
|
||||
mouseUpdate(event);
|
||||
elm.node.removeEventListener('mouseup', mouseup)
|
||||
}
|
||||
field.addEventListener('keypress', keyUpdate);
|
||||
field.addEventListener('input', inputUpdate);
|
||||
field.addEventListener('mousedown', mousedown);
|
||||
|
||||
return field;
|
||||
}
|
||||
|
@ -300,9 +353,12 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
|
||||
field.type = newModel.type;
|
||||
field.placeholder = JS.fromString(newModel.placeHolder);
|
||||
var value = JS.fromString(newModel.content);
|
||||
var value = JS.fromString(newModel.content.string);
|
||||
field.value = value;
|
||||
field.elm_old_value = value;
|
||||
var selection = newModel.content.selection;
|
||||
var direction = selection.direction.ctor === 'Forward' ? 'forward' : 'backward';
|
||||
setRange(field, selection.start, selection.end, direction);
|
||||
}
|
||||
|
||||
function mkField(type) {
|
||||
|
|
Loading…
Reference in a new issue