├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bower.json ├── html ├── .gitignore └── index.html ├── package.json ├── psc-package.json ├── src ├── JQuery.js └── JQuery.purs └── test └── Main.purs /.gitignore: -------------------------------------------------------------------------------- 1 | /.* 2 | !/.gitignore 3 | !/.github 4 | !/.travis.yml 5 | 6 | # Dependencies 7 | bower_components 8 | node_modules 9 | 10 | # Generated files 11 | output 12 | generated-docs 13 | 14 | # Lockfiles 15 | package-lock.json 16 | *.lock 17 | 18 | # Extra files 19 | tmp 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | dist: trusty 3 | sudo: required 4 | node_js: stable 5 | env: 6 | - PATH=$HOME/purescript:$PATH 7 | install: 8 | - TAG=$(basename $(curl --location --silent --output /dev/null -w %{url_effective} https://github.com/purescript/purescript/releases/latest)) 9 | - curl --location --output $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz 10 | - tar -xvf $HOME/purescript.tar.gz -C $HOME/ 11 | - chmod a+x $HOME/purescript 12 | - npm install -g bower 13 | - npm install 14 | - bower install --production 15 | script: 16 | - npm run -s build 17 | - bower install 18 | - npm run -s test 19 | after_success: 20 | - >- 21 | test $TRAVIS_TAG && 22 | echo $GITHUB_TOKEN | pulp login && 23 | echo y | pulp publish --no-push 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 PureScript 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # purescript-jquery 2 | 3 | [![Latest release](http://img.shields.io/bower/v/purescript-jquery.svg)](https://github.com/purescript-contrib/purescript-jquery/releases) 4 | [![Maintainer: paf31](https://img.shields.io/badge/maintainer-paf31-lightgrey.svg)](http://github.com/paf31) 5 | 6 | PureScript type declarations for jQuery. See [module documentation on Pursuit](https://pursuit.purescript.org/packages/purescript-jquery). 7 | 8 | ## Example 9 | 10 | ```purs 11 | main = ready do 12 | -- Get the document body 13 | body <- body 14 | 15 | -- Create a text box 16 | div <- create "
" 17 | input <- create "" 18 | appendText "Your Name: " div 19 | append input div 20 | append div body 21 | 22 | -- Create a paragraph to display a greeting 23 | greeting <- create "

