Code Monkey home page Code Monkey logo

html's Introduction

HTML

Quickly render HTML in Elm.

Examples

The HTML part of an Elm program looks something like this:

import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)

type Msg = Increment | Decrement

view : Int -> Html Msg
view count =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt count) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

If you call view 42 you get something like this:

<div>
  <button>-</button>
  <div>42</div>
  <button>+</button>
</div>

This snippet comes from a complete example. You can play with it online here and read how it works here.

You can play with a bunch of other examples here.

Learn More

Definitely read through guide.elm-lang.org to understand how this all works! The section on The Elm Architecture is particularly helpful.

Implementation

This library is backed by elm/virtual-dom which handles the dirty details of rendering DOM nodes quickly. You can read some blog posts about it here:

html's People

Contributors

adzeitor avatar albronca avatar apanatshka avatar benjamintanweihao avatar camilleriluke avatar chairmanlee8 avatar cmoel avatar evancz avatar gaul avatar halohalospecial avatar joefiorini avatar jragonfyre avatar jwmerrill avatar laszlopandy avatar liamcurry avatar martinos avatar passy avatar process-bot avatar rehno-lindeque avatar rick68 avatar robertjlooby avatar saljam avatar shaydon avatar stevensona avatar sudhirvkumar avatar theseamau5 avatar thsoft avatar tobiasgwaaler avatar vilterp avatar warry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

html's Issues

onChange event

Would it be possible to add the onChange event to Html.Events? I've been adding

onChange : msg -> Attribute msg
onChange message =
    on "change" (Json.succeed message)

into most of my apps because it fires when a user stops typing in input fields unlike onInput which fires every press sending a lot of network requests.

fromElement/toElement are gone?

Sorry, I tried to find an answer everywhere, but failed miserably.

I am trying to migrate from elm 0.16 to 0.17, and part of my view is written with use of Graphics. I know, that this package changed its location, but I really stuck with some other issues.

First, I don't know, how to handle user inputs with subscriptions but without Html.App. Before it was done by foldp and Signal, but all this is gone now. Could you please point to any good tutorial or article, I couldn't find anything about that?

Second, I couldn't find any way to convert Element to Html. Before it could be done with fromElement from Html module, but it is gone in elm-lang/elm-html. Is there any way to do something like that, because in that case I could just convert all Graphics to Html and pass it to view in Html.App.program?

Thank you for your attention!

Removal of value property erases the current value

Hello,
With the following SSCCE:

import Html.App exposing (beginnerProgram)
import Html exposing (input)
import Html.Events exposing (onInput)
import Html.Attributes exposing (value)


main = beginnerProgram
  { model = True
  , view =
      ( \m -> input ( [ onInput (\_ -> ()) ] ++ if m then [ value "test" ] else [] ) [] )
  , update = (\_ _ -> False)
  }

when completing the input field, it sends a message to the update function which puts the model to False and thus the view is updated to remove the value attribute. When this happens the field is emptied, which was not the expected behavior.
I have tested this in elm-lang.org/try both in Firefox and in Chromium.

At first I thought that this may be a problem on the HTML side rather than on the Elm side but then I tested opening the following code in my browser:

<input value="test">

Then I complete the field with one more character, then with Inspect the element in Firefox or the Firebug extension, I manually remove the value attribute. This does not affect what the field contains.

So it might be a problem of Javascript or of Elm. I have not tried to discriminate between these two.

Trouble with input Japanese characters when rapidly typing

This issue is very hard to explain, but it's actually happening.
(For Japanese, this issue is about "高速にタイプすると途中で変換できなくなる件".)

Japanese people type Japanese characters through converting alphabets like this. When I want to input こんにちは, I type konnichiha. Also, during typing, browser shows the text (こんにちは) with underline. This underline indicates "This text is not yet determined, you can also choose alternative plans to describe konnichiha". All of こんにちは, 今日は and コンニチハ can be converted from konnichiha. So we choose one of them before finishing typing. To summarize, this "undetermined state" is important.

Now, the problem is, when "value" attribute of input element is set by program, this "undetermined state" suddenly disappears. Basically, this does not happen because the value in Elm is always equal to the value of input element. But when I type rapidly, it behaves unexpectedly.

Type slowly

action DOM value Elm value Applying patch
type "r" りr
りr no change
type "i" りり
りり no change

Type rapidly

action DOM value Elm value Applying patch
type "r" りr
type "i" りり
りr りr りり ⇒ りr
りり りり りr ⇒ りり

The last two needless changes cause disappearance of "undetermined state". I confirmed this happens only when this line is evaluated. I think this is common issue in Chinese too.

If you can type this kind of language, I also created an example at jsFiddle, which is not Elm but able to see the behavior.

Thanks.


OS: Windows 7
Browser: Chrome 51
Elm: 0.17.0
elm-lang/core: 4.0.3
elm-lang/html: 1.1.0

Runtime error using Html.Attributes.list

I get this error using Html.Attributes.list :

Uncaught TypeError: Cannot assign to read only property 'list' of object '#<HTMLInputElement>'

How to reproduce :

import Html exposing (..)
import Html.App as App
import Html.Attributes exposing (..)

type alias Model = ()
type Msg = Noop

main : Program Never
main =
  App.beginnerProgram
    { model = ()
    , view = view
    , update = always identity
    }

