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
|
# Create Fields
|
||||||
@docs field, password, email
|
@docs field, password, email
|
||||||
|
|
||||||
|
# Field Content
|
||||||
|
@docs Content, Selection, Direction, noContent
|
||||||
|
|
||||||
# Field Style
|
# Field Style
|
||||||
@docs Style, Outline, noOutline, Highlight, noHighlight, Dimensions, uniformly
|
@docs Style, Outline, noOutline, Highlight, noHighlight, Dimensions, uniformly
|
||||||
-}
|
-}
|
||||||
|
@ -72,29 +75,56 @@ defaultStyle =
|
||||||
, style = Text.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
|
{-| 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
|
called `nameField`. As the user types their name, the field will be updated
|
||||||
to match what they have entered.
|
to match what they have entered.
|
||||||
|
|
||||||
name : Input String
|
name : Input Content
|
||||||
name = input ""
|
name = input noContent
|
||||||
|
|
||||||
nameField : Signal Element
|
nameField : Signal Element
|
||||||
nameField = field name.handle id defaultStyle "Name" <~ name.signal
|
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
|
field = Native.Graphics.Input.field
|
||||||
|
|
||||||
{-| Same as `field` but the UI element blocks out each characters. -}
|
{-| 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
|
password = Native.Graphics.Input.password
|
||||||
|
|
||||||
{-| Same as `field` but it adds an annotation that this field is for email
|
{-| 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
|
addresses. This is helpful for auto-complete and for mobile users who may
|
||||||
get a custom keyboard with an `@` and `.com` button.
|
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
|
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
|
-- 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) {
|
function updateIfNeeded(css, attribute, latestAttribute) {
|
||||||
if (css[attribute] !== latestAttribute) {
|
if (css[attribute] !== latestAttribute) {
|
||||||
css[attribute] = latestAttribute;
|
css[attribute] = latestAttribute;
|
||||||
|
@ -259,7 +267,10 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
||||||
|
|
||||||
field.type = model.type;
|
field.type = model.type;
|
||||||
field.placeholder = JS.fromString(model.placeHolder);
|
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_signal = model.signal;
|
||||||
field.elm_handler = model.handler;
|
field.elm_handler = model.handler;
|
||||||
|
@ -271,7 +282,15 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
||||||
String.fromCharCode(event.keyCode) +
|
String.fromCharCode(event.keyCode) +
|
||||||
curr.slice(field.selectionEnd));
|
curr.slice(field.selectionEnd));
|
||||||
var pos = field.selectionEnd + 1;
|
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();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,12 +300,46 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
||||||
if (curr === next) {
|
if (curr === next) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
|
||||||
|
var start = field.selectionStart;
|
||||||
|
var end = field.selectionEnd;
|
||||||
field.value = field.elm_old_value;
|
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('keypress', keyUpdate);
|
||||||
field.addEventListener('input', inputUpdate);
|
field.addEventListener('input', inputUpdate);
|
||||||
|
field.addEventListener('mousedown', mousedown);
|
||||||
|
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
@ -300,9 +353,12 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
||||||
|
|
||||||
field.type = newModel.type;
|
field.type = newModel.type;
|
||||||
field.placeholder = JS.fromString(newModel.placeHolder);
|
field.placeholder = JS.fromString(newModel.placeHolder);
|
||||||
var value = JS.fromString(newModel.content);
|
var value = JS.fromString(newModel.content.string);
|
||||||
field.value = value;
|
field.value = value;
|
||||||
field.elm_old_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) {
|
function mkField(type) {
|
||||||
|
|
Loading…
Reference in a new issue