Merge branch 'text' into dev
This commit is contained in:
commit
5e7ed2bec5
11 changed files with 365 additions and 165 deletions
|
@ -19,14 +19,15 @@ examples in this library, so just read on to get a better idea of how it works!
|
|||
@docs Input, input
|
||||
|
||||
# Basic Input Elements
|
||||
Text fields come later.
|
||||
|
||||
To learn about text fields, see the
|
||||
[`Graphics.Input.Field`](Graphics-Input-Field) library.
|
||||
|
||||
@docs button, customButton, checkbox, dropDown
|
||||
|
||||
# Clicks and Hovers
|
||||
@docs clickable, hoverable
|
||||
|
||||
# Text Fields
|
||||
@docs field, password, email, noContent, FieldContent, Selection, Direction
|
||||
-}
|
||||
|
||||
import Signal (Signal)
|
||||
|
@ -175,57 +176,3 @@ distinguished with IDs or more complex data structures.
|
|||
-}
|
||||
clickable : Handle a -> a -> Element -> Element
|
||||
clickable = Native.Graphics.Input.clickable
|
||||
|
||||
{-| Represents the current content of a text field. For example:
|
||||
|
||||
FieldContent "She sells sea shells" (Selection 0 3 Backward)
|
||||
|
||||
This means the user highlighted the substring `"She"` backwards.
|
||||
-}
|
||||
type FieldContent = { 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:
|
||||
|
||||
FieldContent "" (Selection 0 0 Forward)
|
||||
-}
|
||||
noContent : FieldContent
|
||||
noContent = FieldContent "" (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 FieldContent
|
||||
name = input noContent
|
||||
|
||||
nameField : Signal Element
|
||||
nameField = field name.handle id "Name" <~ name.signal
|
||||
-}
|
||||
field : Handle a -> (FieldContent -> a) -> String -> FieldContent -> Element
|
||||
field = Native.Graphics.Input.field
|
||||
|
||||
{-| Same as `field` but the UI element blocks out each characters. -}
|
||||
password : Handle a -> (FieldContent -> a) -> String -> FieldContent -> 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 -> (FieldContent -> a) -> String -> FieldContent -> Element
|
||||
email = Native.Graphics.Input.email
|
||||
|
||||
-- area : Handle a -> (FieldContent -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> FieldContent -> Element
|
||||
-- area = Native.Graphics.Input.area
|
||||
|
|
130
libraries/Graphics/Input/Field.elm
Normal file
130
libraries/Graphics/Input/Field.elm
Normal file
|
@ -0,0 +1,130 @@
|
|||
module Graphics.Input.Field where
|
||||
{-| This library specifically addresses text fields. It uses the same genral
|
||||
approach as the [`Graphics.Input`](Graphics-Input) module for describing an
|
||||
`Input`, so this library focuses on creating and styling text fields.
|
||||
|
||||
# Create Fields
|
||||
@docs field, password, email
|
||||
|
||||
# Field Content
|
||||
@docs Content, Selection, Direction, noContent
|
||||
|
||||
# Field Style
|
||||
@docs Style, Outline, noOutline, Highlight, noHighlight, Dimensions, uniformly
|
||||
-}
|
||||
|
||||
import Color (Color)
|
||||
import Color
|
||||
import Graphics.Element (Element)
|
||||
import Graphics.Input (Input, Handle)
|
||||
import Native.Graphics.Input
|
||||
import Text
|
||||
|
||||
{-| Easily create uniform dimensions:
|
||||
|
||||
uniformly 4 == { left=4, right=4, top=4, bottom=4 }
|
||||
-}
|
||||
uniformly : Int -> Dimensions
|
||||
uniformly n = Dimensions n n n n
|
||||
|
||||
{-| For setting dimensions of a fields padding or border. The left, right, top,
|
||||
and bottom may all have different sizes.
|
||||
-}
|
||||
type Dimensions = { left:Int, right:Int, top:Int, bottom:Int }
|
||||
|
||||
{-| A field can have a outline around it. This lets you set its color, width,
|
||||
and radius. The radius allows you to round the corners of your field. Set the
|
||||
width to zero to make it invisible.
|
||||
-}
|
||||
type Outline = { color:Color, width:Dimensions, radius:Int }
|
||||
|
||||
{-| An outline with zero width, so you cannot see it. -}
|
||||
noOutline : Outline
|
||||
noOutline = Outline Color.grey (uniformly 0) 0
|
||||
|
||||
{-| When a field is selected, it has an highlight around it by default. Set the
|
||||
width of the `Highlight` to zero to make it go away.
|
||||
-}
|
||||
type Highlight = { color:Color, width:Int }
|
||||
|
||||
{-| An highlight with zero width, so you cannot see it. -}
|
||||
noHighlight : Highlight
|
||||
noHighlight = Highlight Color.blue 0
|
||||
|
||||
{-| Describes the style of a text box. The `style` field describes the style
|
||||
of the text itself. The `outline` field describes the glowing blue outline that
|
||||
shows up when the field has focus. Turn off `outline` by setting its width to
|
||||
zero. The
|
||||
-}
|
||||
type Style =
|
||||
{ padding : Dimensions
|
||||
, outline : Outline
|
||||
, highlight : Highlight
|
||||
, style : Text.Style
|
||||
}
|
||||
|
||||
{-| The default style for a text field. The outline is `Color.grey` with width
|
||||
1 and radius 2. The highlight is `Color.blue` with width 1, and the default
|
||||
text color is black.
|
||||
-}
|
||||
defaultStyle : Style
|
||||
defaultStyle =
|
||||
{ padding = uniformly 4
|
||||
, outline = Outline Color.grey (uniformly 1) 2
|
||||
, highlight = Highlight Color.blue 1
|
||||
, 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 Content
|
||||
name = input noContent
|
||||
|
||||
nameField : Signal Element
|
||||
nameField = field name.handle id "Name" <~ name.signal
|
||||
-}
|
||||
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 -> (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 -> (Content -> a) -> Style -> String -> Content -> Element
|
||||
email = Native.Graphics.Input.email
|
||||
|
||||
-- area : Handle a -> (Content -> a) -> Handle b -> ((Int,Int) -> b) -> (Int,Int) -> String -> Content -> Element
|
||||
-- area = Native.Graphics.Input.area
|
|
@ -6,6 +6,12 @@ Elm.Native.Color.make = function(elm) {
|
|||
|
||||
var Utils = Elm.Native.Utils.make(elm);
|
||||
|
||||
function toCss(c) {
|
||||
return (c._3 === 1)
|
||||
? ('rgb(' + c._0 + ', ' + c._1 + ', ' + c._2 + ')')
|
||||
: ('rgba(' + c._0 + ', ' + c._1 + ', ' + c._2 + ', ' + c._3 + ')');
|
||||
}
|
||||
|
||||
function complement(rgb) {
|
||||
var hsv = toHSV(rgb);
|
||||
hsv.hue = (hsv.hue + 180) % 360;
|
||||
|
@ -63,7 +69,8 @@ Elm.Native.Color.make = function(elm) {
|
|||
return elm.Native.Color.values = {
|
||||
hsva:F4(hsva),
|
||||
hsv:F3(hsv),
|
||||
complement:complement
|
||||
complement:complement,
|
||||
toCss:toCss
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
var Render = ElmRuntime.use(ElmRuntime.Render.Element);
|
||||
var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
|
||||
|
||||
var toCss = Elm.Native.Color.make(elm).toCss;
|
||||
var Text = Elm.Native.Text.make(elm);
|
||||
var Signal = Elm.Signal.make(elm);
|
||||
var newElement = Elm.Graphics.Element.make(elm).newElement;
|
||||
var JS = Elm.Native.JavaScript.make(elm);
|
||||
|
@ -78,7 +80,7 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
|
||||
function updateButton(node, oldModel, newModel) {
|
||||
node.elm_signal = newModel.signal;
|
||||
node.elm_value = nemModel.value;
|
||||
node.elm_value = newModel.value;
|
||||
var txt = newModel.text;
|
||||
if (oldModel.text !== txt) node.innerHTML = txt;
|
||||
}
|
||||
|
@ -215,11 +217,52 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
}
|
||||
}
|
||||
|
||||
function updateIfNeeded(css, attribute, latestAttribute) {
|
||||
if (css[attribute] !== latestAttribute) {
|
||||
css[attribute] = latestAttribute;
|
||||
}
|
||||
}
|
||||
function cssDimensions(dimensions) {
|
||||
return dimensions.top + 'px ' +
|
||||
dimensions.right + 'px ' +
|
||||
dimensions.bottom + 'px ' +
|
||||
dimensions.left + 'px';
|
||||
}
|
||||
function updateFieldStyle(css, style) {
|
||||
updateIfNeeded(css, 'padding', cssDimensions(style.padding));
|
||||
|
||||
var outline = style.outline;
|
||||
updateIfNeeded(css, 'border-width', cssDimensions(outline.width));
|
||||
updateIfNeeded(css, 'border-color', toCss(outline.color));
|
||||
updateIfNeeded(css, 'border-radius', outline.radius + 'px');
|
||||
|
||||
var highlight = style.highlight;
|
||||
if (highlight.width === 0) {
|
||||
css.outline = 'none';
|
||||
} else {
|
||||
updateIfNeeded(css, 'outline-width', highlight.width + 'px');
|
||||
updateIfNeeded(css, 'outline-color', toCss(highlight.color));
|
||||
}
|
||||
|
||||
var textStyle = style.style;
|
||||
updateIfNeeded(css, 'color', toCss(textStyle.color));
|
||||
if (textStyle.typeface.ctor !== '[]') {
|
||||
updateIfNeeded(css, 'font-family', Text.toTypefaces(textStyle.typeface));
|
||||
}
|
||||
if (textStyle.height.ctor !== "Nothing") {
|
||||
updateIfNeeded(css, 'font-size', textStyle.height._0 + 'px');
|
||||
}
|
||||
updateIfNeeded(css, 'font-weight', textStyle.bold ? 'bold' : 'normal');
|
||||
updateIfNeeded(css, 'font-style', textStyle.italic ? 'italic' : 'normal');
|
||||
if (textStyle.line.ctor !== 'Nothing') {
|
||||
updateIfNeeded(css, 'text-decoration', Text.toLine(textStyle.line._0));
|
||||
}
|
||||
}
|
||||
|
||||
function renderField(model) {
|
||||
var field = newNode('input');
|
||||
field.style.border = 'none';
|
||||
field.style.outline = 'none';
|
||||
field.style.backgroundColor = 'transparent';
|
||||
updateFieldStyle(field.style, model.style);
|
||||
field.style.borderStyle = 'solid';
|
||||
field.style.pointerEvents = 'auto';
|
||||
|
||||
field.type = model.type;
|
||||
|
@ -302,6 +345,9 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
}
|
||||
|
||||
function updateField(field, oldModel, newModel) {
|
||||
if (oldModel.style !== newModel.style) {
|
||||
updateFieldStyle(field.style, newModel.style);
|
||||
}
|
||||
field.elm_signal = newModel.signal;
|
||||
field.elm_handler = newModel.handler;
|
||||
|
||||
|
@ -316,10 +362,16 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
}
|
||||
|
||||
function mkField(type) {
|
||||
function field(signal, handler, placeHolder, content) {
|
||||
function field(signal, handler, style, placeHolder, content) {
|
||||
var padding = style.padding;
|
||||
var outline = style.outline.width;
|
||||
var adjustWidth = padding.left + padding.right + outline.left + outline.right;
|
||||
var adjustHeight = padding.top + padding.bottom + outline.top + outline.bottom;
|
||||
return A3(newElement, 200, 30, {
|
||||
ctor: 'Custom',
|
||||
type: type + 'Input',
|
||||
type: type + 'Field',
|
||||
adjustWidth: adjustWidth,
|
||||
adjustHeight: adjustHeight,
|
||||
render: renderField,
|
||||
update: updateField,
|
||||
model: {
|
||||
|
@ -327,14 +379,14 @@ Elm.Native.Graphics.Input.make = function(elm) {
|
|||
handler:handler,
|
||||
placeHolder:placeHolder,
|
||||
content:content,
|
||||
style:style,
|
||||
type:type
|
||||
}
|
||||
});
|
||||
}
|
||||
return F4(field);
|
||||
return F5(field);
|
||||
}
|
||||
|
||||
|
||||
function hoverable(signal, handler, elem) {
|
||||
function onHover(bool) {
|
||||
elm.notify(signal.id, handler(bool));
|
||||
|
|
|
@ -10,7 +10,6 @@ Elm.Native.String.make = function(elm) {
|
|||
var Maybe = Elm.Maybe.make(elm);
|
||||
var JS = Elm.JavaScript.make(elm);
|
||||
var Utils = Elm.Native.Utils.make(elm);
|
||||
var show = Elm.Native.Show.make(elm);
|
||||
|
||||
function isEmpty(str) {
|
||||
return str.length === 0;
|
||||
|
@ -244,7 +243,6 @@ Elm.Native.String.make = function(elm) {
|
|||
endsWith: F2(endsWith),
|
||||
indexes: F2(indexes),
|
||||
|
||||
show:show,
|
||||
toInt: toInt,
|
||||
toFloat: toFloat,
|
||||
toList: toList,
|
||||
|
|
|
@ -4,11 +4,10 @@ Elm.Native.Text.make = function(elm) {
|
|||
elm.Native.Text = elm.Native.Text || {};
|
||||
if (elm.Native.Text.values) return elm.Native.Text.values;
|
||||
|
||||
var JS = Elm.JavaScript.make(elm);
|
||||
var Utils = Elm.Native.Utils.make(elm);
|
||||
var Color = Elm.Native.Color.make(elm);
|
||||
var toCss = Elm.Native.Color.make(elm).toCss;
|
||||
var Element = Elm.Graphics.Element.make(elm);
|
||||
var show = Elm.Native.Show.make(elm).show;
|
||||
var List = Elm.Native.List.make(elm);
|
||||
var Utils = Elm.Native.Utils.make(elm);
|
||||
|
||||
function makeSpaces(s) {
|
||||
if (s.length == 0) { return s; }
|
||||
|
@ -51,13 +50,51 @@ Elm.Native.Text.make = function(elm) {
|
|||
return arr.join('<br/>');
|
||||
}
|
||||
|
||||
function toText(str) { return Utils.txt(properEscape(JS.fromString(str))); }
|
||||
function toText(str) { return Utils.txt(properEscape(str)); }
|
||||
|
||||
// conversions from Elm values to CSS
|
||||
function toTypefaces(list) {
|
||||
var typefaces = List.toArray(list);
|
||||
for (var i = typefaces.length; i--; ) {
|
||||
var typeface = typefaces[i];
|
||||
if (typeface.contains(' ')) {
|
||||
typefaces[i] = "'" + typeface + "'";
|
||||
}
|
||||
}
|
||||
return typefaces.join(',');
|
||||
}
|
||||
function toLine(line) {
|
||||
var ctor = line.ctor;
|
||||
return ctor === 'Under' ? 'underline' :
|
||||
ctor === 'Over' ? 'overline' : 'line-through';
|
||||
}
|
||||
|
||||
// setting styles of Text
|
||||
function style(style, text) {
|
||||
var newText = '<span style="color:' + toCss(style.color) + ';'
|
||||
if (style.typeface.ctor !== '[]') {
|
||||
newText += 'font-family:' + toTypefaces(style.typeface) + ';'
|
||||
}
|
||||
if (style.height.ctor !== "Nothing") {
|
||||
newText += 'font-size:' + style.height._0 + 'px;';
|
||||
}
|
||||
if (style.bold) {
|
||||
newText += 'font-weight:bold;';
|
||||
}
|
||||
if (style.italic) {
|
||||
newText += 'font-style:italic;';
|
||||
}
|
||||
if (style.line.ctor !== 'Nothing') {
|
||||
newText += 'text-decoration:' + toLine(style.line._0) + ';';
|
||||
}
|
||||
newText += '">' + Utils.makeText(text) + '</span>'
|
||||
return Utils.txt(newText);
|
||||
}
|
||||
function height(px, text) {
|
||||
return { style: 'font-size:' + px + 'px;', text:text }
|
||||
}
|
||||
function typeface(name, text) {
|
||||
return { style: 'font-family:' + name + ';', text:text }
|
||||
function typeface(names, text) {
|
||||
return { style: 'font-family:' + toTypefaces(names) + ';', text:text }
|
||||
}
|
||||
function monospace(text) {
|
||||
return { style: 'font-family:monospace;', text:text }
|
||||
|
@ -71,25 +108,16 @@ Elm.Native.Text.make = function(elm) {
|
|||
function link(href, text) {
|
||||
return { href: toText(href), text:text };
|
||||
}
|
||||
function underline(text) {
|
||||
return { line: ' underline', text:text };
|
||||
}
|
||||
function overline(text) {
|
||||
return { line: ' overline', text:text };
|
||||
}
|
||||
function strikeThrough(text) {
|
||||
return { line: ' line-through', text:text };
|
||||
function line(line, text) {
|
||||
return { style: 'text-decoration:' + toLine(line) + ';', text:text };
|
||||
}
|
||||
|
||||
function color(c, text) {
|
||||
var color = (c._3 === 1)
|
||||
? ('rgb(' + c._0 + ', ' + c._1 + ', ' + c._2 + ')')
|
||||
: ('rgba(' + c._0 + ', ' + c._1 + ', ' + c._2 + ', ' + c._3 + ')');
|
||||
return { style: 'color:' + color + ';', text:text };
|
||||
function color(color, text) {
|
||||
return { style: 'color:' + toCss(color) + ';', text:text };
|
||||
}
|
||||
|
||||
function position(align) {
|
||||
function create(text) {
|
||||
function block(align) {
|
||||
return function(text) {
|
||||
var raw = {
|
||||
ctor :'RawHtml',
|
||||
html : Utils.makeText(text),
|
||||
|
@ -100,7 +128,6 @@ Elm.Native.Text.make = function(elm) {
|
|||
var pos = A2(Utils.htmlHeight, 0, raw);
|
||||
return A3(Element.newElement, pos._0, pos._1, raw);
|
||||
}
|
||||
return create;
|
||||
}
|
||||
|
||||
function markdown(text, guid) {
|
||||
|
@ -115,36 +142,25 @@ Elm.Native.Text.make = function(elm) {
|
|||
return A3(Element.newElement, pos._0, pos._1, raw);
|
||||
}
|
||||
|
||||
var text = position('left');
|
||||
function asText(v) {
|
||||
return text(monospace(toText(show(v))));
|
||||
}
|
||||
|
||||
function plainText(v) {
|
||||
return text(toText(v));
|
||||
}
|
||||
|
||||
return elm.Native.Text.values = {
|
||||
toText: toText,
|
||||
|
||||
height : F2(height),
|
||||
italic : italic,
|
||||
bold : bold,
|
||||
underline : underline,
|
||||
overline : overline,
|
||||
strikeThrough : strikeThrough,
|
||||
line : F2(line),
|
||||
monospace : monospace,
|
||||
typeface : F2(typeface),
|
||||
color : F2(color),
|
||||
link : F2(link),
|
||||
|
||||
justified : position('justify'),
|
||||
centered : position('center'),
|
||||
righted : position('right'),
|
||||
text : text,
|
||||
plainText : plainText,
|
||||
markdown : markdown,
|
||||
leftAligned : block('left'),
|
||||
rightAligned : block('right'),
|
||||
centered : block('center'),
|
||||
justified : block('justify'),
|
||||
markdown : markdown,
|
||||
|
||||
asText : asText,
|
||||
toTypefaces:toTypefaces,
|
||||
toLine:toLine,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -76,14 +76,8 @@ Elm.Native.Utils.make = function(elm) {
|
|||
|
||||
function makeText(text) {
|
||||
var style = '';
|
||||
var line = '';
|
||||
var href = '';
|
||||
while (true) {
|
||||
if (text.line) {
|
||||
line += text.line;
|
||||
text = text.text;
|
||||
continue;
|
||||
}
|
||||
if (text.style) {
|
||||
style += text.style;
|
||||
text = text.text;
|
||||
|
@ -95,7 +89,6 @@ Elm.Native.Utils.make = function(elm) {
|
|||
continue;
|
||||
}
|
||||
if (href) text = '<a href="' + href + '">' + text + '</a>';
|
||||
if (line) style += 'text-decoration:' + line + ';';
|
||||
if (style) text = '<span style="' + style + '">' + text + '</span>';
|
||||
return text;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ Cosmetic operations such as padding with extra characters or trimming whitespace
|
|||
@docs map, filter, foldl, foldr, any, all
|
||||
-}
|
||||
|
||||
import Native.Show
|
||||
import Native.String
|
||||
import Maybe (Maybe)
|
||||
|
||||
|
@ -284,7 +285,7 @@ indices = Native.String.indexes
|
|||
show [1,2] == "[1,2]"
|
||||
-}
|
||||
show : a -> String
|
||||
show = Native.String.show
|
||||
show = Native.Show.show
|
||||
|
||||
{-| Try to convert a string into an int, failing on improperly formatted strings.
|
||||
|
||||
|
|
|
@ -6,94 +6,132 @@ module Text where
|
|||
@docs toText
|
||||
|
||||
# Creating Elements
|
||||
@docs plainText, asText, text, centered, justified, righted
|
||||
@docs leftAligned, rightAligned, centered, justified
|
||||
|
||||
# Formatting
|
||||
@docs color, typeface, height, link
|
||||
# Links and Style
|
||||
@docs link, Style, style, Line, defaultStyle
|
||||
|
||||
# Simple Formatting
|
||||
@docs monospace, bold, italic, underline, overline, strikeThrough
|
||||
# Convenience Functions
|
||||
|
||||
There are two convenience functions for creating an `Element` which can be
|
||||
useful when debugging or prototyping:
|
||||
|
||||
@docs plainText, asText
|
||||
|
||||
There are also a bunch of functions to set parts of a `Style` individually:
|
||||
|
||||
@docs typeface, monospace, height, color, bold, italic, line
|
||||
|
||||
-}
|
||||
|
||||
import Basics (..)
|
||||
import Color (Color)
|
||||
import String
|
||||
import Color (Color, black)
|
||||
import Graphics.Element (Element, Three, Pos, ElementPrim, Properties)
|
||||
import Maybe (Maybe)
|
||||
import Maybe (Maybe, Nothing)
|
||||
import JavaScript (JSString)
|
||||
import Native.Show
|
||||
import Native.Text
|
||||
|
||||
data Text = Text
|
||||
|
||||
data Line = Under | Over | Through
|
||||
|
||||
{-| Representation of all the ways you can style `Text`.
|
||||
-}
|
||||
type Style =
|
||||
{ typeface : [String]
|
||||
, height : Maybe Float
|
||||
, color : Color
|
||||
, bold : Bool
|
||||
, italic : Bool
|
||||
, line : Maybe Line
|
||||
}
|
||||
|
||||
{-| Plain black text. It uses the browsers default typeface and text height.
|
||||
No decorations are used:
|
||||
|
||||
{ typeface = []
|
||||
, height = Nothing
|
||||
, color = black
|
||||
, bold = False
|
||||
, italic = False
|
||||
, line = Nothing
|
||||
}
|
||||
-}
|
||||
defaultStyle : Style
|
||||
defaultStyle =
|
||||
{ typeface = []
|
||||
, height = Nothing
|
||||
, color = black
|
||||
, bold = False
|
||||
, italic = False
|
||||
, line = Nothing
|
||||
}
|
||||
|
||||
{-| Convert a string into text which can be styled and displayed. -}
|
||||
toText : String -> Text
|
||||
toText = Native.Text.toText
|
||||
|
||||
{-| Set the typeface of some text. The first argument should be a comma
|
||||
separated listing of the desired typefaces:
|
||||
|
||||
"helvetica, arial, sans-serif"
|
||||
|
||||
Works the same as the CSS font-family property.
|
||||
{-| Set the style of some text.
|
||||
-}
|
||||
typeface : String -> Text -> Text
|
||||
style : Style -> Text -> Text
|
||||
style = Native.Text.style
|
||||
|
||||
{-| Provide a list of prefered typefaces for some text.
|
||||
|
||||
["helvetica","arial","sans-serif"]
|
||||
|
||||
Not everyone has access to the same typefaces, so rendering will use the first
|
||||
typeface in the list that is found on the user's computer. If there are no
|
||||
matches, it will use their default typeface. Works the same as the CSS
|
||||
font-family property.
|
||||
-}
|
||||
typeface : [String] -> Text -> Text
|
||||
typeface = Native.Text.typeface
|
||||
|
||||
{-| Switch to a monospace typeface. Good for code snippets. -}
|
||||
monospace : Text -> Text
|
||||
monospace = Native.Text.monospace
|
||||
|
||||
{-| Create a link. -}
|
||||
{-| Create a link.
|
||||
|
||||
link "http://elm-lang.org" (toText "Elm Website")
|
||||
-}
|
||||
link : String -> Text -> Text
|
||||
link = Native.Text.link
|
||||
|
||||
{-| Set the height of text in pixels. -}
|
||||
height : Float -> Text -> Text
|
||||
height = Native.Text.height
|
||||
|
||||
{-| Set the color of a string. -}
|
||||
color : Color -> Text -> Text
|
||||
color = Native.Text.color
|
||||
|
||||
{-| Make a string bold. -}
|
||||
bold : Text -> Text
|
||||
bold = Native.Text.bold
|
||||
|
||||
{-| Italicize a string. -}
|
||||
italic : Text -> Text
|
||||
italic = Native.Text.italic
|
||||
|
||||
{-| Draw a line above a string. -}
|
||||
overline : Text -> Text
|
||||
overline = Native.Text.overline
|
||||
line : Line -> Text -> Text
|
||||
line = Native.Text.line
|
||||
|
||||
{-| Underline a string. -}
|
||||
underline : Text -> Text
|
||||
underline = Native.Text.underline
|
||||
leftAligned : Text -> Element
|
||||
leftAligned = Native.Text.leftAligned
|
||||
|
||||
{-| Draw a line through a string. -}
|
||||
strikeThrough : Text -> Text
|
||||
strikeThrough = Native.Text.strikeThrough
|
||||
rightAligned : Text -> Element
|
||||
rightAligned = Native.Text.rightAligned
|
||||
|
||||
{-| Display justified, styled text. -}
|
||||
justified : Text -> Element
|
||||
justified = Native.Text.justified
|
||||
|
||||
{-| Display centered, styled text. -}
|
||||
centered : Text -> Element
|
||||
centered = Native.Text.centered
|
||||
|
||||
{-| Display right justified, styled text. -}
|
||||
righted : Text -> Element
|
||||
righted = Native.Text.righted
|
||||
|
||||
{-| Display styled text. -}
|
||||
text : Text -> Element
|
||||
text = Native.Text.text
|
||||
justified : Text -> Element
|
||||
justified = Native.Text.justified
|
||||
|
||||
{-| Display a plain string. -}
|
||||
plainText : String -> Element
|
||||
plainText = Native.Text.plainText
|
||||
plainText str =
|
||||
leftAligned (toText str)
|
||||
|
||||
{-| for internal use only -}
|
||||
markdown : Element
|
||||
|
@ -107,4 +145,5 @@ the browser:
|
|||
Excellent for debugging.
|
||||
-}
|
||||
asText : a -> Element
|
||||
asText = Native.Text.asText
|
||||
asText value =
|
||||
leftAligned (monospace (toText (Native.Show.show value)))
|
||||
|
|
|
@ -91,7 +91,7 @@ function init(display, container, module, ports, moduleToReplace) {
|
|||
checkPorts(elm);
|
||||
} catch(e) {
|
||||
var directions = "<br/> Open the developer console for more details."
|
||||
Module.main = Elm.Text.make(elm).text('<code>' + e.message + directions + '</code>');
|
||||
Module.main = Elm.Text.make(elm).leftAligned('<code>' + e.message + directions + '</code>');
|
||||
reportAnyErrors = function() { throw e; }
|
||||
}
|
||||
inputs = ElmRuntime.filterDeadInputs(inputs);
|
||||
|
|
|
@ -7,7 +7,15 @@ var newElement = Utils.newElement, extract = Utils.extract,
|
|||
addTransform = Utils.addTransform, removeTransform = Utils.removeTransform,
|
||||
fromList = Utils.fromList, eq = Utils.eq;
|
||||
|
||||
function setProps(props, e) {
|
||||
function setProps(elem, e) {
|
||||
var props = elem.props;
|
||||
var element = elem.element;
|
||||
if (element.adjustWidth) {
|
||||
props.width -= element.adjustWidth;
|
||||
}
|
||||
if (element.adjustHeight) {
|
||||
props.height -= element.adjustHeight;
|
||||
}
|
||||
e.style.width = (props.width |0) + 'px';
|
||||
e.style.height = (props.height|0) + 'px';
|
||||
if (props.opacity !== 1) { e.style.opacity = props.opacity; }
|
||||
|
@ -200,7 +208,7 @@ function rawHtml(elem) {
|
|||
return div;
|
||||
}
|
||||
|
||||
function render(elem) { return setProps(elem.props, makeElement(elem)); }
|
||||
function render(elem) { return setProps(elem, makeElement(elem)); }
|
||||
function makeElement(e) {
|
||||
var elem = e.element;
|
||||
switch(elem.ctor) {
|
||||
|
@ -308,7 +316,16 @@ function update(node, curr, next) {
|
|||
}
|
||||
|
||||
function updateProps(node, curr, next) {
|
||||
var props = next.props, currP = curr.props, e = node;
|
||||
var props = next.props;
|
||||
var currP = curr.props;
|
||||
var e = node;
|
||||
var element = next.element;
|
||||
if (element.adjustWidth) {
|
||||
props.width -= element.adjustWidth;
|
||||
}
|
||||
if (element.adjustHeight) {
|
||||
props.height -= element.adjustHeight;
|
||||
}
|
||||
if (props.width !== currP.width) e.style.width = (props.width |0) + 'px';
|
||||
if (props.height !== currP.height) e.style.height = (props.height|0) + 'px';
|
||||
if (props.opacity !== 1 && props.opacity !== currP.opacity) {
|
||||
|
|
Loading…
Reference in a new issue