view model =
  input 
   [ list "autocomplete"
   , type' "text"
   ]
   []

FYI, using [ Attr.property "list" (Json.Encode.string "screens") doesn't work.

Bug in 0.17 - value function isn't setting inputs value as it did in 0.16

In 0.16 if you called value on an input the actual dom value always matched what was passed in.
For example the below input would only ever show the value of model.age

input [ type' "text", value model.age, onInput InputAge
  , on "input" targetValue (\s -> Signal.message address (InputAge s)) ] []

Now in 0.17 the initial call to value set's the dom value, however subsequently the input shows whatever was keyed rather than the model's value.

Here's an example where the model is updated when an int is keyed, but stays the same if a non Int is keyed. As you can see from the gif, when I keyed "jkl" in 0.16, the value of the input stayed empty. When I keyed "jkl" in 0.17 the input showed the value "jkl"

Here's the code for each version:

Example in 0.16
Example in 0.17

Diff

Setting innerHtml property doesn't work

Testable in http://elm-lang.org/try, using Chrome 49

import Html exposing (div)
import Html.Attributes exposing (property)
import Json.Encode as Json

main =
  div [
    property "innerHtml" (Json.string "<h1>Hello world</h1>")
  ] []

Is there any solution to this (setting HTML from string, i.e. from server response)?

value attribute of textarea should be sent to browser only at creation of DOM element

This is a follow-up on issue #52.

elm-lang/html should send the value attribute of textarea to the browser only at creation of the textarea DOM element, and ignored when the textarea is update'd and view'ed. This is to prevent the caret to be moved at the end of the textarea when typing, resulting in misplaced keyboard input. See issue #52 for an example.

Alternative : we could use a defaultValue attribute instead (as for the input), but the value attribute is worthless as it works now, so I see no need to create a separate attribute.

Possible bug in dom patching

First of all, thanks for the awesome work on elm! and, sorry if this isn't actually a bug in this package. I'm just very confused if it is not. This code is very closely adapted from the code shown here: http://guide.elm-lang.org/interop/javascript.html

I have two versions of code, both of which illustrate what I believe to be the same problem manifesting itself in different ways.

details

browser: Firefox 47.0 on OS X 10.11.6
versions of elm:

  • elm-make: 0.17
  • html: 1.1.0
  • virtual-dom: 1.1.1
  • core: 4.0.5

minimal reproducible

I made a minimal reproducible here:
https://github.com/joelmccracken/elm-html-bug-reproducible

I published it as a gh page, here, for your inspection:
https://joelmccracken.github.io/elm-html-bug-reproducible/

first version

The first version raises an error in the JavaScript Console. I'll show the behavior first, and then the code:

elm-console-error

The code to create this is:

port module ImportWizard exposing(main)

import Html.App as App
import Html exposing (text, div, textarea, button, hr)
import Html.Events exposing (onInput, onClick)
import String

type alias Model =
  { csvValue : String
  , results : List String
  }

main =
  App.program
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }


init : (Model, Cmd a)
init =
  ({ csvValue = ""
   , results = ["initial", "value"]
   }
  , Cmd.none)


view model =
  div []
    [ textarea [ onInput Change ] []
    , button [ onClick Check ] [ text "Check"]
    , hr [] []
    , div [] [text (String.join ", " model.results)]
    ]


type Msg
  = Change String
  | Check
  | CSVCheckResult (List String)


update : Msg -> Model -> (Model, Cmd a)
update msg model =
  case msg of
    Change txt -> ({model | csvValue = txt}, Cmd.none)
    Check -> (model, check model.csvValue)
    CSVCheckResult result -> ({ model | results = result}, Cmd.none)


port check : String -> Cmd msg


-- Subscriptions

port checkResults : (List String -> msg) -> Sub msg

subscriptions : Model -> Sub Msg
subscriptions model =
  checkResults CSVCheckResult

There is some supporting coffeescript to boot the help app and work with the port:

#= require application_common
#= require import_wizard

$ ->
  node = document.getElementById('importWizard--wizard')
  app  = Elm.ImportWizard.embed(node)
  app.ports.check.subscribe (poop)->
    console.log "HI THERE"
    app.ports.checkResults.send ["foo", "bar"]

Second version

The code for this version is almost exactly the same, except the hr is removed from the view code. I won't list all the whole code here, I'll just show the section that is different.

elm-changing-wrong-text

The different chunk of code:

view model =
  div []
    [ textarea [ onInput Change ] []
    , button [ onClick Check ] [ text "Check"]
    -- , hr [] []
    , div [] [text (String.join ", " model.results)]
    ]

[Suggestion] disablePropagate (sic) attribute

Hi folks,

It'd be ideal if there was some easier way to disable event propagation. Particularly for onClick. onWithOptions works well..... except it requires me to have a "NoOp" msg in my update loop, when my module had been working great with out.

Is that considered "ok" by TEA standards? If so, so be it, if not, some convenience twiddle to allow me to specify what happens to the event w/o having to create a "dead" Msg type could be useful.

No discussion needed if this isn't deemed appropriate, just a quick 2-cents.

`Lazy` misnomer, lack of documentation, debugging difficulties, examples, etc.

