Code Monkey home page Code Monkey logo

browser's Introduction

Elm in the Browser!

This package allows you to create Elm programs that run in browsers.

Learning Path

I highly recommend working through guide.elm-lang.org to learn how to use Elm. It is built around a learning path that introduces concepts gradually.

You can see the outline of that learning path in the Browser module. It lets you create Elm programs with the following functions:

  1. sandbox — react to user input, like buttons and checkboxes
  2. element — talk to the outside world, like HTTP and JS interop
  3. document — control the <title> and <body>
  4. application — create single-page apps

This order works well because important concepts and techniques are introduced at each stage. If you jump ahead, it is like building a house by starting with the roof! So again, work through guide.elm-lang.org to see examples and really understand how Elm works!

This order also works well because it mirrors how most people introduce Elm at work. Start small. Try using Elm in a single element in an existing JavaScript project. If that goes well, try doing a bit more. Etc.

browser's People

Contributors

aimichal avatar bernardoow avatar danfishgold avatar evancz avatar evxn avatar jfairbank avatar jon4syth avatar lgdean avatar mfeineis avatar norpan avatar ream88 avatar reiner-dolp avatar rl-king avatar robinheghan avatar ryan-senn avatar taj avatar terezka avatar xtian 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

browser's Issues

`a` tags without `href` generate a navigation event

When using Browser.application. If you have an a which doesn't have an href, Elm will generate a navigation event.

Reproduction here: https://github.com/sporto/repro-elm-application-a-tag/blob/master/src/Main.elm

This seems like a bug, a tag is not supposed to be a link unless it has a href.

https://www.w3.org/TR/html5/text-level-semantics.html#the-a-element

If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor) labeled by its contents.

If the a element has no href attribute, then the element represents a placeholder for where a link might otherwise have been placed, if it had been relevant, consisting of just the element’s contents.

In applications links don't have `preventDefault` when compiled with the `--debug` flag

When compiled with --debug, the preventDefault on a tags is not working in applications, resulting in page reloads. Without --debug everything works.
SSCCE:

module Main exposing (..)

import Browser
import Browser.Events
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (href)
import Html.Events exposing (onClick)
import Json.Decode as JD
import Tuple exposing (pair)
import Url
import Url.Builder


main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = LinkClicked
        , onUrlChange = UrlChange
        }


type alias Model =
    { key : Nav.Key }


init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init env _ key =
    pair { key = key } Cmd.none


view : Model -> Browser.Document Msg
view model =
    { title = "My app"
    , body =
        [ Html.h2 [] [ text "Elm 19" ]
        , a [ href "/hello" ] [ text "Go to Hello" ]
        ]
    }


type Msg
    = LinkClicked Browser.UrlRequest
    | UrlChange Url.Url


update msg model =
    pair model Cmd.none

Add functionality for generating `UrlRequest`s explicitly

Currently, a UrlRequest is generated when the user clicks on a link. There should be a function similar to Navigation.pushUrl except that it goes through application.onUrlRequest. This way, we can delegate to application.onUrlRequest from onClick and other handlers.

Here's my use case. I wrote a wrapper around Browser.application that, given the old URL and the new, decides whether to use pushUrl or replaceUrl. That way, all the logic of handling history is collected in one place instead of scattered across the application. This works fine for links, but not for handlers where I have to do the decision locally. Worse, since the old URL is maintained in the wrapper and not in the application, I can't implement this even if I'm OK with duplicating code.

pushUrl without triggering onUrlChange

I've built a SPA that uses navigation for routing. But some of the pages have tabs and I'd like to prevent triggering routing for those while retaining the url history functionality.

Back/Forward navigation broken in navigation-in-elements.md sample code

The How do I manage URL from a Browser.element? guide contains a bug in the sample code that will prevent browser Back/Forward buttons from working.

The popstate event listener is incorrectly attached to the document:

// Inform app of browser navigation (the BACK and FORWARD buttons)
document.addEventListener('popstate', function () {
    app.ports.onUrlChange.send(location.href);
});

This should be added to the window to work:

