summaryrefslogtreecommitdiff
path: root/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
diff options
context:
space:
mode:
Diffstat (limited to 'book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex')
-rw-r--r--book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex17
1 files changed, 7 insertions, 10 deletions
diff --git a/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex b/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
index 171b2d3..98dccc2 100644
--- a/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
+++ b/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
@@ -76,7 +76,7 @@
Scalatags requires that anything you want to embed in a Scalatags fragment be implicitly convertible to @hl.scala{Frag}; here we are providing one for any Scala.Rx @hl.scala{Rx[T]}s, as long as the @hl.scala{T} provided is itself convertible to a @hl.scala{Frag}. We call @hl.scala{r().render} to extract the "current" value of the @hl.scala{Rx}, and then set up an @hl.scala{Obs} that watches the @hl.scala{Rx}, replacing the previous value with the current one every time its value changes.
@p
- Now that the set-up is out of the way, let's consider a simple HTML widhet that lets you enter text in a @hl.html{<textarea>}, and keeps track of the number of words, characters, and counts how long each word is.
+ Now that the set-up is out of the way, let's consider a simple HTML widget that lets you enter text in a @hl.html{<textarea>}, and keeps track of the number of words, characters, and counts how long each word is.
@split
@more
@@ -177,13 +177,10 @@
@p
Overall, these helper functions do nothing special, btu we're defining them first to avoid having to copy-&-paste code throughout the subsequent examples. Now that we've defined all the relevant scaffolding, let's walk through a few ways that we can implement the all-important @hl.scala{handle} method.
- @def scrollDiv = div(
- height:="200px",
- overflow:="scroll"
- )
+ @def exampleDiv = div(height:="200px")
@sect{Direct Use of XMLHttpRequest}
- @example(scrollDiv, "Futures().main0")
+ @example(exampleDiv, "Futures().main0")
@hl.ref("examples/demos/src/main/scala/advanced/Futures.scala", "def handle0", "main")
@p
@@ -195,7 +192,7 @@
This solution is basically equivalent to the initial code given in the @sect.ref{Raw Javascript} section of @sect.ref{Interactive Web Pages}, with the additional code necessary for aggregation. As described in @sect.ref{dom.extensions}, we can make use of the @hl.scala{Ajax} object to make it slightly tidier.
@sect{Using dom.extensions.Ajax}
- @example(scrollDiv, "Futures().main1")
+ @example(exampleDiv, "Futures().main1")
@hl.ref("examples/demos/src/main/scala/advanced/Futures.scala", "def handle1", "main")
@p
@@ -204,7 +201,7 @@
However, we still have the messiness inherent in the result aggregation: we don't actually want to perform our action (writing to the @hl.scala{output} div) when one @hl.scala{Future} is complete, but only when @i{all} the @hl.scala{Future}s are complete. Thus we still need to do some amount of manual book-keeping in the @hl.scala{results} buffer.
@sect{Future Combinators}
- @example(scrollDiv, "Futures().main2")
+ @example(exampleDiv, "Futures().main2")
@hl.ref("examples/demos/src/main/scala/advanced/Futures.scala", "def handle2", "main")
@p
@@ -287,14 +284,14 @@
@example(canvas, "Async().main")
@p
- We have an @hl.scala{async} block, which contains a while loop. Each round around the loop, we wait for the @hl.scala{mousedown} channel to start the path, waiting for either @hl.scala{mousedown} or @hl.scala{mousedown} (which continues the path or ends it respectively), fill the shape, and then wait for another @hl.scala{mousedown} before clearing the canvas and going again.
+ We have an @hl.scala{async} block, which contains a while loop. Each round around the loop, we wait for the @hl.scala{mousedown} channel to start the path, waiting for either @hl.scala{mousemove} or @hl.scala{mouseup} (which continues the path or ends it respectively), fill the shape, and then wait for another @hl.scala{mousedown} before clearing the canvas and going again.
@p
Hopefully you'd agree that this code is much simpler to read and understand than the previous version. In particular, the control-flow of the code goes from top to bottom in a "natural" fashion, rather than jumping around ad-hoc like in the previous callback-based design.
@p
You may be wondering what these @hl.scala{Channel} things are, and where they are coming from. Although these are not provided by Scala, they are pretty straightforward to define ourselves:
- @hl.ref("examples/demos/src/main/scala/advanced/Async.scala", "case class Channel")
+ @hl.ref("examples/demos/src/main/scala/advanced/Async.scala", "class Channel")
@p
The point of @hl.scala{Channel} is to allow us to turn event-callbacks (like those provided by the DOM's @hl.scala{onmouseXXX} properties) into some kind of event-stream, that we can listen to asynchronously (via @hl.scala{apply} that returns a @hl.scala{Future}) or merge via @hl.scala{|}. This is a minimal implementation for what we need now, but it would be easy to provide more functionality (filter, map, etc.) as necessary.