I just spent a whole evening debugging a problem in my application with lazy because even though the component model had changed, lazy was memoizing the function. It was very confusing since events inside the component were firing, sort of (i.e. Html.App.map Msg.Foo (Html.Lazy.lazy Foo.view model.foo)). But were getting short-circuited up the subscription chain and the update functions making it unclear what the problem was. Normally if events aren't firing correctly, those are the two places of suspect along with the ports, but it was a view layer problem.

So I reread the documentation this morning to better understand what's going on. Some problems I noted:

  • lazy doesn't mean lazy evaluation--so right off the bat the name is actually wrong because it doesn't meet initial expectations.
  • "...just bundle the function and arguments up for later" is very vague. I know there's this idea that Elm doesn't want to scare people with ideas and programming concepts, but the documentation should technically explain that this library does a short-circuit with memoization--something people can use a search engine to dive in deeper to the concepts and those that already know can be like "oh okay, I know how this works because it's a part of my lexicon and programming domain knowledge". As it currently documented, the idea is very nebulous and I want something concrete to understand it.
  • As a user trying to understand where is the optimal place to start looking to test out where lazy can help, there is no documentation on where a red flag in your code should be a spot to try it. It's pretty much mysticism. There should be an physical toy example of a problem that lazy can solve and where lazy goes at the view layer.
  • There needs to be some cons listed about chewing up memory because it seems like a magical tool to fix everything. An example of value that changes too often should be listed as a when not to use it.
  • What would also be useful is some intro to new people on how to "definitely benchmark to be sure!". I'd assume that many people aren't sure what they're looking for.

Proposal: add events for when nodes and added and removed

