summaryrefslogtreecommitdiff
path: root/book
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2015-02-04 05:31:48 -0800
committerLi Haoyi <haoyi@dropbox.com>2015-02-04 05:31:48 -0800
commitb094df4a6a6cf1bf7eeb36d842970aa8b3d94d5f (patch)
tree68db445a53fe7f2343a44773cb46d7e882dad7d1 /book
parent49cf861b0a4e351e56ba797541d43cb1da345741 (diff)
downloadhands-on-scala-js-b094df4a6a6cf1bf7eeb36d842970aa8b3d94d5f.tar.gz
hands-on-scala-js-b094df4a6a6cf1bf7eeb36d842970aa8b3d94d5f.tar.bz2
hands-on-scala-js-b094df4a6a6cf1bf7eeb36d842970aa8b3d94d5f.zip
first attempt at updating things for 0.6.0
Diffstat (limited to 'book')
-rw-r--r--book/src/main/scala/book/Utils.scala15
-rw-r--r--book/src/main/scalatex/book/handson/CanvasApp.scalatex2
-rw-r--r--book/src/main/scalatex/book/handson/ClientServer.scalatex2
-rw-r--r--book/src/main/scalatex/book/handson/GettingStarted.scalatex10
-rw-r--r--book/src/main/scalatex/book/handson/WebPage.scalatex4
-rw-r--r--book/src/main/scalatex/book/indepth/CompilationPipeline.scalatex2
6 files changed, 23 insertions, 12 deletions
diff --git a/book/src/main/scala/book/Utils.scala b/book/src/main/scala/book/Utils.scala
index c14a6ba..c62f71f 100644
--- a/book/src/main/scala/book/Utils.scala
+++ b/book/src/main/scala/book/Utils.scala
@@ -35,14 +35,19 @@ object lnk{
a(name, href:=url)
}
object dom{
- def mdnThing(name: String) = lnk(name, "https://developer.mozilla.org/en-US/docs/Web/API/" + name)
+ def mdnThing(name: String, scalaJsName: String = null) = lnk(
+ Option(scalaJsName).getOrElse(name),
+ "https://developer.mozilla.org/en-US/docs/Web/API/" + name
+ )
def mdnEvent(name: String) = lnk(name, "https://developer.mozilla.org/en-US/docs/Web/Events/" + name)
val CanvasRenderingContext2D = mdnThing("CanvasRenderingContext2D")
- val HTMLCanvasElement = mdnThing("HTMLCanvasElement")
val Element = mdnThing("Element")
- val HTMLElement = mdnThing("HTMLElement")
- val HTMLInputElement = mdnThing("HTMLInputElement")
- val HTMLSpanElement = mdnThing("HTMLSpanElement")
+ object html{
+ val Canvas = mdnThing("HTMLCanvasElement", "html.Canvas")
+ val Element = mdnThing("HTMLElement", "html.Element")
+ val Input = mdnThing("HTMLInputElement", "html.Input")
+ val Span = mdnThing("HTMLSpanElement", "html.Span")
+ }
val XMLHttpRequest = mdnThing("XMLHttpRequest")
val getElementById = mdnThing("document.getElementById")
val setInterval = mdnThing("WindowTimers.setInterval")
diff --git a/book/src/main/scalatex/book/handson/CanvasApp.scalatex b/book/src/main/scalatex/book/handson/CanvasApp.scalatex
index ae97dee..e40b211 100644
--- a/book/src/main/scalatex/book/handson/CanvasApp.scalatex
+++ b/book/src/main/scalatex/book/handson/CanvasApp.scalatex
@@ -41,7 +41,7 @@
This code sets up the @lnk.dom.mousedown and @lnk.dom.mouseup events to keep track of whether or not the mouse has currently been clicked. It then draws black squares any time you move the mouse while the button is down. This lets you basically click-and-drag to draw pictures on the canvas. Try it out!
@p
- In general, you have access to all the DOM APIs through the @hl.scala{dom} package as well as through Javascript objects such as the @lnk.dom.HTMLCanvasElement. Setting the @code{onmouseXXX} callbacks is just one way of interacting with the DOM. With Scala.js, you also get a very handy autocomplete in the editor, which you can use to browse the various other APIs that are available for use:
+ In general, you have access to all the DOM APIs through the @hl.scala{dom} package as well as through Javascript objects such as the @lnk.dom.html.Canvas. Setting the @code{onmouseXXX} callbacks is just one way of interacting with the DOM. With Scala.js, you also get a very handy autocomplete in the editor, which you can use to browse the various other APIs that are available for use:
@img(src:="images/Dropdown.png", maxWidth:="100%")
diff --git a/book/src/main/scalatex/book/handson/ClientServer.scalatex b/book/src/main/scalatex/book/handson/ClientServer.scalatex
index 0d60192..5ee3dfe 100644
--- a/book/src/main/scalatex/book/handson/ClientServer.scalatex
+++ b/book/src/main/scalatex/book/handson/ClientServer.scalatex
@@ -103,7 +103,7 @@
@p
In both the client code and the server code, we made use of the same Scalatags HTML generation library. This is pretty neat: transferring rendering logic between client and server no longer means an annoying/messy rewrite! You can simply C&P the Scalatags snippet over. That means it's easy if you want to e.g. shift the logic from one side to the other in order to optimize for performance or time-to-load or other things.
@p
- One thing to take note of is that we're actually using subtly @i{different} implementations of Scalatags on both sides: on the server, we're importing from @hl.scala{scalatags.Text}, while on the client we're using @hl.scala{scalatags.JsDom}. The @hl.scala{Text} backend renders directly to Strings, and is available on both Scala-JVM and Scala.js. The @hl.scala{JsDom} backend, on the other hand, renders to @lnk.dom.HTMLElement-s which only exist on Scala.js. Thus while on the client you can do things like attach event listeners to the rendered @lnk.dom.HTMLElement objects, or checking their runtime @code{.value}, on the server you can't. And that's exactly what you want!
+ One thing to take note of is that we're actually using subtly @i{different} implementations of Scalatags on both sides: on the server, we're importing from @hl.scala{scalatags.Text}, while on the client we're using @hl.scala{scalatags.JsDom}. The @hl.scala{Text} backend renders directly to Strings, and is available on both Scala-JVM and Scala.js. The @hl.scala{JsDom} backend, on the other hand, renders to @lnk.dom.html.Element-s which only exist on Scala.js. Thus while on the client you can do things like attach event listeners to the rendered @lnk.dom.html.Element objects, or checking their runtime @code{.value}, on the server you can't. And that's exactly what you want!
@sect{Shared Code}
@p
diff --git a/book/src/main/scalatex/book/handson/GettingStarted.scalatex b/book/src/main/scalatex/book/handson/GettingStarted.scalatex
index c200f1e..5d4d299 100644
--- a/book/src/main/scalatex/book/handson/GettingStarted.scalatex
+++ b/book/src/main/scalatex/book/handson/GettingStarted.scalatex
@@ -115,7 +115,7 @@
This @hl.scala("@JSExport") annotation is used to tell Scala.js that you want this method to be visible and callable from Javascript. By default, Scala.js does @sect.ref("Fast Optimization", "dead code elimination") and removes any methods or classes which are not used. This is done to keep the compiled executables a reasonable size, since most projects use only a small fraction of e.g. the standard library. @hl.scala("@JSExport") is used to tell Scala.js that the @hl.scala{ScalaJSExample} object and its @hl.scala{def main} method are entry points to the program. Even if they aren't called anywhere internally, they are called externally by Javascript that the Scala.js compiler is not aware of, and should not be removed. In this case, we are going to call this method from Javascript to start the Scala.js program.
@p
- Apart from this annotation, @hl.scala{ScalaJSExample} is just a normal Scala @hl.scala{object}, and behaves like one in every way. Note that the main-method in this case takes a @lnk.dom.HTMLCanvasElement: your exported methods can have any signature, with arbitrary arity or types for parameters or the return value. This is in contrast to the main method on the JVM which always takes an @hl.scala{Array[String]} and returns @hl.scala{Unit}. In fact, there's nothing special about this method at all! It's like any other exported method, we just happen to attribute it the "main" entry point. It is entirely possible to define multiple exported classes and methods, and build a "library" using Scala.js of methods that are intended for external Javascript to use.
+ Apart from this annotation, @hl.scala{ScalaJSExample} is just a normal Scala @hl.scala{object}, and behaves like one in every way. Note that the main-method in this case takes a @lnk.dom.html.Canvas: your exported methods can have any signature, with arbitrary arity or types for parameters or the return value. This is in contrast to the main method on the JVM which always takes an @hl.scala{Array[String]} and returns @hl.scala{Unit}. In fact, there's nothing special about this method at all! It's like any other exported method, we just happen to attribute it the "main" entry point. It is entirely possible to define multiple exported classes and methods, and build a "library" using Scala.js of methods that are intended for external Javascript to use.
@hl.ref(example/"ScalaJSExample.scala", "val ctx", "var count")
@@ -123,7 +123,13 @@
Here we are retrieving a handle to the canvas we will draw on using @hl.scala{document.getElementById}, and from it we can get a @lnk.dom.CanvasRenderingContext2D which we actually use to draw on it.
@p
- We need to perform the @hl.scala{asInstanceOf} call because depending on what you pass to @hl.scala{getElementById} and @hl.scala{getContext}, you could be returned elements and contexts of different types. Hence we need to tell the compiler explicitly that we're expecting a @lnk.dom.HTMLCanvasElement and @lnk.dom.CanvasRenderingContext2D back from these methods for the strings we passed in.
+ We need to perform the @hl.scala{asInstanceOf} call because depending on what you pass to @hl.scala{getElementById} and @hl.scala{getContext}, you could be returned elements and contexts of different types. Hence we need to tell the compiler explicitly that we're expecting a @lnk.dom.html.Canvas and @lnk.dom.CanvasRenderingContext2D back from these methods for the strings we passed in.
+
+ @p
+ Note how the @lnk.dom.html.Canvas comes from the @hl.scala{html} namespace, while the @lnk.dom.CanvasRenderingContext2D comes from the @hl.scala{dom} namespace. Traditionally, these types are imported via their qualified names: e.g. @hl.scala{html.Canvas} rather than just @hl.scala{Canvas}.
+
+ @p
+ In general, @lnk("scala-js-dom", "http://scala-js.github.io/scala-js-dom/") provides @hl.scala{org.scalajs.dom.html} to access the HTML element types of the browser, an @hl.scala{org.scalajs.dom} to access other things. There are a number of other namespaces (@hl.scala{dom.svg}, @hl.scala{dom.idb}, etc.) accessible inside @hl.scala{org.scalajs.dom}: read the @lnk("scala-js-dom docs", "http://scala-js.github.io/scala-js-dom/") to learn more.
@hl.ref(example/"ScalaJSExample.scala", "def run", "dom.setInterval")
diff --git a/book/src/main/scalatex/book/handson/WebPage.scalatex b/book/src/main/scalatex/book/handson/WebPage.scalatex
index 03ed452..a7f754d 100644
--- a/book/src/main/scalatex/book/handson/WebPage.scalatex
+++ b/book/src/main/scalatex/book/handson/WebPage.scalatex
@@ -21,7 +21,7 @@
@BookData.example(div, "webpage.HelloWorld0().main")
@p
- Remember that we're now requiring a @hl.scala{dom.HTMLDivElement} instead of a @hl.scala{dom.HTMLCanvasElement} to be passed in when the Javascript calls @hl.javascript{webpage.HelloWorld0().main(...)}. If you're coming to this point from the previous chapter, you'll need to update the on-page Javascript's @hl.javascript{document.getElementById} to pick a @hl.html{<div>} rather than the @hl.html{<canvas>} we were using in the previous chapter.
+ Remember that we're now requiring a @hl.scala{html.Div} instead of a @hl.scala{html.Canvas} to be passed in when the Javascript calls @hl.javascript{webpage.HelloWorld0().main(...)}. If you're coming to this point from the previous chapter, you'll need to update the on-page Javascript's @hl.javascript{document.getElementById} to pick a @hl.html{<div>} rather than the @hl.html{<canvas>} we were using in the previous chapter.
@p
This approach works, as the above example shows, but has a couple of disadvantages:
@@ -66,7 +66,7 @@
@BookData.example(div(height:="150px"), "webpage.Inputs().main")
@p
- In Scalatags, you build up fragments of type @hl.scala{Frag} using functions like @hl.scala{div}, @hl.scala{h1}, etc., and call @hl.scala{.render} on it to turn it into a real @lnk.dom.Element. Different fragments render to different things: e.g. @hl.scala{input.render} gives you a @lnk.dom.HTMLInputElement, @hl.scala{span.render} gives you a @lnk.dom.HTMLSpanElement. You can then access the properties of these elements: adding callbacks, checking their value, anything you want.
+ In Scalatags, you build up fragments of type @hl.scala{Frag} using functions like @hl.scala{div}, @hl.scala{h1}, etc., and call @hl.scala{.render} on it to turn it into a real @lnk.dom.Element. Different fragments render to different things: e.g. @hl.scala{input.render} gives you a @lnk.dom.html.Input, @hl.scala{span.render} gives you a @lnk.dom.html.Span. You can then access the properties of these elements: adding callbacks, checking their value, anything you want.
@p
In this example, we render and @hl.scala{input} element and a @hl.scala{span}, wire up the input to set the value of the span whenever you press a key in the input, and then stuff both of them into a larger HTML fragment that forms the contents of our @hl.scala{target} element.
diff --git a/book/src/main/scalatex/book/indepth/CompilationPipeline.scalatex b/book/src/main/scalatex/book/indepth/CompilationPipeline.scalatex
index 5d91b62..ece6215 100644
--- a/book/src/main/scalatex/book/indepth/CompilationPipeline.scalatex
+++ b/book/src/main/scalatex/book/indepth/CompilationPipeline.scalatex
@@ -134,7 +134,7 @@
@li
@b{Inlining}: under some circumstances, the optimizer inlines the implementation of methods at call sites. For example, it does so for all "small enough" methods. This typically reduces the code size by a small amount, but offers a several-times speedup of the generated code by inlining away much of the overhead from the abstractions (implicit-conversions, higher-order-functions, etc.) in Scala's standard library.
@li
- @b{Constant-folding}: due to inlining and other optimizations, some variables that could have arbitrary are known to contain a constant. These variables are replaced by their respective constants, which, in turn, can trigger more optimizations.
+ @b{Constant-folding}: due to inlining and other optimizations, some variables that could have arbitrary values are known to contain a constant. These variables are replaced by their respective constants, which, in turn, can trigger more optimizations.
@li
@b{Closure elimination}: probably one of the most important optimizations. When inlining a higher-order method such as @code{map}, the optimizer can in turn inline the anonymous function inside the body of the loop, effectively turning polymorphic dispatch with closures into bare-metal loops.
@p