From a33254276bd211bf33be86eeb871ddbfe36fdb47 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 2 Nov 2014 04:57:37 -0800 Subject: Moved `examples` into `examples/demos`, sketched out a simple example cross-module --- book/src/main/scala/book/Utils.scala | 24 ++++++------ book/src/main/scalatex/book/Index.scalatex | 43 +++++++++++----------- book/src/main/scalatex/book/Intro.scalatex | 2 +- .../main/scalatex/book/handson/CanvasApp.scalatex | 18 ++++----- .../scalatex/book/handson/CrossModules.scalatex | 17 ++++++++- .../main/scalatex/book/handson/WebPage.scalatex | 34 ++++++++--------- 6 files changed, 76 insertions(+), 62 deletions(-) (limited to 'book') diff --git a/book/src/main/scala/book/Utils.scala b/book/src/main/scala/book/Utils.scala index 690cee1..d5272a6 100644 --- a/book/src/main/scala/book/Utils.scala +++ b/book/src/main/scala/book/Utils.scala @@ -44,25 +44,25 @@ object Utils{ var indent = 0 - val headers = Seq[(String => scalatags.Text.Tag, Option[Frag => Frag])]( - (h => div(cls:="header")( + val headers = Seq[((String, String) => scalatags.Text.Tag, Option[Frag => Frag])]( + ((h, s) => div(cls:="header")( h1(h), - h2("Writing client-side web applications in Scala") + h2(s) ), Some(f => div(cls:="content", f))), - (h => div(cls:="header")( + ((h, s) => div(cls:="header")( h1(id:=Utils.munge(h), h), br ), None), - (h1(_), None), - (h2(_), None), - (h3(_), None), - (h4(_), None), - (h5(_), None), - (h6(_), None) + (h1(_, _), None), + (h2(_, _), None), + (h3(_, _), None), + (h4(_, _), None), + (h5(_, _), None), + (h6(_, _), None) ) var structure: Node = null - case class sect(name: String){ + case class sect(name: String, subname: String = ""){ indent += 1 val newNode = Node(name, mutable.Buffer.empty) val (headerWrap, contentWrap) = headers(indent-1) @@ -72,7 +72,7 @@ object Utils{ def apply(args: Frag*) = { val wrappedContents = contentWrap.getOrElse((x: Frag) => x)(args) val res = Seq[Frag]( - headerWrap(name)(cls:="content-subhead", id:=munge(name)), + headerWrap(name, subname)(cls:="content-subhead", id:=munge(name)), wrappedContents ) indent -= 1 diff --git a/book/src/main/scalatex/book/Index.scalatex b/book/src/main/scalatex/book/Index.scalatex index a3c77f6..0ff807d 100644 --- a/book/src/main/scalatex/book/Index.scalatex +++ b/book/src/main/scalatex/book/Index.scalatex @@ -1,8 +1,8 @@ -@sect("Hands-on Scala.js") +@sect("Hands-on Scala.js", "Writing client-side web applications in Scala") @div(cls:="pure-g") @div(cls:="pure-u-1 pure-u-md-13-24") - @hl.ref("examples/src/main/scala/Splash.scala", "var x") + @hl.ref("examples/demos/src/main/scala/Splash.scala", "var x") @div(cls:="pure-u-1 pure-u-md-11-24") @canvas(id:="canvas1", display:="block") @@ -17,31 +17,30 @@ @sect("Intro to Scala.js") @Intro.template - @sect("Hands On") - @sect("Getting Started") - @handson.GettingStarted.template + @sect("Getting Started") + @handson.GettingStarted.template - @sect("Making a Canvas App") - @handson.CanvasApp.template + @sect("Making a Canvas App") + @handson.CanvasApp.template - @sect("Interactive Web Pages") - @handson.WebPage.template + @sect("Interactive Web Pages") + @handson.WebPage.template - @sect("Cross-platform Modules") - @handson.CrossModules.template + @sect("Cross-platform Modules") + @handson.CrossModules.template - @sect("Client-Server Integration") - @handson.ClientServer.template + @sect("Client-Server Integration") + @handson.ClientServer.template - @sect("Scala.js in Depth") - @sect("Javascript Interoperability") - @indepth.JavascriptInterop.template +@sect("Scala.js in Depth", "Exploring Scala.js") + @sect("Javascript Interoperability") + @indepth.JavascriptInterop.template - @sect("Scala.js/Scala-JVM Differences") - @indepth.SemanticDifferences.template + @sect("Deviations from Scala-JVM") + @indepth.SemanticDifferences.template - @sect("The Scala.js Compilation Pipeline") - @indepth.CompilationPipeline.template + @sect("The Compilation Pipeline") + @indepth.CompilationPipeline.template - @sect("Scala.js' Design Space") - @indepth.DesignSpace.template \ No newline at end of file + @sect("Scala.js' Design Space") + @indepth.DesignSpace.template \ No newline at end of file diff --git a/book/src/main/scalatex/book/Intro.scalatex b/book/src/main/scalatex/book/Intro.scalatex index b7c5268..4e09d99 100644 --- a/book/src/main/scalatex/book/Intro.scalatex +++ b/book/src/main/scalatex/book/Intro.scalatex @@ -164,7 +164,7 @@ @p After going through this chapter and following along with the exercises, you should have a good sense of how Scala.js works and how it feels building things in Scala.js. You would not be an expert, but you'll know where to get started if you decide to try out Scala.js for your next project. - @sect{Scala.js in Depth} + @sect{In Depth} @p This section of the book will cover lots of content that does not fit in the earlier Hands-On portion of the book. Things that aren't immediately necessary to get something up and running, things that only advanced users would care about, things that you probably don't need to know but you'd like to know out of intellectual curiosity. diff --git a/book/src/main/scalatex/book/handson/CanvasApp.scalatex b/book/src/main/scalatex/book/handson/CanvasApp.scalatex index ba76493..4d0e2ae 100644 --- a/book/src/main/scalatex/book/handson/CanvasApp.scalatex +++ b/book/src/main/scalatex/book/handson/CanvasApp.scalatex @@ -21,7 +21,7 @@ @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("examples/src/main/scala/canvasapp/ScratchPad.scala", "/*setup*/", end = "/*code*/") + @hl.ref("examples/demos/src/main/scala/canvasapp/ScratchPad.scala", "/*setup*/", end = "/*code*/") @p As described earlier, this code uses the @hl.javascript{document.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. @@ -31,7 +31,7 @@ @div(cls:="pure-g") @div(cls:="pure-u-1 pure-u-md-13-24") - @hl.ref("examples/src/main/scala/canvasapp/ScratchPad.scala", "/*code*/") + @hl.ref("examples/demos/src/main/scala/canvasapp/ScratchPad.scala", "/*code*/") @div(cls:="pure-u-1 pure-u-md-11-24") @canvas(id:="canvas2", display:="block") @@ -56,7 +56,7 @@ @p Again, we need roughly the same boilerplate as just now to set up the canvas: - @hl.ref("examples/src/main/scala/canvasapp/Clock.scala", "/*setup*/", "/*code*/") + @hl.ref("examples/demos/src/main/scala/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. @@ -66,7 +66,7 @@ @div(cls:="pure-g") @div(cls:="pure-u-1 pure-u-md-13-24") - @hl.ref("examples/src/main/scala/canvasapp/Clock.scala", "/*code*/") + @hl.ref("examples/demos/src/main/scala/canvasapp/Clock.scala", "/*code*/") @div(cls:="pure-u-1 pure-u-md-11-24") @canvas(id:="canvas3", display:="block") @@ -99,7 +99,7 @@ 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("examples/src/main/scala/canvasapp/FlappyLine.scala", "/*setup*/", end="/*variables*/") + @hl.ref("examples/demos/src/main/scala/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. @@ -108,7 +108,7 @@ 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 some helpers, so you don't have to mess with this stuff unless you really want to. @sect{Defining our State} - @hl.ref("examples/src/main/scala/canvasapp/FlappyLine.scala", "/*variables*/", end="def runDead") + @hl.ref("examples/demos/src/main/scala/canvasapp/FlappyLine.scala", "/*variables*/", end="def runDead") @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. @@ -117,7 +117,7 @@ One notable thing is that we're using a @hl.scala{collection.mutable.Queue} 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("examples/src/main/scala/canvasapp/FlappyLine.scala", "def runLive", "def runDead") + @hl.ref("examples/demos/src/main/scala/canvasapp/FlappyLine.scala", "def runLive", "def runDead") @p The @hl.scala{runLive} function is the meat of Flappy Box. In it, we @@ -137,13 +137,13 @@ @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("examples/src/main/scala/canvasapp/FlappyLine.scala", "def runDead", end="def run") + @hl.ref("examples/demos/src/main/scala/canvasapp/FlappyLine.scala", "def runDead", end="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("examples/src/main/scala/canvasapp/FlappyLine.scala", "def run()") + @hl.ref("examples/demos/src/main/scala/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 @hl.scala{canvas.onclick} handler to make the player jump by tweaking his velocity, and we call @code{setInterval} to run the @hl.scala{run} function every 20 milliseconds. diff --git a/book/src/main/scalatex/book/handson/CrossModules.scalatex b/book/src/main/scalatex/book/handson/CrossModules.scalatex index 30404ce..9b1f62c 100644 --- a/book/src/main/scalatex/book/handson/CrossModules.scalatex +++ b/book/src/main/scalatex/book/handson/CrossModules.scalatex @@ -1 +1,16 @@ -TODO \ No newline at end of file +@p + We've spent several chapters exploring the experience of making web apps using Scala.js, but any large app (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 + In JVM-land, the standard method for distributing these libraries is as @a("Maven Artifacts", href:="http://stackoverflow.com/questions/2487485/what-is-maven-artifact"). These are typically published in a public location such as @a("Maven Central", href:="http://search.maven.org/"), where others can find and download them for use. Typically downloads are done automatically by the build-tool: in Scala-JVM typically this is SBT. +@p + In Javascript-land, there are multiple ways of acquiring dependencies: @a("CommonJS", href:="http://en.wikipedia.org/wiki/CommonJS") and @a("RequireJS/AMD", href:="http://requirejs.org/") are two competing standards with a host of implementations. Historically, a third approach has been most common: the developer would simply download the modules himself, check it into source-control and manually add a @hl.html{