elm / core Goto Github PK
View Code? Open in Web Editor NEWElm's core libraries
Home Page: http://package.elm-lang.org/packages/elm/core/latest
License: BSD 3-Clause "New" or "Revised" License
Elm's core libraries
Home Page: http://package.elm-lang.org/packages/elm/core/latest
License: BSD 3-Clause "New" or "Revised" License
Not sure if this is a compiler or core library issue or programming error, I haven't identified the cause yet, but it seems like it shouldn't happen due to programming error. Also I have a hard time finding a good description, but when running the example code (a simple slide-like presentation) below, this is what I observe:
image
is followed by a fittedImage
, when both are regular or fitted image, they show up as expectedAlso worth noting: This setup somehow breaks hot reloading in elm-reactor. When changing something, often I have to manually reload for everthing to work.
(using Elm platform 0.16)
module Bugs where
import List exposing ((::), foldr, length, drop, head)
import Signal exposing (Signal, constant, foldp, map2)
import Graphics.Element exposing (..)
import Keyboard
import Debug
import Text exposing (fromString)
slides = [
constant <| centered <| fromString "use arrow keys to go forward/backward",
constant <| fittedImage 100 500 "https://raw.githubusercontent.com/elm-lang/elm-lang.org/master/resources/imgs/shells.jpg",
constant <| image 700 500 "https://raw.githubusercontent.com/elm-lang/elm-lang.org/master/resources/imgs/book.jpg",
constant <| centered <| fromString "go back and it will be a book instead of shells"
]
lastSlide = length slides - 1
updateSlide {x,y} current =
let nextSlide = case x of
-1 -> current - 1
1 -> current + 1
_ -> current
in clamp 0 lastSlide nextSlide
chooseSlide page = drop page >> head
safeSlide e = case e of
Just elem -> elem
Nothing -> centered <| fromString "โฆ"
-- signals
currentSlide = foldp updateSlide 0 Keyboard.arrows
main =
let maybeSlides = applyMany (Signal.map chooseSlide currentSlide) slides
in Signal.map safeSlide maybeSlides
-- debug
slideWatch = Signal.map (Debug.watch "slide") currentSlide
-- taken from elm-signal-extra
combine : List (Signal a) -> Signal (List a)
combine = foldr (map2 (::)) (constant [])
andMap : Signal (a -> b) -> Signal a -> Signal b
andMap = map2 (<|)
applyMany : Signal (List a -> b) -> List (Signal a) -> Signal b
applyMany fs l = andMap fs (combine l)
Graphics.Input.dropDown
only takes a handler function and a list of options to render a drop-down list. However, this provides no way to set the drop-down's current selection. In particular, the selection can update a signal but a new signal cannot update the selection (and trigger a re-render). This is in contrast with other inputs: checkbox
takes a Bool
parameter for the current check state, and field
takes a Content
parameter for the current text and selection.
I'd like to see dropDown
's signature being changed to something along the lines of:
dropDown : (a -> Signal.Message) -> List (String, a) -> a -> Element
where the third parameter is the selected option (which should also be present in the list of options). That way, one can for example map
over the signal (obtained with Channel.subscribe
) and provide the current value of the signal to use for the drop-down's selection. To use the same example as in the documentation:
type Sport = Football | Cricket | Snooker
sport : Signal.Channel (Maybe Sport)
sport = Signal.channel Nothing
sportDropDown : (Maybe Sport) -> Element
sportDropDown currentSport =
dropDown (Signal.send sport)
[ ("" , Nothing)
, ("Football", Just Football)
, ("Cricket" , Just Cricket)
, ("Snooker" , Just Snooker)
] currentSport
main = map sportDropDown (Signal.subscribe sport)
I've been investigating the loading for our elm widgets...
It appears to me that when several widgets are instantiated (embedded), repeated calls to make
for a large module is very slow. In particular, Bootstrap.Html.make()
takes a large amount of time:
One way of testing this quickly is as follows:
for (var i = 0; i < 100; ++i) {
Elm.Bootstrap.Html.make({});
}
The above takes 12.68s on my laptop.
One quick solution might be to memoize the make
function. The generated function currently looks like this...
Elm.Bootstrap.Html.make = function (_elm) { ... }
...I'm not 100% sure if it would be necessary to memoize the function based on the incoming _elm
environment, but it seems like that shouldn't be necessary. One edge case is if someone is uses different versions of the same package for different embedded widgets.
File
module Main where
import Json.Encode as Json
import Signal
import Text (..)
import Time (..)
port out : Signal Json.Value
port out = Signal.sampleOn (every second) (Signal.constant (Json.object []) )
main = plainText "test"
Compile this to a file main.js
and then open this html file:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="main.js"></script>
</head>
<body>
<h1>Test</h1>
<div id="bug"></div>
<script type="text/javascript">
var handler = function(o) { console.log(o) };
var div = document.getElementById('bug');
var test = Elm.embed(Elm.Main, div, { });
test.ports.out.subscribe(handler);
</script>
</body>
</html>
and get the error:
Initialization Error on port 'out':
$Native$Json is not defined
Mouse.y is Mouse.x
ahare-elm
http://share-elm.com/sprout/549f281de4b05f9c59b24872
Minimum example:
import Graphics.Element as E
import Graphics.Input as Input
import Signal as S
chan = S.channel False
main = E.spacer 100 200 |> Input.hoverable (S.send chan)
Produces:
Cannot read property 'make' of undefined
Open the developer console for more details.
It seems to error on var Text = Elm.Native.Text.make(localRuntime);
because Elm.Native.Text
is undefined. Seems like a dependency ordering issue.
From the mailing list:
Right now, the way Http.send works, the Waiting state only occurs for the first request. If the URL changes thereafter, it will maintain the previous Response until the new response comes in. I can see why that would be a useful behavior to have, especially if you hook up your output/views directly to the response signal.
In more stateful applications however, it would be useful to have a different Http.send (not sure what I would name it) which, when the URL changes, will revert to the Waiting state while waiting for the new response to come in. This would allow someone to have a loading animation be displayed whenever requests to the server are happening, so the user is aware that something is being waited on. In this style, if the programmer wants to display the old results while the new results are fetching, he can do that by storing results in his/her application state.
Jeff Smits added that under this new behavior, "you can do a dropIf ((==) Waiting) Waiting to get the old heaviour back." Whereas you cannot derive this new behavior from the old behavior.
Just wanted to put this suggestion out there for the next revision of Http. The change itself is just a single line swap in Native/Http.js
Using containers within a signal causes a runtime error.
I left a comment on the line number here: elm-lang@f465e11#diff-f950e770ebd4e2af43b262f28253b3a1R375
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.arc
Currently, circles are rendered as a 50-gon, which is (just barely) perceptibly pointy.
The initial value of Mouse.position is (0, 0) regardless of the actual position of the mouse until it is moved. Example to reproduce: http://share-elm.com/sprout/54b129a6e4b05f9c59b24f3a
Elm version: 0.14.1
I found an interesting issue when converting between Char
s and KeyCodes
. Most of the credit goes to @Apanatshka for actually isolating the problem!
Example: http://share-elm.com/sprout/54a2d81de4b05f9c59b24a15
Original discussion that led to the discovery: https://groups.google.com/forum/#!topic/elm-discuss/VVKkA0TvFUE
The following code fails to terminate.
import Regex
x : List Regex.Match
x = Regex.find Regex.All (Regex.regex ".*") ""
This issue is part of trying to make animations run more smoothly in Firefox.
Currently, on each draw of a collage, the following is executed:
function nextContext(transforms) {
while (i < kids.length) {
var node = kids[i];
if (node.getContext) {
node.width = w;
node.height = h;
node.style.width = w + 'px';
node.style.height = h + 'px';
++i;
return transform(transforms, node.getContext('2d'));
}
div.removeChild(node);
}
var canvas = makeCanvas(w,h);
div.appendChild(canvas);
// we have added a new node, so we must step our position
++i;
return transform(transforms, canvas.getContext('2d'));
}
Resetting the canvas node's height and width serves two purposes:
Unfortunately, it appears that resetting the canvas this way also produces a canvas-sized amount of garbage on every frame in Firefox.
Clearing the canvas can also be accomplished by calling ctx.clearRect(0, 0, w, h)
. However, this does not reset the transforms. Transforms can be reset through disciplined use of ctx.save()
and ctx.restore()
, but there are currently saves that are never restored:
function transform(transforms, ctx) {
ctx.translate(w/2, h/2);
ctx.scale(1,-1);
var len = transforms.length;
for (var i = 0; i < len; ++i) {
var m = transforms[i];
ctx.save();
ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
}
return ctx;
}
There are two problems here:
translate
and scale
in the first two lines of this functionsave
inside the for loop is not matched anywhere by a corresponding restore
.I think there is a potentially large win to be had by using transforms in a more disciplined way so that it is possible to avoid resetting the canvas width and height on every draw if they have not changed.
Hi,
Textured shapes consume way too much CPU, see this issue:
elm/elm-lang.org#186
(below my original comment)
Hitting this as well with Elm 0.14 on Tacks. Here are Chrome CPU profiling screenshots:
Hello,
Just started playing around with Elm and am finding it very impressive! Keep up the great work.
I noticed that in certain cases attempting to position an element in the middle of another element results in a layout that is off by a single pixel. I believe this is because line 241 and 236 in the source javascript are using the bitwise or
to round towards a single pixel instead of something like Math.round()
.
For a reproduction see this example which should draw a red rectangle with a single pixel border all the way around, but instead draws it with a 2px border at the top and left only.
import Graphics.Element (..)
import Color (red, blue)
main = spacer 99 19
|> color red
|> container 101 21 middle
|> color blue
On an unrelated note, I noticed P, Z, and N seem to refer to different methods of setting an axis origin for positioning. This terminology is unfamiliar to me and I would be interested to know what it refers to.
The offending line is line 20 of /src/Native/Char.js
toCode : function(c) { return c.toUpperCase().charCodeAt(0); },
Or am I missing something?
https://github.com/elm-lang/core/blob/master/src/Char.elm#L85
I was trying to use this with fpsWhen
but a runtime error now occurs.
I have an experimental branch I've been playing with. After the discussion in #152, I've been trying to come up with an elegant and performant way of expressing loops. The concept that I kept coming back to is generators. You can see how they are implemented, and also how list functions can be implemented in terms of them. Note that I was able to remove several native List functions in favor of just the 3 in Native.Generator. It should be possible to do the same with loops in other native modules, e.g. Native.Regex.
So how do they perform? Good, although not as good as I would like. From preliminary testing, the biggest slowdown seems to be allocation / garbage collection of Maybe
objects. The good news is that if we implement Maybe
elision (i.e. Just x
=> x
and Nothing
to null
in JavaScript) in the compiler, Generators should perform extremely close to their non-abstracted counterparts. (Other code will get faster too, of course.)
Below are some benchmark numbers (time in seconds; lower is better). All benchmarking was done on an old laptop to magnify performance gaps. With the exception of the last column, all benchmarks were done over a 500,000 element list. For the last column (foldl
/100), I instead ran the test over 100 5,000 element lists. All higher-order functions (e.g. the f
for map
or the reduce for foldl
) were as simple and dumb as possible to put emphasis on the speed of iteration.
branch | map |
take |
filterMap |
repeat |
---|---|---|---|---|
master | 4.15 | 4.05 | 4.20 | 1.25 |
generators | 4.05 | 3.90 | 4.00 | 1.25 |
branch | any |
foldl |
foldr |
drop |
foldl /100 |
---|---|---|---|---|---|
master | 1.05 | 1.05 | 1.10 | 1.0 | 0.95 |
generators | 1.25 | 1.20 | 1.25 | 1.15 | 1.05 |
The takeaways, in my opinion, are:
Maybe
elision as a compiler optimization, making the wins greater and virtually eliminating the losses.Could we have a function in the Collage or Text package that allows rendering of text to the 2D canvas?
eg: (if in the Collage library)
fromText : Text -> Shape
fromTextWithMaxWidth : Text -> Float -> Shape
I know it's possible to convert the text first to an Element, then to a Form, which overlays a span on the canvas. However this doesn't support text stroke styles, and scaling can be wonky. I'd also like this so we can have text in WebGL (once we've added a function to elm-gl to convert a collage to a webgl texture).
Am happy to have a stab at doing a pull request for this if folks think it's a good idea?
I think that the Transform2D
type is a bit too abstract. I'm currently trying to debug something involving them and it's impossible to actually inspect them. The module itself provides no way to define functions out of the type, and it seems the only place Transform2D
s can be used is in Graphics.Collage.groupTransform
. Such a library is of general use, i.e., not only with forms, and I think some version of the following functions would be quite reasonable to add:
apply : Transform2D -> (Float, Float) -> (Float, Float)
type alias TransformView =
{ matrix : (Float, Float, Float, Float)
, translation : (Float, Float)
}
view : Transform2D -> TransformView
In fact these two functions are interderivable (up to floating point errors), so just one would be enough if you're all feeling spartan.
So, in jvoigtlaender@274cd7e I had been trying (as part of the effort to make timestamp
work in a consistent manner over all signals) to refactor fpsWhen
while preserving its semantics. I failed in that, which luckily was caught by @jwmerrill, and fixed in elm-lang@6a36cd7. Throughout all this, I hadn't been checking what the semantics of fpsWhen
was exactly, only trying to preserve it. Have now looked into the semantics of fpsWhen
and found serious problems, I think.
Let's consider a signal isOn
with the following behavior:
False
True
eventFalse
eventTrue
eventFalse
eventFor example,
isOn = flip member [1,7] <~ keepIf (flip member [1,4,7,8]) 0 (foldp (\_ c -> c+1) 0 (every 500))
Let's now consider the signal obtained by fpsWhen 1 isOn
. Surprisingly, it shows the following behavior (since at least Elm-0.13):
One way to check these claims is to run
main = asText << snd <~ foldp (\(t',d) (t,l) -> (t',(t'-t,d)::l)) (0,[]) (timestamp (fpsWhen 1 isOn))
(for example with different language versions at http://share-elm.com)
Many of the values we see appearing are dubious (for example, isOn
was True
only for 2 seconds overall, and yet we see three time deltas of 1 second each). Also, the events at 2.5 and 4.5 seconds shouldn't be happening at all. It turns out that the clearTimeout
in the implementation of fpsWhen
has no effect whatsoever. PR https://github.com/elm-lang/core/pull/138 fixes that specific "bogus events" aspect. However, even after that fix, the semantics of fpsWhen
is still off. For the above situation it now behaves as follows:
Now the bogus events at 2.5 and 4.5 seconds are gone, but all other events show value 0, even though the isOn
signal has been True
for 2 seconds, of which 1.5 seconds were consecutively, so certainly should have shown some non-0 time value passing, given that our granularity was "1 frame per second".
First applying a style seems to make it impossible to then use Text.color
.
http://share-elm.com/sprout/56506538e4b05f0d6cc4a102
import Graphics.Element (..)
import Graphics.Collage (..)
import Text (..)
import Text
import Color (..)
redText : String -> Text
redText str =
Text.color red (fromString str)
redText' : String -> Text
redText' str =
Text.color red (style defaultStyle (fromString str))
main : Element
main = flow down
[ leftAligned <| redText "Hello, World!"
, leftAligned <| redText' "Hello, World!"
]
Issue for discussion thread https://groups.google.com/d/topic/elm-discuss/7Uwl5-usqjs/discussion
Basically, JavaScript's RegExp
(which is what Elm's Regex
sits on top of) can throw an exception when given an invalid string. Examples:
RegExp("a"); // OK
RegExp("\\"); // Exception!
RegExp("("); // Exception!
RegExp("(?"); // Exception!
RegExp("(?:"); // Exception!
RegExp("?"); // Exception!
RegExp("+"); // Exception!
RegExp("*"); // Exception!
The obvious fix is to make Elm's Regex.regex
return a Result
(or a Maybe
), but that seems like a pain to work with. It's also an API-breaking change, which I have no problems with whatsoever, but others might.
The only other solution I can think of is to escape characters at the end of an input string until no exception is thrown. For example:
RegExp("(?:"); // Exception!
RegExp("(?\\:"); // Exception!
RegExp("(\\?\\:"); // Exception!
RegExp("\\(\\?\\:"); // OK
It's a bit hacky though, and may not follow the principle of least surprise. Thoughts?
The Mouse
module has isDown
and clicks
. The Keyboard
module only has isDown
. I would like a function keypresses : KeyCode -> Signal ()
, analogous to Mouse.clicks
.
I've implemented it like this, but there's probably a better way, and it would be nice if this functionality were in core:
keypresses : KeyCode -> Signal ()
keypresses c = isDown c |> keepIf identity False |> map (always ())
I've defined concat as
concat = A.foldl (\x acc -> log "step" <| x `A.append` acc) A.empty
Using this,
concat << A.repeat 4 <| A.repeat 4 ()
produces
step: Array.fromList [(),(),(),()]
step: Array.fromList [(),(),(),(),(),(),(),()]
step: Array.fromList [(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()]
step: Array.fromList [(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()]
Array.fromList [(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()]
: Array.Array ()
as expected.
concat << A.repeat 4 <| A.repeat 5 ()
produces
step: Array.fromList [(),(),(),(),()]
step: Array.fromList [(),(),(),(),(),(),(),(),(),()]
step: Array.fromList [(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()]
TypeError: Cannot read property 'length' of undefined
The line producing the error is https://github.com/elm-lang/core/blob/master/src/Native/Array.js#L477
With the ongoing work on Http
, I'd like to bravely throw in a feature request for CORS support :)
The protocol for CORS is actually somewhat involved, particularly since it involves a preflight OPTIONS
request which I believe needs to be resent after a timeout period. I think this is usually invisible to the user of most API's, it seems as though things can get tricky.
Using AngularJS's $httpProvider and Restangular, this looks like the following:
$httpProvider.defaults.useXDomain = true
Restangular.setDefaultHttpFields {withCredentials: true}
Restangular.setDefaultHeaders {"Content-Type": "application/json"} # X-Requested-With header can't be used with CORS
While non-CORS restangular requests simply look like
Restangular.setDefaultHeaders
{ "Content-Type": "application/json",
, "X-Requested-With": "XMLHttpRequest"
}
I think swapping the argument to request in the new API might also be handy.
request : String -> String -> String -> List (String, String) -> Request String
Since request is an elaborated version of get
/put
/post
/delete
it seems as though the primary use case is going to be adjusting the headers...
For example, for a regular ajax request, get
might look like
get = Http.request
[ "Content-Type": "application/json",
, "X-Requested-With": "XMLHttpRequest"
]
"GET"
while a CORS ajax request looks somewhat different
corsGet = Http.request
[ "Content-Type": "application/json",
, -- ... ?
]
"GET" -- "OPTIONS" ?
I just happened upon the following extremely confusing behavior. Consider the following program:
module Bad where
import Keyboard
import Time
import Text
import Signal
type Update
= Key {x : Int, y : Int}
| Tick Time.Time
updates =
let time = Time.every 30 in
Signal.mergeMany
[ Signal.map Key (Signal.sampleOn time Keyboard.arrows)
, Signal.map Tick time
]
update u s = case u of
Key arr -> {s | x <- s.x + arr.x, y <- s.y + arr.y}
Tick t -> {s | time <- t}
main =
Signal.foldp update {x=0,y=0,time=0} updates
|> Signal.map (Text.plainText << toString)
If you try running it, you'll notice that the time
field never changes! Somehow those updates aren't making it to the merged signal. Replacing on of the instances of time
with a "new" Time.every 30
makes things work as expected.
The recent discussion on #118 by @jazmit got me thinking...
Shape
currently means "polygon" in Elm (a list of points). I would like to propose that it would make sense to move towards an abstract representation to shapes that makes a distinction between BasicForm
, Shape
and Polygon
.
The invariant that qualifies something to be a Shape
would be the function...
type alias LevelOfDetail = Float
tesselate : LevelOfDetail -> Shape -> Polygon
...so that something like Text
is excluded.
There are a couple of nice attractions:
Circle
to SVG: it will be much cleaner if the algebraic representation is preserved. One could even render shapes relatively cleanly to Html
using stylesheets. There's also a chance render quality could be improved - for example, it might make sense for a renderer to implement specialized anti-aliasing for curves and circles.arc
uses an adaptive tessellation that could take any number of interesting things into account to improve quality and performance. Another example would be a WebGL renderer, rendering circles and curves with shaders.Much of the above probably requires Shape
constructors to be exposed, which I think might be a tad premature. Never-the-less, performance might be something worth looking into sooner. Myself and @TheunisKotze are about to do some testing to see what effect this has on us - we draw a helluvalot of circles. I'll report back!
A.foldr (::) [] <| A.fromList [1 .. 32]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]
A.foldr (::) [] <| A.fromList [1 .. 33]
[32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,33]
A.foldr A.push A.empty <| A.fromList [1 .. 32]
Array.fromList [32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]
A.foldr A.push A.empty <| A.fromList [1 .. 33]
Array.fromList [33,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]
On http://elm-lang.org/blog/Interactive-Programming.elm, it is said: "The hot-swapper can also check to see if the types of the old state matches the types of the new state, ruling out a whole class of hot-swapping-induced runtime errors."
However, that checking is not currently done by the hot-swapper.
Is there a compelling reason for (%) to have the current restricted type Int -> Int -> Int
? Javascript (%) works as expected for non-integers and I often actually need this operation.
All the Travis tests are failing right now because Elm-Test relies on the List function maximum : List comparable -> comparable
function, which has now changed to maximum : List comparable -> Maybe comparable
.
It's pretty easy to fix this with a new version of Elm-Test, but I want to set the correct version bounds, so when all this new core stuff is released it won't mess people up if they're still using core-1.x.x
The comment in the source says
{-| The current state of the left mouse-button.
True when the button is down, and false otherwise. -}
But in reality it is ANY mouse button. This leads to misbehaviour as described in issue elm/elm-lang.org#184. jQuery's docs say:
The mousedown event is sent when any mouse button is clicked. To act only on specific
buttons, we can use the event object's which property. Not all browsers support this property
(Internet Explorer uses button instead), but jQuery normalizes the property so that it is safe
to use in any browser. The value of which will be 1 for the left button, 2 for the middle button,
or 3 for the right button.
Initially, the page loads fine. however, upon clicking the rerendering only the second number is rerendered correctly. The console gives the following error message: Uncaught TypeError: Cannot read property 'style' of undefined
module Bug where
import Text (asText)
import Graphics.Element (..)
import Signal (Signal, foldp, (<~))
import Mouse
display : (Int, Int) -> Element
display (f, s) =
-- No problem with flow down
--flow down [ asText f, asText s ]
-- However, it fails with flow right
flow right [ asText f, asText s ]
-- Each time someone clicks, roll the dice.
handleClick : () -> (Int, Int) -> (Int, Int)
handleClick _ (f, s) = (f + 1, s + 1)
-- Basic wiring
main : Signal Element
main = display <~ (foldp handleClick (0, 0) Mouse.clicks)
I was pondering how to add tests for Collage
, and came up with the idea of using node-canvas to render a data-url and comparing it to a known url.
This would add another test dependency to core, but would add some comfort in making changes to the Native modules.
Perhaps in future it could be combined with a tool to compare the expected DOM output using js-dom or similar and become a general purpose regression testing tool for Elm.
Is this desirable or should we avoid adding extra dependencies to Core?
Currently if you try to embed Elm on a div with children it fails with:
Error: Elm.node must be given an empty DIV. No children allowed!
However there is a valid use case when this should be allowed. I am porting a mobile web app from React, which needs to start up as quickly as possible. My React version did something like this:
<div id='react_container'>
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
</div>
<script src="myapp.js"></script>
<script>
React.renderComponent(MyApp(), document.getElementById('react_container'));
</script>
The spinner div has some CSS animation applied to it, and starts animating immediately while the scripts are loading. Once React has booted up, the first render will replace the children (including spinner) with the real app (or with the same spinner div if the app is still waiting for data). This is a very useful way to lower the perceived loading time.
The issue at elm-compiler#878 mentions it, but it's in the wrong repo, so I'm recreating it here.
LHS arguments greater than LONG_MAX
(4294967295
) return a negative number when using integer division (//
).
main = asText (4294967295 // 2)
-- shows 2147483647
main = asText (4294967296 // 2)
-- shows -2147483648
This is because elm-core's src/Native/Basics.js
div
function is a/b|0
, thus using JavaScript's OR operator, which most converts the LHS to a 32-bit integer and returns a 32-bit integer.
EDIT: I read the JS spec, it's not a bug with JS, just another one of its problems.
It seems a bit arbitrary that Form
s have separate fields for theta
, x
, y
, and scale
given that they could be wrapped in a group with an appropriate Transform2D
(I assume this is an optimization to avoid additional levels of indirection). Canvas supports scaling different amounts in the X and Y directions. Should forms have separate scaleX
and scaleY
fields? Should they just have one field which is a Transform2D
?
The new 0.14 documentation system broke the links to other library elements, e.g. the URL in https://github.com/elm-lang/core/blob/master/src/Graphics/Collage.elm#L132 resolves to the non-existing http://package.elm-lang.org/library/Color.elm#linear.
The program
main = layers []
...produces an exception...
Function 'foldl1' expects a non-empty list!
...due to the two calls to List.maximum
over here: https://github.com/elm-lang/core/blob/53aef4887e668a5732ffff1ad0560bab779e8674/src/Graphics/Element.elm#L330
See here: http://package.elm-lang.org/packages/elm-lang/core/1.0.0/Json-Encode
It says "There is some problem with the docs for 'toString', please inform the package author."
The initial value in a Channel
doesn't appear in a foldp over the channel converted to a Signal.
type Action = Init
| ...
actions : Signal.Channel Action
actions = Signal.channel Init
update : Action -> Model -> Model
update action state =
case Debug.log "action" <| action of -- Debug.log never prints "action: Init"
Init -> ...
model : Model -> Signal Action -> Signal Model
model initialState action =
Signal.foldp update initialState action -- Seems like the initialState here should be
-- combined with the initial action, either
-- to create the first value or to create the
-- first two values in the signal
main = run emptyModel (Signal.subscribe actions)
Initializing a signal with a good initialState
is not always easy because initialization may depend on a signal coming in from a port in which case you need to do something like this:
port userId : Signal Int
main = run emptyModel (Signal.zip (Signal.subscribe actions) userId)
...in this case creating an initial model based on the incoming userId
seems near impossible unless some event can be triggered (perhaps by explicitly calling send
on the userId
port after the widget has been initialized in order to force an update).
This might assist with issues like this one as well: https://github.com/elm-lang/core/issues/91. I'm not taking the work on promises into account, I don't know if this may be handled already in the upcoming implementation.
Take a look at https://github.com/rtfeldman/dreamwriter/blob/75651371541a88a1d85504e70c7e41afd914eaae/Dreamwriter/Model.elm
Notice that emptyState
at the bottom awkwardly has an extra level of indentation compared to the type alias
above. It turns out this extra indentation is currently mandatory for record assignment.
If you attempt to do the "commas at the end of the line" style like this, the parser will let you do indentation "normally" in the case of type alias
(as you can see earlier in the file), but if you try to use this style with record assignment (as with emptyState
) and use "normal" indentation instead of awkward extra indentation, you get the following syntax error:
>> Error when compiling Dreamwriter.Model:
>>
>> Parse error at (line 41, column 1):
>> unexpected "}"
>> expecting a newline or whitespace
Warning: Error when compiling Dreamwriter.Model:
Parse error at (line 41, column 1):
unexpected "}"
expecting a newline or whitespace
In this example, typing in the input field causes it to immediately lose focus.
The issue is apparently that whenever the number of elements in a flow changes, all the elements in the flow are re-rendered. Re-rendering an input causes it to lose focus.
Avoiding re-rendering input fields unnecessarily would mean this bug would manifest less often, but the robust solution is to make sure that re-rendering restores focus.
Some discussion and a work around for this particular case here:
https://groups.google.com/forum/#!topic/elm-discuss/RzGDnQKh5eg
It would be great if forms could be masked with shapes, as discussed here: https://groups.google.com/d/topic/elm-discuss/WAd_Qy5xE94/discussion
Use cases include e.g. Google+-style icons, or together with transitions, even various wipes (e.g. cartoon-style circular).
The filter function for Array seems to be in the Array library but does not appear in the docs
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.