(Note: this is very much related to https://github.com/elm-lang/virtual-dom/issues/11)

Problem

In order to embed a Javascript component into a contained element which is managed by Elm, we need to know when that element exists. There are various possible workarounds (I posted one in the issue referenced above), but they are hacky, unreliable and I am continually finding edge cases where they don't work.

Proposal

Add two new functions to Html.Events:

{-| Capture when Virtualdom has added this node to the DOM -}
onNodeAdded : msg -> Attribute msg

{-| Capture when Virtualdom has removed this node from the DOM -}
onNodeRemoved : msg -> Attribute msg

Having played around with this for a while, I am fairly convinced that this will cover all the use cases of Elm/JS component integration, and from this point on everything could be taken care of in idiomatic Elm using update and ports.

Exploits allowing arbitrary JS code execution via Elm code

As I understand it, the only ways someone can publish a new Elm package and use it to run arbitrary JS code (hijacking the entire Elm runtime of an unsuspecting package consumer) are the following:

  • node "script" [] [ text "injectMalware()" ] (works with Html.node and Html.Keyed.node)
  • a [ href "javascript:injectMalware()" ] []
  • button [ property "onclick" "injectMalware()" ] []
  • img [ property "onload" "injectMalware()", src "blah.jpeg" ] [] (also works with other elements that support onload, e.g. body)

These aren't self-contained examples, granted, which I guess means they aren't proper SSCCEs, but I'm not sure how useful that'd be here. I can make runnable examples of these if that'd be useful, but I assume it wouldn't help.

I found a library that sanitizes user-submitted HTML to prevent XSS attacks. We could use some of these techniques to patch vulnerabilities.

Note: There do exist real-world non-malware uses of this exploit. Closing this off would be a breaking change for them.

Event onWithOptions doesn't allow selective behaviour on events

Sometimes its necessary to stopPropogation and preventDefault on certain events and not others. For instance it may be desired to restrict certain key-presses in a text-input field. Examples include:

  • Credit card entry, numbers and spaces
  • Phone numbers with international codes () and +
  • Hex editor, restrict to A-Z 0-5
  • and many more....

Currently Elm doesn't allow this behaviour because stopPropogation and preventDefault are specified at the time the event listener is registered, and before the event listener has received any events.

I suggest changing the signature of Options to something like this:

type alias Options = { stopPropagation : Json.Decoder Bool , preventDefault : Json.Decoder Bool }

This will allow stopPropogation and preventDefault flags to be based on the content of the event received.

Alternatively since this would be a breaking change could add another Options type and another onWithOptions method.

chrome extensions can cause runtime exceptions due to elm.fullscreen

elm.fullscreen attaches to body. Sadly a lot of chrome extensions actually inject things into the body. This causes errors because the virtual dom goes out so sync with the real dom (that's been messed with). This causes the following error:

(this is an onClick event however anything that changes the dom will mess with it)

error



Main.elm:6446 Uncaught TypeError: Cannot read property 'childNodes' of undefinedaddDomNodesHelp 
@ Main.elm:6446addDomNodesHelp 
@ Main.elm:6454addDomNodesHelp
 @ Main.elm:6454addDomNodesHelp
 @ Main.elm:6454addDomNodes 
@ Main.elm:6400applyPatches 
@ Main.elm:6482updateIfNeeded 
@ Main.elm:5855requestAnimationFrame (async)registerVirtualNode
 @ Main.elm:5834(anonymous function) 
@ Main.elm:3000step 
@ Main.elm:2737work 
@ Main.elm:2793setTimeout (async)enqueue 
@ Main.elm:2782rawSend 
@ Main.elm:2633enqueue
 @ Main.elm:3012eventHandler
 @ Main.elm:6049

I would propose that Elm.fullscreen actually make a "elm-html" div to embed itself into rather using the body itself. I think this would help prevent people from messing with it.

padding kills padding-left

I found a bug.

There are two VirtualDom nodes.

  • (A) styled by "padding-left"
  • (B) styled by "padding"

Now (B) is rendered but (A) is not. When model is changed, (A) is inserted before (B), but (A)'s "padding-left" is not rendered then.

SSCCE:

import Html exposing (div, text)
import Html.Attributes exposing (style)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)

main =
  beginnerProgram { model = "init", view = view, update = update }

view model =
  let
    children1 =
      if model == "clicked" then
        [ div
            [ style [("padding-left", "100px")] ] -- this style will be not rendered
            [ text "this element's padding-left must be 100px" ] ]
      else
        []

    children2 =
      [ div
          [ style [("padding", "20px")]
          , onClick Click
          ]
          [ text "click me" ]
      ]
  in
    div [] (children1 ++ children2)
    -- div [] (children2 ++ children1) -- this is OK

type Msg = Click

update msg model =
  case msg of
    Click ->
      "clicked"

OK patterns:

  • swap children1 and children2
  • "margin" instead of "padding"
  • "padding-left" instead of "padding"
  • no style instead of "padding"
  • render children1 before click event

Html.Events.onInput in <select> does not work in FF

import Html exposing (..)
import Html.App
import Html.Events exposing (..)
import Html.Attributes exposing (..)

main = Html.App.beginnerProgram { model = "", view = view, update = update }

view model =
  div []
    [ select [ onInput Change ]
      [ option [ value "" ] [ text "" ]
      , option [ value "value" ] [ text "hello" ]
      ]
    , p [] [ text <| "model is: '" ++ model ++ "'" ]
    ]

type Msg = Change String

update msg model =
  case msg of
    Change value ->
      let
        _ = Debug.log "" value
      in
        value

The following code works fine on Chrome but on Firefox the onInput hander is not called at all.

I think the problem might be, that Elm is listening on input event which appearently on <select> works in Chrome but not in Firefox (related bug: https://bugzilla.mozilla.org/show_bug.cgi?id=312094)

More cross browser way of handling selects seems to be listening on change event instead of input.

Additional information:

  • OS: win 7
  • Browser: Chrome 52, FF 47
  • Elm: 0.17.1, Html: 1.1.0

event mouseup missed when dragging selection

To reproduce:

  • Load http://elm-lang.org/examples/drag
  • Double click on the word "drag", inside the green component, to select it
  • Click on the selected text, and keep the mouse button down
  • Drag the cursor out of the component, keeping the mouse button down => The component isnt dragged along.
  • Release the mouse button, move the mouse around => The component is being dragged around.

To stop the dragging, another click must be performed.

Experienced on windows, on firefox and chrome.

Focus messed up in inputs using both onInput and value

When you edit the value (eg the first char of many), the focus goes back to the last char, probably because the whole input is redrawn.

I know that Mithril faced a similar issue : https://lhorie.github.io/mithril/mithril.html#dealing-with-focus

Here is a minimal reproduction of the bug:

import Html exposing (Html, Attribute, text, div, input)
import Html.App exposing (beginnerProgram)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import String


main =
  beginnerProgram { model = "", view = view, update = update }


-- UPDATE

type Msg = NewContent String

update (NewContent content) oldContent =
  content


-- VIEW

view content =
  div []
    [ input [ placeholder "Text to reverse", onInput NewContent, myStyle, value content ] []
    , div [ myStyle ] [ text (String.reverse content) ]
    ]

myStyle =
  style
    [ ("width", "100%")
    , ("height", "40px")
    , ("padding", "10px 0")
    , ("font-size", "2em")
    , ("text-align", "center")
    ]

Chaining Html.App.map produces: TypeError: domNode.replaceData is not a function

SSCCE:

import Html exposing (div, button, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)

main =
    beginnerProgram { model = 0, update = update, view = view }


type alias Model = Int

type ButtonMsg = Increment | Decrement

type ItemMsg = Button ButtonMsg

type Msg = Item ItemMsg

update : Msg -> Model -> Model
update msg model =
    case Debug.log "update" msg of
        Item (Button buttonmsg) ->
          case buttonmsg of
            Increment ->
              model + 1
            Decrement ->
              model - 1

buttonView : Model -> Html.Html ButtonMsg
buttonView model =
    div []
        [ button [ onClick Decrement ] [ text "-" ]
        , div [] [ text (toString model) ]
        , button [ onClick Increment ] [ text "+" ]
        ]


view : Model -> Html.Html Msg
view model =
    let
        itemView model =
            Html.App.map Button (buttonView model)
    in
        Html.App.map Item (itemView model)

view2 : Model -> Html.Html Msg 
view2 model =
  Html.App.map (Item<<Button) (buttonView model) 

view3 : Model -> Html.Html Msg 
view3 model =
  Html.App.map Item
  <| div [] [ Html.App.map Button (buttonView model) ]

Both view2 and view3 work as expected.

Runtime TypeError after removing onClick handler

Minimal example: https://gist.github.com/mattjbray/baa73435e9df6f984fabe9aad258f14a

In this example, the onClick handler is removed from the button element after the count reaches 3.

Expected outcome: clicking on the button a fourth time has no effect.

Actual outcome: clicking on the button a fourth time causes a JavaScript error in the browser console:

TypeError: info is null

The brower trace points to this section of the compiled JS:

function makeEventHandler(eventNode, info)
{
    function eventHandler(event)
    {
        var info = eventHandler.info;

        var value = A2(_elm_lang$core$Native_Json.run, info.decoder, event);  // TypeError here

        ...

This is reproducible on the current elm-lang.org/try, which I'm assuming is running Elm 0.17 and elm-lang/html 1.0.0.

(I note that in this contrived example it would probably make more sense to ignore subsequent Incs in the update function rather than removing the onClick handler.)

inputmode attribute

I'd like to use the verbatim and numeric values of the inputmode attribute, currently missing from Html.Attributes. My application involves inputting organisation names and their account details.

values sent to program over inbound port immediately are not being seen by program

I've produced an example here: https://github.com/knewter/counter

It's actually published here: http://knewter.github.io/counter/Counter.html

If you load the page, the counter will have value 0. The Counter.html file has the following code:

var app = Elm.Main.fullscreen();
app.ports.jsMsgs.send(1);
window.app = app;

I mention the last bit because you can open up the browser's console, issue app.ports.jsMsgs.send(1), and the counter will update. So the inbound port works, but it doesn't work immediately.

Lacking onMouseMove

I found onMouseMove is not defined in current Html.Event API. I guess there is some reason for not supporting it (maybe Mouse module is better at some point?), but it is not explained anywhere. So, it's simply inconvenient now.

shiftKey not sent by onkeydown

I've adapted the onentercode from the todomvc example to create onShiftEnter below, but it does not work. I asked on StackOverflow, but I did not get an answer.

I believe that shiftKey is not passed to Elm.

onShiftEnter : Msg -> Attribute Msg
onShiftEnter msg =
  let
    tagger (code, shift) =
      if code == 13 && shift then msg else NoOp
  in
    on "keydown" 
       (Json.Decode.map tagger 
          ( Json.Decode.tuple2 (,)
              (Json.Decode.at ["keyCode"] Json.Decode.int)
              (Json.Decode.at ["shiftKey"] Json.Decode.bool)
          )
       )

Setting Focus and Blur

(Process disclaimer: This is not a bug, but I ran it by maintainer @evancz before posting it here.)

The following would be a way to set focus and blur using only Elm code.

It runs the given String through document.querySelector instead of e.g. document.getElementById so that you can do things like Html.focus "button:first".

(document.querySelector works in IE8+, so it is fine to rely on.)

{-| After the next render, runs [`document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
on the given selector string and [sets focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the
resulting element.

    Html.focus "#searchInput"
-}
focus : String -> Task SelectorError a


{-| After the next render, runs [`document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
on the given selector string and [removes focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur) from the
element it finds.

    Html.blur "#searchInput"

-}
blur : String -> Task SelectorError a


{- Describes the result of a failed call to [`document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector).

`InvalidQueryString` represents a [`SYNTAX_ERR` exception](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector#Notes).
`ElementNotFound` represents the case where `document.querySelector` did not find an element.
-}
type SelectorError
    = InvalidQueryString String
    | ElementNotFound

LICENSE file: Update organization field from BSD template.

Currently line 14 of the LICENSE file:

  • Neither the name of the {organization} nor the names of its contributors...

In other elm-lang repos this line reads:

  • Neither the name of Evan Czaplicki nor the names of other contributors...

The latter is probably the intention.

Since there are contributors, but they are not mentioned here with name (and there is no CLA),
a file with contributors would be appropriate.

Can't find events described in documentation

Good morning everyone, I'm having a lot of fun with Elm so thank you for your job!

Though I found some useful attributes in the docs which actually are not present in the library, for example onKeyUp.

Am I reading the docs the wrong way?

thanks,
pietro

emitting messages from within <form> tags causes page reload

While using Elm with bootstrap to build a webapp, my app started reloading during testing whenever certain buttons were pressed. After looking around a bit for the causes, I discovered it was associated with the following code from one of my components:

import Html
import Html.Attributes as Attr

-- ...

view : Model -> Html Msg
view model =
   Html.div
     [ Attr.class "component-container row col-md-12 text-center"
     ]
     [ Html.div
         [ Attr.class "col-md-8 col-md-offset-2 component" ]
         [ Html.h2 [] [ Html.text "Products" ]
         , Html.ul
             []
             (makeProductList model)
          , Html.form
              [ Attr.class "new-product-form col-md-12" ]
              [ Html.div
                 [ Attr.class "form-group" ]
                  [ Html.input
                     [ Attr.class "form-control"
                     , Attr.placeholder "Product name"
                     , Attr.value model.userInput
                     , Events.onInput SetName
                     ]
                     []
                 , Html.button
                     [ Attr.class "btn btn-default"
                     , Events.onClick (Add model.userInput)
                     ]
                     [ Html.text "Add product" ]
                ]
            ]
         ]

Whenever I would press the "Add product" button, it would cause a page reload, making me lose the data in my model.

Commenting out the Html.form function caused this error to stop happening. Here's the non-error throwing code:

view : Model -> Html Msg
view model =
  Html.div
    [ Attr.class "component-container row col-md-12 text-center"
    ]
    [ Html.div
        [ Attr.class "col-md-8 col-md-offset-2 component" ]
        [ Html.h2 [] [ Html.text "Products" ]
        , Html.ul
            []
            (makeProductList model)
        , {-Html.form                                                                                                                                                                                                                         
            [ Attr.class "new-product-form col-md-12" ]                                                                                                                                                                                       
            [ -}Html.div
                [ Attr.class "form-group" ]
                [ Html.input
                    [ Attr.class "form-control"
                    , Attr.placeholder "Product name"
                    , Attr.value model.userInput
                    , Events.onInput SetName
                    ]
                    []
                , Html.button
                    [ Attr.class "btn btn-default"
                    , Events.onClick (Add model.userInput)
                    ]
                    [ Html.text "Add product" ]
                ]
            {-]-}
        ]
    ]

My project also contained a different component which had a very similar structure in its view function. It caused the very same error, which was solved in the same way.

Suggestions and Feature Requests

This is a meta issue for organizing requests and details in one place. As suggestions arise in normal issues, they will be aggregated here as appropriate.

Major API Changes:

  • Replace Html.map with Html.App.map. Is <map> in use besides this?
  • #36 - remove svg - should only be creating that node with the Svg library anyway
  • #35 - remove autosave - apparently it is not real?
  • #48 - draggable should take Bool
  • #55 - fix textarea for "unmanaged" scenario
  • #56 - disallow various vectors for sneaking in JS code

Minor API Changes

  • #68 - Attribute.indeterminate
  • #75 - Attribute.inputmode
  • #72 - Html.none for when you do not want to show anything
  • #61 - onMouseMove - unclear if everyone wants pageX and pageY only
  • #23 - onChange - unclear if everyone wants String only
  • #51 - Keyed.tbody could be handy
  • #18 - Attribute.map seems reasonable

New Features

  • #20 - better support for file inputs. Needs File and Blob API.
  • #19 - an easier way to hijack nodes from JS
  • #67 - have main be a list of nodes

preventDefault on a per event basis

I want to write an onEnter handler for a textarea. When my handler detects that the enter key has been pressed I want to preventDefault so that the textarea doesn't receive the newline. onWithOptions only allows you to specify preventDefault and stopPropagation when you register the event, rather than an a per event basis. I'm not sure how this might best be handled from an api point of view, perhaps something like:

onEnter : Msg -> Attribute Msg
onEnter msg =
  let
    tagger code =
      if code == 13 then 
        (msg, {stopPropagation = True, preventDefault = True}) 
      else 
        (NoOp, {stopPropagation = False, preventDefault = False}) 
  in
    on "keydown" (JD.map tagger keyCode)

Elm version: 0.17

Uncaught TypeError: Cannot read property 'ctor' of null

The following Elm 0.17 program always creates the above error when typing some text in the first textarea, then clicking the second one.

I could not make it any shorter, and still create the error... Still, it represents an important use case : have a couple of textarea whose value you want to force from time to time, and have a time clock in your model.

Interestingly, as soon as I remove the time ticks subscription, the problem disappears. I may want to go native for the clock...

port module Main exposing (..)

import Html exposing (..)
import Html.App as Html
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Json.Encode
import Json.Decode exposing ((:=))

import String
import Time exposing (Time, millisecond)

type alias Model = 
  { text1 : String
  , text2 : String
  , focus : Int -- 0 = no focus, 1 or 2 when focus on a textarea
  , now : Time }

type Msg 
  = SaveText1 String
  | SaveText2 String
  | Tick Time
  | SetFocus Int

main = Html.program { init = init, view = view, update = update, subscriptions = subscriptions }

init = 
  ( (Model "Hello world" "Good night" 0 0)
  , Cmd.none
  )

subscriptions : Model -> Sub Msg
subscriptions model = 
      Sub.batch 
          ( if model.focus /= 0  then 
              [] -- stop time ticks while textarea has focus
                 -- this is to prevent refreshing the textareas
            else 
              [ Time.every (500 * millisecond) Tick ]
          )

update msg model =
  case msg of 
     SaveText1 txt -> ({model | text1 = txt}, Cmd.none)
     SaveText2 txt -> ({model | text2 = txt}, Cmd.none)
     Tick time -> ( { model | now = time }, Cmd.none )
     SetFocus i -> ( { model | focus = i }, Cmd.none )

view model =
  div []
  [ textarea 
      [ value model.text1
      , on "change" (Json.Decode.map SaveText1 (Json.Decode.at ["target", "value"] Json.Decode.string))
      , onFocus (SetFocus 1)
      , onBlur (SetFocus 0)
      ]
    [ ]
  , textarea 
      [ value model.text2
      , on "change" (Json.Decode.map SaveText2 (Json.Decode.at ["target", "value"] Json.Decode.string))
      , onFocus (SetFocus 2)
      , onBlur (SetFocus 0)
      ]
    [ ]
  , text (toString model)
  ]

The design decisions were wade as follows :

  • I want to update my model only when the focus leaves a textarea --> use on change (see issue #52 and #55)
  • I want a time tick, but I cannot refresh the DOM at every tick when the user is typing, because value will replace user's input --> stop time ticks while a textarea has the focus --> use onFocus and onBlur to keep track of which textarea has focus.

contenteditable support on input events

input event doesn't trigger on contenteditable nodes. at least firefox and webkit already support this. can you add this feature to input event on html.events?

Glitch: "input" element changes when typing regardless of model

I want to restrict the input of an input field. Problem is, Elm allows the input through before applying the update.

Consider this modification of the elm-lang.org field example.

import Html exposing (Html, Attribute, text, div, input)
import Html.App exposing (beginnerProgram)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import String


main =
  beginnerProgram { model = "", view = view, update = update }


-- UPDATE

type Msg = NewContent String

-- Note change (updates to "" always)
update (NewContent content) oldContent =
  ""


-- VIEW

-- Note change (value attribute set to content)
view content =
  div []
    [ input [ value content, placeholder "Text to reverse", onInput NewContent, myStyle ] []
    , div [ myStyle ] [ text (String.reverse content) ]
    ]

myStyle =
  style
    [ ("width", "100%")
    , ("height", "40px")
    , ("padding", "10px 0")
    , ("font-size", "2em")
    , ("text-align", "center")
    ]

If you type in characters, you'll see they slip by before disappearing a few ms after.

Any ideas?

By the way, my use case is for a form, where for example a ZIP code should be only 5 characters. I want the 6th character (or non-integers for that matter) to simply not get typed in. Having characters flash like this looks really unprofessional.

Runtime error: passing empty string to Html.Attributes.attribute

import Html exposing (div, text)
import Html.Attributes exposing (attribute)

main =
  div [ attribute "" "" ] [ text "boom!" ]

Gives:

Main.elm:6123 Uncaught InvalidCharacterError: Failed to execute 'setAttribute' on 'Element': '' is not a valid attribute name.

Using:

    "dependencies": {
        "elm-lang/core": "4.0.1 <= v < 5.0.0",
        "elm-lang/html": "1.1.0 <= v < 2.0.0"
    },

It would be great if `onXXX` events helper method return information about some kind of `TargetEvent` object

These are the current helper method signatures:

onClick : msg -> Attribute msg
onDoubleClick : msg -> Attribute msg
onMouseDown : msg -> Attribute msg
onMouseUp : msg -> Attribute msg
onMouseEnter : msg -> Attribute msg
onMouseLeave : msg -> Attribute msg
onMouseOver : msg -> Attribute msg
onMouseOut : msg -> Attribute msg

I was wondering if each of these helper method provided back with some kind of TargetEvent object from which users can grab the mouse x,y coords etc.

onClick : (TargetEvent -> msg) -> Attribute msg
onDoubleClick : (TargetEvent -> msg) -> Attribute msg
onMouseDown : (TargetEvent -> msg) -> Attribute msg
onMouseUp : (TargetEvent -> msg) -> Attribute msg
onMouseEnter : (TargetEvent -> msg) -> Attribute msg
onMouseLeave : (TargetEvent -> msg) -> Attribute msg
onMouseOver : (TargetEvent -> msg) -> Attribute msg
onMouseOut : (TargetEvent -> msg) -> Attribute msg

Feature Request: Allow a top-level view to return a list of html nodes

Right now, your entire app needs to reside in a div or something similar in order to function. However, there are some UI libraries (semantic-ui.com) that force you to use a structure dependent on the top-level <body> node. As an example, the following would work:

<body>
  <foo />
  <bar />
</body>

but the following wouldn't, and is the only facility we have to embedding fullscreen programs in elm:

<body>
  <div>
    <foo />
    <bar />
  </div>
</body>

I'm thinking an alternative Html.program that takes a view in the form of model -> List (Html msg).

Read-only properties should be defined in terms of the attribute method.

I was creating a form, and certain input elements needed to be outside the form, so I tried using the form : String -> Attribute msg function to indicate the form the elements belong to. In Firefox form is readonly, and cannot be set by setting the corresponding js property, so Firefox threw a TypeError : setting a property that has only a getter error and wouldn't display anything.

After reading this: https://github.com/evancz/elm-html/issues/98, I realized that I ought to be using the attribute : String -> String -> Attribute msg function. Replacing form "form-name" by attribute "form" "form-name" resolved the issue. However, I thought that this should be mentioned for future reference, and probably fixed in the libraries, unless someone knows of a reason that wouldn't be a good idea.

elements / attributes could be more type safe

I had a brainfart and I was trying to set the value attribute on the form element instead of input and it took some time to realize why the input field wasn't getting updated properly.

With the strong type system of elm I'd think the elements could make such use of invalid attribute a compile time error instead of silently ignoring it.

Mssing `key` Attribute leads to buggy diffs

0.16 had a key Attribute, the documentation for which stated:

If you have a list of 20 items and want to remove the 4th one, adding keys ensures that you do not end up doing misaligned diffs on the following 15 items.

I'm encountering the exact same issue because of the lack of key in 0.17.

A small sample that reproduces the issue (pasting this in http://elm-lang.org/try should work):

import Html exposing (..)
import Html.App exposing (beginnerProgram)
import Html.Attributes exposing (class, type', property)
import Html.Events exposing (onClick, on, targetChecked)
import Json.Decode as JD
import Json.Encode as JE

type View = Checked | Unchecked | All


type Msg =
    SetView View
  | Toggle Int


type alias Row =
  { id : Int
  , name : String
  , checked : Bool
  }

type alias Model =
  { data : List Row
  , view : View
  }

model : Model
model =
  { data = [ { id = 0
             , name = "X"
             , checked = False
             }
           , { id = 1
             , name = "Y"
             , checked = True
             }
           , { id = 2
             , name = "Z"
             , checked = False
             }
           ]
  , view = All
  }


update : Msg -> Model -> Model
update msg model =
  case msg of
    SetView v ->
      { model | view = v }

    Toggle id ->
      let toggle r = if r.id == id
                     then
                       { r | checked = not r.checked }
                     else
                       r
      in
        { model | data = List.map toggle model.data }


view : Model -> Html Msg
view model =
  let makeRow r = tr [ ]
                     [ td [ ] [ text (toString r.id) ]
                     , td [ ] [ text r.name ]
                     , td [ ] [ input [ type' "checkbox"
                                      , property "checked" (JE.bool r.checked)
                                      , on "change" (JD.map (\b -> Toggle r.id) targetChecked)
                                      ]
                                      [ ]
                              ]
                     ]
      filter = case model.view of
                 Unchecked ->
                   \r -> r.checked == False

                 Checked ->
                   \r -> r.checked == True

                 All ->
                   always True

      content = table [ ]
                      (List.filter filter model.data |> List.map makeRow)
      makeButton v = button [ onClick (SetView v) ]
                            [ text (toString v) ]
      buttons = List.map makeButton [ Checked, Unchecked, All ]
  in
      div [ ]
          [ div [ ]
                [ content ]
          , div [ ]
                buttons
          , hr [ ] [ ]
          , div [ ]
                [ text (toString model) ]
          ]


main = beginnerProgram { model = model, view = view, update = update }

You can reproduce the issue by selecting the 'Unchecked' view via the button, and checking the first displayed row in that view.

Expected results:

The checked row disappears from the view and the remaining rows are unchecked.

Actual results:

The checked row disappears, however the next row shows a checkmark unexpectedly.

Looking at the dump of the model at the end of the page shows that the model is OK and the problem is most likely in the diffing logic.

Add Attribute.map?

I find it conceptually strange to have to write:

on "event-name" (someGivenDecoder |> Json.Decoder.map MyMessageConstructor)

More meaningful would be:

on "event-name" someGivenDecoder |> Attribute.map MyMessageConstructor

Because it is the attribute result to which I want to attach the MyMessageConstructor. I'm not conceptually trying to make a new decoder, so using Json.Decoder.map for what I want to express seems quite circumvent (when reading/understanding/explaining/teaching that code).

textarea not working correctly in IE (but well in Chrome)

When I type letters in the textarea after the word "Hello", the first one is well positionned, but the latter ones are added at the end of the textarea in Internet Explorer 11.

The same program works ok in Chrome though. Here it is:

import Html exposing (..)
import Html.App as Html
import Html.Events exposing (..)

type alias Model = { textString : String }

type Msg = SaveText String

main = Html.beginnerProgram { model = (Model "Hello world"), view = view, update = update }

update msg model =
  case msg of 
     SaveText txt -> Model txt

view model =
  textarea 
    [ onInput SaveText ] 
  [text model.textString]

You can try it using Try Elm v0.17. Somehow, the caret is moved to the end of the textarea. Why ?

svg element is always 0x0

import Html
import Svg
import Svg.Attributes as A

main =
  let
    rect = Svg.rect [ A.width "100", A.height "100" ] []
    attrs = [ A.viewBox "0 0 300 150" ]
  in
    Html.div []
      [ Html.svg attrs [ rect ]
      , Svg.svg attrs [ rect ]
      ]

In Chrome 51 the first svg element is 0x0 while the latter is 300x150. The content is basically irrelevant, it just makes it visually obvious the element isn't showing up at all.

Not sure if related but the html element has attribute viewbox whereas the svg variant has viewBox, it's presence or absence has no effect on the element size but I believe lowercasing the attributes would lead to broken svg.

'meter' attributes min/max/etc. aren't type safe

> float = 1/0
Infinity : Float
> floatS = toString float
"Infinity" : String
> Html.meter [Html.Attributes.max floatS] []

leads to runtime error

Uncaught TypeError: Failed to set the 'max' property on 'HTMLMeterElement': The provided double value is non-finite.

The argument for 'max' should perhaps be restricted to 'Finite Float' or something like that.

While setting 'min' > 'max' isn't triggering any exceptions (in Chrome) it's kind of nonsense and could perhaps be prevented with additional types like say 'Range (Maybe Float) (Maybe Float)'

Lacking onMouseMove (summary)

This issue is the summary of #50 for quick reference from #53 .

Original comment:

I found onMouseMove is not defined in current Html.Event API. I guess there is some reason for not supporting it (maybe Mouse module is better at some point?), but it is not explained anywhere. So, it's simply inconvenient now.

Typical situation:

For one example, I'm making an app that can edit maps, in which I need to get relative position in a certain area for drag-and-drop. But I'm not sure everyone needs it, or it's the best solution for it.

Typical solution: (Thanks to @jvoigtlaender)

@jinjor's problem sounds as if simply using offsetX and offsetY would be the solution. Should work without being confused by inner elements in the container.

Note: offsetX and offsetY is marked as "experimental" at MDN, but all modern browser seem to support it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.