├── .gitignore ├── LICENSE ├── MODULE.md ├── README.md ├── bower.json ├── examples ├── Backend │ ├── Main.purs │ └── main.html ├── Todomvc │ ├── Controller.purs │ ├── Escape.purs │ ├── Focus.purs │ ├── Main.purs │ ├── Storage.purs │ └── main.html └── TodomvcF │ ├── AppI.purs │ ├── Escape.purs │ ├── Focus.purs │ ├── Main.purs │ ├── StorageF.purs │ ├── StorageI.purs │ ├── ThisF.purs │ ├── ThisI.purs │ ├── TodomvcF.purs │ ├── TodomvcI.purs │ └── main.html ├── gulpfile.js ├── package.json └── src ├── Angular.purs └── Angular ├── Animate.purs ├── Attributes.purs ├── Cache.purs ├── DI.purs ├── Deferred.purs ├── Element.purs ├── FormController.purs ├── Http.purs ├── Http ├── Internal.purs └── Types.purs ├── Injector.purs ├── Interpolate.purs ├── Interval.purs ├── Location.purs ├── Log.purs ├── Module.purs ├── NgModelController.purs ├── Parse.purs ├── Promise.purs ├── Q.purs ├── Scope.purs ├── This.purs └── Timeout.purs /.gitignore: -------------------------------------------------------------------------------- 1 | .psci 2 | node_modules 3 | bower_components 4 | js 5 | externs 6 | dist 7 | output 8 | tmp 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Eric Thul 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the 5 | "Software"), in the Software without restriction, including without 6 | limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to 8 | whom the Software is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /MODULE.md: -------------------------------------------------------------------------------- 1 | # Module Documentation 2 | 3 | ## Module Angular 4 | 5 | ### Values 6 | 7 | bootstrap :: forall e. Element -> [String] -> Eff e Injector 8 | 9 | copy :: forall e a. a -> Eff e a 10 | 11 | extend :: forall e a b c. { | a } -> { | b } -> Eff e { | c } 12 | 13 | 14 | ## Module Angular.Animate 15 | 16 | ### Types 17 | 18 | data Animate :: * 19 | 20 | type AnimateEff e = Eff (nganimate :: NgAnimate | e) Unit 21 | 22 | data NgAnimate :: ! 23 | 24 | 25 | ### Values 26 | 27 | addClass :: forall e f r. Element -> String -> Maybe (Eff f r) -> Animate -> AnimateEff e 28 | 29 | enter :: forall e f r. Element -> Element -> Element -> Maybe (Eff f r) -> Animate -> AnimateEff e 30 | 31 | leave :: forall e f r. Element -> Maybe (Eff f r) -> Animate -> AnimateEff e 32 | 33 | move :: forall e f r. Element -> Element -> Element -> Maybe (Eff f r) -> Animate -> AnimateEff e 34 | 35 | removeClass :: forall e f r. Element -> String -> Maybe (Eff f r) -> Animate -> AnimateEff e 36 | 37 | setClass :: forall e f r. Element -> String -> String -> Maybe (Eff f r) -> Animate -> AnimateEff e 38 | 39 | 40 | ## Module Angular.Attributes 41 | 42 | ### Types 43 | 44 | type AttrEff e r = Eff (ngattr :: NgAttr | e) r 45 | 46 | data Attributes :: * 47 | 48 | data NgAttr :: ! 49 | 50 | 51 | ### Values 52 | 53 | addClass :: forall e. String -> Attributes -> AttrEff e Unit 54 | 55 | attr :: forall e a. Attributes -> AttrEff e { | a } 56 | 57 | get :: forall e a. Attributes -> AttrEff e { | a } 58 | 59 | observe :: forall e f. String -> (String -> Eff f Unit) -> Attributes -> AttrEff e Unit 60 | 61 | removeClass :: forall e. String -> Attributes -> AttrEff e Unit 62 | 63 | set :: forall e. String -> String -> Attributes -> AttrEff e Unit 64 | 65 | updateClass :: forall e. String -> String -> Attributes -> AttrEff e Unit 66 | 67 | 68 | ## Module Angular.Cache 69 | 70 | ### Types 71 | 72 | data Cache :: * 73 | 74 | type CacheEff e r = Eff (ngcache :: NgCache | e) r 75 | 76 | data CacheFactory :: * 77 | 78 | type Key = String 79 | 80 | type Name = String 81 | 82 | data NgCache :: ! 83 | 84 | type Options a = { capacity :: Number | a } 85 | 86 | 87 | ### Values 88 | 89 | cache :: forall e a. Name -> Maybe (Options a) -> CacheFactory -> CacheEff e Cache 90 | 91 | destroy :: forall e. Cache -> CacheEff e Unit 92 | 93 | get :: forall e a. Key -> Cache -> CacheEff e a 94 | 95 | info :: forall e a. Cache -> CacheEff e { size :: Number, id :: String | a } 96 | 97 | put :: forall e a. Key -> a -> Cache -> CacheEff e a 98 | 99 | remove :: forall e. Key -> Cache -> CacheEff e Unit 100 | 101 | removeAll :: forall e. Cache -> CacheEff e Unit 102 | 103 | 104 | ## Module Angular.DI 105 | 106 | ### Types 107 | 108 | data Annotated :: * -> * 109 | 110 | newtype RootElement where 111 | RootElement :: Element -> RootElement 112 | 113 | newtype RootScope a where 114 | RootScope :: Scope a -> RootScope a 115 | 116 | 117 | ### Type Classes 118 | 119 | class Dependency a where 120 | name :: String 121 | 122 | class Injectable a where 123 | dependencies :: a -> [String] 124 | 125 | class (Dependency a) <= Service a where 126 | 127 | 128 | ### Type Class Instances 129 | 130 | instance dependencyAnimate :: Dependency Animate 131 | 132 | instance dependencyAttributes :: Dependency Attributes 133 | 134 | instance dependencyCacheFactory :: Dependency CacheFactory 135 | 136 | instance dependencyElement :: Dependency Element 137 | 138 | instance dependencyHttp :: Dependency Http 139 | 140 | instance dependencyInjector :: Dependency Injector 141 | 142 | instance dependencyInterpolate :: Dependency Interpolate 143 | 144 | instance dependencyInterval :: Dependency Interval 145 | 146 | instance dependencyLocation :: Dependency Location 147 | 148 | instance dependencyLog :: Dependency Log 149 | 150 | instance dependencyParse :: Dependency Parse 151 | 152 | instance dependencyQ :: Dependency Q 153 | 154 | instance dependencyRootElement :: Dependency RootElement 155 | 156 | instance dependencyRootScope :: Dependency (RootScope a) 157 | 158 | instance dependencyScope :: Dependency (Scope a) 159 | 160 | instance dependencyThis :: Dependency (This a) 161 | 162 | instance dependencyTimeout :: Dependency Timeout 163 | 164 | instance injectableEff :: Injectable (Eff e r) 165 | 166 | instance injectableFn :: (Dependency a, Injectable b) => Injectable (a -> b) 167 | 168 | instance serviceAnimate :: Service Animate 169 | 170 | instance serviceCacheFactory :: Service CacheFactory 171 | 172 | instance serviceHttp :: Service Http 173 | 174 | instance serviceInjector :: Service Injector 175 | 176 | instance serviceInterpolate :: Service Interpolate 177 | 178 | instance serviceInterval :: Service Interval 179 | 180 | instance serviceLocation :: Service Location 181 | 182 | instance serviceLog :: Service Log 183 | 184 | instance serviceParse :: Service Parse 185 | 186 | instance serviceQ :: Service Q 187 | 188 | instance serviceRootElement :: Service RootElement 189 | 190 | instance serviceRootScope :: Service (RootScope a) 191 | 192 | instance serviceTimeout :: Service Timeout 193 | 194 | 195 | ### Values 196 | 197 | annotate :: forall a. (Injectable a) => a -> Annotated a 198 | 199 | get :: forall e a. (Service a) => Injector -> InjEff e a 200 | 201 | 202 | ## Module Angular.Deferred 203 | 204 | ### Types 205 | 206 | data Deferred :: * -> * -> * 207 | 208 | type DeferredEff e r = Eff (ngdeferred :: NgDeferred | e) r 209 | 210 | data NgDeferred :: ! 211 | 212 | 213 | ### Values 214 | 215 | notify :: forall e s a b. s -> Deferred a b -> DeferredEff e Unit 216 | 217 | promise :: forall e a b. Deferred a b -> DeferredEff e (Promise a b) 218 | 219 | reject :: forall e a b. a -> Deferred a b -> DeferredEff e Unit 220 | 221 | resolve :: forall e a b. b -> Deferred a b -> DeferredEff e Unit 222 | 223 | 224 | ## Module Angular.Element 225 | 226 | ### Types 227 | 228 | data DeregisterHandler :: # ! -> * 229 | 230 | type ElEff e r = Eff (ngel :: NgEl | e) r 231 | 232 | data Element :: * 233 | 234 | type Handler e = DOMEvent -> Eff e Unit 235 | 236 | data NgEl :: ! 237 | 238 | 239 | ### Values 240 | 241 | (!!) :: Element -> Number -> Maybe HTMLElement 242 | 243 | addClass :: forall e. String -> Element -> ElEff e Element 244 | 245 | after :: forall e. Element -> Element -> ElEff e Element 246 | 247 | bind :: forall e f. String -> Handler f -> Element -> ElEff e (DeregisterHandler f) 248 | 249 | children :: forall e. Element -> ElEff e Element 250 | 251 | clone :: forall e. Element -> ElEff e Element 252 | 253 | contents :: forall e. Element -> ElEff e Element 254 | 255 | controller :: forall e a. Maybe String -> Element -> ElEff e (Maybe a) 256 | 257 | element :: forall e. String -> ElEff e Element 258 | 259 | empty :: forall e. Element -> ElEff e Element 260 | 261 | eq :: forall e. Number -> Element -> ElEff e Element 262 | 263 | find :: forall e. Number -> Element -> ElEff e Element 264 | 265 | getAttr :: forall e. String -> Element -> ElEff e (Maybe String) 266 | 267 | getCss :: forall e. String -> Element -> ElEff e (Maybe String) 268 | 269 | getData :: forall e a. String -> Element -> ElEff e (Maybe a) 270 | 271 | getProp :: forall e. String -> Element -> ElEff e (Maybe String) 272 | 273 | getVal :: forall e. Element -> ElEff e (Maybe String) 274 | 275 | hasClass :: forall e. String -> Element -> ElEff e Boolean 276 | 277 | html :: forall e. Element -> ElEff e String 278 | 279 | inheritedData :: forall e a. Element -> ElEff e { | a } 280 | 281 | injector :: forall e a. Element -> ElEff e (Maybe Injector) 282 | 283 | isolateScope :: forall e a. Element -> ElEff e (Maybe (Scope a)) 284 | 285 | next :: forall e. Element -> ElEff e Element 286 | 287 | off :: forall e f. String -> Element -> ElEff e Element 288 | 289 | offHandler :: forall e f. String -> DeregisterHandler f -> Element -> ElEff e Element 290 | 291 | on :: forall e f. String -> Handler f -> Element -> ElEff e (DeregisterHandler f) 292 | 293 | one :: forall e f. String -> Handler f -> Element -> ElEff e (DeregisterHandler f) 294 | 295 | parent :: forall e. Element -> ElEff e Element 296 | 297 | prepend :: forall e. Element -> Element -> ElEff e Element 298 | 299 | ready :: forall e. Eff e Unit -> Element -> ElEff e Element 300 | 301 | remove :: forall e. Element -> ElEff e Element 302 | 303 | removeAttr :: forall e. String -> Element -> ElEff e Element 304 | 305 | removeClass :: forall e. String -> Element -> ElEff e Element 306 | 307 | removeData :: forall e. String -> Element -> ElEff e Element 308 | 309 | replaceWith :: forall e. Element -> Element -> ElEff e Element 310 | 311 | scope :: forall e a. Element -> ElEff e (Maybe (Scope a)) 312 | 313 | setAllAttr :: forall e a. { | a } -> Element -> ElEff e Element 314 | 315 | setAllCss :: forall e a. { | a } -> Element -> ElEff e Element 316 | 317 | setAllData :: forall e a. { | a } -> Element -> ElEff e Element 318 | 319 | setAllProp :: forall e a. { | a } -> Element -> ElEff e Element 320 | 321 | setAttr :: forall e. String -> String -> Element -> ElEff e Element 322 | 323 | setCss :: forall e. String -> String -> Element -> ElEff e Element 324 | 325 | setData :: forall e a. String -> a -> Element -> ElEff e Element 326 | 327 | setProp :: forall e. String -> String -> Element -> ElEff e Element 328 | 329 | setVal :: forall e. String -> Element -> ElEff e Element 330 | 331 | toggleClass :: forall e. String -> Boolean -> Element -> ElEff e Element 332 | 333 | triggerHandler :: forall e a. String -> [a] -> Element -> ElEff e Element 334 | 335 | unbind :: forall e f. String -> Element -> ElEff e Element 336 | 337 | unbindHandler :: forall e f. String -> DeregisterHandler f -> Element -> ElEff e Element 338 | 339 | wrap :: forall e. Element -> Element -> ElEff e Element 340 | 341 | 342 | ## Module Angular.FormController 343 | 344 | ### Types 345 | 346 | data FormController :: * 347 | 348 | type FormEff e r = Eff (ngform :: NgForm | e) r 349 | 350 | data NgForm :: ! 351 | 352 | 353 | ### Values 354 | 355 | addControl :: forall e a. NgModelController a -> FormController -> FormEff e Unit 356 | 357 | dirty :: forall e. FormController -> FormEff e Boolean 358 | 359 | error :: forall e a. FormController -> FormEff e { | a } 360 | 361 | invalid :: forall e. FormController -> FormEff e Boolean 362 | 363 | pristine :: forall e. FormController -> FormEff e Boolean 364 | 365 | removeControl :: forall e a. NgModelController a -> FormController -> FormEff e Unit 366 | 367 | setDirty :: forall e. FormController -> FormEff e Unit 368 | 369 | setPristine :: forall e. FormController -> FormEff e Unit 370 | 371 | setValidity :: forall e a. ValidationErrorKey -> Boolean -> NgModelController a -> FormController -> FormEff e Unit 372 | 373 | valid :: forall e. FormController -> FormEff e Boolean 374 | 375 | 376 | ## Module Angular.Http 377 | 378 | ### Types 379 | 380 | type Config a b c d = { responseType :: D.ResponseType, withCredentials :: Boolean, timeout :: Either Number (Promise c d), cache :: Either Boolean Cache, xsrfCookieName :: String, xsrfHeaderName :: String, headers :: Headers, "data" :: RequestData b, params :: { | a }, url :: D.Url, method :: D.HttpMethod } 381 | 382 | data Http :: * 383 | 384 | type HttpResponse e r a b c d = HttpEff e (Promise I.ForeignResponse (Response r a b c d)) 385 | 386 | type Response r a b c d = { statusText :: String, config :: Config a b c d, headers :: [String] -> String, status :: Status, "data" :: D.HttpData r } 387 | 388 | 389 | ### Values 390 | 391 | config :: forall a b c d. Config a b c d 392 | 393 | del :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 394 | 395 | del' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 396 | 397 | get :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 398 | 399 | get' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 400 | 401 | head :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 402 | 403 | head' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 404 | 405 | http :: forall e r a b c d. Config a b c d -> Http -> HttpResponse e r a b c d 406 | 407 | jsonp :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 408 | 409 | jsonp' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 410 | 411 | post :: forall e r a b c d. D.Url -> RequestData b -> Http -> HttpResponse e r a b c d 412 | 413 | post' :: forall e r a b c d. D.Url -> RequestData b -> Config a b c d -> Http -> HttpResponse e r a b c d 414 | 415 | put :: forall e r a b c d. D.Url -> RequestData b -> Http -> HttpResponse e r a b c d 416 | 417 | put' :: forall e r a b c d. D.Url -> RequestData b -> Config a b c d -> Http -> HttpResponse e r a b c d 418 | 419 | 420 | ## Module Angular.Injector 421 | 422 | ### Types 423 | 424 | type InjEff e a = Eff (nginj :: NgInj | e) a 425 | 426 | data Injector :: * 427 | 428 | data NgInj :: ! 429 | 430 | 431 | ### Values 432 | 433 | annotate :: forall e a. a -> Injector -> InjEff e [String] 434 | 435 | get :: forall e a. String -> Injector -> InjEff e a 436 | 437 | has :: forall e. String -> Injector -> InjEff e Boolean 438 | 439 | injector :: forall e. [String] -> InjEff e Injector 440 | 441 | instantiate :: forall e r a b. a -> Maybe { | b } -> Injector -> InjEff e r 442 | 443 | invoke :: forall e r a b c. a -> Maybe { | b } -> Maybe { | c } -> Injector -> InjEff e r 444 | 445 | 446 | ## Module Angular.Interpolate 447 | 448 | ### Types 449 | 450 | type Expression a = { | a } -> String 451 | 452 | data Interpolate :: * 453 | 454 | type InterpolateEff e a = Eff (nginterpolate :: NgInterpolate | e) a 455 | 456 | data NgInterpolate :: ! 457 | 458 | 459 | ### Values 460 | 461 | endSymbol :: Interpolate -> String 462 | 463 | interpolate :: forall e a. String -> Maybe Boolean -> Maybe String -> Interpolate -> InterpolateEff e (Expression a) 464 | 465 | startSymbol :: Interpolate -> String 466 | 467 | 468 | ## Module Angular.Interval 469 | 470 | ### Types 471 | 472 | data Interval :: * 473 | 474 | type IntervalEff e r = Eff (nginterval :: NgInterval | e) r 475 | 476 | type IntervalPromise = Promise Unit Number 477 | 478 | data NgInterval :: ! 479 | 480 | 481 | ### Values 482 | 483 | cancel :: forall e. IntervalPromise -> Interval -> IntervalEff e Boolean 484 | 485 | interval :: forall e f r. Eff f r -> Number -> Number -> Boolean -> Interval -> IntervalEff e IntervalPromise 486 | 487 | interval' :: forall e f r. Eff f r -> Number -> Number -> Interval -> IntervalEff e IntervalPromise 488 | 489 | interval'' :: forall e f r. Eff f r -> Number -> Interval -> IntervalEff e IntervalPromise 490 | 491 | intervalk :: forall e f r. Number -> Number -> Boolean -> Interval -> Eff f r -> IntervalEff e IntervalPromise 492 | 493 | 494 | ## Module Angular.Location 495 | 496 | ### Types 497 | 498 | type LocEff e a = Eff (ngloc :: NgLoc | e) a 499 | 500 | data Location :: * 501 | 502 | data NgLoc :: ! 503 | 504 | 505 | ### Values 506 | 507 | getPath :: forall e. Location -> LocEff e String 508 | 509 | setPath :: forall e. String -> Location -> LocEff e String 510 | 511 | 512 | ## Module Angular.Log 513 | 514 | ### Types 515 | 516 | data Log :: * 517 | 518 | type LogEff e = Eff (nglog :: NgLog | e) Unit 519 | 520 | data NgLog :: ! 521 | 522 | 523 | ### Values 524 | 525 | debug :: forall e a. a -> Log -> LogEff e 526 | 527 | error :: forall e a. a -> Log -> LogEff e 528 | 529 | info :: forall e a. a -> Log -> LogEff e 530 | 531 | log :: forall e a. a -> Log -> LogEff e 532 | 533 | warn :: forall e a. a -> Log -> LogEff e 534 | 535 | 536 | ## Module Angular.Module 537 | 538 | ### Types 539 | 540 | data Module :: * 541 | 542 | data NgReadModule :: ! 543 | 544 | data NgRegisterToModule :: ! 545 | 546 | data NgWriteModule :: ! 547 | 548 | type ReadEff e = Eff (ngrmod :: NgReadModule | e) Module 549 | 550 | type RegisterEff e = Eff (nggmod :: NgRegisterToModule | e) Module 551 | 552 | type WriteEff e = Eff (ngwmod :: NgWriteModule | e) Module 553 | 554 | 555 | ### Values 556 | 557 | animation :: forall e a. String -> a -> Module -> RegisterEff e 558 | 559 | config :: forall e a. a -> Module -> RegisterEff e 560 | 561 | constant :: forall e a. String -> a -> Module -> RegisterEff e 562 | 563 | controller :: forall e a. String -> a -> Module -> RegisterEff e 564 | 565 | directive :: forall e a. String -> a -> Module -> RegisterEff e 566 | 567 | factory :: forall e a. String -> a -> Module -> RegisterEff e 568 | 569 | filter :: forall e a. String -> a -> Module -> RegisterEff e 570 | 571 | ngmodule :: forall e. String -> ReadEff e 572 | 573 | ngmodule' :: forall e. String -> [String] -> WriteEff e 574 | 575 | provider :: forall e a. String -> a -> Module -> RegisterEff e 576 | 577 | run :: forall e a. a -> Module -> RegisterEff e 578 | 579 | service :: forall e a. String -> a -> Module -> RegisterEff e 580 | 581 | value :: forall e a. String -> a -> Module -> RegisterEff e 582 | 583 | 584 | ## Module Angular.NgModelController 585 | 586 | ### Types 587 | 588 | type Formatter a = a -> String 589 | 590 | data NgModel :: ! 591 | 592 | data NgModelController :: * -> * 593 | 594 | type NgModelEff e r = Eff (ngmodel :: NgModel | e) r 595 | 596 | type Parser a = String -> Maybe a 597 | 598 | type ValidationErrorKey = String 599 | 600 | 601 | ### Values 602 | 603 | appendFormatters :: forall e a. [Formatter a] -> NgModelController a -> NgModelEff e Unit 604 | 605 | appendParsers :: forall e a. [Parser a] -> NgModelController a -> NgModelEff e Unit 606 | 607 | appendViewChangeListeners :: forall e a. [Eff e Unit] -> NgModelController a -> NgModelEff e Unit 608 | 609 | dirty :: forall e a. NgModelController a -> NgModelEff e Boolean 610 | 611 | error :: forall e a b. NgModelController a -> NgModelEff e { | b } 612 | 613 | invalid :: forall e a. NgModelController a -> NgModelEff e Boolean 614 | 615 | isEmpty :: forall e a. a -> NgModelController a -> NgModelEff e Boolean 616 | 617 | modelValue :: forall e a. NgModelController a -> NgModelEff e a 618 | 619 | prependFormatters :: forall e a. [Formatter a] -> NgModelController a -> NgModelEff e Unit 620 | 621 | prependParsers :: forall e a. [Parser a] -> NgModelController a -> NgModelEff e Unit 622 | 623 | prependViewChangeListeners :: forall e a. [Eff e Unit] -> NgModelController a -> NgModelEff e Unit 624 | 625 | pristine :: forall e a. NgModelController a -> NgModelEff e Boolean 626 | 627 | render :: forall e a. NgModelController a -> NgModelEff e Unit 628 | 629 | setIsEmpty :: forall e a b. (b -> NgModelEff e Boolean) -> NgModelController a -> NgModelEff e (NgModelController b) 630 | 631 | setModelValue :: forall e a b. b -> NgModelController a -> NgModelEff e (NgModelController b) 632 | 633 | setPristine :: forall e a. NgModelController a -> NgModelEff e Unit 634 | 635 | setRender :: forall e a. NgModelEff e Unit -> NgModelController a -> NgModelEff e Unit 636 | 637 | setValidity :: forall e a. ValidationErrorKey -> Boolean -> NgModelController a -> NgModelEff e Unit 638 | 639 | setViewValue :: forall e a. String -> NgModelController a -> NgModelEff e Unit 640 | 641 | valid :: forall e a. NgModelController a -> NgModelEff e Boolean 642 | 643 | viewValue :: forall e a. NgModelController a -> NgModelEff e String 644 | 645 | 646 | ## Module Angular.Parse 647 | 648 | ### Types 649 | 650 | type Expression = String 651 | 652 | data Getter :: * -> * 653 | 654 | data NgParse :: ! 655 | 656 | data Parse :: * 657 | 658 | type ParseEff e r = Eff (ngparse :: NgParse | e) r 659 | 660 | data Setter :: * -> * 661 | 662 | 663 | ### Values 664 | 665 | assign :: forall a. Getter a -> Maybe (Setter a) 666 | 667 | constant :: forall a. Getter a -> Boolean 668 | 669 | get :: forall e a b c. { | a } -> { | b } -> Getter c -> ParseEff e c 670 | 671 | literal :: forall a. Getter a -> Boolean 672 | 673 | parse :: forall e a. Expression -> Parse -> ParseEff e (Getter a) 674 | 675 | set :: forall e a b. { | a } -> b -> Setter b -> ParseEff e b 676 | 677 | 678 | ## Module Angular.Promise 679 | 680 | ### Types 681 | 682 | data Promise :: * -> * -> * 683 | 684 | type PromiseEC e a b = ErrorT a (ContT Unit (Eff e)) b 685 | 686 | 687 | ### Values 688 | 689 | catch :: forall a b c d. (a -> Promise c d) -> Promise a b -> Promise c d 690 | 691 | finally :: forall e r a b. Eff e r -> Promise a b -> Promise a b 692 | 693 | liftPromiseEC :: forall e a b. (Error a) => Eff e (Promise a b) -> PromiseEC e a b 694 | 695 | runPromiseEC :: forall e a b. PromiseEC e a b -> (Either a b -> Eff e Unit) -> Eff e Unit 696 | 697 | then1 :: forall a b c. (b -> Promise a c) -> Promise a b -> Promise a c 698 | 699 | then1' :: forall a b c. (b -> c) -> Promise a b -> Promise a c 700 | 701 | then2 :: forall a b c d. (b -> Promise c d) -> (a -> Promise c d) -> Promise a b -> Promise c d 702 | 703 | then2' :: forall a b c d. (b -> d) -> (a -> c) -> Promise a b -> Promise c d 704 | 705 | then3 :: forall e s t a b c d. (b -> Promise c d) -> (a -> Promise c d) -> (s -> Eff e t) -> Promise a b -> Promise c d 706 | 707 | then3' :: forall e s t a b c d. (b -> d) -> (a -> c) -> (s -> Eff e t) -> Promise a b -> Promise c d 708 | 709 | 710 | ## Module Angular.Q 711 | 712 | ### Types 713 | 714 | data NgQ :: ! 715 | 716 | data Q :: * 717 | 718 | type QEff e r = Eff (ngq :: NgQ | e) r 719 | 720 | 721 | ### Values 722 | 723 | all :: forall e a b. [Promise a b] -> Q -> QEff e (Promise b [a]) 724 | 725 | defer :: forall e a b. Q -> QEff e (Deferred a b) 726 | 727 | reject :: forall e a b. a -> Q -> QEff e (Promise a b) 728 | 729 | when :: forall e a b. b -> Q -> QEff e (Promise a b) 730 | 731 | 732 | ## Module Angular.Scope 733 | 734 | ### Types 735 | 736 | data ApplyExpr e r a where 737 | DefaultApplyExpr :: ApplyExpr e r a 738 | StringApplyExpr :: String -> ApplyExpr e r a 739 | FnApplyExpr :: (Scope a -> Eff e r) -> ApplyExpr e r a 740 | 741 | type Event e a b = { defaultPrevented :: Boolean, preventDefault :: Eff e Unit, stopPropagation :: Eff e Unit, name :: String, currentScope :: Scope b, targetScope :: Scope a } 742 | 743 | data NgReadScope :: ! 744 | 745 | data NgScope :: ! 746 | 747 | data NgWriteScope :: ! 748 | 749 | data OnDeregistration :: * 750 | 751 | type ReadEff e a = Eff (ngrscope :: NgReadScope | e) { | a } 752 | 753 | type ReadWriteEff e r = Eff (ngwscope :: NgWriteScope, ngrscope :: NgReadScope | e) r 754 | 755 | data Scope :: # * -> * 756 | 757 | type ScopeEff e r = Eff (ngscope :: NgScope | e) r 758 | 759 | data WatchDeregistration :: * 760 | 761 | type WatchListener e a b = a -> a -> Scope b -> Eff e Unit 762 | 763 | type WriteEff e = Eff (ngwscope :: NgWriteScope | e) Unit 764 | 765 | 766 | ### Values 767 | 768 | apply :: forall e r a. ApplyExpr e r a -> Scope a -> ScopeEff e r 769 | 770 | applyExpr :: forall e r a. (Scope a -> Eff e r) -> ApplyExpr e r a 771 | 772 | broadcast :: forall e a b c. String -> a -> Scope b -> ScopeEff e (Event e b c) 773 | 774 | defaultApplyExpr :: forall e r a. ApplyExpr e r a 775 | 776 | deregisterOn :: OnDeregistration -> Unit 777 | 778 | deregisterWatch :: WatchDeregistration -> Unit 779 | 780 | destroy :: forall e a. Scope a -> ScopeEff e Unit 781 | 782 | digest :: forall e a. Scope a -> ScopeEff e Unit 783 | 784 | emit :: forall e a b c. String -> a -> Scope b -> ScopeEff e (Event e b c) 785 | 786 | evalAsync :: forall e r a. Maybe (Scope a -> Eff e r) -> Scope a -> ScopeEff e r 787 | 788 | evalSync :: forall e r a b. Maybe (Scope a -> Eff e r) -> Maybe { | b } -> Scope a -> ScopeEff e r 789 | 790 | extendScope :: forall e a b. { | b } -> Scope a -> WriteEff e 791 | 792 | id :: forall a. Scope a -> String 793 | 794 | modifyScope :: forall e a b. ({ | a } -> ReadWriteEff e { | b }) -> Scope a -> ReadWriteEff e Unit 795 | 796 | newScope :: forall e a b. Boolean -> Scope a -> ScopeEff e (Scope b) 797 | 798 | on :: forall e a b c. String -> (Event e a b -> c -> Eff e Unit) -> Scope b -> ScopeEff e OnDeregistration 799 | 800 | parent :: forall a b. Scope a -> Maybe (Scope b) 801 | 802 | readScope :: forall e a. Scope a -> ReadEff e a 803 | 804 | root :: forall a b. Scope a -> Scope b 805 | 806 | stringApplyExpr :: forall e r a. String -> ApplyExpr e r a 807 | 808 | watch :: forall e a b. String -> Maybe (WatchListener e a b) -> Boolean -> Scope b -> ScopeEff e WatchDeregistration 809 | 810 | watchCollection :: forall e a b. String -> WatchListener e a b -> Scope b -> ScopeEff e WatchDeregistration 811 | 812 | writeScope :: forall e a b. String -> b -> Scope a -> WriteEff e 813 | 814 | 815 | ## Module Angular.This 816 | 817 | ### Types 818 | 819 | data NgReadThis :: ! 820 | 821 | data NgWriteThis :: ! 822 | 823 | type ReadEff e a = Eff (ngrthis :: NgReadThis | e) { | a } 824 | 825 | type ReadWriteEff e r = Eff (ngwthis :: NgWriteThis, ngrthis :: NgReadThis | e) r 826 | 827 | data This :: # * -> * 828 | 829 | type WriteEff e = Eff (ngwthis :: NgWriteThis | e) Unit 830 | 831 | 832 | ### Values 833 | 834 | extendThis :: forall e a b. { | b } -> This a -> WriteEff e 835 | 836 | modifyThis :: forall e a b. ({ | a } -> ReadWriteEff e { | b }) -> This a -> ReadWriteEff e Unit 837 | 838 | readThis :: forall e a. This a -> ReadEff e a 839 | 840 | writeThis :: forall e a b. String -> b -> This a -> WriteEff e 841 | 842 | 843 | ## Module Angular.Timeout 844 | 845 | ### Types 846 | 847 | data NgTimeout :: ! 848 | 849 | data Timeout :: * 850 | 851 | type TimeoutEff e r = Eff (ngtimeout :: NgTimeout | e) r 852 | 853 | type TimeoutPromise a = Promise Error a 854 | 855 | 856 | ### Values 857 | 858 | cancel :: forall e r. TimeoutPromise r -> Timeout -> TimeoutEff e Boolean 859 | 860 | timeout :: forall e f r. Eff f r -> Number -> Boolean -> Timeout -> TimeoutEff e (TimeoutPromise r) 861 | 862 | timeout' :: forall e f r. Eff f r -> Number -> Timeout -> TimeoutEff e (TimeoutPromise r) 863 | 864 | timeout'' :: forall e f r. Eff f r -> Timeout -> TimeoutEff e (TimeoutPromise r) 865 | 866 | timeoutk :: forall e f r. Number -> Boolean -> Timeout -> Eff f r -> TimeoutEff e (TimeoutPromise r) 867 | 868 | 869 | ## Module Angular.Http.Internal 870 | 871 | ### Types 872 | 873 | data ForeignConfig :: * 874 | 875 | data ForeignResponse :: * 876 | 877 | 878 | ### Type Class Instances 879 | 880 | instance errorForeignResponse :: Error ForeignResponse 881 | 882 | 883 | ### Values 884 | 885 | foreignConfig :: forall e. HttpEff e ForeignConfig 886 | 887 | getConfigCache :: ForeignConfig -> Either Boolean Cache 888 | 889 | getConfigHeaders :: ForeignConfig -> Headers 890 | 891 | getConfigMethod :: ForeignConfig -> D.HttpMethod 892 | 893 | getConfigParams :: forall a. ForeignConfig -> { | a } 894 | 895 | getConfigRequestData :: forall e a. ForeignConfig -> RequestData a 896 | 897 | getConfigResponseType :: ForeignConfig -> D.ResponseType 898 | 899 | getConfigTimeout :: forall a b. ForeignConfig -> Either Number (Promise a b) 900 | 901 | getConfigUrl :: ForeignConfig -> D.Url 902 | 903 | getConfigWithCredentials :: ForeignConfig -> Boolean 904 | 905 | getConfigXsrfCookieName :: ForeignConfig -> String 906 | 907 | getConfigXsrfHeaderName :: ForeignConfig -> String 908 | 909 | getResponseConfig :: ForeignResponse -> ForeignConfig 910 | 911 | getResponseData :: forall a. D.ResponseType -> ForeignResponse -> D.HttpData a 912 | 913 | getResponseHeaders :: ForeignResponse -> [String] -> String 914 | 915 | getResponseStatus :: ForeignResponse -> Status 916 | 917 | getResponseStatusText :: ForeignResponse -> String 918 | 919 | setConfigCache :: forall e. Either Boolean Cache -> ForeignConfig -> HttpEff e Unit 920 | 921 | setConfigHeaders :: forall e. Headers -> ForeignConfig -> HttpEff e Unit 922 | 923 | setConfigMethod :: forall e. D.HttpMethod -> ForeignConfig -> HttpEff e Unit 924 | 925 | setConfigParams :: forall e a. { | a } -> ForeignConfig -> HttpEff e Unit 926 | 927 | setConfigRequestData :: forall e a. RequestData a -> ForeignConfig -> HttpEff e Unit 928 | 929 | setConfigResponseType :: forall e. D.ResponseType -> ForeignConfig -> HttpEff e Unit 930 | 931 | setConfigTimeout :: forall e a b. Either Number (Promise a b) -> ForeignConfig -> HttpEff e Unit 932 | 933 | setConfigUrl :: forall e. D.Url -> ForeignConfig -> HttpEff e Unit 934 | 935 | setConfigWithCredentials :: forall e. Boolean -> ForeignConfig -> HttpEff e Unit 936 | 937 | setConfigXsrfCookieName :: forall e. String -> ForeignConfig -> HttpEff e Unit 938 | 939 | setConfigXsrfHeaderName :: forall e. String -> ForeignConfig -> HttpEff e Unit 940 | 941 | 942 | ## Module Angular.Http.Types 943 | 944 | ### Types 945 | 946 | data ForeignCache :: * 947 | 948 | data ForeignHeaders :: * 949 | 950 | data ForeignRequestData :: * 951 | 952 | data ForeignResponseData :: * 953 | 954 | data ForeignTimeout :: * 955 | 956 | type Header = Tuple String (Either String (Unit -> String)) 957 | 958 | newtype Headers where 959 | Headers :: [Header] -> Headers 960 | 961 | type HttpEff e r = Eff (nghttp :: NgHttp | e) r 962 | 963 | data NgHttp :: ! 964 | 965 | data RequestData a where 966 | NoRequestData :: RequestData a 967 | StringRequestData :: String -> RequestData a 968 | ObjectRequestData :: a -> RequestData a 969 | 970 | type RequestDataFn a = { objectRequestData :: a -> RequestData a, stringRequestData :: String -> RequestData a, noRequestData :: RequestData a } 971 | 972 | data Status where 973 | OK :: Status 974 | Created :: Status 975 | NoContent :: Status 976 | BadRequest :: Status 977 | Unauthorized :: Status 978 | Forbidden :: Status 979 | NotFound :: Status 980 | InternalServerError :: Status 981 | OtherStatus :: Number -> Status 982 | 983 | 984 | ### Values 985 | 986 | cataRequestData :: forall a b. b -> (String -> b) -> (a -> b) -> RequestData a -> b 987 | 988 | fnHeader :: String -> (Unit -> String) -> Header 989 | 990 | readCacheFn :: Fn3 (Boolean -> Either Boolean Cache) (Cache -> Either Boolean Cache) ForeignCache (Either Boolean Cache) 991 | 992 | readHeadersFn :: forall a b. Fn4 (String -> Either String (Unit -> String)) ((Unit -> String) -> Either String (Unit -> String)) (String -> Either String (Unit -> String) -> Header) ForeignHeaders Headers 993 | 994 | readMethod :: String -> D.HttpMethod 995 | 996 | readRequestDataFn :: forall a. Fn2 (RequestDataFn a) ForeignRequestData (RequestData a) 997 | 998 | readResponseData :: forall a d. (d -> D.HttpData a) -> ForeignResponseData -> D.HttpData a 999 | 1000 | readResponseType :: String -> D.ResponseType 1001 | 1002 | readStatus :: Number -> Status 1003 | 1004 | readTimeoutFn :: forall a b. Fn3 (Number -> Either Number (Promise a b)) (Promise a b -> Either Number (Promise a b)) ForeignTimeout (Either Number (Promise a b)) 1005 | 1006 | stringHeader :: String -> String -> Header 1007 | 1008 | writeRequestData :: forall a. RequestData a -> ForeignRequestData 1009 | 1010 | 1011 | 1012 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # purescript-angular 2 | 3 | [AngularJS 1.2 bindings](MODULE.md) for PureScript. 4 | 5 | **NOTICE**: This module is currently in the experimental stage. 6 | 7 | ## Examples 8 | 9 | ### todomvc 10 | 11 | The [todomvc](http://todomvc.com/architecture-examples/angularjs) has been implemented as an example. The example may be run as follows. 12 | 13 | ```bash 14 | purescript-angular $ npm install 15 | 16 | purescript-angular $ bower install 17 | 18 | purescript-angular $ gulp todomvc 19 | 20 | purescript-angular $ gulp watch.todomvc 21 | ``` 22 | 23 | Then visit: [http://localhost:9501/examples/Todomvc/main.html](http://localhost:9501/examples/Todomvc/main.html). 24 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-angular", 3 | "homepage": "https://github.com/purescript-contrib/purescript-angular", 4 | "description": "AngularJS", 5 | "keywords": [ 6 | "purescript" 7 | ], 8 | "license": "MIT", 9 | "ignore": [ 10 | "**/.*", 11 | "node_modules", 12 | "bower_components", 13 | "examples", 14 | "externs", 15 | "js", 16 | "dist" 17 | ], 18 | "dependencies": { 19 | "purescript-arrays": "~0.3.0", 20 | "purescript-either": "~0.1.4", 21 | "purescript-exceptions": "~0.2.2", 22 | "purescript-foldable-traversable": "~0.2.1", 23 | "purescript-maybe": "~0.2.1", 24 | "purescript-transformers": "~0.4.0", 25 | "purescript-tuples": "~0.2.2", 26 | "purescript-simple-dom": "aktowns/purescript-simple-dom#2b6f81d9fe9e161b8ffc3a3885483c8859a475a8" 27 | }, 28 | "devDependencies": { 29 | "angular": "1.2.26", 30 | "todomvc-common": "0.1.9", 31 | "purescript-strings": "~0.4.1", 32 | "purescript-control": "~0.2.1", 33 | "purescript-free": "~0.2.0", 34 | "purescript-foreign": "~0.3.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/Backend/Main.purs: -------------------------------------------------------------------------------- 1 | module Backend.Main where 2 | 3 | import Control.Monad.Eff 4 | import Data.Either (either) 5 | 6 | import Angular.Http (Http(), get) 7 | import Angular.Module (controller, ngmodule') 8 | import Angular.Promise (liftPromiseEC, runPromiseEC) 9 | import Angular.This (extendThis) 10 | 11 | mainctrl http this = extendThis { text: "" 12 | , submit: submit } this 13 | where 14 | url = "http://localhost:9501/examples/Backend/main.html" 15 | submit a = runPromiseEC (liftPromiseEC $ get url http) 16 | (either (\e -> extendThis { value: "Failed to get" ++ url } this) 17 | (\a -> extendThis { value: a."data" } this)) 18 | 19 | main = do 20 | m <- ngmodule' "backend" [] 21 | controller "Main" mainctrl' m 22 | 23 | foreign import mainctrl' 24 | """ 25 | /*@ngInject*/function mainctrl$prime($http) { 26 | var impl = mainctrl($http)(this); 27 | return impl.apply(this, []); 28 | } 29 | """ :: forall e a. Http -> Eff e Unit 30 | -------------------------------------------------------------------------------- /examples/Backend/main.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 9 | Backend 10 | 12 | 14 | 16 | 17 | 18 |
20 | 23 |
24 | 25 | {{mainctrl.value.value0}} 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/Todomvc/Controller.purs: -------------------------------------------------------------------------------- 1 | module Todomvc.Controller (todoctrl) where 2 | 3 | import qualified Data.Array as A 4 | import qualified Data.String as S 5 | import Data.Foldable 6 | import Data.Maybe 7 | import Control.Apply ((*>)) 8 | import Control.Monad (unless, when) 9 | import Control.Monad.Eff 10 | 11 | import Angular (copy, extend) 12 | import Angular.Location (Location(), getPath, setPath) 13 | import Angular.Scope (Scope(), watch, readScope, extendScope, modifyScope) 14 | import Angular.This (readThis, writeThis) 15 | 16 | import Todomvc.Storage (Store(), Todo(), get, put) 17 | 18 | addTodo scope = do 19 | s <- readScope scope 20 | let title = S.trim s.newTodo 21 | let empty = (S.length title) == 0 22 | unless empty $ do 23 | let todo = { title: title, completed: false } 24 | todos <- get 25 | let res = todos <> [todo] 26 | put res 27 | extendScope { todos: res 28 | , newTodo: "" 29 | , remainingCount: s.remainingCount + 1 } scope 30 | 31 | todoCompleted scope todo 32 | = modifyScope (\s -> do 33 | let change = if todo.completed then -1 else 1 34 | put s.todos 35 | return { remainingCount: s.remainingCount + change } 36 | ) scope 37 | 38 | clearCompletedTodos scope = do 39 | s <- readScope scope 40 | let res = A.filter (\a -> not a.completed) s.todos 41 | put res 42 | extendScope { todos: res } scope 43 | 44 | markAll scope compl 45 | = modifyScope (\s -> do 46 | let res = (\a -> a { completed = not compl }) <$> s.todos 47 | put res 48 | return { todos: res 49 | , remainingCount: if compl then A.length res else 0 } 50 | ) scope 51 | 52 | editTodo scope todo = do 53 | cp <- copy todo 54 | extendScope { editedTodo: Just todo 55 | , originalTodo: Just $ cp } scope 56 | 57 | doneEditing scope todo 58 | = modifyScope (\s -> do 59 | let title = S.trim todo.title 60 | when (S.length title == 0) $ removeTodo scope todo 61 | extend todo { title: title } 62 | put s.todos 63 | return { editedTodo: Nothing } 64 | ) scope 65 | 66 | removeTodo scope todo = do 67 | s <- readScope scope 68 | let res = A.filter (\a -> not $ refEq a todo) s.todos 69 | unless (A.length res == A.length s.todos) do 70 | let c = if todo.completed then 0 else -1 71 | extendScope { todos: res 72 | , remainingCount: s.remainingCount + c } scope 73 | put res 74 | 75 | revertEditing scope todo = do 76 | s <- readScope scope 77 | let res = A.filter (\a -> not $ refEq a todo) s.todos 78 | unless (A.length res == A.length s.todos) do 79 | case s.originalTodo of 80 | Just t -> extendScope { todos: res <> [t] } scope *> 81 | doneEditing scope t 82 | Nothing -> return unit 83 | 84 | watchRemainingCount scope = 85 | let expr = "remainingCount == 0" 86 | listener = \a _ _ -> extendScope { allChecked: a } scope 87 | in watch expr (return listener) false scope 88 | 89 | watchLocationPath scope = 90 | let expr = "location.path()" 91 | listener = \a _ _ -> case a of 92 | "/completed" -> extendScope { statusFilter: { completed: true } } scope 93 | "/active" -> extendScope { statusFilter: { completed: false } } scope 94 | _ -> extendScope { statusFilter: { } } scope 95 | in watch expr (return listener) false scope 96 | 97 | todoctrl scope this location = do 98 | t <- readThis this 99 | path <- getPath location 100 | if S.length path == 0 then setPath "/" location else return "" 101 | watchRemainingCount scope 102 | watchLocationPath scope 103 | todos <- get 104 | let remainingCount = foldl (\b a -> if a.completed then b else b + 1) 0 todos 105 | extendScope { fromMaybe: fromMaybe 106 | , newTodo: "" 107 | , editedTodo: Nothing 108 | , originalTodo: Nothing 109 | , todos: todos 110 | , remainingCount: remainingCount 111 | , location: location 112 | , addTodo: addTodo scope 113 | , todoCompleted: todoCompleted scope 114 | , clearCompletedTodos: clearCompletedTodos scope 115 | , markAll: markAll scope 116 | , editTodo: editTodo scope 117 | , doneEditing: doneEditing scope 118 | , removeTodo: removeTodo scope 119 | , revertEditing: revertEditing scope } scope 120 | -------------------------------------------------------------------------------- /examples/Todomvc/Escape.purs: -------------------------------------------------------------------------------- 1 | module Todomvc.Escape (EscapeDirective(), escape) where 2 | 3 | import Data.Maybe 4 | import Control.Bind ((>=>)) 5 | 6 | import Data.DOM.Simple.Events (keyCode) 7 | 8 | import Angular.Attributes (get) 9 | import Angular.Element (on) 10 | import Angular.Scope (apply, stringApplyExpr) 11 | 12 | foreign import data EscapeDirective :: * 13 | 14 | escapeKey = 27 15 | 16 | link scope element attrs = do 17 | on "keydown" (keyCode >=> \kc -> 18 | if kc == escapeKey 19 | then (get attrs) >>= (\as -> apply (stringApplyExpr as.todoEscape) scope) 20 | else return unit) element 21 | 22 | foreign import escape 23 | " /*@ngInject*/function escape(){ \ 24 | \ return { \ 25 | \ link: function($scope, $element, $attrs){ \ 26 | \ return link($scope)($element)($attrs)(); \ 27 | \ } \ 28 | \ }; \ 29 | \ } " :: EscapeDirective 30 | -------------------------------------------------------------------------------- /examples/Todomvc/Focus.purs: -------------------------------------------------------------------------------- 1 | module Todomvc.Focus (FocusDirective(), focus) where 2 | 3 | import Data.Maybe 4 | import Control.Monad (when) 5 | import Control.Monad.Eff 6 | 7 | import qualified Data.DOM.Simple.Element as D 8 | 9 | import Angular.Attributes (get) 10 | import Angular.Element ((!!)) 11 | import Angular.Scope (watch, apply, applyExpr) 12 | import Angular.Timeout (timeout) 13 | 14 | foreign import data FocusDirective :: * 15 | 16 | link scope element attrs ngtimeout = do 17 | as <- get attrs 18 | let k = maybe (return unit) D.focus (element !! 0) 19 | watch as.todoFocus (Just (\a _ _ -> when a $ const unit <$> (timeout k 0 false ngtimeout))) false scope 20 | 21 | foreign import focus 22 | " /*@ngInject*/function focus($timeout){ \ 23 | \ return { \ 24 | \ link: function($scope, $element, $attrs){ \ 25 | \ return link($scope)($element)($attrs)($timeout)(); \ 26 | \ } \ 27 | \ }; \ 28 | \ } " :: FocusDirective 29 | -------------------------------------------------------------------------------- /examples/Todomvc/Main.purs: -------------------------------------------------------------------------------- 1 | module Todomvc.Main where 2 | 3 | import Angular.Module (controller, directive, ngmodule') 4 | import Angular.DI (annotate) 5 | 6 | import Todomvc.Controller (todoctrl) 7 | import Todomvc.Escape (escape) 8 | import Todomvc.Focus (focus) 9 | 10 | main = do 11 | m <- ngmodule' "todomvc" [] 12 | controller "TodoCtrl" (annotate todoctrl) m 13 | directive "todoEscape" escape m 14 | directive "todoFocus" focus m 15 | -------------------------------------------------------------------------------- /examples/Todomvc/Storage.purs: -------------------------------------------------------------------------------- 1 | module Todomvc.Storage 2 | ( Todo(..) 3 | , Store(..) 4 | , get 5 | , put 6 | ) where 7 | 8 | import Control.Monad.Eff 9 | 10 | type Todo = { title :: String , completed :: Boolean } 11 | 12 | foreign import data Store :: ! 13 | 14 | storageId :: String 15 | storageId = "todos-angularjs-perf-purs" 16 | 17 | foreign import get 18 | " function get(){ \ 19 | \ return JSON.parse(localStorage.getItem(storageId) || '[]'); \ 20 | \ }" 21 | :: forall e. Eff (store :: Store | e) [Todo] 22 | 23 | foreign import put 24 | " function put(todos){ \ 25 | \ return function(){ \ 26 | \ return localStorage.setItem(storageId, JSON.stringify(todos)); \ 27 | \ }; \ 28 | \ }" 29 | :: forall e. [Todo] -> Eff (store :: Store | e) Unit 30 | -------------------------------------------------------------------------------- /examples/Todomvc/main.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | AngularJS • TodoMVC 8 | 10 | 12 | 13 | 14 |
16 | 26 |
29 | 33 | 34 | 56 |
57 | 82 |
83 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /examples/TodomvcF/AppI.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.AppI 2 | ( AppE() 3 | , run 4 | ) where 5 | 6 | import Control.Alt ((<|>)) 7 | import Control.Monad.Eff (Eff()) 8 | import Control.Monad.Free (goEffC, goMC) 9 | import Data.Coyoneda (Natural()) 10 | import Data.Inject (prj) 11 | import Data.Maybe.Unsafe (fromJust) 12 | 13 | import TodomvcF.StorageI (Store(), storageN) 14 | import TodomvcF.ThisF (ThisF(), ForeignThis()) 15 | import TodomvcF.ThisI (FThis(), thisN) 16 | import TodomvcF.TodomvcF (Todomvc()) 17 | import TodomvcF.TodomvcI (AppF(), AppT(), App(), todomvcN) 18 | 19 | type AppE e = Eff (store :: Store, this :: FThis | e) 20 | 21 | appN :: forall e. Natural AppF (AppE e) 22 | appN fa = fromJust $ (storageN <$> prj fa) <|> 23 | ((thisN :: forall e. Natural (ThisF AppT) 24 | (Eff (this :: FThis | e))) <$> prj fa) 25 | 26 | runTodomvc :: forall a. ForeignThis AppT -> Todomvc a -> App a 27 | runTodomvc t = goMC (todomvcN t) 28 | 29 | runApp :: forall e a. App a -> AppE e a 30 | runApp = goEffC appN 31 | 32 | run :: forall e a. ForeignThis AppT -> Todomvc a -> AppE e a 33 | run t = runApp <<< (runTodomvc t) 34 | -------------------------------------------------------------------------------- /examples/TodomvcF/Escape.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.Escape (EscapeDirective(), escape) where 2 | 3 | import Data.Maybe 4 | import Control.Bind ((>=>)) 5 | 6 | import Data.DOM.Simple.Events (keyCode) 7 | 8 | import Angular.Attributes (get) 9 | import Angular.Element (on) 10 | import Angular.Scope (apply, stringApplyExpr) 11 | 12 | foreign import data EscapeDirective :: * 13 | 14 | escapeKey = 27 15 | 16 | link scope element attrs = on "keydown" (keyCode >=> \kc -> 17 | if kc == escapeKey 18 | then (get attrs) >>= (\as -> apply (stringApplyExpr as.todoEscape) scope) 19 | else return unit) element 20 | 21 | foreign import escape """ 22 | /*@ngInject*/function escape(){ 23 | return { 24 | link: function($scope, $element, $attrs){ 25 | return link($scope)($element)($attrs)(); 26 | } 27 | }; 28 | } 29 | """ :: EscapeDirective 30 | -------------------------------------------------------------------------------- /examples/TodomvcF/Focus.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.Focus (FocusDirective(), focus) where 2 | 3 | import Data.Maybe 4 | import Control.Monad (when) 5 | import Control.Monad.Eff 6 | 7 | import qualified Data.DOM.Simple.Element as D 8 | 9 | import Angular.Attributes (get) 10 | import Angular.Element ((!!)) 11 | import Angular.Scope (watch, apply, applyExpr) 12 | import Angular.Timeout (timeout) 13 | 14 | foreign import data FocusDirective :: * 15 | 16 | link scope element attrs ngtimeout = do 17 | as <- get attrs 18 | let k = maybe (return unit) D.focus (element !! 0) 19 | watch as.todoFocus (Just (\a _ _ -> when a $ const unit <$> (timeout k 0 false ngtimeout))) false scope 20 | 21 | foreign import focus """ 22 | /*@ngInject*/function focus($timeout){ 23 | return { 24 | link: function($scope, $element, $attrs){ 25 | return link($scope)($element)($attrs)($timeout)(); 26 | } 27 | }; 28 | } 29 | """ :: FocusDirective 30 | -------------------------------------------------------------------------------- /examples/TodomvcF/Main.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.Main where 2 | 3 | import Control.Monad.Eff (Eff()) 4 | import Data.Array (filter, length) 5 | import Data.Maybe (Maybe(..), fromMaybe) 6 | import qualified Data.String as S 7 | 8 | import Angular.Module (controller, directive, ngmodule') 9 | import Angular.Location (getPath, setPath) 10 | import Angular.This (readThis, extendThis) 11 | 12 | import TodomvcF.AppI (run) 13 | import TodomvcF.Escape (escape) 14 | import TodomvcF.Focus (focus) 15 | import TodomvcF.ThisF (ForeignThis()) 16 | import TodomvcF.TodomvcF (Todo(..), add, all, remove, edit, revert, clearCompleted, markAll, completed, doneEdit) 17 | import TodomvcF.TodomvcI (AppT(..)) 18 | 19 | mainctrl this location = 20 | let app = { newTodo: "" 21 | , todos: [] 22 | , remainingCount: 0 23 | , originalTodo: Nothing :: Maybe Todo 24 | , editedTodo: Nothing :: Maybe Todo } 25 | in do 26 | getPath location >>= (\p -> if S.length p == 0 then setPath "/" location else pure "") 27 | todos <- run (toForeignThis $ AppT app) all 28 | let app' = app { todos = todos 29 | , remainingCount = length (filter (\(Todo t) -> not t.completed) todos) } 30 | extendThis { add: add 31 | , all: all 32 | , remove: remove 33 | , edit: edit 34 | , revert: revert 35 | , clearCompleted: clearCompleted 36 | , markAll: markAll 37 | , completed: completed 38 | , doneEdit: doneEdit 39 | , statusFilter: statusFilter 40 | , location: location 41 | , fromMaybe: fromMaybe 42 | , run: (run <<< toForeignThis <<< AppT) app' 43 | , app: app' } this 44 | where 45 | statusFilter = (\path -> case path of 46 | "/completed" -> Just { completed: true } 47 | "/active" -> Just { completed: false } 48 | _ -> Nothing) <$> getPath location 49 | 50 | main = do 51 | m <- ngmodule' "todomvcf" [] 52 | controller "Main" mainctrl' m 53 | directive "todoEscape" escape m 54 | directive "todoFocus" focus m 55 | 56 | foreign import toForeignThis """ 57 | function toForeignThis(that){ 58 | return that; 59 | } 60 | """ :: AppT -> ForeignThis AppT 61 | 62 | foreign import mainctrl' """ 63 | /*@ngInject*/function mainctrl$prime($location) { 64 | var impl = mainctrl(this)($location); 65 | return impl.apply(this, []); 66 | } 67 | """ :: forall e a. Eff e Unit 68 | -------------------------------------------------------------------------------- /examples/TodomvcF/StorageF.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.StorageF 2 | ( Storage() 3 | , StorageF(..) 4 | , Key() 5 | , Value() 6 | , get 7 | , set 8 | ) where 9 | 10 | import Control.Monad.Free (FreeC(), liftFC) 11 | import Data.Foreign (Foreign()) 12 | import Data.Maybe (Maybe()) 13 | 14 | type Storage a = FreeC StorageF a 15 | 16 | type Key = String 17 | 18 | type Value = Foreign 19 | 20 | data StorageF a 21 | = Get Key (Maybe Value -> a) 22 | | Set Key Value a 23 | 24 | get :: Key -> Storage (Maybe Value) 25 | get k = liftFC $ Get k id 26 | 27 | set :: Key -> Value -> Storage Unit 28 | set k v = liftFC $ Set k v unit 29 | -------------------------------------------------------------------------------- /examples/TodomvcF/StorageI.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.StorageI 2 | ( Store() 3 | , storageN 4 | ) where 5 | 6 | import Control.Monad.Eff (Eff()) 7 | import Data.Coyoneda (Natural()) 8 | import Data.Function (Fn3(..), runFn3) 9 | import Data.Maybe (Maybe(..)) 10 | 11 | import TodomvcF.StorageF (StorageF(..), Key(), Value()) 12 | 13 | foreign import data Store :: ! 14 | 15 | storageN :: forall e. Natural StorageF (Eff (store :: Store | e)) 16 | storageN (Get k l) = l <$> runFn3 getFn Nothing Just k 17 | storageN (Set k v a) = const a <$> runFn3 setFn unit k v 18 | 19 | foreign import getFn """ 20 | function getFn(nothing, just, key) { 21 | return function(){ 22 | var value = localStorage.getItem(key); 23 | return value ? just(value) : nothing; 24 | }; 25 | } 26 | """ :: forall e. Fn3 (Maybe Value) 27 | (Value -> Maybe Value) 28 | Key 29 | (Eff (store :: Store | e) (Maybe Value)) 30 | 31 | foreign import setFn """ 32 | function setFn(unit, key, value){ 33 | return function(){ 34 | localStorage.setItem(key, JSON.stringify(value)); 35 | return unit; 36 | }; 37 | } 38 | """ :: forall e. Fn3 Unit 39 | Key 40 | Value 41 | (Eff (store :: Store | e) Unit) 42 | -------------------------------------------------------------------------------- /examples/TodomvcF/ThisF.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.ThisF 2 | ( This() 3 | , ThisF(..) 4 | , ForeignThis() 5 | , read 6 | , extend 7 | ) where 8 | 9 | import Control.Monad.Free (FreeC(), liftFC) 10 | 11 | foreign import data ForeignThis :: * -> * 12 | 13 | type This b a = FreeC (ThisF b) a 14 | 15 | data ThisF b a 16 | = Read (ForeignThis b) (b -> a) 17 | | Extend b (ForeignThis b) a 18 | 19 | read :: forall b. ForeignThis b -> This b b 20 | read t = liftFC $ Read t id 21 | 22 | extend :: forall b. b -> ForeignThis b -> This b Unit 23 | extend b t = liftFC $ Extend b t unit 24 | -------------------------------------------------------------------------------- /examples/TodomvcF/ThisI.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.ThisI 2 | ( FThis() 3 | , thisN 4 | ) where 5 | 6 | import Control.Monad.Eff (Eff()) 7 | import Data.Coyoneda (Natural()) 8 | import Data.Function (Fn3(..), runFn3) 9 | 10 | import TodomvcF.ThisF (ThisF(..), ForeignThis()) 11 | 12 | foreign import data FThis :: ! 13 | 14 | thisN :: forall b e. Natural (ThisF b) (Eff (this :: FThis | e)) 15 | thisN (Read t k) = (pure <<< k <<< readFn) t 16 | thisN (Extend b t a) = const a <$> runFn3 extendFn unit b t 17 | 18 | foreign import readFn """ 19 | function readFn(that) { 20 | return that; 21 | } 22 | """ :: forall b. ForeignThis b -> b 23 | 24 | foreign import extendFn """ 25 | function extendFn(unit, b, that){ 26 | return function(){ 27 | angular.extend(that, b); 28 | return unit; 29 | }; 30 | } 31 | """ :: forall b e. Fn3 Unit 32 | b 33 | (ForeignThis b) 34 | (Eff (this :: FThis | e) Unit) 35 | -------------------------------------------------------------------------------- /examples/TodomvcF/TodomvcF.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.TodomvcF 2 | ( Todo(..) 3 | , Todomvc() 4 | , TodomvcF(..) 5 | , add 6 | , remove 7 | , edit 8 | , revert 9 | , all 10 | , clearCompleted 11 | , markAll 12 | , completed 13 | , doneEdit 14 | ) where 15 | 16 | import Control.Monad.Free (FreeC(), liftFC) 17 | import Data.Foreign.Class (IsForeign, read, readProp) 18 | 19 | newtype Todo = Todo { title :: String , completed :: Boolean } 20 | 21 | type Todomvc a = FreeC TodomvcF a 22 | 23 | data TodomvcF a 24 | = Add Todo a 25 | | Remove Todo a 26 | | Edit Todo a 27 | | Revert Todo a 28 | | All ([Todo] -> a) 29 | | ClearCompleted a 30 | | MarkAll Boolean a 31 | | Completed Todo a 32 | | DoneEdit Todo a 33 | 34 | instance todoIsForeign :: IsForeign Todo where 35 | read a = do 36 | title <- readProp "title" a 37 | completed <- readProp "completed" a 38 | return $ Todo { title: title 39 | , completed: completed } 40 | 41 | add :: Todo -> Todomvc Unit 42 | add t = liftFC $ Add t unit 43 | 44 | remove :: Todo -> Todomvc Unit 45 | remove t = liftFC $ Remove t unit 46 | 47 | edit :: Todo -> Todomvc Unit 48 | edit t = liftFC $ Edit t unit 49 | 50 | doneEdit :: Todo -> Todomvc Unit 51 | doneEdit t = liftFC $ DoneEdit t unit 52 | 53 | revert :: Todo -> Todomvc Unit 54 | revert t = liftFC $ Revert t unit 55 | 56 | all :: Todomvc [Todo] 57 | all = liftFC $ All id 58 | 59 | clearCompleted :: Todomvc Unit 60 | clearCompleted = liftFC $ ClearCompleted unit 61 | 62 | markAll :: Boolean -> Todomvc Unit 63 | markAll c = liftFC $ MarkAll c unit 64 | 65 | completed :: Todo -> Todomvc Unit 66 | completed t = liftFC $ Completed t unit 67 | -------------------------------------------------------------------------------- /examples/TodomvcF/TodomvcI.purs: -------------------------------------------------------------------------------- 1 | module TodomvcF.TodomvcI 2 | ( AppF() 3 | , App() 4 | , AppT(..) 5 | , todomvcN 6 | ) where 7 | 8 | import Control.Alt ((<|>)) 9 | import Control.Monad (unless, when) 10 | import Control.Monad.Eff (Eff()) 11 | import Control.Monad.Free (FreeC(), injC) 12 | import Data.Coyoneda (Natural()) 13 | import Data.Either (either) 14 | import Data.Foreign (F(), toForeign, readString) 15 | import Data.Foreign.Class (readJSON) 16 | import Data.Functor.Coproduct (Coproduct()) 17 | import Data.Maybe (Maybe(..), maybe) 18 | import qualified Data.Array as A 19 | import qualified Data.String as S 20 | 21 | import TodomvcF.TodomvcF (TodomvcF(..), Todo(..)) 22 | import TodomvcF.StorageF (StorageF(), get, set) 23 | import TodomvcF.ThisF (ThisF(), ForeignThis(), read, extend) 24 | 25 | newtype AppT = AppT { remainingCount :: Number 26 | , todos :: [Todo] 27 | , newTodo :: String 28 | , originalTodo :: Maybe Todo 29 | , editedTodo :: Maybe Todo } 30 | 31 | type AppF = Coproduct StorageF (ThisF AppT) 32 | 33 | type App = FreeC AppF 34 | 35 | todomvcN :: ForeignThis AppT -> Natural TodomvcF App 36 | todomvcN this fa = 37 | case fa of 38 | Add (Todo t) a -> let title = S.trim t.title 39 | empty = (S.length title == 0) 40 | in const a <$> unless empty do 41 | todos <- getOrEmpty 42 | let todos' = [Todo t { title = title }] <> todos 43 | setTodos todos' 44 | AppT this' <- injC $ read this 45 | extendApp (this' { remainingCount = this'.remainingCount + 1 46 | , todos = todos' 47 | , newTodo = "" }) this 48 | 49 | Remove (Todo t) a -> const a <$> remove t 50 | 51 | Edit (Todo t) a -> do 52 | AppT this' <- injC $ read this 53 | extendApp (this' { originalTodo = (Just <<< Todo) t { title = t.title } 54 | , editedTodo = (Just <<< Todo) t }) this 55 | return a 56 | 57 | DoneEdit (Todo t) a -> let title = S.trim t.title 58 | empty = (S.length title == 0) 59 | in do 60 | AppT this' <- injC $ read this 61 | if empty then remove t else setTodos this'.todos 62 | extendApp (this' { editedTodo = Nothing }) this 63 | return a 64 | 65 | Revert (Todo t) a -> do 66 | AppT this' <- injC $ read this 67 | let res = A.filter (not <<< refEq t <<< todoi) this'.todos 68 | n = A.length res 69 | m = A.length this'.todos 70 | const a <$> 71 | unless (n == m) (maybe (return unit) 72 | (\t -> let todos = [t] <> res 73 | in do 74 | setTodos todos 75 | extendApp (this' { todos = todos }) this 76 | return unit) this'.originalTodo) 77 | 78 | All k -> k <$> getOrEmpty 79 | 80 | ClearCompleted a -> do 81 | AppT this' <- injC $ read this 82 | let completed = A.filter (not <<< completedi) this'.todos 83 | setTodos completed 84 | extendApp (this' { remainingCount = this'.remainingCount 85 | , todos = completed }) this 86 | return a 87 | 88 | MarkAll v a -> do 89 | AppT this' <- injC $ read this 90 | let marked = (\(Todo a) -> Todo $ a { completed = not v }) <$> this'.todos 91 | setTodos marked 92 | extendApp (this' { remainingCount = if v then A.length marked else 0 93 | , todos = marked }) this 94 | return a 95 | 96 | Completed (Todo t) a -> do 97 | AppT this' <- injC $ read this 98 | setTodos this'.todos 99 | extendApp (this' { remainingCount = this'.remainingCount + 100 | if t.completed then -1 else 1 }) this 101 | return a 102 | 103 | where 104 | key = "todos-angularjs-perf-purs-f" 105 | completedi (Todo a) = a.completed 106 | todoi (Todo a) = a 107 | parse r = either (const []) id (readString r >>= readJSON) 108 | getOrEmpty = injC $ maybe [] parse <$> get key 109 | setTodos as = injC $ set key (toForeign as) 110 | extendApp a t = injC $ extend (AppT a) t 111 | remove t = do 112 | AppT this' <- injC $ read this 113 | let res = A.filter (not <<< refEq t <<< todoi) this'.todos 114 | n = A.length res 115 | m = A.length this'.todos 116 | unless (n == m) do 117 | setTodos res 118 | extendApp (this' { remainingCount = this'.remainingCount + if t.completed then 0 else -1 119 | , todos = res }) this 120 | -------------------------------------------------------------------------------- /examples/TodomvcF/main.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | AngularJS • TodoMVC 8 | 10 | 12 | 13 | 14 |
16 | 27 |
30 | 34 | 35 | 59 |
60 | 88 |
89 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp') 2 | , clean = require('gulp-clean') 3 | , gutil = require('gulp-util') 4 | , plumber = require('gulp-plumber') 5 | , purescript = require('gulp-purescript') 6 | , http = require('http') 7 | , nstatic = require('node-static') 8 | , config = { 9 | clean: ['dist', '.psci_modules'], 10 | purescript: { 11 | src: [ 12 | 'bower_components/purescript-*/src/**/*.purs*', 13 | 'src/**/*.purs' 14 | ], 15 | examples: { 16 | todomvc: { 17 | src: 'examples/Todomvc/**/*.purs', 18 | options: { 19 | main: 'Todomvc.Main', 20 | output: 'todomvc.js' 21 | } 22 | }, 23 | todomvcf: { 24 | src: 'examples/TodomvcF/**/*.purs', 25 | options: { 26 | main: 'TodomvcF.Main', 27 | output: 'todomvcf.js' 28 | } 29 | }, 30 | backend: { 31 | src: 'examples/Backend/**/*.purs', 32 | options: { 33 | main: 'Backend.Main', 34 | output: 'backend.js' 35 | } 36 | } 37 | }, 38 | dest: 'dist', 39 | docs: 'MODULE.md' 40 | }, 41 | nstatic: { 42 | root: '.', 43 | port: 9501 44 | } 45 | } 46 | ; 47 | 48 | function error(e) { 49 | gutil.log(gutil.colors.magenta('>>>> Error <<<<') + '\n' + e.toString().trim()); 50 | this.emit('end'); 51 | } 52 | 53 | function server(cb) { 54 | var file = new nstatic.Server(config.nstatic.root); 55 | http.createServer(function(request, response){ 56 | request.addListener('end', function(){ 57 | file.serve(request, response); 58 | }).resume(); 59 | }).listen(config.nstatic.port, function(){ 60 | gutil.log('Listening on port ' + gutil.colors.magenta(config.nstatic.port)); 61 | cb(); 62 | }); 63 | } 64 | 65 | function example(ex) { 66 | return (gulp.src([ex.src].concat(config.purescript.src)). 67 | pipe(plumber()). 68 | pipe(purescript.psc(ex.options)). 69 | on('error', error). 70 | pipe(gulp.dest(config.purescript.dest))); 71 | } 72 | 73 | gulp.task('clean', function(){ 74 | return ( 75 | gulp.src(config.clean, {read: false}). 76 | pipe(clean()) 77 | ); 78 | }); 79 | 80 | gulp.task('todomvc', ['clean'], function(){ 81 | return example(config.purescript.examples.todomvc); 82 | }); 83 | 84 | gulp.task('todomvcf', ['clean'], function(){ 85 | return example(config.purescript.examples.todomvcf); 86 | }); 87 | 88 | gulp.task('backend', ['clean'], function(){ 89 | return example(config.purescript.examples.backend); 90 | }); 91 | 92 | gulp.task('make', function(){ 93 | return ( 94 | gulp.src(config.purescript.src). 95 | pipe(plumber()). 96 | pipe(purescript.pscMake({output: config.purescript.dest})). 97 | on('error', error) 98 | ); 99 | }); 100 | 101 | gulp.task('psci', function(){ 102 | return ( 103 | gulp.src(config.purescript.src). 104 | pipe(plumber()). 105 | pipe(purescript.dotPsci()). 106 | on('error', error) 107 | ); 108 | }); 109 | 110 | gulp.task('docs', function(){ 111 | return ( 112 | gulp.src(config.purescript.src[1]). 113 | pipe(plumber()). 114 | pipe(purescript.pscDocs()). 115 | on('error', error). 116 | pipe(gulp.dest(config.purescript.docs)) 117 | ); 118 | }); 119 | 120 | gulp.task('watch', function(cb){ 121 | gulp.watch(config.purescript.src, ['make']); 122 | }); 123 | 124 | gulp.task('watch.todomvc', function(cb){ 125 | gulp.watch([config.purescript.examples.todomvc.src].concat(config.purescript.src), ['todomvc']); 126 | server(cb); 127 | }); 128 | 129 | gulp.task('watch.todomvcf', function(cb){ 130 | gulp.watch([config.purescript.examples.todomvcf.src].concat(config.purescript.src), ['todomvcf']); 131 | server(cb); 132 | }); 133 | 134 | gulp.task('watch.backend', function(cb){ 135 | gulp.watch([config.purescript.examples.backend.src].concat(config.purescript.src), ['backend']); 136 | server(cb); 137 | }); 138 | 139 | gulp.task('default', ['clean', 'make', 'docs', 'psci']); 140 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-angular", 3 | "private": true, 4 | "devDependencies": { 5 | "gulp": "3.8.10", 6 | "gulp-clean": "0.3.1", 7 | "gulp-plumber": "0.6.4", 8 | "gulp-purescript": "0.1.2", 9 | "gulp-util": "3.0.0", 10 | "node-static": "0.7.4" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Angular.purs: -------------------------------------------------------------------------------- 1 | module Angular where 2 | 3 | import Control.Monad.Eff 4 | 5 | import Angular.Injector (Injector()) 6 | import Angular.Element (Element()) 7 | 8 | -- | bind 9 | 10 | foreign import bootstrap 11 | " function bootstrap(element) { \ 12 | \ return function(modules){ \ 13 | \ return function(){ \ 14 | \ return angular.bootstrap(element, modules); \ 15 | \ }; \ 16 | \ }; \ 17 | \ }" 18 | :: forall e. Element -> [String] -> Eff e Injector 19 | 20 | foreign import copy 21 | " function copy(src) { \ 22 | \ return function() { \ 23 | \ return angular.copy(src); \ 24 | \ }; \ 25 | \ }" :: forall e a. a -> Eff e a 26 | 27 | -- | element => Angular.Element 28 | 29 | -- | equals 30 | 31 | foreign import extend 32 | " function extend(dst) { \ 33 | \ return function(src) { \ 34 | \ return function() { \ 35 | \ return angular.extend(dst, src); \ 36 | \ }; \ 37 | \ }; \ 38 | \ }" :: forall e a b c. { | a } -> { | b } -> Eff e { | c } 39 | 40 | -- | forEach 41 | 42 | -- | fromJson 43 | 44 | -- | identity 45 | 46 | -- | injector, see Angular.Injector 47 | 48 | foreign import isArray 49 | " function isArray(value) { \ 50 | \ return function() { \ 51 | \ return angular.isArray(value); \ 52 | \ }; \ 53 | \ }" :: forall e a. a -> Eff e Boolean 54 | 55 | foreign import isDate 56 | " function isDate(value) { \ 57 | \ return function() { \ 58 | \ return angular.isDate(value); \ 59 | \ }; \ 60 | \ }" :: forall e a. a -> Eff e Boolean 61 | 62 | foreign import isDefined 63 | " function isDefined(value) { \ 64 | \ return function() { \ 65 | \ return angular.isDefined(value); \ 66 | \ }; \ 67 | \ }" :: forall e a. a -> Eff e Boolean 68 | 69 | foreign import isElement 70 | " function isElement(value) { \ 71 | \ return function() { \ 72 | \ return angular.isElement(value); \ 73 | \ }; \ 74 | \ }" :: forall e a. a -> Eff e Boolean 75 | 76 | foreign import isFunction 77 | " function isFunction(value) { \ 78 | \ return function() { \ 79 | \ return angular.isFunction(value); \ 80 | \ }; \ 81 | \ }" :: forall e a. a -> Eff e Boolean 82 | 83 | foreign import isNumber 84 | " function isNumber(value) { \ 85 | \ return function() { \ 86 | \ return angular.isNumber(value); \ 87 | \ }; \ 88 | \ }" :: forall e a. a -> Eff e Boolean 89 | 90 | foreign import isObject 91 | " function isObject(value) { \ 92 | \ return function() { \ 93 | \ return angular.isObject(value); \ 94 | \ }; \ 95 | \ }" :: forall e a. a -> Eff e Boolean 96 | 97 | foreign import isString 98 | " function isString(value) { \ 99 | \ return function() { \ 100 | \ return angular.isString(value); \ 101 | \ }; \ 102 | \ }" :: forall e a. a -> Eff e Boolean 103 | 104 | foreign import isUndefined 105 | " function isUndefined(value) { \ 106 | \ return function() { \ 107 | \ return angular.isUndefined(value); \ 108 | \ }; \ 109 | \ }" :: forall e a. a -> Eff e Boolean 110 | 111 | foreign import lowercase 112 | " function lowercase(str) { \ 113 | \ return function() { \ 114 | \ return angular.lowercase(str); \ 115 | \ }; \ 116 | \ }" :: forall e. String -> Eff e String 117 | 118 | -- | module => Angular.Module 119 | 120 | -- | noop 121 | 122 | -- | toJson 123 | 124 | -- | uppercase 125 | -------------------------------------------------------------------------------- /src/Angular/Animate.purs: -------------------------------------------------------------------------------- 1 | module Angular.Animate 2 | ( NgAnimate() 3 | , Animate() 4 | , AnimateEff() 5 | , enter 6 | , leave 7 | , move 8 | , addClass 9 | , removeClass 10 | , setClass 11 | ) where 12 | 13 | import Control.Monad.Eff 14 | import Data.Function 15 | import Data.Maybe 16 | 17 | import Angular.Element (Element()) 18 | 19 | foreign import data Animate :: * 20 | 21 | foreign import data NgAnimate :: ! 22 | 23 | type AnimateEff e = Eff (nganimate :: NgAnimate | e) Unit 24 | 25 | foreign import enterMoveFn 26 | " function enterMoveFn(fn, fromMaybe, element, parent, after, done, $animate){ \ 27 | \ return function(){ \ 28 | \ return $animate[fn](element, parent, after, fromMaybe(undefined)(done)); \ 29 | \ }; \ 30 | \ } " 31 | :: forall e f r. Fn7 String 32 | (Eff f r -> Maybe (Eff f r) -> Eff f r) 33 | Element 34 | Element 35 | Element 36 | (Maybe (Eff f r)) 37 | Animate 38 | (AnimateEff e) 39 | 40 | enter :: forall e f r. Element -> Element -> Element -> Maybe (Eff f r) -> Animate -> AnimateEff e 41 | enter = runFn7 enterMoveFn "enter" fromMaybe 42 | 43 | move :: forall e f r. Element -> Element -> Element -> Maybe (Eff f r) -> Animate -> AnimateEff e 44 | move = runFn7 enterMoveFn "move" fromMaybe 45 | 46 | foreign import leaveFn 47 | " function leaveFn(fromMaybe, element, done, $animate){ \ 48 | \ return function(){ \ 49 | \ return $animate.leave(element, fromMaybe(undefined)(done)); \ 50 | \ }; \ 51 | \ } " 52 | :: forall e f r. Fn4 (Eff f r -> Maybe (Eff f r) -> Eff f r) 53 | Element 54 | (Maybe (Eff f r)) 55 | Animate 56 | (AnimateEff e) 57 | 58 | leave :: forall e f r. Element -> Maybe (Eff f r) -> Animate -> AnimateEff e 59 | leave = runFn4 leaveFn fromMaybe 60 | 61 | foreign import addRemoveClassFn 62 | " function addRemoveClassFn(fn, fromMaybe, element, className, done, $animate){ \ 63 | \ return function(){ \ 64 | \ return $animate[fn](element, className, fromMaybe(undefined)(done)); \ 65 | \ }; \ 66 | \ } " 67 | :: forall e f r. Fn6 String 68 | (Eff f r -> Maybe (Eff f r) -> Eff f r) 69 | Element 70 | String 71 | (Maybe (Eff f r)) 72 | Animate 73 | (AnimateEff e) 74 | 75 | addClass :: forall e f r. Element -> String -> Maybe (Eff f r) -> Animate -> AnimateEff e 76 | addClass = runFn6 addRemoveClassFn "addClass" fromMaybe 77 | 78 | removeClass :: forall e f r. Element -> String -> Maybe (Eff f r) -> Animate -> AnimateEff e 79 | removeClass = runFn6 addRemoveClassFn "removeClass" fromMaybe 80 | 81 | foreign import setClassFn 82 | " function setClassFn(fromMaybe, element, add, remove, done, $animate){ \ 83 | \ return function(){ \ 84 | \ return $animate.setClass(element, add, remove, fromMaybe(undefined)(done)); \ 85 | \ }; \ 86 | \ } " 87 | :: forall e f r. Fn6 (Eff f r -> Maybe (Eff f r) -> Eff f r) 88 | Element 89 | String 90 | String 91 | (Maybe (Eff f r)) 92 | Animate 93 | (AnimateEff e) 94 | 95 | setClass :: forall e f r. Element -> String -> String -> Maybe (Eff f r) -> Animate -> AnimateEff e 96 | setClass = runFn6 setClassFn fromMaybe 97 | -------------------------------------------------------------------------------- /src/Angular/Attributes.purs: -------------------------------------------------------------------------------- 1 | module Angular.Attributes 2 | ( Attributes() 3 | , NgAttr() 4 | , AttrEff() 5 | , addClass 6 | , removeClass 7 | , updateClass 8 | , observe 9 | , set 10 | , get 11 | , attr 12 | ) where 13 | 14 | import Control.Monad.Eff 15 | 16 | foreign import data Attributes :: * 17 | 18 | foreign import data NgAttr :: ! 19 | 20 | type AttrEff e r = Eff (ngattr :: NgAttr | e) r 21 | 22 | foreign import addClass 23 | " function addClass(classVal){ \ 24 | \ return function(attrs){ \ 25 | \ return function(){ \ 26 | \ return attrs.$addClass(classVal); \ 27 | \ }; \ 28 | \ }; \ 29 | \ }" 30 | :: forall e. String -> Attributes -> AttrEff e Unit 31 | 32 | foreign import removeClass 33 | " function removeClass(classVal){ \ 34 | \ return function(attrs){ \ 35 | \ return function(){ \ 36 | \ return attrs.$removeClass(classVal); \ 37 | \ }; \ 38 | \ }; \ 39 | \ }" 40 | :: forall e. String -> Attributes -> AttrEff e Unit 41 | 42 | foreign import updateClass 43 | " function updateClass(newClasses){ \ 44 | \ return function(oldClasses){ \ 45 | \ return function(attrs){ \ 46 | \ return function(){ \ 47 | \ return attrs.$updateClass(newClasses, oldClasses); \ 48 | \ }; \ 49 | \ }; \ 50 | \ }; \ 51 | \ }" 52 | :: forall e. String -> String -> Attributes -> AttrEff e Unit 53 | 54 | foreign import observe 55 | " function observe(key){ \ 56 | \ return function(k){ \ 57 | \ return function(attrs){ \ 58 | \ return function(){ \ 59 | \ return attrs.$observe(key, function(v){return k(v)();}); \ 60 | \ }; \ 61 | \ }; \ 62 | \ }; \ 63 | \ }" 64 | :: forall e f. String -> (String -> Eff f Unit) -> Attributes -> AttrEff e Unit 65 | 66 | foreign import set 67 | " function set(name){ \ 68 | \ return function(value){ \ 69 | \ return function(attrs){ \ 70 | \ return function(){ \ 71 | \ return attrs.$set(name, value); \ 72 | \ }; \ 73 | \ }; \ 74 | \ }; \ 75 | \ }" 76 | :: forall e. String -> String -> Attributes -> AttrEff e Unit 77 | 78 | foreign import get 79 | " function get(attrs){ \ 80 | \ return function(){ \ 81 | \ return attrs; \ 82 | \ }; \ 83 | \ }" 84 | :: forall e a. Attributes -> AttrEff e { | a } 85 | 86 | foreign import attr 87 | " function attr(attrs){ \ 88 | \ return function(){ \ 89 | \ return attrs.$attr; \ 90 | \ }; \ 91 | \ }" 92 | :: forall e a. Attributes -> AttrEff e { | a } 93 | -------------------------------------------------------------------------------- /src/Angular/Cache.purs: -------------------------------------------------------------------------------- 1 | module Angular.Cache 2 | ( Cache() 3 | , CacheFactory() 4 | , CacheEff() 5 | , NgCache() 6 | , Key() 7 | , Name() 8 | , Options() 9 | , cache 10 | , put 11 | , get 12 | , remove 13 | , removeAll 14 | , destroy 15 | , info 16 | ) where 17 | 18 | import Control.Monad.Eff 19 | import Data.Maybe 20 | import Data.Function 21 | 22 | foreign import data NgCache :: ! 23 | 24 | foreign import data Cache :: * 25 | 26 | foreign import data CacheFactory :: * 27 | 28 | type Key = String 29 | 30 | type Name = String 31 | 32 | type Options a = { capacity :: Number | a } 33 | 34 | type CacheEff e r = Eff (ngcache :: NgCache | e) r 35 | 36 | cache :: forall e a. Name -> Maybe (Options a) -> CacheFactory -> CacheEff e Cache 37 | cache = runFn4 cacheFn fromMaybe 38 | 39 | foreign import cacheFn 40 | " function cacheFn(fromMaybe, name, opts, $cacheFactory){ \ 41 | \ return function(){ \ 42 | \ return $cacheFactory(name, fromMaybe(undefined)(opts)); \ 43 | \ }; \ 44 | \ } " 45 | :: forall e a. Fn4 (Options a -> Maybe (Options a) -> Options a) 46 | Name 47 | (Maybe (Options a)) 48 | CacheFactory 49 | (CacheEff e Cache) 50 | 51 | foreign import put 52 | " function put(key){ \ 53 | \ return function(value){ \ 54 | \ return function(cache){ \ 55 | \ return function(){ \ 56 | \ return cache.put(key, value); \ 57 | \ }; \ 58 | \ }; \ 59 | \ }; \ 60 | \ } " 61 | :: forall e a. Key -> a -> Cache -> CacheEff e a 62 | 63 | foreign import get 64 | " function get(key){ \ 65 | \ return function(cache){ \ 66 | \ return function(){ \ 67 | \ return cache.get(key); \ 68 | \ }; \ 69 | \ }; \ 70 | \ } " 71 | :: forall e a. Key -> Cache -> CacheEff e a 72 | 73 | foreign import remove 74 | " function remove(key){ \ 75 | \ return function(cache){ \ 76 | \ return function(){ \ 77 | \ return cache.remove(key); \ 78 | \ }; \ 79 | \ }; \ 80 | \ } " 81 | :: forall e. Key -> Cache -> CacheEff e Unit 82 | 83 | foreign import removeAll 84 | " function removeAll(cache){ \ 85 | \ return function(){ \ 86 | \ return cache.removeAll(); \ 87 | \ }; \ 88 | \ } " 89 | :: forall e. Cache -> CacheEff e Unit 90 | 91 | foreign import destroy 92 | " function destroy(cache){ \ 93 | \ return function(){ \ 94 | \ return cache.destroy(); \ 95 | \ }; \ 96 | \ } " 97 | :: forall e. Cache -> CacheEff e Unit 98 | 99 | foreign import info 100 | " function info(cache){ \ 101 | \ return function(){ \ 102 | \ return cache.info(); \ 103 | \ }; \ 104 | \ } " 105 | :: forall e a. Cache -> CacheEff e { id :: String, size :: Number | a } 106 | -------------------------------------------------------------------------------- /src/Angular/DI.purs: -------------------------------------------------------------------------------- 1 | module Angular.DI ( 2 | Dependency, name 3 | , Service 4 | , RootScope(..) 5 | , RootElement(..) 6 | , get 7 | , Injectable, dependencies 8 | , Annotated() 9 | , annotate 10 | ) where 11 | 12 | import Control.Monad.Eff (Eff()) 13 | import Data.Function 14 | import Angular.Injector (Injector(), InjEff()) 15 | import Angular.Animate (Animate()) 16 | import Angular.Cache (CacheFactory()) 17 | import Angular.Http (Http()) 18 | import Angular.Interpolate (Interpolate()) 19 | import Angular.Interval (Interval()) 20 | import Angular.Location (Location()) 21 | import Angular.Log (Log()) 22 | import Angular.Parse (Parse()) 23 | import Angular.Q (Q()) 24 | import Angular.Timeout (Timeout()) 25 | import Angular.Scope (Scope()) 26 | import Angular.Element (Element()) 27 | import Angular.Attributes (Attributes()) 28 | import Angular.This (This()) 29 | 30 | -- | A type which can by provided by dependency injection. 31 | class Dependency a where 32 | name :: String 33 | 34 | -- | Services which can be retrieved with get 35 | class (Dependency a) <= Service a 36 | 37 | instance dependencyInjector :: Dependency Injector where 38 | name = "$injector" 39 | instance serviceInjector :: Service Injector 40 | 41 | instance dependencyAnimate :: Dependency Animate where 42 | name = "$animate" 43 | instance serviceAnimate :: Service Animate 44 | 45 | instance dependencyCacheFactory :: Dependency CacheFactory where 46 | name = "$cacheFactory" 47 | instance serviceCacheFactory :: Service CacheFactory 48 | 49 | instance dependencyHttp :: Dependency Http where 50 | name = "$http" 51 | instance serviceHttp :: Service Http 52 | 53 | instance dependencyInterpolate :: Dependency Interpolate where 54 | name = "$interpolate" 55 | instance serviceInterpolate :: Service Interpolate 56 | 57 | instance dependencyInterval :: Dependency Interval where 58 | name = "$interval" 59 | instance serviceInterval :: Service Interval 60 | 61 | instance dependencyLocation :: Dependency Location where 62 | name = "$location" 63 | instance serviceLocation :: Service Location 64 | 65 | instance dependencyLog :: Dependency Log where 66 | name = "$log" 67 | instance serviceLog :: Service Log 68 | 69 | instance dependencyParse :: Dependency Parse where 70 | name = "$parse" 71 | instance serviceParse :: Service Parse 72 | 73 | instance dependencyQ :: Dependency Q where 74 | name = "$q" 75 | instance serviceQ :: Service Q 76 | 77 | instance dependencyTimeout :: Dependency Timeout where 78 | name = "$timeout" 79 | instance serviceTimeout :: Service Timeout 80 | 81 | newtype RootScope a = RootScope (Scope a) 82 | 83 | instance dependencyRootScope :: Dependency (RootScope a) where 84 | name = "$rootScope" 85 | instance serviceRootScope :: Service (RootScope a) 86 | 87 | instance dependencyScope :: Dependency (Scope a) where 88 | name = "$scope" 89 | 90 | newtype RootElement = RootElement Element 91 | 92 | instance dependencyRootElement :: Dependency RootElement where 93 | name = "$rootElement" 94 | instance serviceRootElement :: Service RootElement 95 | 96 | instance dependencyElement :: Dependency Element where 97 | name = "$element" 98 | 99 | instance dependencyAttributes :: Dependency Attributes where 100 | name = "$attrs" 101 | 102 | instance dependencyThis :: Dependency (This a) where 103 | -- it would be nice to make a dummy service to avoid the special handling 104 | -- in annotate, but there is nowhere to do so 105 | name = "$this" 106 | 107 | 108 | foreign import getDependency 109 | "function get(dependency) {\ 110 | \ dependency = dependency.name;\ 111 | \ return function ($injector) {\ 112 | \ return function () {\ 113 | \ return $injector.get(dependency);\ 114 | \ };\ 115 | \ };\ 116 | \}" :: forall e a . (Dependency a) => Injector -> InjEff e a 117 | 118 | get :: forall e a . (Service a) => Injector -> InjEff e a 119 | get = getDependency 120 | 121 | 122 | class Injectable a where 123 | dependencies :: a -> [String] 124 | 125 | instance injectableEff :: Injectable (Eff e r) where 126 | dependencies _ = [] 127 | 128 | foreign import dependenciesFn 129 | "function dependenciesFn(dependency) {\ 130 | \ dependency = [dependency.name];\ 131 | \ return function (injectable) {\ 132 | \ return function (/*f*/) {\ 133 | \ return dependency.concat(injectable.dependencies(/*f(a)*/));\ 134 | \ };\ 135 | \ };\ 136 | \}" :: forall a b . (Dependency a, Injectable b) => (a -> b) -> [String] 137 | 138 | instance injectableFn :: (Dependency a, Injectable b) => Injectable (a -> b) where 139 | dependencies f = dependenciesFn f 140 | 141 | 142 | -- | An Eff function with added dependency injection annotations. 143 | foreign import data Annotated :: * -> * 144 | 145 | -- | Infer and annotate a function with its dependencies, that can provided by Injector.invoke or Module functions. 146 | foreign import annotate 147 | "function annotate(injectable) {\ 148 | \ return function (fun) {\ 149 | \ var inject = injectable.dependencies(fun);\ 150 | \ function g(/*...*/) {\ 151 | \ var f = fun;\ 152 | \ for (var i = 0, a = 0; i < inject.length; i++)\ 153 | \ f = f(inject[i] === '$this' ? this : arguments[a++]);\ 154 | \ return f();\ 155 | \ }\ 156 | \ g.prototype = fun.prototype;\ 157 | \ g.$inject = inject.filter(function (d) { return d !== '$this'; });\ 158 | \ return g;\ 159 | \ };\ 160 | \}" :: forall a . (Injectable a) => a -> Annotated a 161 | -------------------------------------------------------------------------------- /src/Angular/Deferred.purs: -------------------------------------------------------------------------------- 1 | module Angular.Deferred 2 | ( Deferred() 3 | , NgDeferred() 4 | , DeferredEff() 5 | , resolve 6 | , reject 7 | , notify 8 | , promise 9 | ) where 10 | 11 | import Control.Monad.Eff 12 | import Data.Function 13 | 14 | import Angular.Promise (Promise()) 15 | 16 | foreign import data Deferred :: * -> * -> * 17 | 18 | foreign import data NgDeferred :: ! 19 | 20 | type DeferredEff e r = Eff (ngdeferred :: NgDeferred | e) r 21 | 22 | foreign import resolveFn 23 | " function resolveFn(a, dfd){ \ 24 | \ return function(){ \ 25 | \ dfd.resolve(a); \ 26 | \ }; \ 27 | \ } " 28 | :: forall e a b. Fn2 b (Deferred a b) (DeferredEff e Unit) 29 | 30 | resolve :: forall e a b. b -> Deferred a b -> DeferredEff e Unit 31 | resolve = runFn2 resolveFn 32 | 33 | foreign import rejectFn 34 | " function rejectFn(a, dfd){ \ 35 | \ return function(){ \ 36 | \ dfd.reject(a); \ 37 | \ }; \ 38 | \ } " 39 | :: forall e a b. Fn2 a (Deferred a b) (DeferredEff e Unit) 40 | 41 | reject :: forall e a b. a -> Deferred a b -> DeferredEff e Unit 42 | reject = runFn2 rejectFn 43 | 44 | foreign import notifyFn 45 | " function notifyFn(a, dfd){ \ 46 | \ return function(){ \ 47 | \ dfd.notify(a); \ 48 | \ }; \ 49 | \ } " 50 | :: forall e s a b. Fn2 s (Deferred a b) (DeferredEff e Unit) 51 | 52 | notify :: forall e s a b. s -> Deferred a b -> DeferredEff e Unit 53 | notify = runFn2 notifyFn 54 | 55 | foreign import promise 56 | " function promise(dfd){ \ 57 | \ return function(){ \ 58 | \ dfd.promise; \ 59 | \ }; \ 60 | \ } " 61 | :: forall e a b. Deferred a b -> DeferredEff e (Promise a b) 62 | -------------------------------------------------------------------------------- /src/Angular/Element.purs: -------------------------------------------------------------------------------- 1 | module Angular.Element 2 | ( Element() 3 | , ElEff() 4 | , NgEl() 5 | , Handler() 6 | , DeregisterHandler() 7 | , element 8 | , addClass 9 | , after 10 | , getAttr 11 | , setAttr 12 | , setAllAttr 13 | , bind 14 | , children 15 | , clone 16 | , contents 17 | , getCss 18 | , setCss 19 | , setAllCss 20 | , getData 21 | , setData 22 | , setAllData 23 | , empty 24 | , eq 25 | , find 26 | , hasClass 27 | , html 28 | , next 29 | , on 30 | , off 31 | , offHandler 32 | , one 33 | , parent 34 | , prepend 35 | , getProp 36 | , setProp 37 | , setAllProp 38 | , ready 39 | , remove 40 | , removeAttr 41 | , removeClass 42 | , removeData 43 | , replaceWith 44 | , toggleClass 45 | , triggerHandler 46 | , unbind 47 | , unbindHandler 48 | , getVal 49 | , setVal 50 | , wrap 51 | , controller 52 | , injector 53 | , scope 54 | , isolateScope 55 | , inheritedData 56 | , (!!) 57 | ) where 58 | 59 | import Prelude (Unit()) 60 | 61 | import Control.Monad.Eff 62 | import Data.Function (Fn3(), Fn4(), Fn5(), runFn3, runFn4, runFn5) 63 | import Data.Maybe 64 | 65 | import Data.DOM.Simple.Types (HTMLElement(), DOMEvent()) 66 | 67 | import Angular.Injector (Injector()) 68 | import Angular.Scope (Scope()) 69 | 70 | type ElEff e r = Eff (ngel :: NgEl | e) r 71 | 72 | type Handler e = DOMEvent -> Eff e Unit 73 | 74 | foreign import data Element :: * 75 | 76 | foreign import data NgEl :: ! 77 | 78 | foreign import data DeregisterHandler :: # ! -> * 79 | 80 | foreign import element 81 | " function element(el) { \ 82 | \ return function(){ \ 83 | \ return angular.element(el); \ 84 | \ }; \ 85 | \ }" 86 | :: forall e. String -> ElEff e Element 87 | 88 | foreign import addClass 89 | " function addClass(cssClasses){ \ 90 | \ return function(el){ \ 91 | \ return function(){ \ 92 | \ return el.addClass(cssClasses); \ 93 | \ }; \ 94 | \ }; \ 95 | \ }" 96 | :: forall e. String -> Element -> ElEff e Element 97 | 98 | foreign import after 99 | " function after(newEl){ \ 100 | \ return function(el){ \ 101 | \ return function(){ \ 102 | \ return el.after(newEl); \ 103 | \ }; \ 104 | \ }; \ 105 | \ }" 106 | :: forall e. Element -> Element -> ElEff e Element 107 | 108 | foreign import getAttrFn 109 | " function getAttrFn(nothing, just, name, el){ \ 110 | \ return function(){ \ 111 | \ var a = el.attr(name); \ 112 | \ return angular.isString(a) ? just(a) : nothing; \ 113 | \ }; \ 114 | \ }" 115 | :: forall e. Fn4 (Maybe String) 116 | (String -> Maybe String) 117 | String 118 | Element 119 | (ElEff e (Maybe String)) 120 | 121 | getAttr :: forall e. String -> Element -> ElEff e (Maybe String) 122 | getAttr = runFn4 getAttrFn Nothing Just 123 | 124 | foreign import setAttr 125 | " function setAttr(name){ \ 126 | \ return function(value){ \ 127 | \ return function(el){ \ 128 | \ return function(){ \ 129 | \ return el.attr(name, value); \ 130 | \ }; \ 131 | \ }; \ 132 | \ }; \ 133 | \ }" 134 | :: forall e. String -> String -> Element -> ElEff e Element 135 | 136 | foreign import setAllAttr 137 | " function setAllAttr(obj){ \ 138 | \ return function(el){ \ 139 | \ return function(){ \ 140 | \ return el.attr(obj); \ 141 | \ }; \ 142 | \ }; \ 143 | \ }" 144 | :: forall e a. { | a } -> Element -> ElEff e Element 145 | 146 | bind :: forall e f. String -> Handler f -> Element -> ElEff e (DeregisterHandler f) 147 | bind = on 148 | 149 | foreign import children 150 | " function children(el){ \ 151 | \ return function(){ \ 152 | \ return el.children(); \ 153 | \ }; \ 154 | \ }" 155 | :: forall e. Element -> ElEff e Element 156 | 157 | foreign import clone 158 | " function clone(el){ \ 159 | \ return function(){ \ 160 | \ return el.clone(); \ 161 | \ }; \ 162 | \ }" 163 | :: forall e. Element -> ElEff e Element 164 | 165 | foreign import contents 166 | " function contents(el){ \ 167 | \ return function(){ \ 168 | \ return el.contents(); \ 169 | \ }; \ 170 | \ }" 171 | :: forall e. Element -> ElEff e Element 172 | 173 | foreign import getCssFn 174 | " function getCssFn(nothing, just, name, el){ \ 175 | \ return function(){ \ 176 | \ var a = el.css(name); \ 177 | \ return angular.isString(a) ? just(a) : nothing; \ 178 | \ }; \ 179 | \ }" 180 | :: forall e. Fn4 (Maybe String) 181 | (String -> Maybe String) 182 | String 183 | Element 184 | (ElEff e (Maybe String)) 185 | 186 | getCss :: forall e. String -> Element -> ElEff e (Maybe String) 187 | getCss = runFn4 getCssFn Nothing Just 188 | 189 | foreign import setCss 190 | " function setCss(name){ \ 191 | \ return function(value){ \ 192 | \ return function(el){ \ 193 | \ return function(){ \ 194 | \ return el.css(name, value); \ 195 | \ }; \ 196 | \ }; \ 197 | \ }; \ 198 | \ }" 199 | :: forall e. String -> String -> Element -> ElEff e Element 200 | 201 | foreign import setAllCss 202 | " function setAllCss(obj){ \ 203 | \ return function(el){ \ 204 | \ return function(){ \ 205 | \ return el.css(obj); \ 206 | \ }; \ 207 | \ }; \ 208 | \ }" 209 | :: forall e a. { | a } -> Element -> ElEff e Element 210 | 211 | foreign import getDataFn 212 | " function getDataFn(nothing, just, name, el){ \ 213 | \ return function(){ \ 214 | \ var a = el.data(name); \ 215 | \ return angular.isDefined(a) ? just(a) : nothing; \ 216 | \ }; \ 217 | \ }" 218 | :: forall e a. Fn4 (Maybe a) 219 | (a -> Maybe a) 220 | String 221 | Element 222 | (ElEff e (Maybe a)) 223 | 224 | getData :: forall e a. String -> Element -> ElEff e (Maybe a) 225 | getData = runFn4 getDataFn Nothing Just 226 | 227 | foreign import setData 228 | " function setData(name){ \ 229 | \ return function(value){ \ 230 | \ return function(el){ \ 231 | \ return function(){ \ 232 | \ return el.data(name, value); \ 233 | \ }; \ 234 | \ }; \ 235 | \ }; \ 236 | \ }" 237 | :: forall e a. String -> a -> Element -> ElEff e Element 238 | 239 | foreign import getAllData 240 | " function getAllData(el){ \ 241 | \ return function(){ \ 242 | \ return el.data(); \ 243 | \ }; \ 244 | \ }" 245 | :: forall e a. Element -> ElEff e { | a } 246 | 247 | foreign import setAllData 248 | " function setAllData(obj){ \ 249 | \ return function(el){ \ 250 | \ return function(){ \ 251 | \ return el.data(obj); \ 252 | \ }; \ 253 | \ }; \ 254 | \ }" 255 | :: forall e a. { | a } -> Element -> ElEff e Element 256 | 257 | foreign import empty 258 | " function empty(el){ \ 259 | \ return function(){ \ 260 | \ return el.empty(); \ 261 | \ }; \ 262 | \ }" 263 | :: forall e. Element -> ElEff e Element 264 | 265 | foreign import eq 266 | " function eq(i){ \ 267 | \ return function(el){ \ 268 | \ return function(){ \ 269 | \ return el.eq(i); \ 270 | \ }; \ 271 | \ }; \ 272 | \ }" 273 | :: forall e. Number -> Element -> ElEff e Element 274 | 275 | foreign import find 276 | " function find(selector){ \ 277 | \ return function(el){ \ 278 | \ return function(){ \ 279 | \ return el.find(selector); \ 280 | \ }; \ 281 | \ }; \ 282 | \ }" 283 | :: forall e. Number -> Element -> ElEff e Element 284 | 285 | foreign import hasClass 286 | " function hasClass(selector){ \ 287 | \ return function(el){ \ 288 | \ return function(){ \ 289 | \ return el.hasClass(selector); \ 290 | \ }; \ 291 | \ }; \ 292 | \ }" 293 | :: forall e. String -> Element -> ElEff e Boolean 294 | 295 | foreign import html 296 | " function html(el){ \ 297 | \ return function(){ \ 298 | \ return el.html(); \ 299 | \ }; \ 300 | \ }" 301 | :: forall e. Element -> ElEff e String 302 | 303 | foreign import next 304 | " function next(el){ \ 305 | \ return function(){ \ 306 | \ return el.next(); \ 307 | \ }; \ 308 | \ }" 309 | :: forall e. Element -> ElEff e Element 310 | 311 | foreign import on 312 | " function on(events){ \ 313 | \ return function(k){ \ 314 | \ return function(el){ \ 315 | \ return function(){ \ 316 | \ var handler = function(event){return k(event)();}; \ 317 | \ el.on(events, handler); \ 318 | \ return handler; \ 319 | \ }; \ 320 | \ }; \ 321 | \ }; \ 322 | \ }" 323 | :: forall e f. String -> Handler f -> Element -> ElEff e (DeregisterHandler f) 324 | 325 | foreign import off 326 | " function off(events){ \ 327 | \ return function(el){ \ 328 | \ return function(){ \ 329 | \ return el.off(events); \ 330 | \ }; \ 331 | \ }; \ 332 | \ }" 333 | :: forall e f. String -> Element -> ElEff e Element 334 | 335 | foreign import offHandler 336 | " function offHandler(events){ \ 337 | \ return function(k){ \ 338 | \ return function(el){ \ 339 | \ return function(){ \ 340 | \ return el.off(events, k); \ 341 | \ }; \ 342 | \ }; \ 343 | \ }; \ 344 | \ }" 345 | :: forall e f. String -> DeregisterHandler f -> Element -> ElEff e Element 346 | 347 | foreign import one 348 | " function one(events){ \ 349 | \ return function(k){ \ 350 | \ return function(el){ \ 351 | \ return function(){ \ 352 | \ var handler = function(event){return k(event)();}; \ 353 | \ el.one(events, handler); \ 354 | \ return handler; \ 355 | \ }; \ 356 | \ }; \ 357 | \ }; \ 358 | \ }" 359 | :: forall e f. String -> Handler f -> Element -> ElEff e (DeregisterHandler f) 360 | 361 | foreign import parent 362 | " function parent(el){ \ 363 | \ return function(){ \ 364 | \ return el.parent(); \ 365 | \ }; \ 366 | \ }" 367 | :: forall e. Element -> ElEff e Element 368 | 369 | foreign import prepend 370 | " function prepend(newEl){ \ 371 | \ return function(el){ \ 372 | \ return function(){ \ 373 | \ return el.prepend(newEl); \ 374 | \ }; \ 375 | \ }; \ 376 | \ }" 377 | :: forall e. Element -> Element -> ElEff e Element 378 | 379 | foreign import getPropFn 380 | " function getPropFn(nothing, just, name, el){ \ 381 | \ return function(){ \ 382 | \ var a = el.prop(name); \ 383 | \ return angular.isString(a) ? just(a) : nothing; \ 384 | \ }; \ 385 | \ }" 386 | :: forall e. Fn4 (Maybe String) 387 | (String -> Maybe String) 388 | String 389 | Element 390 | (ElEff e (Maybe String)) 391 | 392 | getProp :: forall e. String -> Element -> ElEff e (Maybe String) 393 | getProp = runFn4 getPropFn Nothing Just 394 | 395 | foreign import setProp 396 | " function setProp(name){ \ 397 | \ return function(value){ \ 398 | \ return function(el){ \ 399 | \ return function(){ \ 400 | \ return el.prop(name, value); \ 401 | \ }; \ 402 | \ }; \ 403 | \ }; \ 404 | \ }" 405 | :: forall e. String -> String -> Element -> ElEff e Element 406 | 407 | foreign import setAllProp 408 | " function setAllProp(obj){ \ 409 | \ return function(el){ \ 410 | \ return function(){ \ 411 | \ return el.prop(obj); \ 412 | \ }; \ 413 | \ }; \ 414 | \ }" 415 | :: forall e a. { | a } -> Element -> ElEff e Element 416 | 417 | foreign import ready 418 | " function ready(k){ \ 419 | \ return function(el){ \ 420 | \ return function(){ \ 421 | \ return el.ready(k); \ 422 | \ }; \ 423 | \ }; \ 424 | \ }" 425 | :: forall e. Eff e Unit -> Element -> ElEff e Element 426 | 427 | foreign import remove 428 | " function remove(el){ \ 429 | \ return function(){ \ 430 | \ return el.remove(); \ 431 | \ }; \ 432 | \ }" 433 | :: forall e. Element -> ElEff e Element 434 | 435 | foreign import removeAttr 436 | " function removeAttr(name){ \ 437 | \ return function(el){ \ 438 | \ return function(){ \ 439 | \ return el.removeAttr(name); \ 440 | \ }; \ 441 | \ }; \ 442 | \ }" 443 | :: forall e. String -> Element -> ElEff e Element 444 | 445 | foreign import removeClass 446 | " function removeClass(name){ \ 447 | \ return function(el){ \ 448 | \ return function(){ \ 449 | \ return el.removeClass(name); \ 450 | \ }; \ 451 | \ }; \ 452 | \ }" 453 | :: forall e. String -> Element -> ElEff e Element 454 | 455 | foreign import removeData 456 | " function removeData(name){ \ 457 | \ return function(el){ \ 458 | \ return function(){ \ 459 | \ return el.removeData(name); \ 460 | \ }; \ 461 | \ }; \ 462 | \ }" 463 | :: forall e. String -> Element -> ElEff e Element 464 | 465 | foreign import replaceWith 466 | " function replaceWith(newEl){ \ 467 | \ return function(el){ \ 468 | \ return function(){ \ 469 | \ return el.replaceWith(newEl); \ 470 | \ }; \ 471 | \ }; \ 472 | \ }" 473 | :: forall e. Element -> Element -> ElEff e Element 474 | 475 | foreign import text 476 | " function text(el){ \ 477 | \ return function(){ \ 478 | \ return el.text(); \ 479 | \ }; \ 480 | \ }" 481 | :: forall e. Element -> ElEff e String 482 | 483 | foreign import toggleClass 484 | " function toggleClass(selector){ \ 485 | \ return function(condition){ \ 486 | \ return function(el){ \ 487 | \ return function(){ \ 488 | \ return el.toggleClass(selector, condition); \ 489 | \ }; \ 490 | \ }; \ 491 | \ }; \ 492 | \ }" 493 | :: forall e. String -> Boolean -> Element -> ElEff e Element 494 | 495 | foreign import triggerHandler 496 | " function triggerHandler(eventName){ \ 497 | \ return function(eventData){ \ 498 | \ return function(el){ \ 499 | \ return function(){ \ 500 | \ return el.triggerHandler(eventName, eventData); \ 501 | \ }; \ 502 | \ }; \ 503 | \ }; \ 504 | \ }" 505 | :: forall e a. String -> [a] -> Element -> ElEff e Element 506 | 507 | unbind :: forall e f. String -> Element -> ElEff e Element 508 | unbind = off 509 | 510 | unbindHandler :: forall e f. String -> DeregisterHandler f -> Element -> ElEff e Element 511 | unbindHandler = offHandler 512 | 513 | foreign import getValFn 514 | " function getValFn(nothing, just, el){ \ 515 | \ return function(){ \ 516 | \ var a = el.val(); \ 517 | \ return angular.isString(a) ? just(a) : nothing; \ 518 | \ }; \ 519 | \ }" 520 | :: forall e. Fn3 (Maybe String) 521 | (String -> Maybe String) 522 | Element 523 | (ElEff e (Maybe String)) 524 | 525 | getVal :: forall e. Element -> ElEff e (Maybe String) 526 | getVal = runFn3 getValFn Nothing Just 527 | 528 | foreign import setVal 529 | " function setVal(value){ \ 530 | \ return function(el){ \ 531 | \ return function(){ \ 532 | \ return el.val(value); \ 533 | \ }; \ 534 | \ }; \ 535 | \ }" 536 | :: forall e. String -> Element -> ElEff e Element 537 | 538 | foreign import wrap 539 | " function wrap(newEl){ \ 540 | \ return function(el){ \ 541 | \ return function(){ \ 542 | \ return el.wrap(newEl); \ 543 | \ }; \ 544 | \ }; \ 545 | \ }" 546 | :: forall e. Element -> Element -> ElEff e Element 547 | 548 | foreign import controllerFn 549 | " function controllerFn(fromMaybe, nothing, just, name, el){ \ 550 | \ return function(){ \ 551 | \ var a = el.controller(fromMaybe(undefined)(name)); \ 552 | \ return angular.isDefined(a) ? just(a) : nothing; \ 553 | \ }; \ 554 | \ }" 555 | :: forall e a. Fn5 (String -> Maybe String -> String) 556 | (Maybe a) 557 | (a -> Maybe a) 558 | (Maybe String) 559 | Element 560 | (ElEff e (Maybe a)) 561 | 562 | controller :: forall e a. Maybe String -> Element -> ElEff e (Maybe a) 563 | controller = runFn5 controllerFn fromMaybe Nothing Just 564 | 565 | foreign import injectorFn 566 | " function injectorFn(nothing, just, el){ \ 567 | \ return function(){ \ 568 | \ var a = el.injector(); \ 569 | \ return angular.isDefined(a) ? just(a) : nothing; \ 570 | \ }; \ 571 | \ }" 572 | :: forall e a. Fn3 (Maybe Injector) (Injector -> Maybe Injector) Element (ElEff e (Maybe Injector)) 573 | 574 | injector :: forall e a. Element -> ElEff e (Maybe Injector) 575 | injector = runFn3 injectorFn Nothing Just 576 | 577 | foreign import scopeFn 578 | " function scopeFn(nothing, just, el){ \ 579 | \ return function(){ \ 580 | \ var a = el.scope(); \ 581 | \ return angular.isDefined(a) ? just(a) : nothing; \ 582 | \ }; \ 583 | \ }" 584 | :: forall e a. Fn3 (Maybe (Scope a)) (Scope a -> Maybe (Scope a)) Element (ElEff e (Maybe (Scope a))) 585 | 586 | scope :: forall e a. Element -> ElEff e (Maybe (Scope a)) 587 | scope = runFn3 scopeFn Nothing Just 588 | 589 | foreign import isolateScopeFn 590 | " function isolateScopeFn(nothing, just, el){ \ 591 | \ return function(){ \ 592 | \ var a = el.isolateScope(); \ 593 | \ return angular.isDefined(a) ? just(a) : nothing; \ 594 | \ }; \ 595 | \ }" 596 | :: forall e a. Fn3 (Maybe (Scope a)) (Scope a -> Maybe (Scope a)) Element (ElEff e (Maybe (Scope a))) 597 | 598 | isolateScope :: forall e a. Element -> ElEff e (Maybe (Scope a)) 599 | isolateScope = runFn3 isolateScopeFn Nothing Just 600 | 601 | foreign import inheritedData 602 | " function inheritedData(el){ \ 603 | \ return function(){ \ 604 | \ return el.inheritedData(); \ 605 | \ }; \ 606 | \ }" 607 | :: forall e a. Element -> ElEff e { | a } 608 | 609 | foreign import bangbangFn 610 | " function bangbangFn(nothing, just, el, i) { \ 611 | \ var r = el[i]; \ 612 | \ return angular.isDefined(r) ? just(r) : nothing; \ 613 | \ }" 614 | :: Fn4 (Maybe HTMLElement) (HTMLElement -> Maybe HTMLElement) Element Number (Maybe HTMLElement) 615 | 616 | infixl 8 !! 617 | 618 | (!!) :: Element -> Number -> Maybe HTMLElement 619 | (!!) = runFn4 bangbangFn Nothing Just 620 | -------------------------------------------------------------------------------- /src/Angular/FormController.purs: -------------------------------------------------------------------------------- 1 | module Angular.FormController 2 | ( FormController() 3 | , FormEff() 4 | , NgForm() 5 | , addControl 6 | , removeControl 7 | , setValidity 8 | , setDirty 9 | , setPristine 10 | , pristine 11 | , dirty 12 | , valid 13 | , invalid 14 | , error 15 | ) where 16 | 17 | import Control.Monad.Eff 18 | 19 | import Angular.NgModelController (NgModelController(), ValidationErrorKey()) 20 | 21 | foreign import data FormController :: * 22 | 23 | foreign import data NgForm :: ! 24 | 25 | type FormEff e r = Eff (ngform :: NgForm | e) r 26 | 27 | foreign import addControl 28 | " function addControl(control){ \ 29 | \ return function($ctrl){ \ 30 | \ return function(){ \ 31 | \ return $ctrl.$addControl(control); \ 32 | \ }; \ 33 | \ }; \ 34 | \ } " 35 | :: forall e a. NgModelController a -> FormController -> FormEff e Unit 36 | 37 | foreign import removeControl 38 | " function removeControl(control){ \ 39 | \ return function($ctrl){ \ 40 | \ return function(){ \ 41 | \ return $ctrl.$removeControl(control); \ 42 | \ }; \ 43 | \ }; \ 44 | \ } " 45 | :: forall e a. NgModelController a -> FormController -> FormEff e Unit 46 | 47 | foreign import setValidity 48 | " function setValidity(key){ \ 49 | \ return function(isValid){ \ 50 | \ return function(control){ \ 51 | \ return function($ctrl){ \ 52 | \ return function(){ \ 53 | \ return $ctrl.$setValidity(key, isValid, control, $ctrl); \ 54 | \ }; \ 55 | \ }; \ 56 | \ }; \ 57 | \ }; \ 58 | \ } " 59 | :: forall e a. ValidationErrorKey -> Boolean -> NgModelController a -> FormController -> FormEff e Unit 60 | 61 | foreign import setDirty 62 | " function setDirty($ctrl){ \ 63 | \ return function(){ \ 64 | \ return $ctrl.$setDirty(); \ 65 | \ }; \ 66 | \ } " 67 | :: forall e. FormController -> FormEff e Unit 68 | 69 | foreign import setPristine 70 | " function setPristine($ctrl){ \ 71 | \ return function(){ \ 72 | \ return $ctrl.$setPristine(); \ 73 | \ }; \ 74 | \ } " 75 | :: forall e. FormController -> FormEff e Unit 76 | 77 | foreign import pristine 78 | " function pristine($ctrl){ \ 79 | \ return function(){ \ 80 | \ return $ctrl.$pristine; \ 81 | \ }; \ 82 | \ } " 83 | :: forall e. FormController -> FormEff e Boolean 84 | 85 | foreign import dirty 86 | " function dirty($ctrl){ \ 87 | \ return function(){ \ 88 | \ return $ctrl.$dirty; \ 89 | \ }; \ 90 | \ } " 91 | :: forall e. FormController -> FormEff e Boolean 92 | 93 | foreign import valid 94 | " function valid($ctrl){ \ 95 | \ return function(){ \ 96 | \ return $ctrl.$valid; \ 97 | \ }; \ 98 | \ } " 99 | :: forall e. FormController -> FormEff e Boolean 100 | 101 | foreign import invalid 102 | " function invalid($ctrl){ \ 103 | \ return function(){ \ 104 | \ return $ctrl.$invalid; \ 105 | \ }; \ 106 | \ } " 107 | :: forall e. FormController -> FormEff e Boolean 108 | 109 | foreign import error 110 | " function error($ctrl){ \ 111 | \ return function(){ \ 112 | \ return $ctrl.$error; \ 113 | \ }; \ 114 | \ } " 115 | :: forall e a. FormController -> FormEff e { | a } 116 | -------------------------------------------------------------------------------- /src/Angular/Http.purs: -------------------------------------------------------------------------------- 1 | module Angular.Http 2 | ( Http() 3 | , HttpResponse() 4 | , Response() 5 | , Config() 6 | , config 7 | , http 8 | , get 9 | , get' 10 | , del 11 | , del' 12 | , head 13 | , head' 14 | , jsonp 15 | , jsonp' 16 | , post 17 | , post' 18 | , put 19 | , put' 20 | ) where 21 | 22 | import Data.Either 23 | import Data.Function 24 | import Data.Maybe 25 | import Data.Tuple 26 | 27 | import qualified Data.DOM.Simple.Ajax as D 28 | 29 | import Angular.Cache (Cache()) 30 | import qualified Angular.Http.Internal as I 31 | import Angular.Http.Types 32 | import Angular.Promise (Promise(), then1') 33 | 34 | foreign import data Http :: * 35 | 36 | type HttpResponse e r a b c d = HttpEff e (Promise I.ForeignResponse (Response r a b c d)) 37 | 38 | type ForeignHttpResponse e = HttpEff e (Promise I.ForeignResponse I.ForeignResponse) 39 | 40 | type Response r a b c d 41 | = { "data" :: D.HttpData r 42 | , status :: Status 43 | , headers :: [String] -> String 44 | , config :: Config a b c d 45 | , statusText :: String 46 | } 47 | 48 | type Config a b c d 49 | = { method :: D.HttpMethod 50 | , url :: D.Url 51 | , params :: { | a } 52 | , "data" :: RequestData b 53 | , headers :: Headers 54 | , xsrfHeaderName :: String 55 | , xsrfCookieName :: String 56 | , cache :: Either Boolean Cache 57 | , timeout :: Either Number (Promise c d) 58 | , withCredentials :: Boolean 59 | , responseType :: D.ResponseType 60 | } 61 | 62 | xsrfHeaderName = "X-XSRF-TOKEN" 63 | 64 | xsrfCookieName = "XSRF-TOKEN" 65 | 66 | config :: forall a b c d. Config a b c d 67 | config = { method: D.GET 68 | , url: "/" 69 | , params: runFn0 emptyParams 70 | , "data": NoRequestData 71 | , headers: Headers [] 72 | , xsrfHeaderName: xsrfHeaderName 73 | , xsrfCookieName: xsrfCookieName 74 | , cache: Left false 75 | , timeout: Left 0 76 | , withCredentials: false 77 | , responseType: D.Default } 78 | 79 | http :: forall e r a b c d. Config a b c d -> Http -> HttpResponse e r a b c d 80 | http c h = (then1' foreignResponse) <$> (foreignConfig c >>= runFn2 httpFn h) 81 | 82 | get :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 83 | get u = runHttpFn' D.GET u config 84 | 85 | get' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 86 | get' = runHttpFn' D.GET 87 | 88 | del :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 89 | del u = runHttpFn' D.DELETE u config 90 | 91 | del' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 92 | del' = runHttpFn' D.DELETE 93 | 94 | head :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 95 | head u = runHttpFn' D.HEAD u config 96 | 97 | head' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 98 | head' = runHttpFn' D.HEAD 99 | 100 | jsonp :: forall e r a b c d. D.Url -> Http -> HttpResponse e r a b c d 101 | jsonp u = runHttpFn' D.JSONP u config 102 | 103 | jsonp' :: forall e r a b c d. D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 104 | jsonp' = runHttpFn' D.JSONP 105 | 106 | post :: forall e r a b c d. D.Url -> RequestData b -> Http -> HttpResponse e r a b c d 107 | post u d = runHttpFn'' D.POST u d config 108 | 109 | post' :: forall e r a b c d. D.Url -> RequestData b -> Config a b c d -> Http -> HttpResponse e r a b c d 110 | post' = runHttpFn'' D.POST 111 | 112 | put :: forall e r a b c d. D.Url -> RequestData b -> Http -> HttpResponse e r a b c d 113 | put u d = runHttpFn'' D.PUT u d config 114 | 115 | put' :: forall e r a b c d. D.Url -> RequestData b -> Config a b c d -> Http -> HttpResponse e r a b c d 116 | put' = runHttpFn'' D.PUT 117 | 118 | runHttpFn' :: forall e r a b c d. D.HttpMethod -> D.Url -> Config a b c d -> Http -> HttpResponse e r a b c d 119 | runHttpFn' m u c h = do 120 | conf <- foreignConfig c 121 | res <- runFn4 httpFn' (show m) u conf h 122 | return $ then1' foreignResponse res 123 | 124 | runHttpFn'' :: forall e r a b c d. D.HttpMethod -> D.Url -> RequestData b -> Config a b c d -> Http -> HttpResponse e r a b c d 125 | runHttpFn'' m u d c h = do 126 | conf <- foreignConfig c 127 | res <- runFn5 httpFn'' (show m) u (writeRequestData d) conf h 128 | return $ then1' foreignResponse res 129 | 130 | foreignConfig :: forall e a b c d. Config a b c d -> HttpEff e I.ForeignConfig 131 | foreignConfig conf = do 132 | c <- I.foreignConfig 133 | I.setConfigMethod conf.method c 134 | I.setConfigUrl conf.url c 135 | I.setConfigParams conf.params c 136 | I.setConfigRequestData conf."data" c 137 | I.setConfigHeaders conf.headers c 138 | I.setConfigXsrfHeaderName conf.xsrfHeaderName c 139 | I.setConfigXsrfCookieName conf.xsrfCookieName c 140 | I.setConfigCache conf.cache c 141 | I.setConfigTimeout conf.timeout c 142 | I.setConfigWithCredentials conf.withCredentials c 143 | I.setConfigResponseType conf.responseType c 144 | return c 145 | 146 | foreignResponse :: forall r a b c d. I.ForeignResponse -> Response r a b c d 147 | foreignResponse res = 148 | let conf = I.getResponseConfig res 149 | in { "data": I.getResponseData (I.getConfigResponseType conf) res 150 | , status: I.getResponseStatus res 151 | , headers: I.getResponseHeaders res 152 | , config: { method: I.getConfigMethod conf 153 | , url: I.getConfigUrl conf 154 | , params: I.getConfigParams conf 155 | , "data": I.getConfigRequestData conf 156 | , headers: I.getConfigHeaders conf 157 | , xsrfHeaderName: I.getConfigXsrfHeaderName conf 158 | , xsrfCookieName: I.getConfigXsrfCookieName conf 159 | , cache: I.getConfigCache conf 160 | , timeout: I.getConfigTimeout conf 161 | , withCredentials: I.getConfigWithCredentials conf 162 | , responseType: I.getConfigResponseType conf 163 | } 164 | , statusText: I.getResponseStatusText res 165 | } 166 | 167 | foreign import httpFn 168 | " function httpFn($http, conf){ \ 169 | \ return function(){ \ 170 | \ return $http(conf); \ 171 | \ }; \ 172 | \ } " 173 | :: forall e. Fn2 Http I.ForeignConfig (ForeignHttpResponse e) 174 | 175 | foreign import httpFn' 176 | " function httpFn$prime(method, url, conf, $http){ \ 177 | \ return function(){ \ 178 | \ return $http[method.toLowerCase()](url, conf); \ 179 | \ } \ 180 | \ } " 181 | :: forall e. Fn4 String 182 | D.Url 183 | I.ForeignConfig 184 | Http 185 | (ForeignHttpResponse e) 186 | 187 | foreign import httpFn'' 188 | " function httpFn$prime$prime(method, url, data, conf, $http){ \ 189 | \ return function(){ \ 190 | \ return $http[method.toLowerCase()](url, data, conf); \ 191 | \ } \ 192 | \ } " 193 | :: forall e. Fn5 String 194 | D.Url 195 | ForeignRequestData 196 | I.ForeignConfig 197 | Http 198 | (ForeignHttpResponse e) 199 | 200 | foreign import emptyParams 201 | " function emptyParams(){ \ 202 | \ return {}; \ 203 | \ } " 204 | :: forall a. Fn0 { | a} 205 | -------------------------------------------------------------------------------- /src/Angular/Http/Internal.purs: -------------------------------------------------------------------------------- 1 | module Angular.Http.Internal 2 | ( ForeignConfig() 3 | , ForeignResponse() 4 | , setConfigMethod 5 | , getConfigMethod 6 | , setConfigUrl 7 | , getConfigUrl 8 | , setConfigParams 9 | , getConfigParams 10 | , setConfigRequestData 11 | , getConfigRequestData 12 | , setConfigHeaders 13 | , getConfigHeaders 14 | , setConfigXsrfHeaderName 15 | , getConfigXsrfHeaderName 16 | , setConfigXsrfCookieName 17 | , getConfigXsrfCookieName 18 | , setConfigCache 19 | , getConfigCache 20 | , setConfigTimeout 21 | , getConfigTimeout 22 | , setConfigWithCredentials 23 | , getConfigWithCredentials 24 | , setConfigResponseType 25 | , getConfigResponseType 26 | , getResponseData 27 | , getResponseStatus 28 | , getResponseHeaders 29 | , getResponseConfig 30 | , getResponseStatusText 31 | , foreignConfig 32 | ) where 33 | 34 | import Control.Monad.Eff 35 | import Control.Monad.Error 36 | import Data.Either 37 | import Data.Foldable (for_) 38 | import Data.Function 39 | import Data.Tuple 40 | 41 | import qualified Data.DOM.Simple.Ajax as D 42 | 43 | import Angular.Cache 44 | import Angular.Http.Types 45 | import Angular.Promise (Promise()) 46 | 47 | foreign import data ForeignConfig :: * 48 | 49 | foreign import data ForeignResponse :: * 50 | 51 | foreign import unimplementedForeignResponse 52 | """ 53 | function unimplementedForeignResponse(){ 54 | return { 55 | }; 56 | } 57 | """ :: ForeignResponse 58 | 59 | instance errorForeignResponse :: Error ForeignResponse where 60 | noMsg = unimplementedForeignResponse 61 | strMsg = \_ -> unimplementedForeignResponse 62 | 63 | setConfigMethod :: forall e. D.HttpMethod -> ForeignConfig -> HttpEff e Unit 64 | setConfigMethod m = runFn3 setConfigPropFn "method" (show m) 65 | 66 | getConfigMethod:: ForeignConfig -> D.HttpMethod 67 | getConfigMethod c = readMethod $ runFn2 getConfigPropFn "method" c 68 | 69 | setConfigUrl :: forall e. D.Url -> ForeignConfig -> HttpEff e Unit 70 | setConfigUrl = runFn3 setConfigPropFn "url" 71 | 72 | getConfigUrl :: ForeignConfig -> D.Url 73 | getConfigUrl = runFn2 getConfigPropFn "url" 74 | 75 | setConfigParams :: forall e a. { | a } -> ForeignConfig -> HttpEff e Unit 76 | setConfigParams = runFn3 setConfigPropFn "params" 77 | 78 | getConfigParams :: forall a. ForeignConfig -> { | a} 79 | getConfigParams = runFn2 getConfigPropFn "params" 80 | 81 | setConfigRequestData :: forall e a. RequestData a -> ForeignConfig -> HttpEff e Unit 82 | setConfigRequestData = 83 | let k = "data" 84 | in cataRequestData (runFn3 setConfigPropFn k (runFn0 undefinedFn)) 85 | (runFn3 setConfigPropFn k) 86 | (runFn3 setConfigPropFn k) 87 | 88 | getConfigRequestData :: forall e a. ForeignConfig -> RequestData a 89 | getConfigRequestData c = runFn2 readRequestDataFn { noRequestData: NoRequestData 90 | , stringRequestData: StringRequestData 91 | , objectRequestData: ObjectRequestData } $ runFn2 getConfigPropFn "data" c 92 | 93 | setConfigHeaders :: forall e. Headers -> ForeignConfig -> HttpEff e Unit 94 | setConfigHeaders (Headers h) c = 95 | let k = "headers" in for_ h $ \a -> 96 | case a of 97 | Tuple l (Left v) -> runFn4 setInnerConfigPropFn k l v c 98 | Tuple l (Right v) -> runFn4 setInnerConfigPropFn k l v c 99 | 100 | getConfigHeaders :: ForeignConfig -> Headers 101 | getConfigHeaders c = runFn4 readHeadersFn Left Right Tuple $ runFn2 getConfigPropFn "headers" c 102 | 103 | setConfigXsrfHeaderName :: forall e. String -> ForeignConfig -> HttpEff e Unit 104 | setConfigXsrfHeaderName = runFn3 setConfigPropFn "xsrfHeaderName" 105 | 106 | getConfigXsrfHeaderName :: ForeignConfig -> String 107 | getConfigXsrfHeaderName = runFn2 getConfigPropFn "xsrfHeaderName" 108 | 109 | setConfigXsrfCookieName :: forall e. String -> ForeignConfig -> HttpEff e Unit 110 | setConfigXsrfCookieName = runFn3 setConfigPropFn "xsrfCookieName" 111 | 112 | getConfigXsrfCookieName :: ForeignConfig -> String 113 | getConfigXsrfCookieName = runFn2 getConfigPropFn "xsrfCookieName" 114 | 115 | setConfigCache :: forall e. Either Boolean Cache -> ForeignConfig -> HttpEff e Unit 116 | setConfigCache = let k = "cache" in either (runFn3 setConfigPropFn k) (runFn3 setConfigPropFn k) 117 | 118 | getConfigCache :: ForeignConfig -> (Either Boolean Cache) 119 | getConfigCache c = runFn3 readCacheFn Left Right $ runFn2 getConfigPropFn "cache" c 120 | 121 | setConfigTimeout :: forall e a b. Either Number (Promise a b) -> ForeignConfig -> HttpEff e Unit 122 | setConfigTimeout = let k = "timeout" in either (runFn3 setConfigPropFn k) (runFn3 setConfigPropFn k) 123 | 124 | getConfigTimeout :: forall a b. ForeignConfig -> Either Number (Promise a b) 125 | getConfigTimeout c = runFn3 readTimeoutFn Left Right $ runFn2 getConfigPropFn "timeout" c 126 | 127 | setConfigWithCredentials :: forall e. Boolean -> ForeignConfig -> HttpEff e Unit 128 | setConfigWithCredentials = runFn3 setConfigPropFn "withCredentials" 129 | 130 | getConfigWithCredentials :: ForeignConfig -> Boolean 131 | getConfigWithCredentials = runFn2 getConfigPropFn "withCredentials" 132 | 133 | setConfigResponseType :: forall e. D.ResponseType -> ForeignConfig -> HttpEff e Unit 134 | setConfigResponseType r = runFn3 setConfigPropFn "responseType" (show r) 135 | 136 | getConfigResponseType :: ForeignConfig -> D.ResponseType 137 | getConfigResponseType c = readResponseType $ runFn2 getConfigPropFn "responseType" c 138 | 139 | getResponseData :: forall a. D.ResponseType -> ForeignResponse -> D.HttpData a 140 | getResponseData t = get t <<< runFn2 getResponsePropFn "data" where 141 | get D.Default = readResponseData D.TextData 142 | get D.ArrayBuffer = readResponseData D.ArrayBufferData 143 | get D.Blob = readResponseData D.BlobData 144 | get D.Document = readResponseData D.DocumentData 145 | get D.Json = readResponseData D.JsonData 146 | get D.Text = readResponseData D.TextData 147 | get D.MozBlob = readResponseData D.BlobData 148 | get D.MozChunkedText = readResponseData D.TextData 149 | get D.MozChunkedArrayBuffer = readResponseData D.ArrayBufferData 150 | 151 | getResponseStatus :: ForeignResponse -> Status 152 | getResponseStatus r = readStatus $ runFn2 getResponsePropFn "status" r 153 | 154 | getResponseHeaders :: ForeignResponse -> ([String] -> String) 155 | getResponseHeaders = runFn2 getResponsePropFn "headers" 156 | 157 | getResponseConfig :: ForeignResponse -> ForeignConfig 158 | getResponseConfig = runFn2 getResponsePropFn "config" 159 | 160 | getResponseStatusText :: ForeignResponse -> String 161 | getResponseStatusText = runFn2 getResponsePropFn "statusText" 162 | 163 | foreign import foreignConfig 164 | " function foreignConfig(){ \ 165 | \ return {}; \ 166 | \ } " 167 | :: forall e. HttpEff e ForeignConfig 168 | 169 | foreign import setConfigPropFn 170 | " function setConfigPropFn(k, v, conf){ \ 171 | \ return function(){ \ 172 | \ conf[k] = v; \ 173 | \ }; \ 174 | \ } " 175 | :: forall e a. Fn3 String a ForeignConfig (HttpEff e Unit) 176 | 177 | foreign import setInnerConfigPropFn 178 | " function setInnerConfigPropFn(k1, k2, v, conf){ \ 179 | \ return function(){ \ 180 | \ if (angular.isUndefined(conf[k1])) { \ 181 | \ conf[k1] = {}; \ 182 | \ } \ 183 | \ conf[k1][k2] = v; \ 184 | \ }; \ 185 | \ } " 186 | :: forall e a. Fn4 String String a ForeignConfig (HttpEff e Unit) 187 | 188 | foreign import getConfigPropFn 189 | " function getConfigPropFn(k, conf){ \ 190 | \ return conf[k]; \ 191 | \ } " 192 | :: forall a. Fn2 String ForeignConfig a 193 | 194 | foreign import getResponsePropFn 195 | " function getResponsePropFn(k, response){ \ 196 | \ return response[k]; \ 197 | \ } " 198 | :: forall a. Fn2 String ForeignResponse a 199 | 200 | foreign import undefinedFn 201 | " function undefinedFn(){ \ 202 | \ return undefined; \ 203 | \ } " 204 | :: forall a. Fn0 a 205 | -------------------------------------------------------------------------------- /src/Angular/Http/Types.purs: -------------------------------------------------------------------------------- 1 | module Angular.Http.Types 2 | ( NgHttp() 3 | , HttpEff() 4 | , Status(..) 5 | , RequestData(..) 6 | , Header() 7 | , Headers(..) 8 | , RequestDataFn() 9 | , ForeignRequestData() 10 | , ForeignResponseData() 11 | , ForeignCache() 12 | , ForeignHeaders() 13 | , ForeignTimeout() 14 | , stringHeader 15 | , fnHeader 16 | , readCacheFn 17 | , readRequestDataFn 18 | , readResponseData 19 | , readHeadersFn 20 | , readMethod 21 | , readResponseType 22 | , readStatus 23 | , readTimeoutFn 24 | , cataRequestData 25 | , writeRequestData 26 | ) where 27 | 28 | import Control.Monad.Eff 29 | import Data.Either 30 | import Data.Function 31 | import Data.Tuple 32 | 33 | import Angular.Cache (Cache()) 34 | import Angular.Promise (Promise()) 35 | 36 | import qualified Data.DOM.Simple.Types as D 37 | import qualified Data.DOM.Simple.Ajax as D 38 | 39 | foreign import data NgHttp :: ! 40 | 41 | foreign import data ForeignRequestData :: * 42 | 43 | foreign import data ForeignResponseData :: * 44 | 45 | foreign import data ForeignHeaders :: * 46 | 47 | foreign import data ForeignCache :: * 48 | 49 | foreign import data ForeignTimeout :: * 50 | 51 | type HttpEff e r = Eff (nghttp :: NgHttp | e) r 52 | 53 | data Status = OK | Created | NoContent | BadRequest | Unauthorized | Forbidden | NotFound | InternalServerError | OtherStatus Number 54 | 55 | data RequestData a 56 | = NoRequestData 57 | | StringRequestData String 58 | | ObjectRequestData a 59 | 60 | type Header = Tuple String (Either String (Unit -> String)) 61 | 62 | newtype Headers = Headers [Header] 63 | 64 | stringHeader :: String -> String -> Header 65 | stringHeader k v = Tuple k $ Left v 66 | 67 | fnHeader :: String -> (Unit -> String) -> Header 68 | fnHeader k v = Tuple k $ Right v 69 | 70 | type RequestDataFn a 71 | = { noRequestData :: RequestData a 72 | , stringRequestData :: String -> RequestData a 73 | , objectRequestData :: a -> RequestData a 74 | } 75 | 76 | foreign import readRequestDataFn 77 | " function readRequestDataFn(fn, data){ \ 78 | \ if (angular.isUndefined(data)) return fn.noRequestData; \ 79 | \ else if (angular.isString(data)) return fn.stringRequestData(data); \ 80 | \ else return fn.objectRequestData(data); \ 81 | \ } " 82 | :: forall a. Fn2 (RequestDataFn a) ForeignRequestData (RequestData a) 83 | 84 | cataRequestData :: forall a b 85 | . b 86 | -> (String -> b) 87 | -> (a -> b) 88 | -> RequestData a 89 | -> b 90 | cataRequestData f g h d = 91 | case d of 92 | NoRequestData -> f 93 | StringRequestData a -> g a 94 | ObjectRequestData a -> h a 95 | 96 | foreign import writeRequestData 97 | " function writeRequestData(data){ \ 98 | \ return cataRequestData(undefined) \ 99 | \ (angular.identity) \ 100 | \ (angular.identity) \ 101 | \ (data); \ 102 | \ } " 103 | :: forall a. RequestData a -> ForeignRequestData 104 | 105 | foreign import readResponseDataFn 106 | " function readResponseDataFn(no, fn, data){ \ 107 | \ if (angular.isUndefined(data)) return no; \ 108 | \ else return fn(data); \ 109 | \ } " 110 | :: forall a d. Fn3 (D.HttpData a) (d -> D.HttpData a) ForeignResponseData (D.HttpData a) 111 | 112 | readResponseData :: forall a d. (d -> D.HttpData a) -> ForeignResponseData -> D.HttpData a 113 | readResponseData = runFn3 readResponseDataFn D.NoData 114 | 115 | foreign import readHeadersFn 116 | " function readHeadersFn(left, right, tuple, headers){ \ 117 | \ if (angular.isUndefined(headers)) return []; \ 118 | \ else { \ 119 | \ var arr = []; \ 120 | \ angular.forEach(headers, function(v, k){ \ 121 | \ arr.push(tuple(k)(angular.isString(v) ? left(v) : right(v))); \ 122 | \ }); \ 123 | \ return arr; \ 124 | \ } \ 125 | \ } " 126 | :: forall a b. Fn4 (String -> Either String (Unit -> String)) 127 | ((Unit -> String) -> Either String (Unit -> String)) 128 | (String -> Either String (Unit -> String) -> Header) 129 | ForeignHeaders 130 | Headers 131 | 132 | readStatus :: Number -> Status 133 | readStatus s = 134 | case s of 135 | 200 -> OK 136 | 201 -> Created 137 | 204 -> NoContent 138 | 400 -> BadRequest 139 | 401 -> Unauthorized 140 | 403 -> Forbidden 141 | 404 -> NotFound 142 | 500 -> InternalServerError 143 | a -> OtherStatus a 144 | 145 | readMethod :: String -> D.HttpMethod 146 | readMethod m = 147 | case m of 148 | "GET" -> D.GET 149 | "POST" -> D.POST 150 | "PUT" -> D.PUT 151 | "DELETE" -> D.DELETE 152 | "PATCH" -> D.PATCH 153 | "HEAD" -> D.HEAD 154 | "OPTIONS" -> D.OPTIONS 155 | "JSONP" -> D.JSONP 156 | 157 | readResponseType :: String -> D.ResponseType 158 | readResponseType r = 159 | case r of 160 | "" -> D.Default 161 | "arraybuffer" -> D.ArrayBuffer 162 | "blob" -> D.Blob 163 | "document" -> D.Document 164 | "json" -> D.Json 165 | "text" -> D.Text 166 | "moz-blob" -> D.MozBlob 167 | "moz-chunked-test" -> D.MozChunkedText 168 | "moz-chunked-arraybuffer" -> D.MozChunkedArrayBuffer 169 | 170 | foreign import readCacheFn 171 | " function readCacheFn(left, right, cache){ \ 172 | \ return (cache === true || cache === false) ? left(cache) : right(cache); \ 173 | \ } " 174 | :: Fn3 (Boolean -> Either Boolean Cache) 175 | (Cache -> Either Boolean Cache) 176 | ForeignCache 177 | (Either Boolean Cache) 178 | 179 | foreign import readTimeoutFn 180 | " function readTimeoutFn(left, right, timeout){ \ 181 | \ return angular.isNumber(timeout) ? left(timeout) : right(timeout); \ 182 | \ } " 183 | :: forall a b. Fn3 (Number -> Either Number (Promise a b)) 184 | (Promise a b -> Either Number (Promise a b)) 185 | ForeignTimeout 186 | (Either Number (Promise a b)) 187 | -------------------------------------------------------------------------------- /src/Angular/Injector.purs: -------------------------------------------------------------------------------- 1 | module Angular.Injector 2 | ( Injector() 3 | , InjEff() 4 | , NgInj() 5 | , get 6 | , invoke 7 | , has 8 | , instantiate 9 | , annotate 10 | , injector 11 | ) where 12 | 13 | import Control.Monad.Eff 14 | import Data.Function 15 | import Data.Maybe 16 | 17 | foreign import data Injector :: * 18 | 19 | foreign import data NgInj :: ! 20 | 21 | type InjEff e a = Eff (nginj :: NgInj | e) a 22 | 23 | get :: forall e a. String -> Injector -> InjEff e a 24 | get = runFn2 getFn 25 | 26 | invoke :: forall e r a b c. a -> Maybe { | b } -> Maybe { | c } -> Injector -> InjEff e r 27 | invoke = runFn5 invokeFn maybe 28 | 29 | has :: forall e. String -> Injector -> InjEff e Boolean 30 | has = runFn2 hasFn 31 | 32 | instantiate :: forall e r a b. a -> Maybe { | b } -> Injector -> InjEff e r 33 | instantiate = runFn4 instantiateFn maybe 34 | 35 | annotate :: forall e a. a -> Injector -> InjEff e [String] 36 | annotate = runFn2 annotateFn 37 | 38 | foreign import injector 39 | " function injector(modules){ \ 40 | \ return function(){ \ 41 | \ return angular.injector(modules); \ 42 | \ }; \ 43 | \ } " 44 | :: forall e. [String] -> InjEff e Injector 45 | 46 | foreign import getFn 47 | " function getFn(name, $injector){ \ 48 | \ return function(){ \ 49 | \ return $injector.get(name); \ 50 | \ } \ 51 | \ } " 52 | :: forall e a. Fn2 String Injector (InjEff e a) 53 | 54 | foreign import invokeFn 55 | " function invokeFn(maybe, fn, self, locals, $injector){ \ 56 | \ return function(){ \ 57 | \ return $injector.invoke(fn, \ 58 | \ maybe(undefined)(angular.identity)(self), \ 59 | \ maybe(undefined)(angular.identity)(locals)); \ 60 | \ } \ 61 | \ } " 62 | :: forall e r s t u a b c. Fn5 (t -> (u -> t) -> Maybe s -> t) a (Maybe { | b }) (Maybe { | c }) Injector (InjEff e r) 63 | 64 | foreign import hasFn 65 | " function hasFn(name, $injector){ \ 66 | \ return function(){ \ 67 | \ return $injector.get(name); \ 68 | \ } \ 69 | \ } " 70 | :: forall e. Fn2 String Injector (InjEff e Boolean) 71 | 72 | foreign import instantiateFn 73 | " function instantiateFn(maybe, type, locals, $injector){ \ 74 | \ return function(){ \ 75 | \ return $injector.instantiate(type, maybe(undefined)(angular.identity)(locals)); \ 76 | \ } \ 77 | \ } " 78 | :: forall e r s t u a b. Fn4 (t -> (u -> t) -> Maybe s -> t) a (Maybe { | b }) Injector (InjEff e r) 79 | 80 | foreign import annotateFn 81 | " function annotateFn(fn, $injector){ \ 82 | \ return function(){ \ 83 | \ return $injector.annotate(fn); \ 84 | \ } \ 85 | \ } " 86 | :: forall e a. Fn2 a Injector (InjEff e [String]) 87 | -------------------------------------------------------------------------------- /src/Angular/Interpolate.purs: -------------------------------------------------------------------------------- 1 | module Angular.Interpolate 2 | ( NgInterpolate() 3 | , Interpolate() 4 | , InterpolateEff() 5 | , Expression() 6 | , interpolate 7 | , startSymbol 8 | , endSymbol 9 | ) where 10 | 11 | import Control.Monad.Eff 12 | import Data.Function 13 | import Data.Maybe 14 | 15 | foreign import data Interpolate :: * 16 | 17 | foreign import data NgInterpolate :: ! 18 | 19 | type Expression a = { | a } -> String 20 | 21 | type InterpolateEff e a = Eff (nginterpolate :: NgInterpolate | e) a 22 | 23 | foreign import interpolateFn 24 | " function interpolateFn(fromMaybe, text, mustHaveExpression, trustedContext, $interpolate){ \ 25 | \ return function(){ \ 26 | \ return $interpolate(text, \ 27 | \ fromMaybe(undefined)(mustHaveExpression), \ 28 | \ fromMaybe(undefined)(trustedContext)); \ 29 | \ }; \ 30 | \ } " 31 | :: forall e a. Fn5 (forall a. a -> Maybe a -> a) 32 | String 33 | (Maybe Boolean) 34 | (Maybe String) 35 | Interpolate 36 | (InterpolateEff e (Expression a)) 37 | 38 | interpolate :: forall e a. String -> Maybe Boolean -> Maybe String -> Interpolate -> InterpolateEff e (Expression a) 39 | interpolate = runFn5 interpolateFn fromMaybe 40 | 41 | foreign import startSymbol 42 | " function startSymbol($interpolate){ \ 43 | \ return $interpolate.startSymbol(); \ 44 | \ } " 45 | :: Interpolate -> String 46 | 47 | foreign import endSymbol 48 | " function endSymbol($interpolate){ \ 49 | \ return $interpolate.endSymbol(); \ 50 | \ } " 51 | :: Interpolate -> String 52 | -------------------------------------------------------------------------------- /src/Angular/Interval.purs: -------------------------------------------------------------------------------- 1 | module Angular.Interval 2 | ( Interval() 3 | , NgInterval() 4 | , IntervalEff() 5 | , IntervalPromise() 6 | , interval 7 | , interval' 8 | , interval'' 9 | , intervalk 10 | , cancel 11 | ) where 12 | 13 | import Control.Monad.Eff 14 | import Data.Function 15 | import Data.Maybe 16 | 17 | import Angular.Promise (Promise()) 18 | 19 | foreign import data Interval :: * 20 | 21 | foreign import data NgInterval :: ! 22 | 23 | type IntervalEff e r = Eff (nginterval :: NgInterval | e) r 24 | 25 | type IntervalPromise = Promise Unit Number 26 | 27 | foreign import intervalFn 28 | " function intervalFn(fromMaybe, fn, delay, count, invokeApply, $interval){ \ 29 | \ return function(){ \ 30 | \ return $interval(fn, delay, fromMaybe(undefined)(count), fromMaybe(undefined)(invokeApply)); \ 31 | \ }; \ 32 | \ } " 33 | :: forall e f r. Fn6 (forall a. a -> Maybe a -> a) 34 | (Eff f r) 35 | Number 36 | (Maybe Number) 37 | (Maybe Boolean) 38 | Interval 39 | (IntervalEff e IntervalPromise) 40 | 41 | interval :: forall e f r. Eff f r -> Number -> Number -> Boolean -> Interval -> IntervalEff e IntervalPromise 42 | interval fn delay count invoke = runFn6 intervalFn fromMaybe fn delay (Just count) (Just invoke) 43 | 44 | interval' :: forall e f r. Eff f r -> Number -> Number -> Interval -> IntervalEff e IntervalPromise 45 | interval' fn delay count = runFn6 intervalFn fromMaybe fn delay (Just count) Nothing 46 | 47 | interval'' :: forall e f r. Eff f r -> Number -> Interval -> IntervalEff e IntervalPromise 48 | interval'' fn delay = runFn6 intervalFn fromMaybe fn delay Nothing Nothing 49 | 50 | intervalk :: forall e f r. Number -> Number -> Boolean -> Interval -> Eff f r -> IntervalEff e IntervalPromise 51 | intervalk delay count invoke interval fn = runFn6 intervalFn fromMaybe fn delay (Just count) (Just invoke) interval 52 | 53 | foreign import cancelFn 54 | " function cancelFn(promise, $interval){ \ 55 | \ return function(){ \ 56 | \ return $interval.cancel(promise); \ 57 | \ }; \ 58 | \ } " 59 | :: forall e. Fn2 IntervalPromise 60 | Interval 61 | (IntervalEff e Boolean) 62 | 63 | cancel :: forall e. IntervalPromise -> Interval -> IntervalEff e Boolean 64 | cancel = runFn2 cancelFn 65 | -------------------------------------------------------------------------------- /src/Angular/Location.purs: -------------------------------------------------------------------------------- 1 | module Angular.Location 2 | ( Location() 3 | , LocEff() 4 | , NgLoc() 5 | , getPath 6 | , setPath 7 | ) where 8 | 9 | import Control.Monad.Eff 10 | 11 | foreign import data Location :: * 12 | 13 | foreign import data NgLoc :: ! 14 | 15 | type LocEff e a = Eff (ngloc :: NgLoc | e) a 16 | 17 | foreign import getPath 18 | " function getPath(loc){ \ 19 | \ return function(){ \ 20 | \ return loc.path(); \ 21 | \ }; \ 22 | \ }" 23 | :: forall e. Location -> LocEff e String 24 | 25 | foreign import setPath 26 | " function setPath(path){ \ 27 | \ return function(loc){ \ 28 | \ return function(){ \ 29 | \ return loc.path(path); \ 30 | \ }; \ 31 | \ }; \ 32 | \ }" 33 | :: forall e. String -> Location -> LocEff e String 34 | -------------------------------------------------------------------------------- /src/Angular/Log.purs: -------------------------------------------------------------------------------- 1 | module Angular.Log 2 | ( NgLog() 3 | , Log() 4 | , LogEff() 5 | , log 6 | , info 7 | , warn 8 | , error 9 | , debug 10 | ) where 11 | 12 | import Control.Monad.Eff 13 | import Data.Function 14 | 15 | foreign import data Log :: * 16 | 17 | foreign import data NgLog :: ! 18 | 19 | type LogEff e = Eff (nglog :: NgLog | e) Unit 20 | 21 | foreign import logFn 22 | " function logFn(fn, message, $log){ \ 23 | \ return function(){ \ 24 | \ return $log[fn](message); \ 25 | \ }; \ 26 | \ } " 27 | :: forall e a. Fn3 String a Log (LogEff e) 28 | 29 | log :: forall e a. a -> Log -> LogEff e 30 | log = runFn3 logFn "log" 31 | 32 | info :: forall e a. a -> Log -> LogEff e 33 | info = runFn3 logFn "info" 34 | 35 | warn :: forall e a. a -> Log -> LogEff e 36 | warn = runFn3 logFn "warn" 37 | 38 | error :: forall e a. a -> Log -> LogEff e 39 | error = runFn3 logFn "error" 40 | 41 | debug :: forall e a. a -> Log -> LogEff e 42 | debug = runFn3 logFn "debug" 43 | -------------------------------------------------------------------------------- /src/Angular/Module.purs: -------------------------------------------------------------------------------- 1 | module Angular.Module 2 | ( Module() 3 | , NgReadModule() 4 | , NgWriteModule() 5 | , NgRegisterToModule() 6 | , ReadEff() 7 | , WriteEff() 8 | , RegisterEff() 9 | , ngmodule 10 | , ngmodule' 11 | , provider 12 | , factory 13 | , service 14 | , value 15 | , constant 16 | , animation 17 | , filter 18 | , controller 19 | , directive 20 | , config 21 | , run 22 | ) where 23 | 24 | import Control.Monad.Eff 25 | import Data.Function 26 | 27 | foreign import data Module :: * 28 | 29 | foreign import data NgReadModule :: ! 30 | 31 | foreign import data NgWriteModule :: ! 32 | 33 | foreign import data NgRegisterToModule :: ! 34 | 35 | type ReadEff e = Eff (ngrmod :: NgReadModule | e) Module 36 | 37 | type WriteEff e = Eff (ngwmod :: NgWriteModule | e) Module 38 | 39 | type RegisterEff e = Eff (nggmod :: NgRegisterToModule | e) Module 40 | 41 | ngmodule :: forall e. String -> ReadEff e 42 | ngmodule = readModuleFn 43 | 44 | ngmodule' :: forall e. String -> [String] -> WriteEff e 45 | ngmodule' = runFn2 writeModuleFn 46 | 47 | provider :: forall e a. String -> a -> Module -> RegisterEff e 48 | provider = runFn4 registerNamedToModuleFn "provider" 49 | 50 | factory :: forall e a. String -> a -> Module -> RegisterEff e 51 | factory = runFn4 registerNamedToModuleFn "factory" 52 | 53 | service :: forall e a. String -> a -> Module -> RegisterEff e 54 | service = runFn4 registerNamedToModuleFn "service" 55 | 56 | value :: forall e a. String -> a -> Module -> RegisterEff e 57 | value = runFn4 registerNamedToModuleFn "value" 58 | 59 | constant :: forall e a. String -> a -> Module -> RegisterEff e 60 | constant = runFn4 registerNamedToModuleFn "constant" 61 | 62 | animation :: forall e a. String -> a -> Module -> RegisterEff e 63 | animation = runFn4 registerNamedToModuleFn "animation" 64 | 65 | filter :: forall e a. String -> a -> Module -> RegisterEff e 66 | filter = runFn4 registerNamedToModuleFn "filter" 67 | 68 | controller :: forall e a. String -> a -> Module -> RegisterEff e 69 | controller = runFn4 registerNamedToModuleFn "controller" 70 | 71 | directive :: forall e a. String -> a -> Module -> RegisterEff e 72 | directive = runFn4 registerNamedToModuleFn "directive" 73 | 74 | config :: forall e a. a -> Module -> RegisterEff e 75 | config = runFn3 registerUnnamedToModuleFn "config" 76 | 77 | run :: forall e a. a -> Module -> RegisterEff e 78 | run = runFn3 registerUnnamedToModuleFn "run" 79 | 80 | foreign import readModuleFn 81 | "function readModuleFn(name){\ 82 | \ return function(){\ 83 | \ return angular.module(name);\ 84 | \ };\ 85 | \}" :: forall e. String -> ReadEff e 86 | 87 | foreign import writeModuleFn 88 | "function writeModuleFn(name, modules){\ 89 | \ return function(){\ 90 | \ return angular.module(name, modules);\ 91 | \ };\ 92 | \}" :: forall e. Fn2 String [String] (WriteEff e) 93 | 94 | foreign import registerNamedToModuleFn 95 | "function registerNamedToModuleFn(type, name, a, module){\ 96 | \ return function(){\ 97 | \ return module[type](name, a);\ 98 | \ };\ 99 | \}" :: forall e a. Fn4 String String a Module (RegisterEff e) 100 | 101 | foreign import registerUnnamedToModuleFn 102 | "function registerUnnamedToModuleFn(type, a, module){\ 103 | \ return function(){\ 104 | \ return module[type](a);\ 105 | \ };\ 106 | \}" :: forall e a. Fn3 String a Module (RegisterEff e) 107 | -------------------------------------------------------------------------------- /src/Angular/NgModelController.purs: -------------------------------------------------------------------------------- 1 | module Angular.NgModelController 2 | ( NgModelController() 3 | , NgModel() 4 | , NgModelEff() 5 | , Parser() 6 | , Formatter() 7 | , ValidationErrorKey() 8 | , render 9 | , setRender 10 | , isEmpty 11 | , setIsEmpty 12 | , setValidity 13 | , setPristine 14 | , setViewValue 15 | , viewValue 16 | , modelValue 17 | , setModelValue 18 | , appendParsers 19 | , prependParsers 20 | , appendFormatters 21 | , prependFormatters 22 | , appendViewChangeListeners 23 | , prependViewChangeListeners 24 | , error 25 | , pristine 26 | , dirty 27 | , valid 28 | , invalid 29 | ) where 30 | 31 | import Control.Monad.Eff 32 | import Data.Function 33 | import Data.Maybe 34 | 35 | foreign import data NgModelController :: * -> * 36 | 37 | foreign import data NgModel :: ! 38 | 39 | type NgModelEff e r = Eff (ngmodel :: NgModel | e) r 40 | 41 | type ValidationErrorKey = String 42 | 43 | type Parser a = String -> Maybe a 44 | 45 | type Formatter a = a -> String 46 | 47 | foreign import render 48 | " function render($ctrl){ \ 49 | \ return function(){ \ 50 | \ return $ctrl.$render(); \ 51 | \ }; \ 52 | \ } " 53 | :: forall e a. NgModelController a -> NgModelEff e Unit 54 | 55 | foreign import setRender 56 | " function setRender(render){ \ 57 | \ return function($ctrl){ \ 58 | \ $ctrl.$render = render; \ 59 | \ return {}; \ 60 | \ }; \ 61 | \ } " 62 | :: forall e a. NgModelEff e Unit -> NgModelController a -> NgModelEff e Unit 63 | 64 | foreign import isEmpty 65 | " function isEmpty(value){ \ 66 | \ return function($ctrl){ \ 67 | \ return $ctrl.$isEmpty(value); \ 68 | \ }; \ 69 | \ } " 70 | :: forall e a. a -> NgModelController a -> NgModelEff e Boolean 71 | 72 | foreign import setIsEmpty 73 | " function setIsEmpty(isEmpty){ \ 74 | \ return function($ctrl){ \ 75 | \ $ctrl.$isEmpty = function(a){return isEmpty(a)();}; \ 76 | \ return $ctrl; \ 77 | \ }; \ 78 | \ } " 79 | :: forall e a b. (b -> NgModelEff e Boolean) -> NgModelController a -> NgModelEff e (NgModelController b) 80 | 81 | foreign import setValidity 82 | " function setValidity(validationErrorKey){ \ 83 | \ return function(isValid){ \ 84 | \ return function($ctrl){ \ 85 | \ return $ctrl.$setValidity(validationErrorKey, isValid); \ 86 | \ }; \ 87 | \ }; \ 88 | \ } " 89 | :: forall e a. ValidationErrorKey -> Boolean -> NgModelController a -> NgModelEff e Unit 90 | 91 | foreign import setPristine 92 | " function setPristine($ctrl){ \ 93 | \ return function(){ \ 94 | \ return $ctrl.$setPristine(); \ 95 | \ }; \ 96 | \ } " 97 | :: forall e a. NgModelController a -> NgModelEff e Unit 98 | 99 | foreign import setViewValue 100 | " function setViewValue(value){ \ 101 | \ return function($ctrl){ \ 102 | \ return function(){ \ 103 | \ return $ctrl.$setViewValue(value); \ 104 | \ }; \ 105 | \ }; \ 106 | \ } " 107 | :: forall e a. String -> NgModelController a -> NgModelEff e Unit 108 | 109 | foreign import viewValue 110 | " function viewValue($ctrl){ \ 111 | \ return function(){ \ 112 | \ return $ctrl.$viewValue; \ 113 | \ }; \ 114 | \ } " 115 | :: forall e a. NgModelController a -> NgModelEff e String 116 | 117 | foreign import modelValue 118 | " function modelValue($ctrl){ \ 119 | \ return function(){ \ 120 | \ return $ctrl.$modelValue; \ 121 | \ }; \ 122 | \ } " 123 | :: forall e a. NgModelController a -> NgModelEff e a 124 | 125 | foreign import setModelValue 126 | " function setModelValue(value){ \ 127 | \ return function($ctrl){ \ 128 | \ return function(){ \ 129 | \ $ctrl.$modelValue = value; \ 130 | \ return $ctrl; \ 131 | \ }; \ 132 | \ }; \ 133 | \ } " 134 | :: forall e a b. b -> NgModelController a -> NgModelEff e (NgModelController b) 135 | 136 | foreign import appendParsersFn 137 | " function appendParsersFn(fromMaybe, parsers, $ctrl){ \ 138 | \ return function(){ \ 139 | \ var as = []; \ 140 | \ angular.forEach(parsers, function(p){ \ 141 | \ as.push(function(v){ \ 142 | \ return fromMaybe(undefined)(p(v)); \ 143 | \ }); \ 144 | \ }); \ 145 | \ $ctrl.$parsers.push.apply($ctrl.$parsers, as); \ 146 | \ return {}; \ 147 | \ }; \ 148 | \ } " 149 | :: forall e a. Fn3 (a -> Maybe a -> a) 150 | [Parser a] 151 | (NgModelController a) 152 | (NgModelEff e Unit) 153 | 154 | appendParsers :: forall e a. [Parser a] -> NgModelController a -> NgModelEff e Unit 155 | appendParsers = runFn3 appendParsersFn fromMaybe 156 | 157 | foreign import prependParsersFn 158 | " function prependParsersFn(fromMaybe, parsers, $ctrl){ \ 159 | \ return function(){ \ 160 | \ var as = []; \ 161 | \ angular.forEach(parsers, function(p){ \ 162 | \ as.push(function(v){ \ 163 | \ return fromMaybe(undefined)(p(v)); \ 164 | \ }); \ 165 | \ }); \ 166 | \ $ctrl.$parsers.unshift.apply($ctrl.$parsers, as); \ 167 | \ return {}; \ 168 | \ }; \ 169 | \ } " 170 | :: forall e a. Fn3 (a -> Maybe a -> a) 171 | [Parser a] 172 | (NgModelController a) 173 | (NgModelEff e Unit) 174 | 175 | prependParsers :: forall e a. [Parser a] -> NgModelController a -> NgModelEff e Unit 176 | prependParsers = runFn3 prependParsersFn fromMaybe 177 | 178 | foreign import appendFormatters 179 | " function appendFormatters(formatters){ \ 180 | \ return function($ctrl){ \ 181 | \ return function(){ \ 182 | \ $ctrl.$formatters.push.apply($ctrl.$formatters, formatters); \ 183 | \ return {}; \ 184 | \ }; \ 185 | \ }; \ 186 | \ } " 187 | :: forall e a. [Formatter a] -> NgModelController a -> NgModelEff e Unit 188 | 189 | foreign import prependFormatters 190 | " function prependFormatters(formatters){ \ 191 | \ return function($ctrl){ \ 192 | \ return function(){ \ 193 | \ $ctrl.$formatters.unshift.apply($ctrl.$formatters, formatters); \ 194 | \ return {}; \ 195 | \ }; \ 196 | \ }; \ 197 | \ } " 198 | :: forall e a. [Formatter a] -> NgModelController a -> NgModelEff e Unit 199 | 200 | foreign import appendViewChangeListeners 201 | " function appendViewChangeListeners(listeners){ \ 202 | \ return function($ctrl){ \ 203 | \ return function(){ \ 204 | \ $ctrl.$viewChangeListeners.push.apply($ctrl.$viewChangeListeners, listeners); \ 205 | \ return {}; \ 206 | \ }; \ 207 | \ }; \ 208 | \ } " 209 | :: forall e a. [Eff e Unit] -> NgModelController a -> NgModelEff e Unit 210 | 211 | foreign import prependViewChangeListeners 212 | " function prependViewChangeListeners(listeners){ \ 213 | \ return function($ctrl){ \ 214 | \ return function(){ \ 215 | \ $ctrl.$viewChangeListeners.unshift.apply($ctrl.$viewChangeListeners, listeners); \ 216 | \ return {}; \ 217 | \ }; \ 218 | \ }; \ 219 | \ } " 220 | :: forall e a. [Eff e Unit] -> NgModelController a -> NgModelEff e Unit 221 | 222 | foreign import error 223 | " function error($ctrl){ \ 224 | \ return function(){ \ 225 | \ return $ctrl.$error; \ 226 | \ }; \ 227 | \ } " 228 | :: forall e a b. NgModelController a -> NgModelEff e { | b } 229 | 230 | foreign import pristine 231 | " function pristine($ctrl){ \ 232 | \ return function(){ \ 233 | \ return $ctrl.$pristine; \ 234 | \ }; \ 235 | \ } " 236 | :: forall e a. NgModelController a -> NgModelEff e Boolean 237 | 238 | foreign import dirty 239 | " function dirty($ctrl){ \ 240 | \ return function(){ \ 241 | \ return $ctrl.$dirty; \ 242 | \ }; \ 243 | \ } " 244 | :: forall e a. NgModelController a -> NgModelEff e Boolean 245 | 246 | foreign import valid 247 | " function valid($ctrl){ \ 248 | \ return function(){ \ 249 | \ return $ctrl.$valid; \ 250 | \ }; \ 251 | \ } " 252 | :: forall e a. NgModelController a -> NgModelEff e Boolean 253 | 254 | foreign import invalid 255 | " function invalid($ctrl){ \ 256 | \ return function(){ \ 257 | \ return $ctrl.$invalid; \ 258 | \ }; \ 259 | \ } " 260 | :: forall e a. NgModelController a -> NgModelEff e Boolean 261 | -------------------------------------------------------------------------------- /src/Angular/Parse.purs: -------------------------------------------------------------------------------- 1 | module Angular.Parse 2 | ( NgParse() 3 | , Parse() 4 | , ParseEff() 5 | , Expression() 6 | , Getter() 7 | , Setter() 8 | , parse 9 | , get 10 | , assign 11 | , literal 12 | , constant 13 | , set 14 | ) where 15 | 16 | import Control.Monad.Eff 17 | import Data.Function 18 | import Data.Maybe 19 | 20 | foreign import data Parse :: * 21 | 22 | foreign import data NgParse :: ! 23 | 24 | foreign import data Getter :: * -> * 25 | 26 | foreign import data Setter :: * -> * 27 | 28 | type ParseEff e r = Eff (ngparse :: NgParse | e) r 29 | 30 | type Expression = String 31 | 32 | foreign import parseFn 33 | " function parseFn(expression, $parse){ \ 34 | \ return function(){ \ 35 | \ return $parse(expression); \ 36 | \ }; \ 37 | \ } " 38 | :: forall e a. Fn2 Expression Parse (ParseEff e (Getter a)) 39 | 40 | parse :: forall e a. Expression -> Parse -> ParseEff e (Getter a) 41 | parse = runFn2 parseFn 42 | 43 | foreign import getFn 44 | " function getFn(context, locals, getter){ \ 45 | \ return function(){ \ 46 | \ return getter(context, locals); \ 47 | \ }; \ 48 | \ } " 49 | :: forall e a b c. Fn3 { | a } { | b } (Getter c) (ParseEff e c) 50 | 51 | get :: forall e a b c. { | a } -> { | b } -> Getter c -> ParseEff e c 52 | get = runFn3 getFn 53 | 54 | foreign import assignFn 55 | " function assignFn(nothing, just, getter){ \ 56 | \ var fn = getter.assign; \ 57 | \ return angular.isFunction(fn) ? just(fn) : nothing; \ 58 | \ } " 59 | :: forall a. Fn3 (Maybe (Setter a)) 60 | (Setter a -> Maybe (Setter a)) 61 | (Getter a) 62 | (Maybe (Setter a)) 63 | 64 | assign :: forall a. Getter a -> Maybe (Setter a) 65 | assign = runFn3 assignFn Nothing Just 66 | 67 | foreign import literal 68 | " function literal(getter){ \ 69 | \ return getter.literal; \ 70 | \ } " 71 | :: forall a. Getter a -> Boolean 72 | 73 | foreign import constant 74 | " function constant(getter){ \ 75 | \ return getter.constant; \ 76 | \ } " 77 | :: forall a. Getter a -> Boolean 78 | 79 | foreign import setFn 80 | " function setFn(context, value, setter){ \ 81 | \ return function(){ \ 82 | \ return setter(context, value); \ 83 | \ }; \ 84 | \ } " 85 | :: forall e a b. Fn3 { | a } b (Setter b) (ParseEff e b) 86 | 87 | set :: forall e a b. { | a } -> b -> Setter b -> ParseEff e b 88 | set = runFn3 setFn 89 | -------------------------------------------------------------------------------- /src/Angular/Promise.purs: -------------------------------------------------------------------------------- 1 | module Angular.Promise 2 | ( Promise() 3 | , PromiseEC() 4 | , then1 5 | , then1' 6 | , then2 7 | , then2' 8 | , then3 9 | , then3' 10 | , catch 11 | , finally 12 | , liftPromiseEC 13 | , runPromiseEC 14 | ) where 15 | 16 | import Control.Monad.Cont.Trans (ContT(..), runContT) 17 | import Control.Monad.Eff 18 | import Control.Monad.Error (Error) 19 | import Control.Monad.Error.Trans (ErrorT(..), runErrorT) 20 | import Control.Monad.Trans (lift) 21 | 22 | import Data.Either (Either(Right, Left)) 23 | import Data.Function 24 | 25 | foreign import data Promise :: * -> * -> * 26 | 27 | type PromiseEC e a b = ErrorT a (ContT Unit (Eff e)) b 28 | 29 | foreign import then1Fn 30 | """ 31 | function then1Fn(f, fa){ 32 | return fa['then'](f); 33 | } 34 | """ :: forall a b c d. Fn2 (b -> c) (Promise a b) (Promise a d) 35 | 36 | then1 :: forall a b c. (b -> Promise a c) -> Promise a b -> Promise a c 37 | then1 = runFn2 then1Fn 38 | 39 | then1' :: forall a b c. (b -> c) -> Promise a b -> Promise a c 40 | then1' = runFn2 then1Fn 41 | 42 | foreign import then2Fn 43 | """ 44 | function then2Fn(f, g, fa){ 45 | return fa['then'](f, g); 46 | } 47 | """ :: forall s t a b c d. Fn3 (b -> d) (a -> c) (Promise a b) (Promise s t) 48 | 49 | then2 :: forall a b c d. (b -> Promise c d) -> (a -> Promise c d) -> Promise a b -> Promise c d 50 | then2 = runFn3 then2Fn 51 | 52 | then2' :: forall a b c d. (b -> d) -> (a -> c) -> Promise a b -> Promise c d 53 | then2' = runFn3 then2Fn 54 | 55 | foreign import then3Fn 56 | """ 57 | function then3Fn(f, g, h, fa){ 58 | return fa['then'](f, g, function(a){ 59 | return h(a)(); 60 | }); 61 | } 62 | """ :: forall e q r s t a b c d. Fn4 (b -> d) 63 | (a -> c) 64 | (s -> Eff e t) 65 | (Promise a b) 66 | (Promise q r) 67 | 68 | then3 :: forall e s t a b c d. (b -> Promise c d) -> (a -> Promise c d) -> (s -> Eff e t) -> Promise a b -> Promise c d 69 | then3 = runFn4 then3Fn 70 | 71 | then3' :: forall e s t a b c d. (b -> d) -> (a -> c) -> (s -> Eff e t) -> Promise a b -> Promise c d 72 | then3' = runFn4 then3Fn 73 | 74 | foreign import catchFn 75 | """ 76 | function catchFn(f, fa){ 77 | return fa['catch'](f); 78 | } 79 | """ :: forall a b c d. Fn2 (a -> Promise c d) (Promise a b) (Promise c d) 80 | 81 | catch :: forall a b c d. (a -> Promise c d) -> Promise a b -> Promise c d 82 | catch = runFn2 catchFn 83 | 84 | foreign import finallyFn 85 | """ 86 | function finallyFn(f, fa){ 87 | return fa['finally'](f); 88 | } 89 | """ :: forall e r a b. Fn2 (Eff e r) (Promise a b) (Promise a b) 90 | 91 | finally :: forall e r a b. Eff e r -> Promise a b -> Promise a b 92 | finally = runFn2 finallyFn 93 | 94 | foreign import then2ECFn 95 | """ 96 | function then2ECFn(f, g, fa){ 97 | return function(){ 98 | var run = function(k){ 99 | return function(a){ 100 | return k(a)(); 101 | }; 102 | }; 103 | fa['then'](run(f), run(g)); 104 | }; 105 | } 106 | """ :: forall e a b c. Fn3 (b -> c) (a -> c) (Promise a b) (Eff e Unit) 107 | 108 | promiseEC :: forall e a b. Promise a b -> PromiseEC e a b 109 | promiseEC = ErrorT <<< ContT <<< cb 110 | where 111 | cb fa k = runFn3 then2ECFn (k <<< Right) (k <<< Left) fa 112 | 113 | liftPromiseEC :: forall e a b. (Error a) => Eff e (Promise a b) -> PromiseEC e a b 114 | liftPromiseEC fa = (lift $ lift fa) >>= promiseEC 115 | 116 | runPromiseEC :: forall e a b. PromiseEC e a b -> (Either a b -> Eff e Unit) -> Eff e Unit 117 | runPromiseEC = runContT <<< runErrorT 118 | -------------------------------------------------------------------------------- /src/Angular/Q.purs: -------------------------------------------------------------------------------- 1 | module Angular.Q 2 | ( Q() 3 | , QEff() 4 | , NgQ() 5 | , defer 6 | , reject 7 | , when 8 | , all 9 | ) where 10 | 11 | import Control.Monad.Eff 12 | import Data.Function 13 | 14 | import Angular.Deferred (Deferred()) 15 | import Angular.Promise (Promise()) 16 | 17 | foreign import data Q :: * 18 | 19 | foreign import data NgQ :: ! 20 | 21 | type QEff e r = Eff (ngq :: NgQ | e) r 22 | 23 | foreign import defer 24 | " function defer($q){ \ 25 | \ return function(){ \ 26 | \ return $q.defer(); \ 27 | \ }; \ 28 | \ } " 29 | :: forall e a b. Q -> (QEff e (Deferred a b)) 30 | 31 | foreign import rejectFn 32 | " function rejectFn(e, $q){ \ 33 | \ return function(){ \ 34 | \ return $q.reject(e); \ 35 | \ }; \ 36 | \ } " 37 | :: forall e a b. Fn2 a Q (QEff e (Promise a b)) 38 | 39 | reject :: forall e a b. a -> Q -> QEff e (Promise a b) 40 | reject = runFn2 rejectFn 41 | 42 | foreign import whenFn 43 | " function whenFn(a, $q){ \ 44 | \ return function(){ \ 45 | \ return $q.when(a); \ 46 | \ }; \ 47 | \ } " 48 | :: forall e a b. Fn2 b Q (QEff e (Promise a b)) 49 | 50 | when :: forall e a b. b -> Q -> QEff e (Promise a b) 51 | when = runFn2 whenFn 52 | 53 | foreign import allFn 54 | " function allFn(a, $q){ \ 55 | \ return function(){ \ 56 | \ return $q.all(a); \ 57 | \ }; \ 58 | \ } " 59 | :: forall e a b. Fn2 [Promise a b] Q (QEff e (Promise b [a])) 60 | 61 | all :: forall e a b. [Promise a b] -> Q -> QEff e (Promise b [a]) 62 | all = runFn2 allFn 63 | -------------------------------------------------------------------------------- /src/Angular/Scope.purs: -------------------------------------------------------------------------------- 1 | module Angular.Scope 2 | ( Scope() 3 | , ScopeEff() 4 | , NgReadScope() 5 | , NgWriteScope() 6 | , NgScope() 7 | , ReadEff() 8 | , WriteEff() 9 | , ReadWriteEff() 10 | , WatchListener() 11 | , Event() 12 | , ApplyExpr(..) 13 | , WatchDeregistration() 14 | , OnDeregistration() 15 | , readScope 16 | , writeScope 17 | , extendScope 18 | , modifyScope 19 | , newScope 20 | , watch 21 | , watchCollection 22 | , digest 23 | , destroy 24 | , evalSync 25 | , evalAsync 26 | , applyExpr 27 | , stringApplyExpr 28 | , defaultApplyExpr 29 | , apply 30 | , on 31 | , emit 32 | , broadcast 33 | , deregisterWatch 34 | , deregisterOn 35 | , id 36 | , root 37 | , parent 38 | ) where 39 | 40 | import Prelude (Unit(), ($)) 41 | import Control.Monad.Eff 42 | import Control.Monad.Eff.Unsafe 43 | import Data.Maybe 44 | import Data.Function (Fn2(), Fn3(), Fn4(), Fn5(), runFn2, runFn3, runFn4, runFn5) 45 | 46 | type WatchListener e a b = a -> a -> Scope b -> Eff e Unit 47 | 48 | type Event e a b 49 | = { targetScope :: Scope a 50 | , currentScope :: Scope b 51 | , name :: String 52 | , stopPropagation :: Eff e Unit 53 | , preventDefault :: Eff e Unit 54 | , defaultPrevented :: Boolean 55 | } 56 | 57 | data ApplyExpr e r a 58 | = DefaultApplyExpr 59 | | StringApplyExpr String 60 | | FnApplyExpr (Scope a -> Eff e r) 61 | 62 | foreign import data Scope :: # * -> * 63 | 64 | foreign import data WatchDeregistration :: * 65 | 66 | foreign import data OnDeregistration :: * 67 | 68 | foreign import data NgReadScope :: ! 69 | 70 | foreign import data NgWriteScope :: ! 71 | 72 | foreign import data NgScope :: ! 73 | 74 | type ReadEff e a = Eff (ngrscope :: NgReadScope | e) { | a } 75 | 76 | type WriteEff e = Eff (ngwscope :: NgWriteScope | e) Unit 77 | 78 | type ReadWriteEff e r = Eff (ngrscope :: NgReadScope, ngwscope :: NgWriteScope | e) r 79 | 80 | type ScopeEff e r = Eff (ngscope :: NgScope | e) r 81 | 82 | modifyScope :: forall e a b. ({ | a} -> ReadWriteEff e { | b }) -> Scope a -> ReadWriteEff e Unit 83 | modifyScope k s = do 84 | s' <- readScope s 85 | w <- unsafeInterleaveEff $ k s' 86 | extendScope w s 87 | 88 | foreign import readScope 89 | "function readScope($scope){\ 90 | \ return function(){\ 91 | \ return $scope;\ 92 | \ };\ 93 | \}" :: forall e a. Scope a -> ReadEff e a 94 | 95 | foreign import writeScopeFn 96 | "function writeScopeFn(prop, value, $scope){\ 97 | \ return function(){\ 98 | \ $scope[prop] = value;\ 99 | \ };\ 100 | \}" :: forall e a b. Fn3 String b (Scope a) (WriteEff e) 101 | 102 | writeScope :: forall e a b. String -> b -> Scope a -> WriteEff e 103 | writeScope = runFn3 writeScopeFn 104 | 105 | foreign import extendScopeFn 106 | "function extendScopeFn(obj, $scope){\ 107 | \ return function(){\ 108 | \ angular.extend($scope, obj);\ 109 | \ };\ 110 | \}" :: forall e a b. Fn2 { | b } (Scope a) (WriteEff e) 111 | 112 | extendScope :: forall e a b. { | b } -> Scope a -> WriteEff e 113 | extendScope = runFn2 extendScopeFn 114 | 115 | foreign import newScopeFn 116 | " function newScopeFn(isolate, $scope){ \ 117 | \ return $scope.$new(isolate); \ 118 | \ }" 119 | :: forall e a b. Fn2 Boolean (Scope a) (ScopeEff e (Scope b)) 120 | 121 | newScope :: forall e a b. Boolean -> Scope a -> ScopeEff e (Scope b) 122 | newScope = runFn2 newScopeFn 123 | 124 | foreign import watchFn 125 | " function watchFn(maybe, exp, listener, objEq, $scope){ \ 126 | \ return maybe(function(){return $scope.$watch(exp, undefined, objEq);}) \ 127 | \ (function(k){return function(){return $scope.$watch(exp, function(a1,a2,$scope){k(a1)(a2)($scope)()}, objEq);}}) \ 128 | \ (listener); \ 129 | \ }" 130 | :: forall e a b. Fn5 (Eff e WatchDeregistration 131 | -> (WatchListener e a b -> Eff e WatchDeregistration) 132 | -> Maybe (WatchListener e a b) 133 | -> Eff e WatchDeregistration) 134 | String 135 | (Maybe (WatchListener e a b)) 136 | Boolean 137 | (Scope b) 138 | (ScopeEff e WatchDeregistration) 139 | 140 | watch :: forall e a b. String -> Maybe (WatchListener e a b) -> Boolean -> Scope b -> ScopeEff e WatchDeregistration 141 | watch = runFn5 watchFn maybe 142 | 143 | foreign import watchCollectionFn 144 | " function watchCollectionFn(exp, listener, $scope){ \ 145 | \ return function(){ \ 146 | \ return $scope.$watchCollection(exp, function(a1,a2,$scope){ \ 147 | \ return listener(a1)(a2)($scope)(); \ 148 | \ }); \ 149 | \ }; \ 150 | \ }" 151 | :: forall e a b. Fn3 String (WatchListener e a b) (Scope b) (ScopeEff e WatchDeregistration) 152 | 153 | watchCollection :: forall e a b. String -> WatchListener e a b -> Scope b -> ScopeEff e WatchDeregistration 154 | watchCollection = runFn3 watchCollectionFn 155 | 156 | foreign import digest 157 | " function digest($scope){ \ 158 | \ return function(){ \ 159 | \ return $scope.$digest(); \ 160 | \ }; \ 161 | \ }" 162 | :: forall e a. Scope a -> ScopeEff e Unit 163 | 164 | foreign import destroy 165 | " function destroy($scope){ \ 166 | \ return function(){ \ 167 | \ return $scope.$destroy(); \ 168 | \ }; \ 169 | \ }" 170 | :: forall e a. Scope a -> ScopeEff e Unit 171 | 172 | foreign import evalSyncFn 173 | " function evalSyncFn(maybe, expr, locals, $scope){ \ 174 | \ return maybe(function(){return $scope.$eval(undefined, maybe(undefined)(angular.identity)(locals));}) \ 175 | \ (function(k){return function(){return $scope.$eval(function($scope){return k($scope)();}, \ 176 | \ maybe(undefined)(angular.identity)(locals));}}) \ 177 | \ (expr); \ 178 | \ } " 179 | :: forall e r s t a b c. Fn4 (t -> (s -> t) -> Maybe s -> t) 180 | (Maybe (Scope a -> Eff e r)) 181 | (Maybe { | b }) 182 | (Scope a) 183 | (ScopeEff e r) 184 | 185 | evalSync :: forall e r a b. Maybe (Scope a -> Eff e r) -> Maybe { | b } -> Scope a -> ScopeEff e r 186 | evalSync = runFn4 evalSyncFn maybe 187 | 188 | foreign import evalAsyncFn 189 | " function evalAsyncFn(maybe, expr, scope){ \ 190 | \ return maybe(function(){return scope.$evalAsync();}) \ 191 | \ (function(k){return function(){return scope.$evalAsync(function(scope){return k(scope)();});}}) \ 192 | \ (expr); \ 193 | \ } " 194 | :: forall e r s t a b. Fn3 (t -> (s -> t) -> Maybe s -> t) 195 | (Maybe (Scope a -> Eff e r)) 196 | (Scope a) 197 | (ScopeEff e r) 198 | 199 | evalAsync :: forall e r a. Maybe (Scope a -> Eff e r) -> Scope a -> ScopeEff e r 200 | evalAsync = runFn3 evalAsyncFn maybe 201 | 202 | defaultApplyExpr :: forall e r a. ApplyExpr e r a 203 | defaultApplyExpr = DefaultApplyExpr 204 | 205 | stringApplyExpr :: forall e r a. String -> ApplyExpr e r a 206 | stringApplyExpr = StringApplyExpr 207 | 208 | applyExpr :: forall e r a. (Scope a -> Eff e r) -> ApplyExpr e r a 209 | applyExpr = FnApplyExpr 210 | 211 | cataApply :: forall e r a b 212 | . b 213 | -> (String -> b) 214 | -> ((Scope a -> Eff e r) -> b) 215 | -> ApplyExpr e r a 216 | -> b 217 | cataApply f g h a = 218 | case a of 219 | DefaultApplyExpr -> f 220 | StringApplyExpr a -> g a 221 | FnApplyExpr a -> h a 222 | 223 | foreign import applyFn 224 | " function applyFn(expr, $scope){ \ 225 | \ return function(){ \ 226 | \ return $scope.$apply(cataApply(undefined) \ 227 | \ (angular.identity) \ 228 | \ (function(a){return a(scope)();}) \ 229 | \ (expr)); \ 230 | \ }; \ 231 | \ }" 232 | :: forall e r a. Fn2 (ApplyExpr e r a) (Scope a) (ScopeEff e r) 233 | 234 | apply :: forall e r a. ApplyExpr e r a -> Scope a -> ScopeEff e r 235 | apply = runFn2 applyFn 236 | 237 | foreign import onFn 238 | " function onFn(name, listener, $scope){ \ 239 | \ return function(){ \ 240 | \ return $scope.$on(name, function(event, arg){ \ 241 | \ return listener(event)(arg)(); \ 242 | \ }); \ 243 | \ }; \ 244 | \ }" 245 | :: forall e a b c. Fn3 String 246 | (Event e a b -> c -> Eff e Unit) 247 | (Scope b) 248 | (ScopeEff e OnDeregistration) 249 | 250 | on :: forall e a b c. String -> (Event e a b -> c -> Eff e Unit) -> Scope b -> ScopeEff e OnDeregistration 251 | on = runFn3 onFn 252 | 253 | foreign import emitFn 254 | " function emitFn(name, arg, $scope){ \ 255 | \ return function(){ \ 256 | \ return $scope.$emit(name, arg); \ 257 | \ }; \ 258 | \ } " 259 | :: forall e a b c. Fn3 String a (Scope b) (ScopeEff e (Event e b c)) 260 | 261 | emit :: forall e a b c. String -> a -> Scope b -> ScopeEff e (Event e b c) 262 | emit = runFn3 emitFn 263 | 264 | foreign import broadcastFn 265 | " function broadcastFn(name, arg, $scope){ \ 266 | \ return function(){ \ 267 | \ return $scope.$broadcast(name, arg); \ 268 | \ }; \ 269 | \ } " 270 | :: forall e a b c. Fn3 String a (Scope b) (ScopeEff e (Event e b c)) 271 | 272 | broadcast :: forall e a b c. String -> a -> Scope b -> ScopeEff e (Event e b c) 273 | broadcast = runFn3 broadcastFn 274 | 275 | foreign import deregisterWatch "function deregisterWatch(dereg){return dereg();}" :: WatchDeregistration -> Unit 276 | 277 | foreign import deregisterOn "function deregisterOn(dereg){return dereg();}" :: OnDeregistration -> Unit 278 | 279 | foreign import id "function id(scope){return scope.$id;}" :: forall a. Scope a -> String 280 | 281 | foreign import root "function root(scope){return scope.$root;}" :: forall a b. Scope a -> Scope b 282 | 283 | foreign import parentFn 284 | " function parentFn(nothing, just, scope){ \ 285 | \ var a = scope.$parent; \ 286 | \ return a ? just(a) : nothing; \ 287 | \ }" 288 | :: forall a b. Fn3 (Maybe (Scope b)) (Scope b -> Maybe (Scope b)) (Scope a) (Maybe (Scope b)) 289 | 290 | parent :: forall a b. Scope a -> Maybe (Scope b) 291 | parent = runFn3 parentFn Nothing Just 292 | -------------------------------------------------------------------------------- /src/Angular/This.purs: -------------------------------------------------------------------------------- 1 | module Angular.This 2 | ( This() 3 | , ReadEff() 4 | , WriteEff() 5 | , ReadWriteEff() 6 | , NgReadThis() 7 | , NgWriteThis() 8 | , readThis 9 | , writeThis 10 | , extendThis 11 | , modifyThis 12 | ) where 13 | 14 | import Control.Monad.Eff 15 | import Control.Monad.Eff.Unsafe 16 | import Data.Function 17 | 18 | foreign import data This :: # * -> * 19 | 20 | foreign import data NgReadThis :: ! 21 | 22 | foreign import data NgWriteThis :: ! 23 | 24 | type ReadEff e a = Eff (ngrthis :: NgReadThis | e) { | a } 25 | 26 | type WriteEff e = Eff (ngwthis :: NgWriteThis | e) Unit 27 | 28 | type ReadWriteEff e r = Eff (ngrthis :: NgReadThis, ngwthis :: NgWriteThis | e) r 29 | 30 | writeThis :: forall e a b. String -> b -> This a -> WriteEff e 31 | writeThis = runFn3 writeThisFn 32 | 33 | extendThis :: forall e a b. { | b } -> This a -> WriteEff e 34 | extendThis = runFn2 extendThisFn 35 | 36 | modifyThis :: forall e a b. ({ | a } -> ReadWriteEff e { | b }) -> This a -> ReadWriteEff e Unit 37 | modifyThis k t = do 38 | t' <- readThis t 39 | w <- unsafeInterleaveEff $ k t' 40 | extendThis w t 41 | 42 | foreign import readThis 43 | " function readThis($this){ \ 44 | \ return function(){ \ 45 | \ return $this; \ 46 | \ } \ 47 | \ } " :: forall e a. This a -> ReadEff e a 48 | 49 | foreign import extendThisFn 50 | "function extendThisFn(obj, $this){\ 51 | \ return function(){\ 52 | \ angular.extend($this, obj);\ 53 | \ };\ 54 | \}" :: forall e a b. Fn2 { | b } (This a) (WriteEff e) 55 | 56 | foreign import writeThisFn 57 | " function writeThisFn(prop, value, $this){ \ 58 | \ return function(){ \ 59 | \ $this[prop] = value; \ 60 | \ }; \ 61 | \ } " :: forall e a b. Fn3 String b (This a) (WriteEff e) 62 | -------------------------------------------------------------------------------- /src/Angular/Timeout.purs: -------------------------------------------------------------------------------- 1 | module Angular.Timeout 2 | ( Timeout() 3 | , NgTimeout() 4 | , TimeoutEff() 5 | , TimeoutPromise() 6 | , timeout 7 | , timeout' 8 | , timeout'' 9 | , timeoutk 10 | , cancel 11 | ) where 12 | 13 | import Control.Monad.Eff 14 | import Control.Monad.Eff.Exception (Error()) 15 | import Data.Function 16 | import Data.Maybe 17 | 18 | import Angular.Promise (Promise()) 19 | 20 | foreign import data Timeout :: * 21 | 22 | foreign import data NgTimeout :: ! 23 | 24 | type TimeoutEff e r = Eff (ngtimeout :: NgTimeout | e) r 25 | 26 | type TimeoutPromise a = Promise Error a 27 | 28 | foreign import timeoutFn 29 | " function timeoutFn(fromMaybe, fn, delay, invokeApply, $timeout){ \ 30 | \ return function(){ \ 31 | \ return $timeout(fn, fromMaybe(undefined)(delay), fromMaybe(undefined)(invokeApply)); \ 32 | \ }; \ 33 | \ } " 34 | :: forall e f r. Fn5 (forall a. a -> Maybe a -> a) 35 | (Eff f r) 36 | (Maybe Number) 37 | (Maybe Boolean) 38 | Timeout 39 | (TimeoutEff e (TimeoutPromise r)) 40 | 41 | timeout :: forall e f r. Eff f r -> Number -> Boolean -> Timeout -> TimeoutEff e (TimeoutPromise r) 42 | timeout fn delay invoke = runFn5 timeoutFn fromMaybe fn (Just delay) (Just invoke) 43 | 44 | timeout' :: forall e f r. Eff f r -> Number -> Timeout -> TimeoutEff e (TimeoutPromise r) 45 | timeout' fn delay = runFn5 timeoutFn fromMaybe fn (Just delay) Nothing 46 | 47 | timeout'' :: forall e f r. Eff f r -> Timeout -> TimeoutEff e (TimeoutPromise r) 48 | timeout'' fn = runFn5 timeoutFn fromMaybe fn Nothing Nothing 49 | 50 | timeoutk :: forall e f r. Number -> Boolean -> Timeout -> Eff f r -> TimeoutEff e (TimeoutPromise r) 51 | timeoutk delay invoke timeout fn = runFn5 timeoutFn fromMaybe fn (Just delay) (Just invoke) timeout 52 | 53 | foreign import cancelFn 54 | " function cancelFn(fromMaybe, promise, $timeout){ \ 55 | \ return function(){ \ 56 | \ return $timeout.cancel(fromMaybe(undefined)(promise)); \ 57 | \ }; \ 58 | \ } " 59 | :: forall e r. Fn3 ((TimeoutPromise r) -> Maybe (TimeoutPromise r) -> (TimeoutPromise r)) 60 | (Maybe (TimeoutPromise r)) 61 | Timeout 62 | (TimeoutEff e Boolean) 63 | 64 | cancel :: forall e r. TimeoutPromise r -> Timeout -> TimeoutEff e Boolean 65 | cancel promise = runFn3 cancelFn fromMaybe (Just promise) 66 | --------------------------------------------------------------------------------