elm / browser Goto Github PK
View Code? Open in Web Editor NEWCreate Elm programs that run in browsers!
Home Page: https://package.elm-lang.org/packages/elm/browser/latest/
License: BSD 3-Clause "New" or "Revised" License
Create Elm programs that run in browsers!
Home Page: https://package.elm-lang.org/packages/elm/browser/latest/
License: BSD 3-Clause "New" or "Revised" License
Hi!
Just want to point out that links to:
in README don't work.
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:
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.
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
HI
I tried use the note Url in Elements but I found some problem at subscriptions.
I think the code is missing the function composition.
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.
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:
<use>
tagThe 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?
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?
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" ] [])
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
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.
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#getViewportOf
The whole bunch of MDN links is now broken. Looks like the Element in the URL changed to HTMLElement.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight (this works)
Beyond the freeze in the main view as mentioned in #16, I can't seem to click anything when accessing the debugger:
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
According to the documentation, Browser.Dom.getElement
should return the scene, viewport, and element of the target, specified by the id
argument, as getViewportOf
does. It is, however, returning the scene and element of the document, as getViewport
does. [1]
Is this intentional, or just a copy-paste error?
[1] https://github.com/elm/browser/blob/master/src/Elm/Kernel/Browser.js#L407
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.
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 "+" ]
]
index.html
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:
here is the broken link:
browser/src/Browser/Events.elm
Line 199 in c147521
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:
#myAnchor
or /samePage#myAnchor
/newPageAnchor#anchorOnDifferentPage
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.
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);
});
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.
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 }
}
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?
An example of it not working at all.
https://ellie-app.com/37Z8hxpgpK4a1
It looks like the cause is
browser/src/Browser/Events.elm
Line 206 in c7f8086
info.changes
but visibilityInfo
in browser/src/Elm/Kernel/Browser.js
Line 242 in c7f8086
change
The following code works fine when compiled without --debug
, but once it's compiled with --debug
, clicking either of the links does nothing.
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
}
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Events
"Check out how that works in this example." links to https://github.com/elm/browser/blob/1.0.0/examples/wasd.md which no longer exists
See https://github.com/elm/browser/blob/1.0.1/src/Browser/Events.elm#L94
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
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.
Empty links, i.e. a
elements without a href
attribute or with href ""
will cause External
UrlRequest
s 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:
href
is omitted it should not be considered a hyperlink (source)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 )
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.
Not every application takes control of whole domain. If application lives e.g. under path https://example.com/myapp
then URL https://example.com/otherapp
needs to be considered to be an external url.
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
.
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.
--optimize
flagmodule 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
}
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.
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
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
}
As it just came up in Slack: onResize
does have a link pointing to TODO
which obviously does not work.
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.
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.
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Events#onVisibilityChange
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Events#onKeyDown
Example links result in a 404
https://github.com/elm/browser/blob/1.0.0/examples/wasd.md
should be
https://github.com/elm/browser/blob/master/examples/wasd.elm
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?
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).
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.
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.
When compiled with --debug
, the preventDefault on a
tags is not working in application
s, 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
When popup is shown, the debugger tab is
This makes debugging footer difficult😔
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.
I have created a gist with the issue here: https://gist.github.com/michaeljones/0bb4ffabcdf97b3c757004449009ce43
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.
https://github.com/elm/browser/blob/1.0.1/examples/drag.elm
This seems to be no valid elm 0.19 code, see the type definition for Model
https://github.com/elm/browser/blob/1.0.0/notes/keyboard.md
doesn't provide enough information
Congratulations for the 0.19 release!
I've been really exited about this release and one of the features I was waiting is the SSR support (It was mentioned in the roadmap), but I don't see any config or example about it, just this piece of code https://github.com/elm/browser/blob/master/src/Elm/Kernel/Browser.server.js , was SSR not implemented at the end?
Thank you
The Elm 0.19 time-traveling debugger cannot be expanded if the browser blocks popups. It throws errors due to an unhandled null. The same configuration works on Elm 0.18, so this appears to be a regression.
SSCCE: https://gist.github.com/klazuka/b824de5cf1551c1f567c627daa126f81
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
Html.Events
on the outermost <div>
. Unfortunately this won't work if the focus gets somehow changed to the body.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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.