// Inform app of browser navigation (the BACK and FORWARD buttons)
window.addEventListener('popstate', function () {
    app.ports.onUrlChange.send(location.href);
});

TypeError in Debugger

Expected
When update gets called, the debugger updates.

** Actual **
A TypeError is thrown TypeError: Cannot read property 'childNodes' of undefined in the function _Virtual_Dom_addDomNodesHelp which is called by updateIfNeeded in _Browser_makeAnimator.

Looks related to 0c91ab5 , the childNodes in this case are text nodes with newlines in them.

** Environment **
Elm 0.19
elm/browser 1.0.1
elm/virtual-dom 1.0.2

Debugger seems to not register any click events

Beyond the freeze in the main view as mentioned in #16, I can't seem to click anything when accessing the debugger:

image

Clicking the dropdown arrows, or any item in the left list does nothing. I just started learning elm so I'm not sure what the expected behaviour is, but I assume we should be able to see the full model correct?

I've set this up by using create-elm-app. Snapshot of my project


Update:

It seems like the problem occurs on my MBP, with Mojave. It works fine on my other laptop with Kubuntu. Both are using Chrome

clicking link with download "" generates Browser.Internal event

creating a link like:
a [ class "align-center", href "/static/certificate/file.pdf", download "" ] [ Icons.print, span [] [ text "AVETTA" ] ] will create the unwanted event.
if we provide the filename in download attribute like download "myFile.pdf" it will download the file.

Debugger click-to-resume overlay broken on 0.19

There's a regression in the Elm 0.19 debugger's "click-to-resume" feature. In Elm 0.18, when you time-travel into the past, a big "click-to-resume" overlay covers your app and clicking it time travels to the present. But in 0.19, the overlay is not shown. Clicking anywhere in your app while in this state will do nothing. It's especially bad if the user closes the debugger popup window while in this state, as they will be unable to reopen the debugger in order to resume.

Steps to reproduce

First, compile Main.elm using --debug

module Main exposing (..)

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

main = Browser.sandbox { init = 0 , view = view , update = update }

type Msg = Increment

update _ n = n + 1

view n =
    div []
        [ text (String.fromInt n)
        , button [ onClick Increment ] [ text "+" ]
        ]
  1. open the resulting index.html
  2. click the "+" button a few times
  3. open the Elm debugger popup
  4. select a msg from the past
  5. observe that inputs are blocked, but no overlay is shown

Here's a video demonstrating the bug in Safari (Chrome looks similar)

Notice that after time-travelling, clicking the "+" button in the Elm app does nothing, and the user has no way to know why it's not working.

I would expect an overlay to be shown like how Elm 0.18 does it:
elm18 click to resume

Jumping to fragments does not work in a good way in `Browser.application`

For a Browser.application the docs recommend to handle UrlRequest like this

case msg of
    ClickedLink urlRequest ->
      case urlRequest of
        Internal url -> ( model, Nav.pushUrl model.key (Url.toString url))
        External url -> ( model, Nav.load url )

However, this won't do anything with links like the following <a href="#someAnchor">Jump</a> (to jump to <a name="someAnchor"></a>) since they will count as Internal UrlRequests.
It is possible to jump to fragments using Nav.load but the suggested code above will only change the url with Nav.pushUrl.

Notes:
There are a couple of cases to consider, links like:

  1. #myAnchor or /samePage#myAnchor
    Links pointing to anchors on the same page can be used to safely jump to the anchor immediately using the browsers default behavior, because the page is already rendered.
  2. /newPageAnchor#anchorOnDifferentPage
    However when navigating to an new page an anchor on a new page, SPAs behave differently than server rendered pages. The url changes first and only after some async data is loading the page containing the anchor is actually rendered. Only once the page is rendered it is possible to jump to the anchor. This case introduces a time gap between clicking the link and being able to navigate to the anchor.

It would be nice to have a solution for the first case that is close to browser behavior, but the preventDefault on every link seems to make it tough right now.
The second case (navigating to a new page) doesn't seem to be elm specific but a general SPA "problem". Other frameworks and routers have similar issues https://github.com/rafrex/react-router-hash-link/tree/react-router-v2/3#react-router-hash-link-scroll and seem to use some kind of polling of the DOM to check if the anchor has been rendered.

