summaryrefslogtreecommitdiff
path: root/book/src/main/scalatex/handson
diff options
context:
space:
mode:
Diffstat (limited to 'book/src/main/scalatex/handson')
-rw-r--r--book/src/main/scalatex/handson/CanvasApp.scalatex211
-rw-r--r--book/src/main/scalatex/handson/ClientServer.scalatex271
-rw-r--r--book/src/main/scalatex/handson/CommandLine.scalatex184
-rw-r--r--book/src/main/scalatex/handson/GettingStarted.scalatex332
-rw-r--r--book/src/main/scalatex/handson/PublishingModules.scalatex150
-rw-r--r--book/src/main/scalatex/handson/WebPage.scalatex269
6 files changed, 1417 insertions, 0 deletions
diff --git a/book/src/main/scalatex/handson/CanvasApp.scalatex b/book/src/main/scalatex/handson/CanvasApp.scalatex
new file mode 100644
index 0000000..c485610
--- /dev/null
+++ b/book/src/main/scalatex/handson/CanvasApp.scalatex
@@ -0,0 +1,211 @@
+@import book.BookData._
+@val canvasapp = wd/'examples/'demos/'src/'main/'scala/'canvasapp
+@p
+ By this point, you've already cloned and got your hands dirty fiddling around with the toy @lnk("workbench-example-app", "https://github.com/lihaoyi/workbench-example-app"). You have your editor set up, SBT installed, and have published the example application in a way you can host online for other people to see. Maybe you've even made some changes to the application to see what happens. Hopefully you're curious, and want to learn more.
+
+@p
+ In this section of the book, we will walk through making a small canvas application. This will expose you to important concepts like:
+
+@ul
+ @li
+ Taking input with Javascript event handlers
+ @li
+ Writing your application logic in Scala
+ @li
+ Using a timer to drive periodic actions
+
+@p
+ In general, while the previous chapter was mostly set-up and exploring the Scala.js project, this chapter will walk you through actually writing a non-trivial, self-contained Scala.js application. Throughout this chapter, we will only be making modifications to @code{ScalaJSExample.scala}; the rest of the project will remain unchanged.
+
+@sect{Making a Sketchpad using Mouse Input}
+
+ @p
+ To begin with, lets remove all the existing stuff in our @code{.scala} file and leave only the @hl.scala{object} and the @hl.scala{main} method. Let's start off with some necessary boilerplate:
+
+ @hl.ref(canvasapp/"ScratchPad.scala", "/*setup*/", end = "/*code*/")
+
+ @p
+ As described earlier, this code uses the @lnk.dom.getElementById function to fish out the @code{canvas} element that we interested in from the DOM. It then gets a rendering context from that @code{canvas}, and sets the height and width of the canvas to completely fill its containing element. Lastly, it fills out the canvas light-gray, so that we can see it on the page.
+
+ @p
+ Next, let's set some event handlers on the canvas:
+
+ @split
+ @more
+ @hl.ref(canvasapp/"ScratchPad.scala", "/*code*/")
+
+ @less
+ @book.BookData.example(canvas, "canvasapp.ScratchPad().main")
+
+ @p
+ 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.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%")
+
+ @p
+ Apart from mouse events, keyboard events, scroll events, input events, etc. are all usable from Scala.js as you'd expect. If you have problems getting this to work, feel free to click on the link @i(cls:="fa fa-link ") icon below the code snippet to see what the full code for the example looks like
+
+@sect{Making a Clock using setInterval}
+
+ @p
+ You've already seen this in the previous example, but @lnk.dom.setInterval can be used to schedule recurring, periodic events in your program. Common use cases include running the @lnk("event loop for a game", "http://gameprogrammingpatterns.com/game-loop.html"), making smooth animations, and other tasks of that sort which require some work to happen over a period of time.
+
+ @p
+ Again, we need roughly the same boilerplate as just now to set up the canvas:
+
+ @hl.ref(canvasapp/"Clock.scala", "/*setup*/", "/*code*/")
+
+ @p
+ The only thing unusual here is that I'm going to create a @hl.scala{linearGradient} in order to make the stopwatch look pretty. This is by no means necessary, and you could simply make the @hl.scala{fillStyle} @hl.scala{"black"} if you want to keep things simple.
+
+ @p
+ Once that's done, it's only a few lines of code to set up a nice, live clock:
+
+ @split
+ @more
+ @hl.ref(canvasapp/"Clock.scala", "/*code*/")
+
+ @less
+ @book.BookData.example(canvas, "canvasapp.Clock().main")
+
+ @p
+ As you can see, we're using more @lnk("Canvas APIs", "https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D"), in this case dealing with rendering text on the canvas. Another thing we're using is the Javascript @lnk("Date", "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date") class, in Scala.js under the full name @hl.scala{scala.scalajs.js.Date}, here imported as @hl.scala{js.Date}. Again, click on the link @i(cls:="fa fa-link ") icon to view the full-code if you're having trouble here.
+
+@sect{Tying it together: Flappy Box}
+
+ @p
+ You've just seen two examples of how to use Scala.js, together with the Javascript DOM APIs, to make simple applications. However, we've only used the "Scala" in Scala.js in the most rudimentary fashion: setting a few primitives here and there, defining some methods, mainly just gluing together a few Javascript APIs
+
+ @p
+ In this example we will make a spiritual clone of the popular @lnk("Flappy Bird", "http://en.wikipedia.org/wiki/Flappy_Bird") video game. This game involves a few simple rules
+
+ @ul
+ @li
+ Your character starts in the middle of the screen
+ @li
+ Gravity pulls your character down
+ @li
+ Clicking/tapping the screen makes your character jump up
+ @li
+ There are obstacles that approach your character from the right side of the screen, and you have to make sure you go through the hole in each obstacle to avoid hitting it
+ @li
+ Don't go out of bounds!
+
+ @p
+ It's a relatively simple game, but there should be enough "business logic" in here that we won't be simply gluing together APIs. Let's start!
+
+ @sect{Setting Up the Canvas}
+ @hl.ref(canvasapp/"FlappyLine.scala", "/*setup*/", end="/*variables*/")
+
+ @p
+ This section of the code is peripherally necessary, but not core to the implementation or logic of Flappy Box. We see the same @hl.scala{canvas}/@hl.scala{renderer} logic we've seen in all our examples, along with some logic to make the canvas a reasonable size, and some configuration of how we will render text to the canvas.
+
+ @p
+ In general, code like this will usually end up being necessary in a Scala.js program: the Javascript APIs that the browser provides to do things often ends up being somewhat roundabout and verbose. It's somewhat annoying to have to do for a small program such as this one, but in a larger application, the cost is both spread out over thousands of lines of code and also typically hidden away in helper functions, so the verbosity and non-idiomatic-scala-ness doesn't bother you much.
+
+ @sect{Defining our State}
+ @hl.ref(canvasapp/"FlappyLine.scala", "/*variables*/", end="def runLive")
+
+ @p
+ This is where we start defining things that are relevant to Flappy Box. There are roughly two groups of values here: immutable constants in the top group, and mutable variables in the bottom. The rough meaning of each variable is documented in the comments, and we'll see exactly how we use them later.
+
+ @p
+ One notable thing is that we're using a @lnk("collection.mutable.Queue", "http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html") to store the list of obstacles. This is defined in the Scala standard library; in general, all the collections in the Scala standard library can be used without issue in Scala.js.
+
+ @sect{Game Logic}
+ @hl.ref(canvasapp/"FlappyLine.scala", "def runLive", "def runDead")
+
+ @p
+ The @hl.scala{runLive} function is the meat of Flappy Box. In it, we
+
+ @ul
+ @li
+ Clear the canvas
+ @li
+ Generate new obstacles
+ @li
+ Apply velocity and acceleration to the player
+ @li
+ Check for collisions or out-of-bounds, killing the player if it happens
+ @li
+ Rendering everything, including the player as the namesake box
+
+ @p
+ This function basically contains all the game logic, from motion, to collision-detection, to rendering, so it's pretty large. Not that large though! And entirely understandable, even if it takes a few moments to read through.
+
+ @hl.ref(canvasapp/"FlappyLine.scala", "def runDead", "def run()")
+
+ @p
+ This is the function that handles what happens when you're dead. Essentially, we reset all the mutable variables to their initial state, and just count down the @hl.scala{dead} counter until it reaches zero and we're considered alive again.
+
+ @sect{A Working Product}
+ @hl.ref(canvasapp/"FlappyLine.scala", "def run()")
+
+ @p
+ And finally, this is the code that kicks everything off: we define the @hl.scala{run} function to swap between @hl.scala{runLive} and @hl.scala{runDead}, register an @lnk.dom.onclick handler to make the player jump by tweaking his velocity, and we call @lnk.dom.setInterval to run the @hl.scala{run} function every 20 milliseconds.
+
+ @p
+ At almost 100 lines of code, this is quite a meaty example! Nonetheless, when all is said and done, you will find that the example actually works! Try it out!
+
+ @div
+ @book.BookData.example(canvas, "canvasapp.FlappyLine().main")
+
+@sect{Canvas Recap}
+ @p
+ We've now gone through the workings of building a handful of toy applications using Scala.js. What have we learnt in the process?
+
+ @sect{Development Speed}
+ @p
+ We've by now written a good chunk of Scala.js code, and perhaps debugged some mysterious errors, and tried some new things. One thing you've probably noticed is the efficiency of the process: you make a change in your editor, the browser reloads itself, and life goes on. There is a compile cycle, but after a few runs the compiler warms up and the compilation cycle drops to less than a second.
+ @p
+ Apart from the compilation/reload speed, you've probably noticed the benefit of tooling around Scala.js. Unlike Javascript editors, your existing Scala IDEs like @lnk.misc.IntelliJ or @lnk.misc.Eclipse can give very useful help when you're working with Scala.js. Autocomplete, error-highlighting, jump-to-definition, and a myriad other modern conveniences that are missing when working in dynamically-typed languages are present when working in Scala.js. This makes the code much less mysterious: you're no longer trying to guess what methods a value has, or what a method returns: it's all laid out in front of you in plain sight.
+
+ @sect{Full Scala}
+ @p
+ All of the examples so far have been very self-contained: they do not touch the HTML DOM, they do not make Ajax calls, or try to access web services. They don't push the limits of the browser's API.
+
+ @p
+ Nevertheless, these examples have exercised a good amount of the Scala language. List comprehensions, collections, the math library, and more. In general, most of the Scala standard library works under Scala.js, as well as a large number of third-party libraries. Unlike many other compile-to-Javascript languages out there, this isn't a language-that-looks-like-Scala: it is Scala through and through, with a tiny number of semantic differences.
+
+ @sect{Seamless Javascript Interop}
+ @p
+ Even if we take some time to read through the code we've written, it is not immediately obvious which bits of code are Scala and which bits are Javascript! It all kind of meshes together, for example if we take the Flappy Box source code:
+
+ @ul
+ @li
+ @hl.scala{obstacles} is a Scala @lnk("mutable.Queue", "http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html"), as we defined it earlier, and all the methods on it are Scala method calls
+ @li
+ @hl.scala{renderer} is a Javascript @lnk.dom.CanvasRenderingContext2D, and all the methods on it are Javascript method calls directly on the Javascript object
+ @li
+ @hl.scala{frame} is a Scala @hl.scala{Int}, and obeys Scala semantics, though it is implemented as a Javascript @hl.js{Number} under the hood.
+ @li
+ @hl.scala{playerY} and @hl.scala{playerV} are Scala @hl.scala{Double}s, implemented directly as Javascript @hl.js{Number}s
+
+ @p
+ This reveals something pretty interesting about Scala.js: even though Scala at-first-glance is a very different language from Javascript, the interoperation with Javascript is so seamless that you can't even tell from the code which values/methods are defined in Scala and which values/methods come from Javascript!
+ @p
+ These two classes of values/methods are treated very differently by the compiler when it comes to emitting the executable Javascript blob, but the compiler does not need extra syntax telling it which things belong to Scala and which to Javascript: the types are sufficient. @hl.scala{renderer}, for example is of type @lnk.dom.CanvasRenderingContext2D which is a subtype of @hl.scala{scalajs.js.Object}, indicating to the compiler that it needs special treatment. Primitives like @hl.scala{Double}s and @hl.scala{Int}s have similar treatment
+
+ @p
+ Overall, this seamless mix of Scala and Javascript values/methods/functions is a common theme in Scala.js applications, so you should expect to see more of it in later chapters of the book.
+
+ @hr
+
+ @p
+ You've now had some experience building small canvas applications in Scala.js. Why not try exercising your new-found skills? Here are some possibilities:
+
+ @ul
+ @li
+ Make more video games! I have a set of @lnk("retro-games ported to Scala.js", "http://lihaoyi.github.io/scala-js-games/"). Maybe re-make one of them without looking at the source, or maybe port some other game you're familiar with and enjoy playing. Even just drawing things on canvas, games can get @lnk("pretty elaborate", "http://lihaoyi.github.io/roll/").
+
+ @li
+ Explore the APIs! We've touched on a small number of Javascript APIs here, mainly for dealign with the canvas, but modern browsers offer a whole @lnk("zoo of functionality", "https://developer.mozilla.org/en-US/docs/Web/API"). Try making an application that uses @lnk("localStorage", "https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage") to save state even when you close the tab, or an application that works with the HTML DOM.
+
+ @li
+ Draw something pretty! We have a working canvas, a nice programming language, and a way to easily publish the results online. @lnk("Various", "http://www.scala-js-fiddle.com/gist/77a3840678d154257ca1/KochSnowflake.scala") @lnk("fractals", "http://www.scala-js-fiddle.com/gist/77a3840678d154257ca1/KochCurve.scala"), or @lnk("colorful visualizations", "http://www.scala-js-fiddle.com/gist/9443f8e0ecc68d1058ad/RayTracer.scala") are all possibilities.
+
+ @p
+ By this point you've some experience building stand-alone, single-canvas Scala.js applications, which has hopefully given you a feel for how Scala.js works. The problem is that few web applications satisfy the criteria of being stand-alone single-page canvas applications! Most web applications need to deal with the DOM of the HTML page, need to fetch data from web services, and generally need to do a lot of other messy things. We'll go into that in the next chapter
diff --git a/book/src/main/scalatex/handson/ClientServer.scalatex b/book/src/main/scalatex/handson/ClientServer.scalatex
new file mode 100644
index 0000000..eef99b3
--- /dev/null
+++ b/book/src/main/scalatex/handson/ClientServer.scalatex
@@ -0,0 +1,271 @@
+@import book.BookData._
+
+@def lazyload(id: String) = script(raw(s"""
+ window.addEventListener("load", function(){
+ document.getElementById("$id").src = 'https://hands-on-scala-js.herokuapp.com/'
+ })
+"""))
+
+
+@p
+ Historically, sharing code across client & server has been a holy-grail for web development. There are many things which have made it hard in the past:
+
+@ul
+ @li
+ Javascript on the client v.s. PHP/Perl/Python/Ruby/Java on the server
+ @li
+ Most back-ends make heavy use of C extensions, and front-end code was tightly coupled to the DOM. Even if you manage to port the main language
+@p
+ There have been some attempts in recent years with more traction: Node.js, for example, has been very successful at running Javascript on the server, the Clojure/Clojurescript community has their own version of cross-built code, and there are a number of smaller, more esoteric platforms.
+
+@p
+ Scala.js lets you share code between client and server relatively straightforwardly. As we saw in the previous chapter, where we made a shared module. Let's work to turn that shared module into a working client-server application!
+
+@val server = wd/'examples/'crossBuilds/'clientserver/'app/'jvm/'src/'main/'scala/'simple
+@val client = wd/'examples/'crossBuilds/'clientserver/'app/'js/'src/'main/'scala/'simple
+
+@sect{A Client-Server Setup}
+ @p
+ Getting started with client-server integration, let's go with the simplest configuration possible: a Spray server and a Scala.js client. Most of the other web-frameworks (@lnk.misc.Play, @lnk.misc.Scalatra, etc.) will have more complex configurations, but the basic mechanism of wiring up Scala.js to your web framework will be the same. Just like our project in @sect.ref{Cross Publishing Libraries}, our project will look like this:
+
+ @hl.sh
+ $ tree
+ .
+ ├── build.sbt
+ ├── project/build.sbt
+ └── app
+    ├── shared/src/main/scala/simple/FileData.scala
+    ├── js/src/main/scala/simple/Client.scala
+    └── jvm/src/main/scala/simple/
+ ├── Page.scala
+ └── Server.scala
+
+ @p
+ First, let's do the wiring in @code{build.sbt}:
+
+ @hl.ref(wd/'examples/'crossBuilds/'clientserver/"build.sbt")
+
+ @p
+ Again, we are using @hl.scala{crossProject} to define our @code{js/} and @code{jvm/} sub-projects. Both projects share a number of settings: the settings to add @lnk.github.Scalatags and @lnk.github.uPickle to the build. Note that those two dependencies use the triple @code{%%%} instead of the double @code{%%} to declare: this means that for each dependency, we will pull in the Scala-JVM or Scala.js version depending on whether it's being used in a Scala.js project. Note also the @hl.scala{packageArchetype.java_application} setting, which isn't strictly necessary depending on what you want to do with the application, but this example needs it as part of the deployment to Heroku.
+
+ @p
+ The @code{js/} sub-project is uneventful, with a dependency on the by-now-familiar @code{scalajs-dom} library. The @code{jvm/} project, on the other hand, is interesting: it contains the dependencies required for us to set up out Spray server, and one additional thing: we add the output of @code{fastOptJS} from the client to the @code{resources} on the server. This will allow the @code{server} to serve the compiled-javascript from our @code{client} project from its resources.
+
+ @p
+ Next, let's kick off the Spray server in our Scala-JVM main method:
+
+
+ @hl.ref(server/"Server.scala")
+
+ @p
+ This is a not-very-interesting @lnk("spray-routing", "http://spray.io/documentation/1.2.2/spray-routing/") application: we set up a server on @code{localhost:8080}, have the root URL serve the main page on GET, and have other GET URLs serve resources. This includes the @code{js-fastopt.js} file that is now in our resources because of our @code{build.sbt} config earlier! We also add a POST route to allow the client ask the server to list files various directories.
+
+ @p
+ The HTML template @hl.scala{Page.skeleton} is not shown above; I put it in a separate file for neatness:
+
+ @hl.ref(server/"Page.scala")
+
+ @p
+ This is a typical @lnk.github.Scalatags HTML snippet. Note that since we're serving it directly from the server in Scala code, we do not need to leave a @code{.html} file somewhere on the filesystem! We can declare all HTML, including the skeleton of the page, in Scalatags. Otherwise it's the same as what we saw in earlier chapters: A simple HTML page which includes a script tag to run our Scala.js application.
+ @p
+ Lastly, we'll set up the Scala.js main method, which we are calling in the @hl.xml{<script>} tag above to kick off the client-side application.
+
+ @hl.ref(client/"Client.scala")
+
+ @p
+ Again this is a simple Scala.js application, not unlike what we saw in earlier chapters. However, there is one difference: earlier, we made our Ajax calls to @code{api.openweathermap.org/...}. Here, we're making it to @code{/ajax}: the same server the page is served from!
+
+ @p
+ You may have noticed in both client and server, we have made reference to a mysterious @hl.scala{FileData} type which holds the name and size of each file. @hl.scala{FileData} is defined in the @code{shared/} folder, so it can be accessed from both Scala-JVM and Scala.js:
+
+
+ @hl.ref(wd/'examples/'crossBuilds/'clientserver/'app/'shared/'src/'main/'scala/'simple/"FileData.scala")
+
+ @p
+ Now, if we go to the browser at @code{localhost:8080}, we should see our web-page!
+
+ @iframe(id:="heroku1", width:="100%", height:="350px", "frameBorder".attr:="0")
+ @lazyload("heroku1")
+
+
+ @p
+ This is a real, live example running on a @lnk("Heroku server", "https://hands-on-scala-js.herokuapp.com/"). Feel free to poke around and explore the filesystem on the server, just to convince yourself that this actually works and is not just a mock up.
+
+@sect{Client-Server Reflections}
+ @p
+ By now you've already set up your first client-server application. However, it might not be immediately clear what we've done and why it's interesting! Here are some points to consider.
+
+ @sect{Shared Templating}
+
+ @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.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
+ One thing that we skimmed over is the fact that we could easily define our @hl.scala{case class FileData(name: String, size: Long)} in the @code{shared/} folder, and have it instantly and consistently available on both client and server. This perhaps does not seem so amazing: we've already done many similar things earlier when we were building Cross-platform Modules. Nevertheless, in the context of web development, it is a relatively novel idea to be able to ad-hoc share bits of code between client and server.
+ @p
+ Sharing code is not limited to class definitions: @i{anything} can be shared. Objects, classes, interfaces/traits, functions and algorithms, constants: all of these are things that you will likely want to share at some point or another. Traditionally, people have simply re-implemented the same code twice in two languages, or have resorted to awkward Ajax calls to push the logic to the server. With Scala.js, you no longer need to do so: you can easily, create ad-hoc bits of code which are available on both platforms.
+
+ @sect{Boilerplate-free Serialization}
+ @p
+ The Ajax/RPC layer is one of the more fragile parts of web applications. Often, you have your various Ajax endpoints written once on the server, have a set of routes written to connect those Ajax endpoints to URLs, and client code (traditionally Javascript) made calls to those URLs with "raw" data: basically whatever you wanted, packed in an ad-hoc mix of CSV and JSON and raw-strings.
+
+ @p
+ This has always been annoying boilerplate, and Scala.js removes it. With @lnk.github.uPickle, you can simply call @hl.scala{upickle.write(...)} and @hl.scala{upickle.read[T](...)} to convert your collections, primitives or case-classes to and from JSON. This means you do not need to constantly re-invent different ways of making Ajax calls: you can just fling the data right across the network from client to server and back again.
+
+@sect{What's Left?}
+ @p
+ We've built a small client-server web application with a Scala.js web-client that makes Ajax calls to a Scala-JVM web-server running on Spray. We performed these Ajax calls using uPickle to serialize the data back and forth, so serializing the arguments and return-value was boilerplate-free and correct.
+
+ @p
+ However, there is still some amount of duplication in the code. In particular, the definition of the endpoint name "list" is duplicated 4 times:
+
+ @hl.ref(server/"Server.scala", """path("ajax" / "list")""", "")
+ @hl.ref(server/"Server.scala", "list(", "")
+ @hl.ref(server/"Server.scala", "def list", "")
+ @hl.ref(client/"Client.scala", "ajax/list", "")
+
+ @p
+ Three times on the server and once on the client! What's worse, two of the appearances of @hl.scala{"list"} are in string literals, which are not checked by the compiler to match up with themselves or the name of the method @hl.scala{list}. Apart from this, there is one other piece of duplication that is unchecked: the type being returned from @hl.scala{list} (@hl.scala{Seq[FileData]}) is being repeated on the client in @hl.scala{upickle.read[Seq[FileData]]} in order to de-serialize the serialized data. This leaves three opportunities for error wide-open:
+
+ @ul
+ @li
+ You could change the string literals @hl.scala{"list"} and forget to change the method-name @hl.scala{list}, thus confusing future maintainers of the code.
+ @li
+ You could change one of literal @hl.scala{"list"}s but forget to change the other, thus causing an error at run-time (e.g. a 404 NOT FOUND response)
+ @li
+ You could update the return type of the @hl.scala{list} method and forget to update the @hl.scala{upickle.read} deserialization call on the client, resulting in a deserialization failure at runtime.
+
+ @p
+
+ @p
+ Neither of these scenarios is great! Although we've already made great progress in making our client-server application type-safe (via Scala.js on the client) and DRY (via shared code in @code{shared/}) we still have this tiny bit of annoying, un-checked duplication and danger lurking in the code-base. The basic problem is that what is normally called the "routing layer" in the web application is still unsafe, and so these silly errors can go un-caught and blow up on unsuspecting developers at run-time. Let's see how we can fix it.
+
+@sect{Autowire}
+
+ @p
+ @lnk("Autowire", "https://github.com/lihaoyi/autowire") is a library that turns your request routing layer from a fragile, hand-crafted mess into a solid, type-checked, boilerplate-free experience. Autowire basically turns what was previously a stringly-typed, hand-crafted Ajax call and route:
+
+ @hl.ref(client/"Client.scala", "ajax/list", "")
+
+ @p
+ Into a safe, type-checked function call:
+
+ @val client2 = wd/'examples/'crossBuilds/'clientserver2/'app/'js/'src/'main/'scala/'simple
+ @val server2 = wd/'examples/'crossBuilds/'clientserver2/'app/'jvm/'src/'main/'scala/'simple
+ @hl.ref(client2/"Client.scala", ".call()", "")
+
+ @p
+ Let's see how we can do that.
+
+ @sect{Setting up Autowire}
+
+ @p
+ To begin with, Autowire requires you to provide three things:
+
+ @ul
+ @li
+ An @hl.scala{autowire.Server} on the Server, set up to feed the incoming request into Autowire's routing logic
+ @li
+ An @hl.scala{autowire.Client} on the Client, set up to take a serialized request and send it across the network to the server.
+ @li
+ An interface (A Scala @hl.scala{trait}) which defines the interface between these two
+
+ @p
+ Let's start with our client-server interface definition
+
+ @hl.ref(wd/'examples/'crossBuilds/'clientserver2/'app/'shared/'src/'main/'scala/'simple/"Shared.scala")
+
+ @p
+ Here, you can see that in addition to sharing the @hl.scala{FileData} class, we are also creating an @hl.scala{Api} trait which contains the signature of our @hl.scala{list} method. The exact name of the trait doesn't matter. We need it to be in @code{shared/} so that the code in both client and server can reference it.
+
+ @p
+ Next, let's look at modifying our server code to make use of Autowire:
+
+ @hl.ref(server2/"Server.scala")
+
+ @p
+ Now, instead of hard-coding the route @hl.scala{"ajax" / "list"}, we now take in any route matching @hl.scala{"ajax" / Segments}, feeding the resultant path segments into the @hl.scala{Router} object:
+
+ @hl.ref(server2/"Server.scala", "path(")
+ @p
+ The @hl.scala{Router} object in turn simply defines how you intend the objects to be serialized and deserialized:
+
+ @hl.ref(server2/"Server.scala", "object Router", "object Server")
+
+ @p
+ In this case using uPickle. Note how the @hl.scala{route} call explicitly states the type (here @hl.scala{Api}) that it is to generate routes against; this ensures that only methods which you explicitly put in your public interface @hl.scala{Api} are publically reachable.
+
+ @p
+ Next, let's look at the modified client code:
+
+ @hl.ref(client2/"Client.scala")
+
+ @p
+ There are two main modifications here: the existence of the new @hl.scala{Ajaxer} object, and the modification to the Ajax call-site. Let's first look at @hl.scala{Ajaxer}:
+
+ @hl.ref(client2/"Client.scala", "object Ajaxer", "@JSExport")
+
+ @p
+ Like the @hl.scala{Router} object, @hl.scala{Ajaxer} also defines how you perform the serialization and deserialization of data-structures, again using uPickle. Unlike the @hl.scala{Router} object, @hl.scala{Ajaxer} also defines how the out-going Ajax call gets sent over the network. Here we're doing it using the @hl.scala{Ajax.post} method.
+
+ @p
+ Lastly, let's look at the modified callsite for the ajax call itself:
+
+ @hl.ref(client2/"Client.scala", "def update", "")
+
+ @p
+ There are a few things of note here:
+
+ @ul
+ @li
+ The previous call to @hl.scala{Ajax.post} with the path as a string has been replaced by calling @hl.scala{Ajaxer[Api].list(...).call()}, since the logic of actually performing the POST is specified once-and-only-once in the @hl.scala{Ajaxer} object.
+ @li
+ While @hl.scala{Ajax.post} returned a @hl.scala{Future[dom.XMLHttpRequest]} and left us to call @hl.scala{upickle.read} and deserialize the data ourselves, @hl.scala{Ajaxer[Api].list(...).call()} now returns a @hl.scala{Future[Seq[FileData]]}! Thus we don't need to worry about making a mistake in the deserialization logic when we write it by hand.
+
+ @p
+ Other than that, nothing much has changed. If you've done this correctly, the web application will look and behave exactly as it did earlier!
+
+ @iframe(id:="heroku2", width:="100%", height:="350px", "frameBorder".attr:="0")
+ @lazyload("heroku2")
+
+
+ @p
+ So why did we do this in the first place?
+
+ @sect{Why Autowire?}
+ @p
+ Overall, this set up requires some boilerplate to define the @hl.scala{Ajaxer} and @hl.scala{Router} objects, as well as the @hl.scala{Api} trait. However, these can be defined just once and used over and over; while it might be wasteful/unnecessary for making a single Ajax call, the cost is much less amortized over a number of Ajax calls. In a non-trivial web application with dozens of routes being called all over the place, spending a dozen lines setting up things up-front isn't a huge cost.
+
+ @p
+ What have we gotten in exchange? It turns out that by using Autowire, we have eliminated the three failure modes described earlier, that could:
+
+ @ul
+ @li
+ It is impossible for the route and the endpoint method-name to diverge accidentally: if the endpoint is called @hl.scala{list}, the requests will go through the @code{/list} URL. No room for discussion, or to make a mistake
+ @li
+ You cannot accidentally rename the route on the server without changing the client, or vice versa. Attempts to do so will cause a compilation error, and even your IDE should highlight it as red. Try it out!
+
+ @li
+ There is no chance of messing up the serialization/deserialization code, e.g. writing a response of type A on the server and trying to read a data-structure of type B on the client. You have no opportunity to make an error: you pass arguments to the Ajax call, and they are serialized/deserialized automatically, such that by the time you get access to the value on the server, it is already of the correct type! The same applies to serializing/deserializing the return-value on the client. There is simply no place for you as a developer to accidentally make a mistake!
+
+ @p
+ Although the functionality of the web application is the same, it is mostly in terms of @i{safety} that we have made the biggest gains. All of the common failure modes described earlier have been guarded against, and you as a developer will have a hard time trying to make a mal-formed Ajax call. It's worth taking some time to poke at the source code to see the boundaries of the type-safety provided by autowire, as it is a very different experience from the traditional "route it manually" approach to making interactive client-server applications.
+
+@hr
+
+@p
+ Hopefully this chapter has given you a glimpse of how a basic client-server application works using Scala.js. Although it is specific to a Spray server, there isn't any reason why you couldn't set up an equivalent thing for your Play, Scalatra or whichever other web framework that you're using.
+
+@p
+ It's probably worth taking a moment to play around with the existing client-server system you have set up. Ideas for improvement include:
+
+@ul
+ @li
+ Try adding additional functionality to the client-server interface: what about making it show the contents of a file if you've entered its full path? This can be added as a separate Ajax call or as part of the existing one.
+ @li
+ How about setting up the build.sbt so it serves the fully-optimized Scala.js blob, @code{client-opt.js}? This is probably what you want before deployment into production, and the same technique as we used to serve the fast-optimized version applies here too.
+ @li
+ What if you wanted to use another server rather than Spray? How about trying to set up a Play or Scalatra server to serve our Scala.js application code? \ No newline at end of file
diff --git a/book/src/main/scalatex/handson/CommandLine.scalatex b/book/src/main/scalatex/handson/CommandLine.scalatex
new file mode 100644
index 0000000..d3b888c
--- /dev/null
+++ b/book/src/main/scalatex/handson/CommandLine.scalatex
@@ -0,0 +1,184 @@
+@import book.BookData._
+
+@p
+ We've by this point done a bunch of work in the browser: we've made a small game that runs in the web browser on the HTML5 canvas, and we've made a number of small web-apps that interact with HTML and 3rd party web-services. However, there's a whole other side to the Scala.js ecosystem: the command line interace, or CLI.
+
+@p
+ Even though the goal of Scala.js is to get your code running in peoples' browsers, it still is useful to be familiar with the things that you can do in the command-line. It is much easier to write-code-print-results in the command line without having to set up a HTML page and opening a browser to test it, and this extends to things like unit test suites, which are almost exclusively run in the command-line using @code{sbt ~test} to keep re-running them when the code changes.
+
+@p
+ The Scala.js command line is where you go to do things to your Scala.js code. Although Scala.js comes with @lnk("standalone executables", "http://www.scala-js.org/downloads.html") that can be used from any shell (sh, bash, zsh, etc.) the primary supported way of setting up, compiling and testing your Scala.js applications is through @lnk("SBT", "http://www.scala-sbt.org/"): Scala's primary build tool.
+
+@p
+ You've already used fragments of the Scala.js CLI in earlier chapters of this book: @code{~fastOptJS} is what you used for development, @code{fullOptJS} for publishing. Apart from these, Scala.js allows you to execute code via @lnk.misc.Rhino/@lnk.misc.Nodejs/@lnk.misc.PhantomJS from the command-line, as well as running test-suites under the same conditions. This chapter will go deeper into the various things you can do with the Scala.js command line:
+
+@ul
+ @li
+ @code{compile}: converting code from Scala source into not-yet-executable Scala.js IR
+ @li
+ @code{package}: bundling up our Scala.js IR into a @code{.jar} file, for publishing or distribution as a library
+ @li
+ @code{fastOptJS}: aggregating our Scala.js IR and converting it to a @code{.js} executable.
+ @li
+ @code{fullOptJS}: aggregating our Scala.js IR and converting it to a smaller, faster @code{.js} executable.
+ @li
+ @code{run}: run your compiled Scala.js code as Javascript in Rhino, Node.js or Phantom.js
+ @li
+ @code{test}: run your compiled Scala.js code as a test suite in Rhino, Node.js or Phantom.js
+
+@p
+ Now, let's open up your SBT console in your Scala.js app
+
+@hl.sh
+ >
+
+@p
+ And let's get started!
+
+@sect{Commands}
+ @p
+ The most fundamental thing you can do in the Scala.js CLI is to compile your code. Let's go through the various mechanisms of "compiling" things:
+
+ @sect{The compile Command}
+ @hl.sh
+ > compile
+
+ @p
+ Just as you can @code{compile} Scala-JVM projects, you can also @code{compile} Scala.js projects. Like compiling Scala-JVM projects, this leaves a bunch of @code{.class} files in your @code{target} directory. Unlike Scala-JVM projects, this also leaves a bunch of @code{.sjsir} files, which correspond to your Scala.js output files:
+
+ @hl.sh
+ classes
+ └── example
+ ├── Point$.class
+ ├── Point$.sjsir
+ ├── Point.class
+ ├── Point.sjsir
+ ├── ScalaJSExample$$anonfun$main$1.class
+ ├── ScalaJSExample$$anonfun$run$1.class
+ ├── ScalaJSExample$.class
+ ├── ScalaJSExample$.sjsir
+ └── ScalaJSExample.class
+
+ @p
+ However, unlike on Scala-JVM, you cannot directly run the @code{.sjsir} files spat out by the Scala.js compiler. These files are an Intermediate Representation, which needs to go through the next step in the compilation pipeline before being turned into Javascript.
+
+ @sect{The package Command}
+ @hl.sh
+ > package
+ @p
+ Also like on Scala-JVM, Scala.js also supports the @code{package} command. This command generates a @code{.jar} like it does in Scala-JVM, except this version appends this weird @code{_sjs0.6} suffix.
+
+ @hl.sh
+ target/scala-2.11/
+ └── example_sjs0.6_2.11-0.1-SNAPSHOT.jar
+
+ @p
+ The purpose of this suffix is to link the compiled @code{.jar} file to the version of Scala.js used to compile it. This allows you to make sure that you don't accidentally depend on a version of a jar that is incompatible with your current version.
+
+ @p
+ Again, unlike Scala-JVM, these @code{.jar} files are not directly executable: the @code{.sjsir} files need further processing to turn into runnable Javascript. Instead, their sole purpose is to hold bundles of @code{.sjsir} files to be published and depended-upon: they can be @code{publishLocal}ed to be used by other projects on your computer, or @code{publishSigned}ed to @lnk("Maven Central", "http://search.maven.org/"), just like any Scala-JVM project.
+
+ @sect{The fastOptJS Command}
+ @hl.sh
+ > fastOptJS
+ @p
+ @code{fastOptJS} is a command we've used in earlier chapters. It basically runs the @sect.ref{Fast Optimization} stage of the compilation pipeline. This results in a moderately-sized executable, which you can then load in the browser with a @hl.xml{<script>} tag and run.
+
+ @p
+ This is the first phase which actually results in an executable blob of Javascript. I won't go into much detail about this command: you've used it before, and more details about the particular kind of optimization and how it fits into the large process is available in the chapter on The Compilation Pipeline. Nonetheless, it's fast, produces not-too-huge output code, and is what you typically use for iterative development in the browser.
+
+ @sect{The fullOptJS Command}
+ @hl.sh
+ > fullOptJS
+ @p
+ @code{fullOptJS} is another command that we've seen before: it performs an aggressive, somewhat slower @sect.ref{Full Optimization} pass on the generated Javascript. This results in a much smaller executable Javascript blob, which you can also load via a @hl.xml{<script>} tag and run.
+ @p
+ Again, I won't go into much details, as exactly what this optimization does is described in the chapter on the Compilation Pipeline. This command is somewhat too-slow to be running during iterative development, and is instead typically used just before deployment to minimize the size of the file your users have to download.
+
+ @sect{The run Command}
+ @hl.sh
+ > run
+ @p
+ Here's something you haven't seen before: the @code{run} command gives you the ability to run a Scala.js program from the command line. This prints its output to standard output (i.e. the terminal). Like Scala-JVM, you need a @code{main} method to run to kick off your program. Unlike Scala-JVM, the main method is marked on an @hl.scala{object} which @hl.scala{extends scala.scalajs.js.JSApp}, e.g.
+
+ @hl.scala
+ // src/main/scala/RunMe.scala
+ object RunMe extends scala.scalajs.js.JSApp{
+ def main(): Unit = {
+ println("Hello World!")
+ println("In Scala.js, (1.0).toString is ${(1.0).toString}!")
+ }
+ }
+
+ @p
+ Running @code{sbt run} with the above Scala.js code will print out
+
+ @hl.sh
+ Hello World!
+ In Scala.js, (1.0).toString is 1!
+
+ @p
+ This exhibits the weirdness of @hl.scala{Double.toString} in Scala.js, which is one of the few ways in which @sect.ref("Deviations from Scala-JVM", "Scala.js deviates from Scala-JVM"). This also shows us we're really running on Scala.js: on Scala-JVM, @hl.scala{(1.0).toString} returns @hl.scala{"1.0"} rather than @hl.scala{"1"}!
+
+ @p
+ One thing you may be wondering is: when you run a Scala.js program in the terminal, how does it execute the output Javascript? What about the DOM? and Ajax calls? Can it access the filesystem? The answer to all these questions is "it depends": it turns out there are multiple ways you can run Scala.js from the command-line, dictated by the @i{stage} and the @i{environment}.
+
+ @p
+ By default, runs are done in the @code{PreLinkStage}, which uses the Rhino environment. With the sbt setting @hl.scala{jsDependencies += RuntimeDOM}, the Scala.js runner will automatically set up @b{env.js} in Rhino so that you have access to an emulation of the DOM API.
+
+ @p
+ You can enable a different stage, @code{FastOptStage} or @code{FullOptStage}, with the following sbt command:
+
+ @hl.sh
+ > set scalaJSStage in Global := FastOptStage
+
+ @p
+ In @code{FastOptStage} and @code{FullOptStage}, the environment can be one of @b{Node.js} or @b{PhantomJS}. These JavaScript VMs must be installed separately.
+
+ @ul
+ @li
+ By default, Node.js is used.
+ @li
+ With the sbt setting @hl.scala{jsDependencies += RuntimeDOM}, PhantomJS is used instead, so that a headless DOM is available.
+
+ @p
+ Typically, the best way to get started is using Rhino, since it's setup-free, and setting up Node.js or PhantomJS later as necessary. The next two sections elaborate on the differences between these ways of running your code. Check out the later sections on @sect.ref{Headless Runtimes} and @sect.ref{Stages} to learn more about the other settings and why you would want to use them.
+
+ @sect{The test Command}
+ @hl.sh
+ > test
+
+ @p
+ The @code{sbt test} command behaves very similarly to @code{sbt run}. It also runs on Rhino, Node.js or PhantomJS, dependending of the stage and the dependency on the DOM.
+ @p
+ The difference is that instead of simply running your @code{main} method, @code{sbt test} runs whatever test-suite you have set-up, which will look through your @code{tests/} folder to find suites of tests it has to run, and aggregate the results formatted nicely for you to see. The exact operation of this depends on which testing library you're using.
+ @p
+ We won't spend much time talking about @code{sbt test} here. Not because it's not important: it most certainly is! Rather, we will be spending a good amount of time setting up tests in @sect.ref("Cross Publishing Libraries", "the next chapter"), so feel free to jump ahead if you want to see an example usage of @code{sbt test}.
+
+@sect{Headless Runtimes}
+ @ul
+ @li
+ @lnk.misc.Rhino is the default way of running Scala.js applications. The upside of using Rhino is that it is pure-Java, and doesn't need any additional binaries or installation. The downside of using Rhino is that it is slow: maybe a hundred times slower than the alternatives, making it not suitable for running long-running, compute-intensive programs.
+ @li
+ @lnk.misc.Nodejs, a relatively new Javascript runtime based on Google's V8 Javascript engine, Node.js lets you run your Scala.js application from the command line much faster than in Rhino, with performance that matches that of modern browsers. However, you need to separately @lnk("install Node.js", "http://nodejs.org/download/") in order to use it. Node.js does not have DOM or browser-related functionality. You need to set the stage with @code{set scalaJSStage in Global := FastOptStage} to run using Node.js.
+ @li
+ @lnk.misc.PhantomJS is a headless Webkit browser. This means that unlike Node.js, PhantomJS provides you with a full DOM and all its APIs to use in your tests, if you wish to e.g. test interactions with the HTML of the web page. On the other hand, it is somewhat slower than Node.js, though still much faster than Rhino. Like Node.js, it needs to be installed separately. You need to set the stage with @code{set scalaJSStage in Global := FastOptStage}, as well as setting the @hl.scala{jsDependencies += RuntimeDOM} flag in your SBT configuration, to use PhantomJS.
+ @p
+ These are your three options to run your Scala.js code via the command-line. Generally, it's easiest to get started with Rhino since it's the default and requires no setup, though you will quickly find it worthwhile to setup Node.js or PhantomJS to speed up your runs and tests.
+
+@sect{Stages}
+ @p
+ Let us recap the three different stages of execution, and what they mean.
+
+ @ul
+ @li
+ @code{PreLinkStage} (the default): this does not perform any optimization of the output Scala.js files, and does lazy-loading to minimize the amount of files being loading into the interpreter. This is necessary for Rhino because it can't handle large blobs of Javascript, but doesn't map to any compilation mode you'd use for the browser.
+ @li
+ @code{FastOptStage}: this performs the same compilation and optimization as @code{sbt fastOptJS}, as described under Fast Optimizations. It then takes the entire output executable (which probably weighs around 1mb) and hands it to Node.js or PhantomJS, which then run it.
+ @li
+ @code{FullOptStage}: this performs the same compilation and optimization as @code{sbt fullOptJS}, as described under Full Optimizations. This takes longer to run than the @code{FastOptStage}, and results in a smaller/faster executable. Practically speaking, this size/speed advantage does not matter from the command line, but @code{FullOptStage} is still useful to verify that the behavior does not change (it shouldn't!) under the aggressive full optimization. This is typically used in continuous integration builds, but rarely manually.
+
+@hr
+
+@p
+ Hopefully by this point you more-or-less know your way around the Scala.js command-line tools. As mentioned earlier, command line tools make it much easier to run a bunch of Scala.js code, e.g. unit tests, without having to muck around with HTML pages or refreshing the browser. That will come in handy soon, as we're next going to learn to publish a standalone, distributable Scala.js module. And what's a module without tests... \ No newline at end of file
diff --git a/book/src/main/scalatex/handson/GettingStarted.scalatex b/book/src/main/scalatex/handson/GettingStarted.scalatex
new file mode 100644
index 0000000..e803fc1
--- /dev/null
+++ b/book/src/main/scalatex/handson/GettingStarted.scalatex
@@ -0,0 +1,332 @@
+@import book.BookData._
+
+@p
+ To get started with Scala.js, you will need to prepare a few things:
+
+@ul
+ @li
+ @lnk("sbt", "http://www.scala-sbt.org/"): SBT is the most common build-tool in the Scala community, and is what we will use for building our Scala.js application. Their home page has a link to download and install it. (If you are already using Typesafe Activator, that is effectively sbt.)
+ @li
+ An editor for Scala: @lnk("IntelliJ Scala", "http://blog.jetbrains.com/scala/") and @lnk("Eclipse ScalaIDE", "http://scala-ide.org/") are the most popular choices and work on all platforms, though there are others.
+ @li
+ @lnk("Git", "http://git-scm.com/"): This is a version-control system that we will use to download and manage our Scala.js projects.
+ @li
+ A terminal: on OSX you have @lnk("Terminal.app", "http://guides.macrumors.com/Terminal") already installed, in Linux you have @lnk("Terminal", "https://help.ubuntu.com/community/UsingTheTerminal"), and on Windows you have @lnk("PowerShell", "http://en.wikipedia.org/wiki/Windows_PowerShell").
+ @li
+ Your favorite web browser: @lnk("Chrome", "https://www.google.com/chrome") and @lnk("Firefox", "https://www.mozilla.org/en-US/firefox") are the most popular.
+
+@p
+ If you've worked with Scala before, you probably already have most of these installed. Otherwise, take a moment to download them before we get to work.
+
+@p
+ The quickest way to get started with Scala.js is to @code{git clone} @lnk("workbench-example-app", "https://github.com/lihaoyi/workbench-example-app"), go into the repository root, and run @code{sbt ~fastOptJS}
+
+@hl.sh
+ git clone https://github.com/lihaoyi/workbench-example-app
+ cd workbench-example-app
+ sbt ~fastOptJS
+
+@p
+ This should result in a bunch of spam to the console, and may take a few minutes the first time as SBT resolves and downloads all necessary dependencies. A successful run looks like this
+
+@pre
+ haoyi-mbp:Workspace haoyi$ git clone https://github.com/lihaoyi/workbench-example-app
+ Cloning into 'workbench-example-app'...
+ remote: Counting objects: 876, done.
+ remote: Total 876 (delta 0), reused 0 (delta 0)
+ Receiving objects: 100% (876/876), 676.59 KiB | 317.00 KiB/s, done.
+ Resolving deltas: 100% (308/308), done.
+ Checking connectivity... done.
+ haoyi-mbp:Workspace haoyi$ cd workbench-example-app/
+ haoyi-mbp:workbench-example-app haoyi$ sbt ~fastOptJS
+ [info] Loading global plugins from /Users/haoyi/.sbt/0.13/plugins
+ [info] Updating {file:/Users/haoyi/.sbt/0.13/plugins/}global-plugins...
+ [info] Resolving org.fusesource.jansi#jansi;1.4 ...
+ [info] Done updating.
+ [info] Loading project definition from /Users/haoyi/Dropbox (Personal)/Workspace/workbench-example-app/project
+ [info] Updating {file:/Users/haoyi/Dropbox%20(Personal)/Workspace/workbench-example-app/project/}workbench-example-app-build...
+ [info] Resolving org.fusesource.jansi#jansi;1.4 ...
+ [info] Done updating.
+ [info] Set current project to Example (in build file:/Users/haoyi/Dropbox%20(Personal)/Workspace/workbench-example-app/)
+ [INFO] [10/26/2014 15:42:09.791] [SystemLol-akka.actor.default-dispatcher-2] [akka://SystemLol/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:12345
+ [info] Updating {file:/Users/haoyi/Dropbox%20(Personal)/Workspace/workbench-example-app/}workbench-example-app...
+ [info] Resolving jline#jline;2.12 ...
+ [info] Done updating.
+ [info] Compiling 1 Scala source to /Users/haoyi/Dropbox (Personal)/Workspace/workbench-example-app/target/scala-2.11/classes...
+ [info] Fast optimizing /Users/haoyi/Dropbox (Personal)/Workspace/workbench-example-app/target/scala-2.11/example-fastopt.js
+ [info] workbench: Checking example-fastopt.js
+ [info] workbench: Refreshing http://localhost:12345/target/scala-2.11/example-fastopt.js
+ [success] Total time: 11 s, completed Oct 26, 2014 3:42:21 PM
+ 1. Waiting for source changes... (press enter to interrupt)
+
+@p
+ The line @code{Waiting for source changes...} is telling you that your Scala.js program is ready! Now, when you go to the web URL @code{http://localhost:12345/target/scala-2.11/classes/index-dev.html} in your browser, you should see the following:
+
+ @img(src:="images/Hello World.png", maxWidth:="100%")
+
+@p
+ Congratulations, you just built and ran your first Scala.js application! If something here does not happen as expected, it means that one of the steps did not complete successfully. Make sure you can get this working before you proceed onward.
+
+@sect{Opening up the Project}
+
+ @p
+ The next thing to do once you have the project built and running in your browser is to load it into your editor. Both IntelliJ and Eclipse should let you import the Scala.js project without any hassle. Opening it and navigating to @code{ScalaJSExample.scala} would look like this:
+
+ @img(src:="images/IntelliJ Hello.png", maxWidth:="100%")
+
+ @p
+ Let's try changing one line to change the background fill from black to white:
+
+ @hl.diff
+ - ctx.fillStyle = "black"
+ + ctx.fillStyle = "white"
+
+ @p
+ Because we started @code{sbt ~fastOptJS} with the @code{~} prefix earlier, it should pick up the change and automatically recompile. The example project is set up to automatically refresh the page when recompilation is complete.
+
+ @img(src:="images/Hello World White.png", maxWidth:="100%")
+
+ @p
+ If you open up your browser's developer console, you'll see that the SBT log output is being mirrored there:
+
+ @img(src:="images/Hello World Console.png", maxWidth:="100%")
+
+ @p
+ Apart from the SBT log output (which is handled by Workbench) any @hl.scala{println}s in your Scala.js code will also end up in the browser console (the @code{main} you see in the console is printed inside the Scala.js application, see if you can find it!) and so will the stack traces for any thrown exceptions.
+
+@sect{The Application Code}
+
+ @p
+ We've downloaded, compiled, ran, and made changes to our first Scala.js application. Let's now take a closer look at the code that we just ran:
+ @val example = cloneRoot/"workbench-example-app"/'src/'main/'scala/'example
+ @hl.ref(example/"ScalaJSExample.scala")
+
+ @p
+ It's a good chunk of code, though not a huge amount. To someone who didn't know about Scala.js, they would just think it's normal Scala, albeit with this unusual @hl.scala{dom} library and a few weird annotations. Let's pick it apart starting from the top:
+
+ @hl.ref(example/"ScalaJSExample.scala", "case class Point", "@JSExport")
+
+ @p
+ Here we are defining a @hl.scala{Point} case class which represents a X/Y position, with some basic operators defined on it. This is done mostly for convenience later on, when we want to manipulate these two-dimensional points. Scala.js is Scala, and supports the entirety of the Scala language. @hl.scala{Point} here behaves identically as it would if you had run Scala on the JVM.
+
+ @hl.ref(example/"ScalaJSExample.scala", "@JSExport", "val ctx")
+
+ @p
+ 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.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")
+
+ @p
+ 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.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")
+
+ @p
+ This is the part of the Scala.js program which does the real work. It runs 10 iterations of a @lnk("small algorithm", "http://en.wikipedia.org/wiki/Sierpinski_triangle#Chaos_game") that generates a Sierpinski Triangle point-by-point. The steps, as described by the linked article, are roughly:
+
+ @ul
+ @li
+ Pick a random corner of the large-triangle
+ @li
+ Move your current-position @hl.scala{p} halfway between its current location and that corner
+ @li
+ Draw a dot
+ @li
+ Repeat
+
+ @p
+ In this example, the triangle is hard-coded to be 255 pixels high by 255 pixels wide, and some math is done to pick a color for each dot which will give the triangle a pretty gradient.
+
+ @hl.ref(example/"ScalaJSExample.scala", "dom.setInterval")
+
+ @p
+ Now this is the call that actually does the useful work. All this method does is call @hl.scala{dom.setInterval}, which tells the browser to run the @hl.scala{run} method every 50 milliseconds. As mentioned earlier, the @hl.scala{dom.*} methods are simply facades to their native Javascript equivalents, and @hl.scala{dom.setInterval} is @lnk("no different", "https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setInterval"). Note how you can pass a Scala lambda to @hl.scala{setInterval} to have it called by the browser, where in Javascript you'd need to pass a Javascript @hl.js{function(){...}}
+
+@sect{The Project Code}
+
+ @p
+ We've already taken a look at the application code for a simple, self-contained Scala.js application, but this application is not @i{entirely} self contained. It's wrapped in a small SBT project that sets up the necessary dependencies and infrastructure for this application to work.
+
+ @sect{project/build.sbt}
+ @hl.ref(cloneRoot/"workbench-example-app"/'project/"build.sbt")
+
+ @p
+ This is the list of SBT plugins used by this small example application. There are two of them: the Scala.js plugin (which contains the Scala.js compiler and other things, e.g. tasks such as @code{fastOptJS}) and the @lnk("Workbench", "https://github.com/lihaoyi/workbench") plugin, which is used to provide the auto-reload-on-change behavior and the forwarding of SBT logspam to the browser console.
+
+ @p
+ Of the two, only the Scala.js plugin is really necessary. The Workbench plugin is a convenience that makes development easier. Without it you'd need to keep a terminal open to view the SBT logspam, and manually refresh the page when compilation finished. Not the end of the world.
+
+
+ @sect{build.sbt}
+ @hl.ref(cloneRoot/"workbench-example-app"/"build.sbt")
+
+ @p
+ The @code{build.sbt} project file for this application is similarly unremarkable: It includes the settings for the two SBT plugins we saw earlier, as well as boilerplate @hl.scala{name}/@hl.scala{version}/@hl.scala{scalaVersion} values common to all projects.
+
+ @p
+ Of interest is the @hl.scala{libraryDependencies}. In Scala-JVM, this key is used to declare dependencies on libraries from Maven Central, so you can use them in your Scala-JVM projects. In Scala.js, the same key is used to declare dependencies on libraries so you can use them in your Scala.js projects! Re-usable libraries can be built and published with Scala.js just as you do on Scala-JVM, and here we make use of one which provides the typed facades with which we used to access the DOM in the application code.
+
+ @p
+ Lastly, we have two Workbench related settings: @hl.scala{bootSnippet} basically tells Workbench how to restart your application when a new compilation run finishes, and @hl.scala{updateBrowsers} actually tells it to perform this application-restarting.
+
+ @sect{src/main/resources/index-dev.html}
+ @hl.ref(cloneRoot/"workbench-example-app"/'src/'main/'resources/"index-dev.html")
+
+ @p
+ This is the HTML page which our toy app lives in, and the same page that we have so far been using to view the app in the browser. To anyone who has used HTML, most of it is probably familiar. Things of note are the @hl.xml{<script>} tags: @hl.scala{"../example-fastopt.js"} Is the executable blob spat out by the compiler, which we need to include in the HTML page for anything to happen. This is where the results of your compiled Scala code appear. @hl.scala{"workbench.js"} is the client for the Workbench plugin that connects to SBT, reloads the browser and forwards logspam to the browser console.
+
+ @p
+ The @hl.scala{example.ScalaJSExample().main()} call is what kicks off the Scala.js application and starts its execution. Scala.js follows Scala semantics in that @hl.scala{object}s are evaluated lazily, with no top-level code allowed. This is in contrast to Javascript, where you can include top-level statements and object-literals in your code which execute immediately. In Scala.js, nothing happens when @code{../example-fastopt.js} is imported! We have to call the main-method first. In this case, we're passing the canvas object (attained using @hl.js{getElementById}) to it so it knows where to do its thing.
+
+
+ @p
+ @hl.scala{document.getElementById} is the exact same API that's used in normal Javascript, as documented @lnk("here", "https://developer.mozilla.org/en-US/docs/Web/API/document.getElementById"). In fact, the entire @hl.scala{org.scalajs.dom} namespace (imported at the top of the file) comprises statically typed facades for the javascript APIs provided by the browser.
+
+ @p
+ Lastly, only @hl.scala("@JSExport")ed objects and methods can be called from Javascript. Also, although this example only exports the @hl.scala{main} method which is called once, there is nothing stopping you from exporting any number of objects and methods and calling them whenever you need to. In this way, you can easily make a Scala.js "library" which is available to external Javascript as an API.
+
+@sect{Publishing}
+ @p
+ The last thing that we'll do with our toy application is to publish it. If you look in the @code{target/scala-2.11} folder, you'll see the output of everything we've done so far:
+
+ @hl.sh
+ target/scala-2.11
+ ├── classes
+ │   ├── JS_DEPENDENCIES
+ │   ├── example
+ │   │   ├── Point$.class
+ │   │   ├── Point$.sjsir
+ │   │   ├── Point.class
+ │   │   ├── Point.sjsir
+ │   │   ├── ScalaJSExample$$anonfun$main$1.class
+ │   │   ├── ScalaJSExample$$anonfun$run$1.class
+ │   │   ├── ScalaJSExample$.class
+ │   │   ├── ScalaJSExample$.sjsir
+ │   │   └── ScalaJSExample.class
+ │   ├── index-dev.html
+ │   └── index-opt.html
+ ├── example-fastopt.js
+ └── example-fastopt.js.map
+
+ @p
+ All the @code{.class} and @code{.sjsir} files are the direct output of the Scala.js compiler, and aren't necessary to actually run the application. The only two files necessary are @code{index-dev.html} and @code{example-fastopt.js}. You may recognize @code{index-dev.html} as the file that we were navigating to in the browser earlier.
+
+ @p
+ These two files can be extracted and published as-is: you can put them on @lnk("Github-Pages", "https://pages.github.com/"), @lnk("Amazon Web Services", "http://docs.aws.amazon.com/gettingstarted/latest/swh/website-hosting-intro.html"), or a hundred other places. However, one thing of note is the fact that the generated Javascript file is quite large:
+
+ @hl.sh
+ haoyi-mbp:temp haoyi$ du -h target/scala-2.11/example-fastopt.js
+ 656K target/scala-2.11/example-fastopt.js
+
+ @p
+ 656 Kilobytes for a hello world app! That is clearly too large. If you examine the contents of the file, you'll see that your code has been translated into something like this:
+
+ @hl.js
+ var v1 = i;
+ if (((count$1.elem$1 % 3000) === 0)) {
+ ScalaJS.m.Lexample_ScalaJSExample$().example$ScalaJSExample$$clear$1__Lorg_scalajs_dom_CanvasRenderingContext2D__V(ctx$1)
+ };
+ count$1.elem$1 = ((1 + count$1.elem$1) | 0);
+ var jsx$1 = ScalaJS.as.Lexample_Point(p$1.elem$1);
+ var this$4 = ScalaJS.m.s_util_Random$();
+ p$1.elem$1 = jsx$1.$$plus__Lexample_Point__Lexample_Point(ScalaJS.as.Lexample_Point(corners$1.apply__I__O(this$4.self$1.nextInt__I__I(3)))).$$div__I__Lexample_Point(2);
+ var height = (512.0 / ((255 + ScalaJS.as.Lexample_Point(p$1.elem$1).y$1) | 0));
+ var r = ((ScalaJS.as.Lexample_Point(p$1.elem$1).x$1 * height) | 0);
+ var g = ((((255 - ScalaJS.as.Lexample_Point(p$1.elem$1).x$1) | 0) * height) | 0);
+
+ @p
+ As you can see, this code is still very verbose, with lots of unnecessarily long identifiers such as @hl.js{Lexample_ScalaJSExample$} in it. This is because we've only performed the @sect.ref{Fast Optimization} on this file, to try and keep the time taken to edit -> compile while developing reasonably short.
+
+ @sect{Optimization}
+ @p
+ If we're planning on publishing the app for real, we can run the @sect.ref{Full Optimization}. This takes several seconds longer than the @sect.ref{Fast Optimization}, but results in a significantly smaller and leaner output file @code{example-opt.js}.
+
+ @hl.sh
+ haoyi-mbp:temp haoyi$ du -h target/scala-2.11/example-opt.js
+ 104K target/scala-2.11/example-opt.js
+
+ @p
+ 104 Kilobytes! Better. Not great, though! In general, Scala.js does not produce tiny executables, although the output size of the compiled executables is dropping all the time. If you look inside that file, you'll see all of the long identifiers have been replaced by short ones by the @lnk("Google Closure Compiler", "https://developers.google.com/closure/compiler/").
+
+ @hl.js("""
+ y=fb(gb((new F).Ya(["rgb(",", ",", ",")"])),(new F).Ya([(255-c.l.Db|0)*y|0,c.l.Db*y|0,c.l.Eb]));a.fillStyle=y;a.fillRect(c.l.Db,c.l.Eb,1,1);w=1+w|0}}}(a,b,c,e),50)}Xa.prototype.main=function(a){Ya(a)};Xa.prototype.a=new x({$g:0},!1,"example.ScalaJSExample$",B,{$g:1,b:1});var hb=void 0;function bb(){hb||(hb=(new Xa).c());return hb}ba.example=ba.example||{};ba.example.ScalaJSExample=bb;function Da(){this.Pb=null}Da.prototype=new A;
+ """)
+
+ @p
+ These files are basically unreadable, but nonetheless behave the same as the @code{-fastopt} versions. Try it out by opening the @code{index-opt.html} file in the @code{target/scala-2.11/classes} directory with your browser: you should see the thing as when opening @code{index-dev}, except it will be pulling in the fully-optmized version of your application.
+
+ @p
+ This means you can develop and debug using @code{fastOptJS}, and only spend the extra time (and increased debugging-difficulty) on the @code{fullOptJS} version just as you're going to publish it, with the assurance that although the code is much more compact, its behavior will not change.
+
+ @sect{Blob Size}
+ @p
+ Even the fully-optimized version of our toy Scala.js app are pretty large. There are some factors that mitigate the large size of these executables:
+
+ @ul
+ @li
+ A large portion of this 104k is the Scala standard library, and so the size of the compiled blob does not grow that fast as your program grows. For example, while this ~50 line application is 104k, a @lnk("much larger ~2000 line application", "https://github.com/lihaoyi/roll") is only 288k.
+ @li
+ This size is pre-@lnk("gzip", "http://en.wikipedia.org/wiki/Gzip"), and most webservers serve their contents compressed via gzip to reduce the download size. Gzip cuts the actual download size down to 28k, which is more acceptable.
+ @li
+ You will likely have other portions of the page that are of similar size: e.g. @lnk("JQuery", "http://jquery.com/") is extremely popular, and weights in at a comparable 32kb minified and gzipped, while @lnk("React.js", "http://facebook.github.io/react/downloads.html") weighs in at a cool 150kb gzipped. Scala.js arguably provides more than either of these libraries.
+
+ @p
+ Regardless, there is ongoing work to shrink the size of these executables. If you want to read more about this, check out the section on @sect.ref("The Compilation Pipeline") to learn about what we currently do to crunch the executables down.
+
+ @hr
+
+ @p
+ In general, all the output of the Scala.js compiler is bundled up into the @code{example-fastopt.js} and @code{example-opt.js} files. As a first approximation, these files can be included directly on a HTML page (as we have here, with @code{index-dev.html} and @code{index-opt.html}) and published together as a working web app. Even zipping them up and emailing them to a friend is sufficient to give someone a working, live version of your hard work!
+
+ @p
+ More advanced users would want to integrate them into their build process or serve them from a web server, all of which is entirely possible. You just need to run the Scala.js compiler and place the output @code{.js} file somewhere your web server can pick it up, e.g. in some static-resource folder. We cover an example setup of this with a Scala webserver in our chapter @sect.ref("Integrating Client-Server").
+
+@sect{Recap}
+
+ @p
+ If you've made it this far, you've downloaded, made modifications to, and published a toy Scala.js application. At the same time, we've gone over many of the key concepts in the Scala.js development process:
+
+ @ul
+ @li
+ Getting a Scala.js application
+ @li
+ Building it and seeing it work in the browser
+ @li
+ Made modifications to it to see it update
+ @li
+ Examined the source code to try and understand what it's doing
+ @li
+ Examined the output code, at two levels of optimization, to see how the Scala.js compiler works
+ @li
+ Packaged the application in a form that can be easily published online
+
+ @p
+ Hopefully this gives a good sense of the workflow involved in developing a Scala.js application end-to-end, as well as a feel for the magic involved in the compilation process. Nevertheless, we have barely written any Scala.js code itself!
+
+ @p
+ Since you have a working development environment set up, you should take this time to poke around what you can do with our small Sierpinski-Triangle drawing app. Possible exercises include:
+
+ @ul
+ @li
+ Javascript includes APIs for @lnk("getting the size of the window", "http://stackoverflow.com/questions/1248081/get-the-browser-viewport-dimensions-with-javascript") and @lnk("changing the size of a canvas", "http://stackoverflow.com/questions/9251480/set-canvas-size-using-javascript"). These Javascript APIs are available in Scala.js, and we've already used some of them in the course of this example. Try making the Canvas full-screen, and re-positioning the corners of the triangle to match.
+ @li
+ The @lnk.dom.CanvasRenderingContext2D has a bunch of methods on it that can be used to draw things. Here we only draw 1x1 rectangles to put points on the canvas; try modifying the code to make it draw something else.
+ @li
+ We've looked at the @code{master} branch of @code{workbench-example-app}, but this project also has several other branches showing off different facets of Scala.js: @lnk("dodge-the-dots", "https://github.com/lihaoyi/workbench-example-app/tree/dodge-the-dots") and @lnk("space-invaders", "https://github.com/lihaoyi/workbench-example-app/tree/space-invaders") are both interesting branches worth playing with as a beginner. Check them out!
+ @li
+ Try publishing the output code somewhere. You only need @code{example-opt.js} and @code{index-opt.html}; try putting them somewhere online where the world can see it.
+
+ @p
+ When you're done poking around our toy web application, read on to the next chapter, where we will explore making something more meaty using the Scala.js toolchain!
diff --git a/book/src/main/scalatex/handson/PublishingModules.scalatex b/book/src/main/scalatex/handson/PublishingModules.scalatex
new file mode 100644
index 0000000..395ead9
--- /dev/null
+++ b/book/src/main/scalatex/handson/PublishingModules.scalatex
@@ -0,0 +1,150 @@
+@import book.BookData._
+@p
+ We've spent several chapters exploring the experience of making web apps using Scala.js, but any large application (web or not!) likely relies on a host of libraries in order to implement large chunks of its functionality. Ideally these libraries would be re-usable, and can be shared among different projects, teams or even companies.
+
+@p
+ Not all code is developed in the browser. Maybe you want to run simple snippets of Scala.js which don't interact with the browser at all, and having to keep a browser open is an overkill. Maybe you want to write unit tests for your browser-destined code, so you can verify that it works without firing up Chrome. Maybe it's not a simple script but a re-distributable library, and you want to run the same command-line unit tests on both Scala.js and Scala-JVM to verify that the behavior is identical. This chapter will go through all these cases.
+
+
+@sect{A Simple Cross-Built Library}
+
+ @p
+ As always, we will start with an example: in this case a toy library whose sole purpose in life is to take a series of timestamps (milliseconds UTC) and format them into a single, newline-delimited string. This is what the project layout looks like:
+
+ @hl.sh
+ $ tree
+ .
+ ├── build.sbt
+ ├── project/build.sbt
+ └── library
+    ├── js/src/main/scala/simple/Platform.scala
+    ├── jvm/src/main/scala/simple/Platform.scala
+    └── shared/src/main/scala/simple/Simple.scala
+
+ @p
+ As you can see, we have three main places where code lives: @code{js/} is where Scala-JS specific code lives, @code{jvm/} for Scala-JVM specific code, and @code{shared/} for code that is common between both platforms. Depending on your project, you may have more or less code in the @code{shared/} folder: a mostly-the-same cross-compiled module may have most or all its code in @code{shared/} while a @sect.ref("Integrating Client-Server", "client-server web application") would have lots of client/server js/jvm-specific code.
+
+ @sect{Build Configuration}
+ @p
+ From the bash shell in the project root. Let's take a look at the various files that make up this project. First, the @code{build.sbt} files:
+
+ @hl.ref(wd/'examples/'crossBuilds/'simple/'project/"build.sbt")
+
+ @p
+ The @code{project/build.sbt} file is uneventful: it simply includes the Scala.js SBT plugin. However, the @code{build.sbt} file is a bit more interesting:
+
+ @hl.ref(wd/'examples/'crossBuilds/'simple/"build.sbt")
+
+ @p
+ Unlike the equivalent @code{build.sbt} files you saw in earlier chapters, this does not simply enable the @hl.scala{ScalaJSPlugin} to the root project. Rather, it uses the @hl.scala{crossProject} function provided by the Scala.js plugin to set up two projects: one in the @code{app/js/} folder and one in the @code{jvm/} folder. We also have places to put settings related to either the JS side, the JVM side, or both. In this case, we add a dependency on @lnk("uTest", "https://github.com/lihaoyi/utest"), which we will use as the test framework for our library. Note how we use triple @hl.scala{%%%} to indicate that we're using the platform-specific version of uTest, such that the Scala.js or Scala-JVM version will be properly pulled in when compiling for each platform.
+
+ @sect{Source Files}
+ @val simple = wd/'examples/'crossBuilds/'simple
+ @p
+ Now, let's look at the contents of the @code{.scala} files that make up the meat of this project:
+
+ @hl.ref(simple/'library/'shared/'src/'main/'scala/'simple/"Simple.scala")
+
+ @p
+ In @code{Simple.scala} we have the shared, cross-platform API of our library: a single @hl.scala{object} with a single method @hl.scala{def} which does what we want, which can then be used in either Scala.js or Scala-JVM. In general, you can put as much shared logic here as you want: classes, objects, methods, anything that can run on both Javascript and on the JVM. We're chopping off the last 5 characters (the milliseconds) to keep the formatted dates slightly less verbose.
+
+ @p
+ However, when it comes to actually formatting the date, we have a problem: Javascript and Java provide different utilities for formatting dates! They both let you format them, but they provide different APIs. Thus, to do the formatting of each individual date, we call out to the @hl.scala{Platform.format} function, which is implemented twice: once in @code{js/} and once in @code{jvm/}:
+
+ @split
+ @half
+ @hl.ref(simple/'library/'js/'src/'main/'scala/'simple/"Platform.scala")
+
+ @half
+ @hl.ref(simple/'library/'jvm/'src/'main/'scala/'simple/"Platform.scala")
+
+ @p
+ In the @code{js/} version, we are using the Javascript @hl.js{Date} object to take the millis and do what we want. In the @code{jvm/} version, we instead use @hl.scala{java.text.SimpleDateFormat} with a custom formatter (The syntax is defined @lnk("here", "http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html")).
+
+ @p
+ Again, you can put as much platform-specific logic in these files as you want, to account for differences in the available APIs. Maybe you want to use @lnk.dom.JSONparse for parsing JSON blobs in @code{js/}, but @lnk("Jackson", "http://jackson.codehaus.org/") or @lnk("GSON", "https://code.google.com/p/google-gson/") for parsing them in @code{jvm/}.
+
+ @sect{Running the Module}
+ @hl.sh
+ > ;libraryJS/test ;libraryJVM/test
+ [info] Compiling 1 Scala source to library/js/target/scala-2.10/test-classes...
+ [info] ---------------------------Results---------------------------
+ [info] simple.SimpleTest Success
+ [info] format Success
+ [info] nil Success
+ [info] timeZero Success
+ [info] zero Success
+ [info] 0
+ [info]
+ [info] Tests: 5
+ [info] Passed: 5
+ [info] Failed: 0
+ [success] Total time: 12 s, completed Feb 4, 2015 8:44:49 AM
+ [info] Compiling 1 Scala source to library/jvm/target/scala-2.10/test-classes...
+ [info] 1/5 simple.SimpleTest.format.nil Success
+ [info] 2/5 simple.SimpleTest.format.timeZero Success
+ [info] 3/5 simple.SimpleTest.format Success
+ [info] 4/5 simple.SimpleTest.zero Success
+ [info] 0.0
+ [info] 5/5 simple.SimpleTest Success
+ [info] ---------------------------Results---------------------------
+ [info] simple.SimpleTest Success
+ [info] format Success
+ [info] nil Success
+ [info] timeZero Success
+ [info] zero Success
+ [info] 0.0
+ [info]
+ [info] Tests: 5
+ [info] Passed: 5
+ [info] Failed: 0
+ [success] Total time: 2 s, completed Feb 4, 2015 8:44:51 AM
+
+ @p
+ As you can see, both runs printed the same results, modulo three things:
+
+ @ul
+ @li
+ The @code{"Compiling 1 Scala source to..."} line, which tells us that both JS and JVM versions are being compiled.
+ @li
+ The time taken: the second run is instant while the first takes eleven seconds! This is because by default we run on @lnk.misc.Rhino, which is a simple interpreter hundreds of times slower than running code natively on the JVM.
+ @li
+ In Scala-JVM the double 1.0 is printed as @code{1.0}, while in Scala.js it's printed as @code{1}. This is one of a small number of differences between Scala.js and Scala-JVM, and verifies that we are indeed running on both platforms!
+
+ @p
+ Apart from running each sub-project manually as we did above, you can also simply hit @code{test} and SBT will run tests for both
+
+@sect{Further Work}
+ @p
+ You've by this point set up a basic cross-building Scala.js/Scala-JVM project! If you wish, you can do more things with this project you've set up:
+
+ @ul
+ @li
+ Flesh it out! Currently this module only does a single, trivial thing. If you've done any web development before, I'm sure you can find some code snippet, function or algorithm that you'd like to share between client and server. Try implementing it in the @code{shared/} folder to be usable in both Scala.js and Scala-JVM
+ @li
+ Publish it! Both @code{sbt publishLocal} and @code{sbt publishSigned} work on this module, for publishing either locally, Maven Central via Sonatype, or Bintray. Running the command bare should be sufficient to publish both the @code{js} or @code{jvm} projects, or you can also specify which one e.g. @code{jvm/publishLocal} to publish only one subproject.
+ @li
+ Cross-cross build it! You can use @hl.scala{crossScalaVersions} in your @hl.scala{crossProject} to build a library that works across all of {Scala.js, Scala-JVM} X {2.10, 2.11}. Many existing libraries, such as @lnk("Scalatags", "https://github.com/lihaoyi/scalatags") or @lnk("uTest", "https://github.com/lihaoyi/utest") are published like that.
+
+ @p
+ Now that you've gotten your code cross-compiling to Scala.js/Scala-JVM, the sky's the limit in what you can do. In general, although a large amount of your Scala-JVM code @i{does} deal with files or networks or other Scala-JVM-speciic functionality, in most applications there is a large library of helpers which don't. These could easily be packaged up into a cross-platform library and shared with your front-end Scala.js (or even pure-Javascript!) code.
+
+@sect{Other Testing Libraries}
+ @p
+ You can also try using a different testing library. While uTest was the first Scala.js testing library, it is definitely not the last! Here are a few alternatives worth trying:
+
+ @ul
+ @li
+ @lnk("Minitest", "https://github.com/monifu/minitest")
+ @li
+ @lnk("zCheck", "https://github.com/InTheNow/zcheck")
+ @li
+ @lnk("oTest", "https://github.com/cgta/otest")
+ @li
+ @lnk("Greenlight", "https://github.com/greencatsoft/greenlight")
+
+ @p
+ These (and others) are built and maintained by members of the community, so if one of them does not fit your tastes, it is worth trying the others.
+
+ @p
+ Note that you cannot use @lnk("Scalatest", "http://www.scalatest.org/") or @lnk("Specs2", "http://etorreborre.github.io/specs2") in Scala.js. Despite the popularity of those libraries, they depend on too many Java-specific details of Scala-JVM to be easily ported to Scala.js. Thus you'll have to use one of the (relatively new) libraries which supports Scala.js, such as uTest or those above.
diff --git a/book/src/main/scalatex/handson/WebPage.scalatex b/book/src/main/scalatex/handson/WebPage.scalatex
new file mode 100644
index 0000000..cc232f2
--- /dev/null
+++ b/book/src/main/scalatex/handson/WebPage.scalatex
@@ -0,0 +1,269 @@
+@import book.BookData._
+
+@p
+ Most web applications aren't neat little games which live on a single canvas: they are large, structured HTML pages, which involve displaying data (whether from the user or from the web) in multiple ways, while allowing the user to make changes to the data that can be saved back to whatever remote web-service/database it came from.
+
+@p
+ At this point, you are already competent at using Scala.js to make basic, self-contained canvas applications. In this chapter, we will cover how to use Scala.js to build the sort of interactive-web-pages that make up the bulk of the modern-day internet. We'll cover how to use powerful libraries that turn front-end development form the typical fragile-mess into a structured, robust piece of software.
+
+@val webpage = wd/'examples/'demos/'src/'main/'scala/'webpage
+
+@sect{Hello World: HTML}
+
+ @p
+ The most basic way of building interactive web pages using Scala.js is to use the Javascript APIs to blat HTML strings directly into some container @hl.xml{<div>} or @hl.xml{<body>}. This approach works, as the following code snippet demonstrates:
+
+ @split
+ @more
+ @hl.ref(webpage/"HelloWorld0.scala")
+
+ @less
+ @book.BookData.example(div, "webpage.HelloWorld0().main")
+
+ @p
+ 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.js{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.js{document.getElementById} to pick a @hl.xml{<div>} rather than the @hl.xml{<canvas>} we were using in the previous chapter.
+
+ @p
+ This approach works, as the above example shows, but has a couple of disadvantages:
+
+ @ul
+ @li
+ It is untyped: it is easy to accidentally mistype something, and result in malformed HTML. A typo such as @hl.xml{<dvi>} would go un-noticed at build-time. Depending on where the typo happens, it could go un-noticed until the application is deployed, causing subtle bugs that only get resolved much later.
+ @li
+ It is insecure: @lnk("Cross-site Scripting", "http://en.wikipedia.org/wiki/Cross-site_scripting") is a real thing, and it is easy to forget to escape the values you are putting into your HTML strings. Above they're constants like @hl.scala{"dog"}, but if they're user-defined, you may not notice there is a problem until something like @hl.scala{"<script>...</script>"} sneaks through and your users' accounts & data is compromised.
+
+ @p
+ There are more, but we won't go deep into the intricacies of these problems. Suffice to say it makes mistakes easy to make and hard to catch, and we have something better...
+
+@sect{Scalatags}
+ @p
+ @lnk("Scalatags", "https://github.com/lihaoyi/scalatags") is a cross-platform Scala.js/Scala-JVM library that is designed to generate HTML. To use Scalatags, you need to add it as a dependency to your Scala.js SBT project, in the @code{build.sbt} file:
+
+ @hl.ref(wd/'examples/'demos/"build.sbt", "scalatags", "")
+
+ @p
+ With that, the above snippet of code re-written using Scalatags looks as follows:
+
+ @split
+ @more
+ @hl.ref(webpage/"HelloWorld1.scala")
+
+ @less
+ @book.BookData.example(div, "webpage.HelloWorld1().main")
+
+ @p
+ Scalatags has some nice advantages over plain HTML: it's type-safe, so typos like @hl.scala{dvi} get caught at compile-time. It's also secure, such that you don't need to worry about script-tags in strings or similar. The @lnk("Scalatags Readme", "https://github.com/lihaoyi/scalatags#scalatags") elaborates on these points and other advantages. As you can see, it takes just 1 import at the top of the file to bring it in scope, and then you can use all of Scalatags' functionality.
+
+ @p
+ The Scalatags github page has @lnk("comprehensive documentation", "https://github.com/lihaoyi/scalatags#hello-world") on how to express all manner of HTML fragments using Scalatags, so anyone who's familiar with how HTML works can quickly get up to speed. Instead of a detailed listing, we'll walk through some interactive examples to show Scalatags in action!
+
+ @sect{User Input}
+ @split
+ @more
+ @hl.ref(webpage/"Inputs.scala", "val box")
+
+ @less
+ @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.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.
+
+ @sect{Re-rendering}
+ @p
+ Let's look at a slightly longer example. While above we spliced small snippets of text into the DOM, here we are going to re-render entire sections of HTML! The goal of this little exercise is to make a filtering search-box: starting from a default list of items, narrow it down as the user enters text into the box.
+
+ @p
+ To begin with, let's define our list of items: Fruits!
+
+ @hl.ref(webpage/"Search0.scala", "val listings", "def")
+
+ @p
+ Next, let's think about how we want to render these fruits. One natural way would be as a list, which in HTML is represented by a @hl.xml{<ul>} with @hl.xml{<li>}s inside of it if we wanted the list to be unordered. We'll make it a @hl.scala{def}, because we know up-front we're going to need to re-render this listing as the search query changes. Lastly, we know we want 1 list item for each fruit, but only if the fruit starts with the search query.
+
+ @hl.ref(webpage/"Search0.scala", "def renderListings", "lazy val")
+
+ @p
+ Using a @hl.scala{for}-loop with a filter inside the Scalatags fragment is just normal Scala, since you can nest arbitrary Scala expressions inside a Scalatags snippet. In this case, we're converting both the fruit and the search query to lower case so we can compare them case-insensitively.
+
+ @p
+ Lastly, we just need to define the input box and output-container (as we did earlier), set the @lnk.dom.onkeyup event handler, and place it in a larger fragment, and then into our target:
+
+ @split
+ @more
+ @hl.ref(webpage/"Search0.scala", "val output")
+
+ @less
+ @example(div, "webpage.Search0().main")
+
+ @p
+ And there you have it! A working search box. This is a relatively self-contained example: all the items its searching are available locally, no Ajax calls, and there's no fancy handling of the searched items. If we want to, for example, highlight the matched section of each fruit's name, we can modify the @hl.scala{def renderListings} call to do so:
+
+ @split
+ @more
+ @hl.ref(webpage/"Search1.scala", "def renderListings", "lazy val")
+
+ @less
+ @example(div, "webpage.Search1().main")
+
+ @p
+ Here, instead of sticking the name of the matched fruits directly into the @hl.scala{li}, we instead first split off the part which matches the query, and then highlght the first section yellow. Easy!
+
+ @hr
+
+ @p
+ Hopefully this has given you a good overview of how to do things using Scala.js and Scalatags. I won't go too deep into the various ways you can use Scalatags: the @lnk("documentation", "https://github.com/lihaoyi/scalatags") should cover most of it. Now that you've gone through this experience, it's worth re-iterating a few things you've probably already noticed about Scalatags
+
+ @ul
+ @li
+ It's safe! If you make a trivial syntactic mistake, the compiler will catch it, because Scalatags is plain Scala. Try it!
+ @li
+ It's composable! You can easily define fragments and assign them to variables, to be used later. You can break apart large Scalatags fragments the same way you break apart normal code, avoiding the huge monolithic HTML templates that are common in other templating systems.
+ @li
+ It's Scala! You have the full power of the Scala language to write your fragments. No need to learn special syntax/cases for conditionals or repetitions: you can use plain-old-Scala @hl.scala{if}-@hl.scala{else}s, @hl.scala{for}-loops, etc.
+
+ @p
+ Now that you've gotten a quick overview of the kinds of things you can do with Scalatags, let's move on to the next section of our hands-on tutorial...
+
+@sect{Using Web Services}
+
+ @p
+ One half of the web application faces forwards towards the user, managing and rendering HTML or Canvas for the user to view and interact with. Another half faces backwards, talking to various web-services or databases which turn the application from a standalone-widget into part of a greater whole. We've already seen how to make the front half, let's now talk about working with the back half.
+
+ @sect{Raw Javascript}
+ @split
+ @more
+ @hl.ref(webpage/"Weather0.scala", "val xhr")
+
+ @less
+ @example(div(height:="400px"), "webpage.Weather0().main")
+ @p
+ The above snippet of code uses the raw Javascript Ajax API in order to make a request to @lnk("openweathermap.org", "http://openweathermap.org/"), to get the weather data for the city of Singapore as a JSON blob. The part of the API that we'll be using is documented @lnk("here", "http://openweathermap.org/current"), and if you're interested you can read all about the various options that they provide. For now, we're unceremoniously dumping it in a @hl.scala{pre} so you can see the raw response data.
+
+ @p
+ As you can see, using the raw Javascript API to make the Ajax call looks almost identical to actually doing this in Javascript, shown below:
+
+ @split
+ @more
+ @hl.ref(wd/'examples/'demos/'src/'main/'resources/'webpage/"weather.js", "var xhr")
+
+ @less
+ @example(div, "WeatherJs")
+
+ @p
+ The primary syntactic differences are:
+
+ @ul
+ @li
+ @hl.scala{val}s for immutable data v.s. mutable @hl.js{var}s.
+ @li
+ @hl.scala("=>") v.s. @hl.js{function} to define the callback.
+ @li
+ Scalatags' @hl.scala{pre} v.s. @hl.js{document.createElement("pre")}
+
+ @p
+ Overall, they're pretty close, which is a common theme in Scala.js: using Javascript APIs in Scala.js is often as seamless and easy as using them in Javascript itself, and it often looks almost identical.
+
+ @sect{dom.extensions}
+ @p
+ Although the Javascript XMLHttpRequest API is workable, it's kind of awkward and clunky compared to what you're used to in Scala. We create a half-baked object, set some magic properties, and call a magic function, which all has to be done in the correct order or it won't work.
+
+ @p
+ With Scala.js, we provide a simpler API that is more clearly functional. First, you need to import some things into scope:
+
+ @hl.ref(webpage/"Weather1.scala", "import dom", "val url =")
+
+ @p
+ The first import brings in Scala adapters to several DOM APIs, which allow you to use them more idiomatically from Scala. The second brings in an implicit @hl.scala{scala.concurrent.ExecutionContext} that we'll need to run our asynchronous operations.
+
+ @p
+ Then we need the code itself:
+
+ @split
+ @more
+ @hl.ref(webpage/"Weather1.scala", "val url")
+
+ @less
+ @example(div(height:="400px", overflow:="scroll"), "webpage.Weather1().main")
+
+ @p
+ A single call to @hl.scala{Ajax.get(...)}, with the URL, and we receive a @hl.scala{scala.concurrent.Future} that we can use to get access to the result when ready. Here we're just using it's @hl.scala{onSuccess}, but we could use it in a for-comprehension, with @lnk("Scala Async", "https://github.com/scala/async"), or however else we can use normal @hl.scala{Future}s
+
+ @sect{Parsing the Data}
+ @p
+ We've taken the data-dump from OpenWeatherMap in three different ways, but there's still something missing: we need to actually parse the JSON data to make use of it! Most people don't use their JSON data as strings but as structured documents, querying and extracting only the bits we need.
+
+ @p
+ First, let's make the call prettyprint the document, so at least we can see what it contains:
+
+ @split
+ @more
+ @hl.ref(webpage/"Weather2.scala", "Ajax.get")
+
+ @less
+ @example(div(height:="400px"), "webpage.Weather2().main")
+
+ @p
+ We do this by taking @hl.scala{xhr.responseText} and putting it through both @hl.scala{JSON.parse} and @hl.scala{JSON.stringify}, passing in a @hl.scala{space} argument to tell @hl.scala{JSON.stringify} to spread it out nicely.
+
+ @p
+ Now that we've pretty-printed it, we can immediately see what data it contains and which part of the data we want. Let's change the previous example's @hl.scala{onSuccess} call to extract the @hl.scala{weather}, @hl.scala{temp} and @hl.scala{humidity} and put them in a nice, human-friendly format for us to enjoy:
+
+ @split
+ @more
+ @hl.ref(webpage/"Weather3.scala", "Ajax.get")
+
+ @less
+ @example(div(height:="400px", overflow:="scroll"), "webpage.Weather3().main")
+
+ @p
+ First we parse the incoming response, extract a bunch of values from it, and then stick it in a Scalatags fragment for us to see. Note how we can use the names of the attributes e.g. @hl.scala{json.name} even though @hl.scala{name} is a dynamic property which you can't be sure exists: this is because @hl.scala{json} is of type @hl.scala{js.Dynamic}, which allows us to refer to arbitrary parameters and methods on the underlying object without type-checking.
+
+ @p
+ Calls on @hl.scala{js.Dynamic} resolve directly to javascript property/method references, and will fail at run-time with an exception if used wrongly. This is also why we need to call @hl.scala{.toString} or @hl.scala{.asInstanceOf}on the values before use: without these casts, the compiler can't be sure what kind of value is underneath the @hl.scala{js.Dynamic} type, and so we have to provide it the guarantee that it is what it needs.
+
+@sect{Tying it together: Weather Search}
+ @p
+ At this point we've made a small app that allows us to search from a pre-populated list of words, as well as a small app that lets us query a remote web-service to find the weather in Singapore. The natural thing to do is to put these things together to make a app that will let us search from a list of countries and query the weather in any country we desire. Let's start!
+
+ @hl.ref(webpage/"WeatherSearch.scala", "lazy val box", "def fetchWeather")
+
+ @p
+ This sets up the basics: an input box, an output div, and sets an @hl.scala{onkeyup} that fetches the weather data each time you hit a key. It then renders all these components and sticks them into the @hl.scala{target} div. This is basically the same stuff we saw in the early examples, with minor tweaks e.g. adding a @hl.scala{maxHeight} and @hl.scala{overflowY:="scroll"} to the @hl.scala{output} box in case the output is too large. Whenever we enter something in the box, we call the function @hl.scala{fetchWeather}, which is defined as:
+
+ @hl.ref(webpage/"WeatherSearch.scala", "def fetchWeather", "def showResults")
+
+ @p
+ This is where the actual data fetching happens. It's relatively straightforward: we make an @hl.scala{Ajax.get} request, @hl.scala{JSON.parse} the response, and feed it into the callback function. We're using a slightly different API from earlier: we now have the @hl.scala{"type=like"} flag, which is documented in the @lnk("OpenWeatherMap API docs", "http://openweathermap.org/current#other") to return multiple results for each city whose name matches your query.
+
+ @p
+ Notably, before we re-render the results, we check whether the @hl.scala{query} that was passed in is the same value that's in the @hl.scala{box}. This is to prevent a particularly slow ajax call from finishing out-of-order, potentially stomping over the results of more recent searches. We also check whether the @hl.scala{.list: js.Dynamic} property we want is an instance of @hl.scala{js.Array}: if it isn't, it means we don't have any results to show, and we can skip the whole render-output step.
+
+ @hl.ref(webpage/"WeatherSearch.scala", "def showResults")
+
+ @p
+ Here is the meat and potatoes of this program: every time it gets called with an array of weather-data, we iterate over the cities in that array. It then does a similar sort of data-extraction that we did earlier, putting the results into the @hl.scala{output} div we defined above, including highlighting.
+
+ @example(div, "webpage.WeatherSearch().main")
+
+ @p
+ And that's the working example! Try searching for cities like "Singapore" or "New York" or "San Francisco" and watch as the search narrows as you enter more characters into the text box. Note that the OpenWeatherMap API limits ambiguous searches to about a dozen results, so if a city doesn't turn up in a partial-search, try entering more characters to narrow it down.
+
+@sect{Interactive Web Pages Recap}
+ @p
+ In this chapter, we've explored the basics of how you can use Scala.js to build interactive web pages. The two main contributions are using Scalatags to render HTML in a concise, safe way, and making Ajax calls to external web services. We combined these two capabilities in a small weather-search app that let a user interactively search for the weather in different cities around the world.
+ @p
+ Some things you may have noticed in the process:
+
+ @ul
+ @li
+ Using Scalatags to render HTML fragments, and managing them at runtime with callbacks and getting/setting properties, is really quite nice
+ @li
+ Using @hl.scala{new dom.XMLHttpRequest} to make web requests feels just like the Javascript code to do so
+ @li
+ Using @hl.scala{Ajax.get(...)} and working with the resultant : @hl.scala{Future} feels a lot cleaner than directly using the Javascript API
+
+ @p
+ You're at this point reasonably pro