├── .gitignore ├── resources └── texture.png ├── elm-package.json ├── Stamps.elm ├── README.md └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff/ 2 | elm.js 3 | -------------------------------------------------------------------------------- /resources/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evancz/elm-html-and-js/HEAD/resources/texture.png -------------------------------------------------------------------------------- /elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "example project for embedding Elm in HTML plus JS interops", 4 | "repository": "https://github.com/evancz/elm-html-and-js.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "3.0.0 <= v < 4.0.0" 12 | }, 13 | "elm-version": "0.16.0 <= v < 0.17.0" 14 | } 15 | -------------------------------------------------------------------------------- /Stamps.elm: -------------------------------------------------------------------------------- 1 | module Stamps where 2 | 3 | import Color exposing (..) 4 | import Graphics.Collage exposing (..) 5 | import Graphics.Element exposing (..) 6 | import Mouse 7 | import Window 8 | 9 | 10 | -- Import reset events from JS 11 | port reset : Signal () 12 | 13 | 14 | -- Events can either be mouse clicks or reset events 15 | events : Signal (Maybe (Int,Int)) 16 | events = 17 | Signal.merge 18 | (Signal.map Just (Signal.sampleOn Mouse.clicks Mouse.position)) 19 | (Signal.map (always Nothing) reset) 20 | 21 | 22 | -- Keep a list of stamps, resetting when appropriate 23 | clickLocations : Signal (List (Int,Int)) 24 | clickLocations = 25 | let update event locations = 26 | case event of 27 | Just loc -> loc :: locations 28 | Nothing -> [] 29 | in 30 | Signal.foldp update [] events 31 | 32 | 33 | -- Show the stamp list on screen 34 | scene : (Int, Int) -> List (Int, Int) -> Element 35 | scene (w,h) locs = 36 | let drawPentagon (x,y) = 37 | ngon 5 20 38 | |> filled (hsla (toFloat x) 1 0.5 0.7) 39 | |> move (toFloat x - toFloat w / 2, toFloat h / 2 - toFloat y) 40 | |> rotate (toFloat x) 41 | in 42 | layers 43 | [ collage w h (List.map drawPentagon locs) 44 | , show "Click to stamp a pentagon." 45 | ] 46 | 47 | 48 | main = 49 | Signal.map2 scene Window.dimensions clickLocations 50 | 51 | -- Export the number of stamps 52 | port count : Signal Int 53 | port count = 54 | Signal.map List.length clickLocations 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTML/JS integration — [live demo](http://evancz.github.io/elm-html-and-js) 2 | 3 | This project illustrates how to embed an Elm program in an HTML 4 | page and how to communicate with JavaScript. 5 | 6 | ### Build Instructions 7 | 8 | git clone https://github.com/evancz/elm-html-and-js.git 9 | cd elm-html-and-js 10 | elm-make Stamps.elm --output elm.js 11 | open index.html 12 | 13 | ### Overview of API Usage 14 | 15 | If you create an Elm module named `Stamps`, it will be named 16 | `Elm.Stamps` in JavaScript. To instantiate a module you can 17 | use any of the following functions: 18 | 19 | ```javascript 20 | Elm.fullscreen(Elm.Stamps, {reset:[]}); // take over the whole page 21 | Elm.embed(Elm.Stamps, div, {reset:[]}); // embed in a specific DOM node 22 | Elm.worker(Elm.Stamps, {reset:[]}); // instantiate without graphics 23 | ``` 24 | 25 | Each of these creates a module instance that you can communicate 26 | with from JavaScript. 27 | 28 | ```javascript 29 | // Embed the Stamps module in a div with ID 'elm-stamps' 30 | var div = document.getElementById('elm-stamps'); 31 | var stamps = Elm.embed(Elm.Stamps, div, {reset:[]}); 32 | 33 | // You can send and receive values through 34 | // ports 'reset' and 'count'. 35 | stamps.ports.reset.send([]); 36 | stamps.ports.count.subscribe(function(event) { 37 | console.log(event.value); 38 | }); 39 | ``` 40 | Communication between Elm and JavaScript happens by sending events 41 | through ports, like `reset` and `count`. Elm interprets 42 | these ports as signals and JavaScript interprets them as event streams. 43 | In Elm, you declare ports like this: 44 | 45 | ```haskell 46 | -- incoming reset events 47 | port reset : Signal () 48 | 49 | -- outgoing count of stamps 50 | port count : Signal Int 51 | port count = length <~ stamps 52 | ``` 53 | 54 | Values passed along named channels must conform to [these 55 | rules](http://elm-lang.org/learn/Ports.elm#customs-and-border-protection). 56 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |This demo shows how to:
33 |The white square is an Elm program, but the rest is HTML, CSS, and JS. 38 | See the source code 39 | for more info. 40 |
41 | 42 | 43 | 44 |There are currently 0 stamps. 45 | 46 |
47 |You have created 0 stamps in total.
48 |