Example in Browser.Events.onClick doc does not work (click event evaluated twice)

The example is as follows:

Subscribe to mouse clicks anywhere on screen. Maybe you need to create a custom drop down. You could listen for clicks when it is open, letting you know if someone clicked out of it:

import Browser.Events as Events
import Json.Decode as D

type Msg = ClickOut

subscriptions : Model -> Sub Msg
subscriptions model =
  case model.dropDown of
    Closed _ ->
      Sub.none

    Open _ ->
      Events.onClick (D.succeed ClickOut)

The stated use case is exactly what I wanted to achieve. So I tried, but it seems not working.
https://ellie-app.com/4r8RQNZX4P4a1

module Main exposing (main)

import Browser
import Browser.Events
import Html exposing (..)
import Html.Attributes exposing (style)
import Html.Events exposing (onClick)
import Json.Decode exposing (succeed)


type alias Model =
    { dropDown : Bool }


initialModel : () -> ( Model, Cmd Msg )
initialModel _ =
    ( { dropDown = False }, Cmd.none )


type Msg
    = DropDown Bool


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        DropDown isOpen ->
            ( { model | dropDown = isOpen }, Cmd.none )


view : Model -> Html Msg
view model =
    div []
        [ button [ onClick (DropDown (not model.dropDown)) ] [ text "Drop Down" ]
        , ul
            [ style "border" "solid black 1px"
            , style "display" <|
                if model.dropDown then
                    "block"

                else
                    "none"
            ]
            [ li [] [ text "Item 1" ]
            , li [] [ text "Item 2" ]
            ]
        ]


subscriptions : Model -> Sub Msg
subscriptions model =
    let
        _ =
            Debug.log "subCalled" model
    in
    if model.dropDown then
        -- Browser.Events.onClick (succeed (DropDown False)) -- Toggle this line to see the bug
        Sub.none

    else
        Sub.none


main : Program () Model Msg
main =
    Browser.element
        { init = initialModel
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

When you uncomment the commented line above to provide "click out", the dropdown button itself stops working.
Dropdown part is not shown at all even if you click the button.

Apparently, a click event is evaluated twice, within a single frame, before AND after model update?
To prove that, I introduced "step" state before activating "click out" subscription:
https://ellie-app.com/4r9djjXTZ4Fa1

module Main exposing (main)

import Browser
import Browser.Events
import Html exposing (..)
import Html.Attributes exposing (style)
import Html.Events exposing (onClick)
import Json.Decode exposing (succeed)


type alias Model =
    { dropDown : DD }


type DD
    = JustOpened
    | ReadyToClose
    | Closed


initialModel : () -> ( Model, Cmd Msg )
initialModel _ =
    ( { dropDown = Closed }, Cmd.none )


type Msg
    = Open
    | GetReady
    | Close


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Open ->
            ( { model | dropDown = JustOpened }, Cmd.none )

        GetReady ->
            ( { model | dropDown = ReadyToClose }, Cmd.none )

        Close ->
            ( { model | dropDown = Closed }, Cmd.none )


view : Model -> Html Msg
view model =
    div []
        [ button
            [ onClick <|
                case model.dropDown of
                    Closed ->
                        Open

                    _ ->
                        Close
            ]
            [ text "Drop Down" ]
        , ul
            [ style "border" "solid black 1px"
            , style "display" <|
                case model.dropDown of
                    Closed ->
                        "none"

                    _ ->
                        "block"
            ]
            [ li [] [ text "Item 1" ]
            , li [] [ text "Item 2" ]
            ]
        ]


subscriptions : Model -> Sub Msg
subscriptions model =
    case model.dropDown of
        JustOpened ->
            Browser.Events.onAnimationFrame (\_ -> GetReady)

        ReadyToClose ->
            Browser.Events.onClick (succeed Close)

        Closed ->
            Sub.none


main : Program () Model Msg
main =
    Browser.element
        { init = initialModel
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

This works, since it avoids suspected "double evaluation" by delaying state transition with onAnimationFrame.

Actually, this problem had alreaday reported when it was Mouse.clicks in Elm 0.18.
https://discourse.elm-lang.org/t/mouse-clicks-subscription-created-and-executed-following-click-event/1067
The problem continued in Browser.Events.onClick but I do not see the issue on the repository, so let me file it here.

Unknown import in "wasd.elm" example

Running "wasd.elm" example on latest version of elm/browser results in following error:


-- UNKNOWN IMPORT ----------------------------------------- examples/keytest.elm

I cannot find a `Browser.Window` module to import.

    import Browser.Window

I cannot find that module! Is there a typo in the module name?

The "source-directories" field of your elm.json tells me to only look in the
examples directory, but it is not there. Maybe it is in a package that is not
installed yet?

Why can't Browser.application have an element mount point?

Right now Browser.application wipes clean the <body>. The body can be used as a place for useful stuff to exst. For us, it was a) scripts to not be in the head, and b) inlining our SVG icons.