" 24 | css { color: "red" } greeting 25 | append greeting body 26 | 27 | -- Listen for change events on the text box 28 | on "change" (handleChange input greeting) input 29 | 30 | where 31 | handleChange :: JQuery -> JQuery -> JQueryEvent -> JQuery -> Effect Unit 32 | handleChange input greeting _ _ = unsafePartial do 33 | val <- getValue input 34 | for_ (runExcept (readString val)) \name -> do 35 | log $ "Name changed to " <> name 36 | setText ("Hello, " <> name) greeting 37 | ``` 38 | 39 | (from [test/Main.purs](test/Main.purs)). 40 | 41 | ## Installation 42 | 43 | bower i purescript-jquery 44 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-jquery", 3 | "homepage": "https://github.com/purescript/purescript-jquery", 4 | "description": "Type declarations for jQuery", 5 | "keywords": [ 6 | "purescript" 7 | ], 8 | "license": "MIT", 9 | "ignore": [ 10 | "**/.*", 11 | "bower_components", 12 | "node_modules", 13 | "output", 14 | "bower.json", 15 | "Gruntfile.js", 16 | "package.json" 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "git://github.com/paf31/purescript-jquery.git" 21 | }, 22 | "dependencies": { 23 | "purescript-web-dom": "^1.0.0", 24 | "purescript-effect": "^2.0.0", 25 | "purescript-foreign": "^5.0.0" 26 | }, 27 | "devDependencies": { 28 | "purescript-console": "^4.1.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /html/.gitignore: -------------------------------------------------------------------------------- 1 | index.js 2 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | purescript-jquery example 5 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "clean": "rimraf output && rimraf .pulp-cache", 5 | "test": "pulp build -I test && pulp browserify -m Test.Main --to html/index.js", 6 | "build": "pulp build" 7 | }, 8 | "devDependencies": { 9 | "pulp": "^14.0.0", 10 | "purescript-psa": "^0.7.3", 11 | "rimraf": "^3.0.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /psc-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "source": "https://github.com/purescript/package-sets.git", 4 | "set": "psc-0.10.1", 5 | "depends": [ 6 | "arrays", 7 | "bifunctors", 8 | "console", 9 | "control", 10 | "datetime", 11 | "distributive", 12 | "dom", 13 | "eff", 14 | "either", 15 | "enums", 16 | "exceptions", 17 | "foldable-traversable", 18 | "foreign", 19 | "functions", 20 | "generics", 21 | "identity", 22 | "integers", 23 | "invariant", 24 | "js-date", 25 | "lazy", 26 | "lists", 27 | "math", 28 | "maybe", 29 | "media-types", 30 | "monoid", 31 | "newtype", 32 | "nonempty", 33 | "nullable", 34 | "partial", 35 | "prelude", 36 | "proxy", 37 | "st", 38 | "strings", 39 | "tailrec", 40 | "transformers", 41 | "tuples", 42 | "unfoldable", 43 | "unsafe-coerce" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /src/JQuery.js: -------------------------------------------------------------------------------- 1 | /* global exports */ 2 | "use strict"; 3 | 4 | exports.ready = function(func) { 5 | return function() { 6 | jQuery(document).ready(func); 7 | }; 8 | }; 9 | 10 | exports.select = function(selector) { 11 | return function() { 12 | return jQuery(selector); 13 | }; 14 | }; 15 | 16 | exports.find = function(selector) { 17 | return function(ob) { 18 | return function() { 19 | return ob.find(selector); 20 | }; 21 | }; 22 | }; 23 | 24 | exports.parent = function(ob) { 25 | return function() { 26 | return ob.parent(); 27 | }; 28 | }; 29 | 30 | exports.closest = function(selector) { 31 | return function(ob) { 32 | return function() { 33 | return ob.closest(selector); 34 | }; 35 | }; 36 | }; 37 | 38 | exports.create = function(html) { 39 | return function() { 40 | return jQuery(html); 41 | }; 42 | }; 43 | 44 | exports.setAttr = function(attr) { 45 | return function(val) { 46 | return function(ob) { 47 | return function() { 48 | ob.attr(attr, val); 49 | }; 50 | }; 51 | }; 52 | }; 53 | 54 | exports.getAttrImpl = function(attr) { 55 | return function(ob) { 56 | return function() { 57 | return ob.attr(attr); 58 | }; 59 | }; 60 | }; 61 | 62 | exports.attr = function(attrs) { 63 | return function(ob) { 64 | return function() { 65 | ob.attr(attrs); 66 | }; 67 | }; 68 | }; 69 | 70 | exports.css = function(props) { 71 | return function(ob) { 72 | return function() { 73 | ob.css(props); 74 | }; 75 | }; 76 | }; 77 | 78 | exports.hasClass = function(cls) { 79 | return function(ob) { 80 | return function() { 81 | return ob.hasClass(cls); 82 | }; 83 | }; 84 | }; 85 | 86 | exports.toggleClass = function(cls) { 87 | return function(ob) { 88 | return function() { 89 | ob.toggleClass(cls); 90 | }; 91 | }; 92 | }; 93 | 94 | exports.setClass = function(cls) { 95 | return function(flag) { 96 | return function(ob) { 97 | return function() { 98 | ob.toggleClass(cls, flag); 99 | }; 100 | }; 101 | }; 102 | }; 103 | 104 | exports.setProp = function(p) { 105 | return function(val) { 106 | return function(ob) { 107 | return function() { 108 | ob.prop(p, val); 109 | }; 110 | }; 111 | }; 112 | }; 113 | 114 | exports.getProp = function(p) { 115 | return function(ob) { 116 | return function() { 117 | return ob.prop(p); 118 | }; 119 | }; 120 | }; 121 | 122 | exports.append = function(ob1) { 123 | return function(ob) { 124 | return function() { 125 | ob.append(ob1); 126 | }; 127 | }; 128 | }; 129 | 130 | exports.unsafeAppendHtml = function(s) { 131 | return function(ob) { 132 | return function() { 133 | ob.append(s); 134 | }; 135 | }; 136 | }; 137 | 138 | exports.appendText = function(s) { 139 | return function(ob) { 140 | return function() { 141 | ob.append(document.createTextNode(s)); 142 | }; 143 | }; 144 | }; 145 | 146 | exports.body = function() { 147 | return jQuery(document.body); 148 | }; 149 | 150 | exports.remove = function(ob) { 151 | return function() { 152 | ob.remove(); 153 | }; 154 | }; 155 | 156 | exports.clear = function(ob) { 157 | return function() { 158 | ob.empty(); 159 | }; 160 | }; 161 | 162 | exports.before = function(ob) { 163 | return function(ob1) { 164 | return function() { 165 | ob1.before(ob); 166 | }; 167 | }; 168 | }; 169 | 170 | exports.getText = function(ob) { 171 | return function() { 172 | return ob.text(); 173 | }; 174 | }; 175 | 176 | exports.setText = function(text) { 177 | return function(ob) { 178 | return function() { 179 | ob.text(text); 180 | }; 181 | }; 182 | }; 183 | 184 | exports.getHtml = function(ob) { 185 | return function() { 186 | return ob.html(); 187 | }; 188 | }; 189 | 190 | exports.setHtml = function(html) { 191 | return function(ob) { 192 | return function() { 193 | ob.html(html); 194 | }; 195 | }; 196 | }; 197 | 198 | exports.getValue = function(ob) { 199 | return function() { 200 | return ob.val(); 201 | }; 202 | }; 203 | 204 | exports.setValue = function(val) { 205 | return function(ob) { 206 | return function() { 207 | ob.val(val); 208 | }; 209 | }; 210 | }; 211 | 212 | exports.toggle = function(ob) { 213 | return function() { 214 | ob.toggle(); 215 | }; 216 | }; 217 | 218 | exports.setVisible = function(flag) { 219 | return function(ob) { 220 | return function() { 221 | ob.toggle(flag); 222 | }; 223 | }; 224 | }; 225 | 226 | exports.toArray = function(ob) { 227 | return function() { 228 | var els = ob.toArray(); 229 | var copy = []; 230 | for (var i = 0; i < els.length; i++) { 231 | copy.push(jQuery(els[i])); 232 | } 233 | return copy; 234 | }; 235 | }; 236 | 237 | exports.on = function(evt) { 238 | return function(act) { 239 | return function(ob) { 240 | return function() { 241 | ob.on(evt, function(e) { 242 | act(e)(jQuery(this))(); 243 | }); 244 | }; 245 | }; 246 | }; 247 | }; 248 | 249 | exports.delegate = function(evt) { 250 | return function(sel) { 251 | return function(act) { 252 | return function(ob) { 253 | return function() { 254 | ob.on(evt, sel, function(e) { 255 | act(e)(jQuery(this))(); 256 | }); 257 | }; 258 | }; 259 | }; 260 | }; 261 | }; 262 | 263 | 264 | exports.off = function(evt) { 265 | return function(ob) { 266 | return function() { 267 | return ob.off(evt); 268 | }; 269 | }; 270 | }; 271 | 272 | 273 | exports.deafen = function(ob) { 274 | return function() { 275 | return ob.off(); 276 | }; 277 | }; 278 | 279 | exports.preventDefault = function(e) { 280 | return function() { 281 | e.preventDefault(); 282 | }; 283 | }; 284 | 285 | exports.stopPropagation = function(e) { 286 | return function() { 287 | e.stopPropagation(); 288 | }; 289 | }; 290 | 291 | exports.stopImmediatePropagation = function(e) { 292 | return function() { 293 | e.stopImmediatePropagation(); 294 | }; 295 | }; 296 | 297 | exports.getTarget = function(e) { 298 | return function() { 299 | return jQuery(e.target); 300 | }; 301 | }; 302 | 303 | exports.getCurrentTarget = function(e) { 304 | return function() { 305 | return jQuery(e.currentTarget); 306 | }; 307 | }; 308 | 309 | exports.getPageX = function(e) { 310 | return function() { 311 | return e.pageX; 312 | }; 313 | }; 314 | 315 | exports.getPageY = function(e) { 316 | return function() { 317 | return e.pageY; 318 | }; 319 | }; 320 | 321 | exports.getWhich = function(e) { 322 | return function() { 323 | return e.which; 324 | }; 325 | }; 326 | 327 | exports.getMetaKey = function(e) { 328 | return function() { 329 | return e.metaKey; 330 | }; 331 | }; 332 | 333 | 334 | exports.clone = function(ob) { 335 | return function() { 336 | return ob.clone(); 337 | }; 338 | }; 339 | 340 | exports.cloneWithDataAndEvents = function(ob) { 341 | return function() { 342 | return ob.clone(true); 343 | }; 344 | }; 345 | -------------------------------------------------------------------------------- /src/JQuery.purs: -------------------------------------------------------------------------------- 1 | -- | This module defines foreign types and functions for working with 2 | -- | the jQuery library. 3 | 4 | module JQuery 5 | ( JQuery 6 | , JQueryEvent 7 | , Selector 8 | , ready 9 | , select 10 | , find 11 | , parent 12 | , closest 13 | , create 14 | , setAttr 15 | , getAttr 16 | , attr 17 | , css 18 | , hasClass 19 | , toggleClass 20 | , setClass 21 | , addClass 22 | , removeClass 23 | , setProp 24 | , getProp 25 | , append 26 | , remove 27 | , clear 28 | , before 29 | , appendText 30 | , body 31 | , getText 32 | , setText 33 | , getHtml 34 | , setHtml 35 | , getValue 36 | , setValue 37 | , toggle 38 | , setVisible 39 | , hide 40 | , display 41 | , on 42 | , on' 43 | , off 44 | , off' 45 | , toArray 46 | , preventDefault 47 | , stopPropagation 48 | , stopImmediatePropagation 49 | , getTarget 50 | , getCurrentTarget 51 | , getPageX 52 | , getPageY 53 | , getWhich 54 | , getMetaKey 55 | , clone 56 | , cloneWithDataAndEvents 57 | ) where 58 | 59 | import Prelude (Unit) 60 | import Effect (Effect) 61 | import Foreign (Foreign, isUndefined, unsafeFromForeign) 62 | import Data.Functor (map) 63 | import Data.Maybe (Maybe(..)) 64 | 65 | -- | The type of collections of jQuery-wrapped nodes. 66 | foreign import data JQuery :: Type 67 | 68 | -- | Type of jQuery event objects. 69 | foreign import data JQueryEvent :: Type 70 | 71 | -- | A type synonym to help readability of type signatures. 72 | type Selector = String 73 | 74 | -- | Run a function when the document is loaded. 75 | foreign import ready :: forall a. Effect a -> Effect Unit 76 | 77 | -- | Wrapper function for jQuery selection $('..') 78 | foreign import select :: Selector -> Effect JQuery 79 | 80 | -- | Find child nodes matching a selector 81 | foreign import find :: Selector -> JQuery -> Effect JQuery 82 | 83 | -- | Get the parent elements. 84 | foreign import parent :: JQuery -> Effect JQuery 85 | 86 | -- | Find the closest element matching the selector. 87 | foreign import closest :: Selector -> JQuery -> Effect JQuery 88 | 89 | -- | Create an element. 90 | foreign import create :: String -> Effect JQuery 91 | 92 | -- | Set a single attribute. 93 | foreign import setAttr :: forall a. String -> a -> JQuery -> Effect Unit 94 | 95 | foreign import getAttrImpl :: String -> JQuery -> Effect Foreign 96 | 97 | -- | Get an attribute value. 98 | getAttr :: String -> JQuery -> Effect (Maybe String) 99 | getAttr str jq = map foreignToString (getAttrImpl str jq) 100 | where foreignToString f = 101 | if isUndefined f 102 | then Nothing 103 | else Just (unsafeFromForeign f) 104 | 105 | -- | Set multiple attributes. 106 | foreign import attr :: forall attr. { | attr } -> JQuery -> Effect Unit 107 | 108 | -- | Set CSS properties. 109 | foreign import css :: forall css. { | css } -> JQuery -> Effect Unit 110 | 111 | -- | Test if an element has a CSS class. 112 | foreign import hasClass :: String -> JQuery -> Effect Boolean 113 | 114 | -- | Toggle the specified CSS class. 115 | foreign import toggleClass :: String -> JQuery -> Effect Unit 116 | 117 | -- | Set the specified CSS class. 118 | foreign import setClass :: String -> Boolean -> JQuery -> Effect Unit 119 | 120 | -- | Add the specified CSS class. 121 | addClass :: String -> JQuery -> Effect Unit 122 | addClass cls = setClass cls true 123 | 124 | -- | Remove the specified CSS class. 125 | removeClass :: String -> JQuery -> Effect Unit 126 | removeClass cls = setClass cls false 127 | 128 | -- | Set a single property. 129 | foreign import setProp :: forall a. String -> a -> JQuery -> Effect Unit 130 | 131 | -- | Get a property value. 132 | foreign import getProp :: String -> JQuery -> Effect Foreign 133 | 134 | -- | Append the first node as a child node of the second. 135 | foreign import append :: JQuery -> JQuery -> Effect Unit 136 | 137 | -- | Remove selected elements. 138 | foreign import remove :: JQuery -> Effect Unit 139 | 140 | -- | Remove child elements. 141 | foreign import clear :: JQuery -> Effect Unit 142 | 143 | -- | Insert an element before another. 144 | foreign import before :: JQuery -> JQuery -> Effect Unit 145 | 146 | -- | Append text as a child node. Importantly, if jQuery recognises the String 147 | -- | as HTML, the parsed HTML will be appended, rather than the string. Hence, 148 | -- | this function can be dangerous when dealing with unchecked user input. 149 | foreign import unsafeAppendHtml :: String -> JQuery -> Effect Unit 150 | 151 | -- | Append text as a child node. 152 | foreign import appendText :: String -> JQuery -> Effect Unit 153 | 154 | -- | Get the document body node. 155 | foreign import body :: Effect JQuery 156 | 157 | -- | Get the text content of an element. 158 | foreign import getText :: JQuery -> Effect String 159 | 160 | -- | Set the text content of an element. 161 | foreign import setText :: String -> JQuery -> Effect Unit 162 | 163 | -- | Get the html content of an element. 164 | foreign import getHtml :: JQuery -> Effect String 165 | 166 | -- | Set the html content of an element 167 | foreign import setHtml :: String -> JQuery -> Effect Unit 168 | 169 | -- | Get the value of a form element. 170 | foreign import getValue :: JQuery -> Effect Foreign 171 | 172 | -- | Set the value of a form element. 173 | foreign import setValue :: forall a. a -> JQuery -> Effect Unit 174 | 175 | -- | Toggle visibility of an element. 176 | foreign import toggle :: JQuery -> Effect Unit 177 | 178 | -- | Set the visibility of an element. 179 | foreign import setVisible :: Boolean -> JQuery -> Effect Unit 180 | 181 | -- | Hide elements. 182 | hide :: JQuery -> Effect Unit 183 | hide = setVisible false 184 | 185 | -- | Show elements. 186 | display :: JQuery -> Effect Unit 187 | display = setVisible true 188 | 189 | -- | Register an event handler. 190 | foreign import on :: forall a. String -> (JQueryEvent -> JQuery -> Effect a) -> JQuery -> Effect Unit 191 | 192 | -- | Register an event handler for elements matching a selector. 193 | foreign import delegate :: forall a. String -> Selector -> (JQueryEvent -> JQuery -> Effect a) -> JQuery -> Effect Unit 194 | 195 | on':: forall a. String -> Selector -> (JQueryEvent -> JQuery -> Effect a) -> JQuery -> Effect Unit 196 | on' = delegate 197 | 198 | -- | Remove an event handler. 199 | foreign import off :: String -> JQuery -> Effect Unit 200 | 201 | -- | Remove all event handler. 202 | foreign import deafen :: JQuery -> Effect Unit 203 | 204 | off':: JQuery -> Effect Unit 205 | off' = deafen 206 | 207 | -- | Get an array of matching elements. 208 | foreign import toArray :: JQuery -> Effect (Array JQuery) 209 | 210 | -- | Prevent the default action for an event. 211 | foreign import preventDefault :: JQueryEvent -> Effect Unit 212 | 213 | -- | Stop propagation an event. 214 | foreign import stopPropagation :: JQueryEvent -> Effect Unit 215 | 216 | -- | Stop immediate propagation an event. 217 | foreign import stopImmediatePropagation :: JQueryEvent -> Effect Unit 218 | 219 | -- | Get the `target` propery of the event object. 220 | foreign import getTarget :: JQueryEvent -> Effect JQuery 221 | 222 | -- | Get the `currentTarget` property from the event object. 223 | foreign import getCurrentTarget :: JQueryEvent -> Effect JQuery 224 | 225 | -- | Get the `pageX` property from the event object. 226 | foreign import getPageX :: JQueryEvent -> Effect Number 227 | 228 | -- | Get the `pageY` property from the event object. 229 | foreign import getPageY :: JQueryEvent -> Effect Number 230 | 231 | -- | Get the `which` property from the event object. 232 | foreign import getWhich :: JQueryEvent -> Effect Int 233 | 234 | -- | Get the `metaKey` property from the event object. 235 | foreign import getMetaKey :: JQueryEvent -> Effect Boolean 236 | 237 | -- | Create a deep copy of the set of matched elements. 238 | foreign import clone :: JQuery -> Effect JQuery 239 | 240 | -- | Create a deep copy of the set of matched elements, 241 | -- | including event handlers and element data. 242 | foreign import cloneWithDataAndEvents :: JQuery -> Effect JQuery 243 | -------------------------------------------------------------------------------- /test/Main.purs: -------------------------------------------------------------------------------- 1 | module Test.Main where 2 | 3 | import Prelude hiding (append) 4 | 5 | import Effect (Effect) 6 | import Effect.Console (log) 7 | import JQuery (JQuery, JQueryEvent, on, append, css, create, appendText, body, ready, setText, getValue) 8 | import Control.Monad.Except (runExcept) 9 | import Foreign (readString) 10 | import Data.Foldable (for_) 11 | import Partial.Unsafe (unsafePartial) 12 | 13 | main :: Effect Unit 14 | main = 15 | ready $ do 16 | -- Get the document body 17 | body <- body 18 | 19 | -- Create a text box 20 | div <- create "

" 21 | input <- create "" 22 | appendText "Your Name: " div 23 | append input div 24 | append div body 25 | 26 | -- Create a paragraph to display a greeting 27 | greeting <- create "

" 28 | css { color: "red" } greeting 29 | append greeting body 30 | 31 | -- Listen for change events on the text box 32 | on "change" (handleChange input greeting) input 33 | where 34 | handleChange :: JQuery -> JQuery -> JQueryEvent -> JQuery -> Effect Unit 35 | handleChange input greeting _ _ = unsafePartial do 36 | val <- getValue input 37 | for_ (runExcept (readString val)) \name -> do 38 | log $ "Name changed to " <> name 39 | setText ("Hello, " <> name) greeting 40 | --------------------------------------------------------------------------------