Inlining the SVG icons previous allowed us:

  1. one less network request for a required resource
  2. IE11 support
  3. no flash of content for getting the #id from a <use> tag
  4. Not having to deal with hashing/asset management as NRI's Webpack asset plugin does not support v0.19.

The v0.18 did not clear the body. Clearing the element is fine and whatever, but since the body of document still serves as a storage space for other content, there shouldn't be anything wrong with mounting at <body><div id="app"></div>... OTHER STUFF...</body>. Sure, the application would now have to measure different elements than the body, but what's wrong with that?

Currently no way of using preventDefault on window events

I could really use it right now for limited keyboard accessibility, where the user doesn't have access to the Tab key or to a mouse. Their only means of navigation are the arrow keys. I can do Html.Events.preventDefaultOn on the outermost div but there's still a possibility of that not working if focus gets changed to the body.

There are some who have commented in Slack that this would also be beneficial for game development.

Browser.application programs cannot handle URLs with uncommon protocols like dat://

I wanted to use Elm to write an app for Beaker - p2p browser which that adds dat protocol support and p2p apps are loaded from URLs like

dat://id.hashbase.io/elm

Unfortunately it seems to break some assumptions made by Browser.application here the error reported in the console:

elm:733 Uncaught Error: Browser.application programs cannot handle URLs like this:

    dat://id.hashbase.io/elm

What is the root? The root of your file system? Try looking at this program with `elm reactor` or some other server.
    at _Debug_crash (elm:733)
    at _Browser_getUrl (elm:4024)
    at init (elm:4014)
    at _Platform_initialize (elm:1871)
    at elm:3909
    at Object.init (elm:30)
    at elm:5254
_Debug_crash @ elm:733
_Browser_getUrl @ elm:4024
init @ elm:4014
_Platform_initialize @ elm:1871
(anonymous) @ elm:3909
(anonymous) @ elm:30
(anonymous) @ elm:5254

Scheduling problem when using Navigation.pushUrl

I have discovered a problem that I suspect have to do with how commands and subscriptions are scheduled. I'll try to make clear what I have found so far. And since Ellie does not support Browser.application I'll paste an SSCCE here.

module Main exposing (main)

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


type alias Model =
    { key : Browser.Navigation.Key
    , subscribeToAnimationFrames : Bool
    }


type Msg
    = Navigate
    | UrlChanged
    | AnimationFrame


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Navigate ->
            ( model
            , Browser.Navigation.pushUrl model.key "#foo"
            )

        UrlChanged ->
            ( { model | subscribeToAnimationFrames = True }
            , Cmd.none
            )

        AnimationFrame ->
            ( { model | subscribeToAnimationFrames = False }
            , Cmd.none
            )


view : Model -> Browser.Document Msg
view model =
    { title = "Test"
    , body =
        [ button [ onClick Navigate ] [ text "Click this button to cause the problem" ]
        , Html.h1 []
            [ Html.text "Subscribe to animation frames: "
            , Html.text (Debug.toString model.subscribeToAnimationFrames)
            ]
        , Html.pre
            []
            [ Html.text (Debug.toString model)
            ]
        ]
    }


subscriptions : Model -> Sub Msg
subscriptions model =
    if model.subscribeToAnimationFrames then
        Browser.Events.onAnimationFrame (always AnimationFrame)

    else
        Sub.none


main : Program () Model Msg
main =
    Browser.application
        { init = \_ _ key -> ( Model key False, Cmd.none )
        , onUrlChange = always UrlChanged
        , onUrlRequest = always Navigate
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

When the application receives the message Navigate it navigates to another url. When the browser changes url the message UrlChanged is sent to the application. When this happens the subscriptions that result from the first update gets applied after the subscriptions that result from the second update.

This means that when then UrlChanged message is sent to the application and I want to subscribe to Browser.Events.onAnimationFrame it is "cancelled" by the resulting subscriptions from the previous update. So even if model.subscribeToAnimationFrames is True there is no guarantee that the application is subscribed to Browser.Events.onAnimationFrame.

Let me know if I need to provide any more info.

Browser.element with navigation

Hi ; transitioning to Elm in an older system, we've been using Elm 0.18 to implant incrementally element-style elm parts as pages that still get the benefits of the existing non-elm menus and layout.

We've also successfully used Navigation in some of those parts.

Now we're trying to migrate to 0.19 ; but there is no Browser.elementWithNavigation or such to make an element that's embedded into a non-elm page rather than replacing the whole page, so everywhere we transitioned to Browser.application has no layout.

Is there a library that implements an application-like function that would offer navigation for element-like embedded elm parts?

clicking links (<a> elements) with href omitted or with an empty href incorrectly generates External UrlRequest's

Empty links, i.e. a elements without a href attribute or with href "" will cause External UrlRequests to be generated, and if handled as suggested in the Elm guide will cause page reloads.

This can be handled in update if you know about it, but is non-standard behavior that I think would surprise most people. it is also behavior that a lot of code depends on, among them elm-bulma, and it miight therefore not be immediately apparent what the cause is.

As far as I can understand, the standard behavior is:

  • When href is omitted it should not be considered a hyperlink (source)
  • When href is an empty string, it should be considered a reference to the beginning of the document (source)

My suggestion is to simply not emit a UrlRequest if href is omitted, and to emit an Internal UrlRequest if it is an empty string.

Here's a minimal, complete and verifiable example:

module Main exposing (main)

import Browser
import Browser.Navigation
import Html exposing (..)
import Url


type alias Model =
    ()


type Msg
    = UrlRequested Browser.UrlRequest
    | UrlChanged Url.Url


init () _ _ =
    ( (), Cmd.none )


update msg model =
    case msg of
        UrlRequested (Browser.Internal _) ->
            ( model, Cmd.none )

        UrlRequested (Browser.External url) ->
            ( model, Browser.Navigation.load url )

        UrlChanged _ ->
            ( model, Cmd.none )


view model =
    { title = ""
    , body = [ a [] [ text "click to reload" ] ]
    }


main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = UrlRequested
        , onUrlChange = UrlChanged
        }

My solution/workaround is to add a branch in update to do nothing on External "". For others coming across this looking for an easy fix, here's the fixed update function:

update msg model =
    case msg of
        UrlRequested (Browser.Internal _) ->
            ( model, Cmd.none )

        UrlRequested (Browser.External "") ->
            ( model, Cmd.none )

        UrlRequested (Browser.External url) ->
            ( model, Browser.Navigation.load url )

        UrlChanged _ ->
            ( model, Cmd.none )

Links with a download attribute don't work in an application because of preventDefault

The preventDefault on links in a Browser.application also blocks downloading when using the download attribute on a tags.
SSCCE:
Run this with elm reactor and click on the link. -> Nothing happens.
When changing this to use document instead of application everything works.

module Main exposing (main)

import Browser
import Html exposing (Html)
import Html.Attributes as Attr
import Url

type Msg
    = UrlRequest Browser.UrlRequest
    | UrlChange Url.Url

main : Platform.Program () {} Msg
main =
    Browser.application
        { init = \flags url key -> Tuple.pair {} Cmd.none
        , view =
            \_ ->
                { title = "Downoload SSCCE"
                , body = [ Html.a [ Attr.download "file", Attr.href "/Main.elm" ] [ Html.text "Download elm file" ] ]
                }
        , update = \_ model -> Tuple.pair model Cmd.none
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = UrlRequest
        , onUrlChange = UrlChange
        }

Browser.Dom.NotFound is not a function

Hi @evancz, I've found something that looks like mistake of generated JS code. I'm not sure that this module is right place where I should leave my issue, but I got the problem exactly with Browser.Dom.

The problem

Elm complier unbox things like type Height = Height Float to just be a float at runtime. Constructor of type just replaced with identity function under hood. In case with Browser.Dom.NotFound the initialisation of NotFound constructor is placed before initialisation of identity function, so elm$browser$Browser$Dom$NotFound goes to be undefined when it called.

Everything works good when elm$core$Basics$identity is moved to start of generated file.

Environment

  • macOS Hight Sierra (10.13.6)
  • Google Chrome (71.0.3578.98)
  • elm (0.19)
  • build must be run with --optimize flag

SSCCE

module Main exposing (main)

import Browser
import Browser.Dom
import Html exposing (text)
import Task


main : Program () () ()
main =
    Browser.element
        { init =
            \_ ->
                ( ()
                , Task.attempt (\_ -> ()) (Browser.Dom.focus "null_node")
                )
        , view = \_ -> text "Hello cruel world!"
        , update = \_ _ -> ( (), Cmd.none )
        , subscriptions = \_ -> Sub.none
        }

Way to `preventDefault` on `Browser.Events` needed

The issue
I am building an editor using Elm, so I am handling all sorts of keyboard input. I just learned that the subscriptions in Browser.Events unfortunately don't provide the possibilty to prevendDefault the browser behavior. This is unfortunate because sometime I need the tab key to do something different than switch to the next tabIndex element or intercept key strokes on inputs.
Possible workaround

  1. Using Html.Events on the outermost <div>. Unfortunately this won't work if the focus gets somehow changed to the body.
  2. Ports: Works but needs JavaScript code and makes one leave the safe Elm haven.

Error: Could not find any packages named elm/browser.

Hello, I can not install this package when run elm package install elm/browser

I got the message:

Error: Could not find any packages named elm/browser.

Here are some packages that have similar names:

    elm-lang/svg
    elm-lang/core
    elm-lang/dom
    elm-lang/mouse

Maybe you want one of those?

My elm-package.json is:

{
    "version": "1.0.0",
    "summary": "helpful summary of your project, less than 80 characters",
    "repository": "https://github.com/user/project.git",
    "license": "BSD3",
    "source-directories": [
        "."
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "5.1.1 <= v < 6.0.0",
        "elm-lang/html": "2.0.0 <= v < 3.0.0",
        "elm-lang/http": "1.0.0 <= v < 2.0.0"
    },
    "elm-version": "0.18.0 <= v < 0.19.0"
}

Please help me stupid.

Runtime error when using pushUrl with `--debug` flag on.

Compiling with the --debug flag makes this SSCCE crash with a runtime error when the button is clicked: key.a is not a function. There is no runtime error when --debug is ommitted

module Main exposing (..)

import Browser
import Browser.Events
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Events exposing (onClick)
import Json.Decode as JD
import Tuple exposing (pair)
import Url
import Url.Builder

main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = LinkClicked
        , onUrlChange = UrlChange
        }

type alias Model =
    { key : Nav.Key }

init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )

init env _ key =
    pair { key = key } Cmd.none

view : Model -> Browser.Document Msg

view model =
    { title = "My app"
    , body =
        [ Html.h2 [] [ text "Elm 19" ]
        , button [ onClick ButtonClick ]
            [ text "Click Me" ]
        ]
    }

type Msg = LinkClicked Browser.UrlRequest | UrlChange Url.Url | ButtonClick

update msg model =
    case msg of
        LinkClicked urlRequest ->
            case urlRequest of
                Browser.Internal url ->
                    ( model, Nav.pushUrl model.key (Url.toString url))
                Browser.External url ->
                    ( model, Nav.load url)
        UrlChange url ->
            pair model Cmd.none
        ButtonClick ->
            pair model <| Nav.pushUrl model.key (Url.Builder.absolute [ "hello" ] [])

Fragment links stop working in `--debug`

The following code works fine when compiled without --debug, but once it's compiled with --debug, clicking either of the links does nothing.

SSCCE

module Main exposing (main)

import Browser exposing (Document)
import Browser.Navigation as Nav
import Html exposing (a, li, text, ul)
import Html.Attributes exposing (href)
import Time
import Url exposing (Url)


type alias Model =
    { navKey : Nav.Key
    , url : Url
    }


init : () -> Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url navKey =
    ( { url = url, navKey = navKey }
    , Cmd.none
    )


view : Model -> Document Msg
view model =
    { title = "SSCCE"
    , body =
        [ text ("I think the current url is " ++ Url.toString model.url)
        , ul []
            [ li [] [ a [ href "#foo" ] [ text "#foo" ] ]
            , li [] [ a [ href "#bar" ] [ text "#bar" ] ]
            ]
        ]
    }


type Msg
    = LinkClicked Browser.UrlRequest
    | UrlChanged Url


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        LinkClicked (Browser.Internal url) ->
            ( model
            , Nav.pushUrl model.navKey (Url.toString url)
            )

        LinkClicked (Browser.External href) ->
            ( model
            , Nav.load href
            )

        UrlChanged url ->
            ( { model | url = url }, Cmd.none )


main : Program () Model Msg
main =
    Browser.application
        { init = init
        , onUrlChange = UrlChanged
        , onUrlRequest = LinkClicked
        , subscriptions = \_ -> Sub.none
        , update = update
        , view = view
        }

Svg.a and Svg.Attributes.xlinkHref bypass SPA features and cause a pageload

Hello,

I'm not this if this belongs here or in elm/svg, xlinkHref always causes a pageload when using a Browser.application, the following SSCCE showcases this issue:

module Main exposing (main)

import Browser
import Html exposing (Html)
import Html.Attributes
import Svg exposing (Svg)
import Svg.Attributes


view _ =
    { title = "test"
    , body =
        [ Html.a [ Html.Attributes.href "/ok" ] [ Html.text "OK" ]
        , Svg.svg []
            [ Svg.a [ Svg.Attributes.xlinkHref "/nok" ]
                [ Svg.text_ [ Svg.Attributes.y "100px" ]
                    [ Svg.text "NOK" ]
                ]
            ]
        ]
    }


main : Program () () ()
main =
    Browser.application
        { init = \_ _ _ -> ( (), Cmd.none )
        , view = view
        , update = \_ _ -> ( (), Cmd.none )
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = \_ -> ()
        , onUrlChange = \_ -> ()
        }

Thanks

Inconsistent cross browser result from Browser.Dom.getViewport

Safari and Chrome have a different scene.height if content is less than the browsers height

It looks like Safari takes the height of the rendered content if it's less.

SSCCEE

module Main exposing (main)

import Browser
import Browser.Dom
import Html exposing (..)
import Task


main : Program () (Maybe Browser.Dom.Viewport) Msg
main =
    Browser.document
        { init = \_ -> ( Nothing, Task.attempt GotViewport Browser.Dom.getViewport )
        , update = update
        , subscriptions = \_ -> Sub.none
        , view = \viewport -> { title = "", body = [ text (Debug.toString viewport) ] }
        }


type Msg
    = GotViewport (Result () Browser.Dom.Viewport)


update : Msg -> Maybe Browser.Dom.Viewport -> ( Maybe Browser.Dom.Viewport, Cmd Msg )
update msg viewport =
    case msg of
        GotViewport (Ok x) ->
            ( Just x, Cmd.none )

        GotViewport _ ->
            ( viewport, Cmd.none )

Safari:

{ scene = { width = 840, height = 34 }
, viewport = { x = 0, y = 0, width = 840, height = 480 }
}

Chrome:

{ scene = { width = 840, height = 480 }
, viewport = { x = 0, y = 0, width = 840, height = 480 }
}

Allow debugger to use iframe browsing-context

Allow an existing iframe with the attribute "name" being "elm-debugger" to be used as the browsing context for the debugger. This way, the application or page can choose to have the debugger integrated instead of having it outside in another window. Some of developers (me) are unable to focus well enough to not loose track of a debug window and it's associated page.

pull request with the proposed change:
#78

API feature request: expose HTMLElement.offsetTop

Rationale: given a bunch of elements in a container, it's a common use case to set the container's viewport so that a specific element is visible. In JavaScript, one can scroll an element to the top of its immediate parent quite tersely, taking advantage of HMLElement.offsetTop:

container.scrollTop = element.offsetTop;

The current Browser.Dom.getViewportOf exposes clientHeight and scrollTop, but no part of the API exposes offsetTop -- getElement only provides browser-scene relative values, so we have to do relatively bulky and fussy coordinate math to implement the same scroll in pure Elm.

README links are broken

staticPage — learn how to show things with elm-lang/html
sandbox — react to user input, like buttons and checkboxes
embed — talk to the outside world, like HTTP and JS interop
fullscreen — create single-page apps

^ These don't work. Are they supposed to be links?

Debugger tab is always shown on 0.19

When popup is shown, the debugger tab is

  • hidden on 0.18 (expected)
  • still shown on 0.19 (regression)

This makes debugging footer difficult😔

Proposal: Auto fix target _blank vulnerability

Since 0.19 Elm aims to mitigate some attack vectors which exist in HTML and JS. In that spirit, one good addition would be automatically adding rel="noopener" whenever the target attribute is set to a _blank value. This could be implemented within the Browser package or maybe even Html.

The vulnerabilty
Pages that have been opened via target="_blank" can control their opener via

var openerWindow = window.opener // do malicousStuff with the openerWindow

Some Browser such as Firefox even added that behavior of automatically adding rel="noopener" to their engines. https://www.ghacks.net/2018/11/30/firefox-security-relnoopener-for-target_blank/

Relevant links:

'a' tag with target="_blank" opens in the same tab under Browser.application

I have recently updated my app to Elm 0.19 & Browser.application and an a link with an external URL and target="_blank" no longer opens that URL in new tab. Instead it opens in the same tab.

I do not know how to work around this. I'm not sure what other information to include. I can attempt to put together an example if that would be useful.

Unable to preventDefault on 'a' tag in Browser.application

I've been struggling with using preventDefault to stop an a tag with href from navigating to that page. I would like to stop it and do a Browser.Navigation.replaceUrl instead in this one place.

Unfortunately due to this code in Browser and this code in virtual-dom we have very little control over the event that is driving the navigation. I can add preventDefault to my event listener but not to the core Elm one.

I'm not sure what the solution is but it seems like their needs to be client control over whether or not the default behaviour is executed and there doesn't seem to be at the moment.

Example

I have created a gist with the issue here: https://gist.github.com/michaeljones/0bb4ffabcdf97b3c757004449009ce43

Work around

Due to this line if we don't want the UrlRequest to come back into the application then we can add a target to the node and that should avoid that. I guess it doesn't matter what the target it is the intention is to suppress the behaviour but _self is the default value so that should cause the fewest issues.

Debugger overlay is appended to the first ancestor produced by Elm

The #elm-debugger-overlay is being appended to the main ancestor produced by Elm.

module Main exposing (main)

import Browser
import Html exposing (Html, text)

main : Program () () msg
main =
    Browser.sandbox
        { init = ()
        , view = always (text "Whoops")
        , update = \_ _ -> ()
        }

Compile with --debug flag, and you should see an "Uncaught DOMException" in the console.

This sometimes causes some children of the main ancestor to not be removed properly from the DOM (as seen here: https://gist.github.com/hecrj/0109624ded453bbedca03a733f1ba1e2).

Getting a Browser.Navigation.Key for testing

When using Browser.application I will put the Key in my model for later use.

When testing I want to create a model, but I don't have a way to get a Key. So we cannot test functions that take Model.

Seems that a function to get a Key is necessary to test.

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.