summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-12-28 18:30:51 +0100
committerLi Haoyi <haoyi@dropbox.com>2014-12-28 18:30:51 +0100
commite27f2ba244d0fef1a654da99d8c8a36cfef5a61a (patch)
tree1c025b74acec6ea48f287b0d06186eaa2fbe5a71
parent47495632fb60bb6bdc4b61b3e00333dbe1182e7b (diff)
parenta10f9f097944a2586d2d98fc09a3e43bb77d0250 (diff)
downloadhands-on-scala-js-e27f2ba244d0fef1a654da99d8c8a36cfef5a61a.tar.gz
hands-on-scala-js-e27f2ba244d0fef1a654da99d8c8a36cfef5a61a.tar.bz2
hands-on-scala-js-e27f2ba244d0fef1a654da99d8c8a36cfef5a61a.zip
merged
-rw-r--r--book/src/main/scalatex/book/handson/GettingStarted.scalatex2
-rw-r--r--book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex4
-rw-r--r--book/src/main/scalatex/book/indepth/SemanticDifferences.scalatex2
m---------examples/crossBuilds/clientserver0
-rw-r--r--examples/crossBuilds/clientserver/Procfile1
-rw-r--r--examples/crossBuilds/clientserver/build.sbt38
-rw-r--r--examples/crossBuilds/clientserver/client/shared/main/scala/simple/FileData.scala3
-rw-r--r--examples/crossBuilds/clientserver/client/src/main/scala/simple/Client.scala36
-rw-r--r--examples/crossBuilds/clientserver/project/build.properties1
-rw-r--r--examples/crossBuilds/clientserver/project/build.sbt6
l---------examples/crossBuilds/clientserver/server/shared1
-rw-r--r--examples/crossBuilds/clientserver/server/src/main/scala/simple/Page.scala21
-rw-r--r--examples/crossBuilds/clientserver/server/src/main/scala/simple/Server.scala46
13 files changed, 157 insertions, 4 deletions
diff --git a/book/src/main/scalatex/book/handson/GettingStarted.scalatex b/book/src/main/scalatex/book/handson/GettingStarted.scalatex
index a32ba9e..d2486c2 100644
--- a/book/src/main/scalatex/book/handson/GettingStarted.scalatex
+++ b/book/src/main/scalatex/book/handson/GettingStarted.scalatex
@@ -320,7 +320,7 @@
@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 look 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!
+ 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.
diff --git a/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex b/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
index d49728f..98dccc2 100644
--- a/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
+++ b/book/src/main/scalatex/book/indepth/AdvancedTechniques.scalatex
@@ -76,7 +76,7 @@
Scalatags requires that anything you want to embed in a Scalatags fragment be implicitly convertible to @hl.scala{Frag}; here we are providing one for any Scala.Rx @hl.scala{Rx[T]}s, as long as the @hl.scala{T} provided is itself convertible to a @hl.scala{Frag}. We call @hl.scala{r().render} to extract the "current" value of the @hl.scala{Rx}, and then set up an @hl.scala{Obs} that watches the @hl.scala{Rx}, replacing the previous value with the current one every time its value changes.
@p
- Now that the set-up is out of the way, let's consider a simple HTML widhet that lets you enter text in a @hl.html{<textarea>}, and keeps track of the number of words, characters, and counts how long each word is.
+ Now that the set-up is out of the way, let's consider a simple HTML widget that lets you enter text in a @hl.html{<textarea>}, and keeps track of the number of words, characters, and counts how long each word is.
@split
@more
@@ -284,7 +284,7 @@
@example(canvas, "Async().main")
@p
- We have an @hl.scala{async} block, which contains a while loop. Each round around the loop, we wait for the @hl.scala{mousedown} channel to start the path, waiting for either @hl.scala{mousedown} or @hl.scala{mousedown} (which continues the path or ends it respectively), fill the shape, and then wait for another @hl.scala{mousedown} before clearing the canvas and going again.
+ We have an @hl.scala{async} block, which contains a while loop. Each round around the loop, we wait for the @hl.scala{mousedown} channel to start the path, waiting for either @hl.scala{mousemove} or @hl.scala{mouseup} (which continues the path or ends it respectively), fill the shape, and then wait for another @hl.scala{mousedown} before clearing the canvas and going again.
@p
Hopefully you'd agree that this code is much simpler to read and understand than the previous version. In particular, the control-flow of the code goes from top to bottom in a "natural" fashion, rather than jumping around ad-hoc like in the previous callback-based design.
diff --git a/book/src/main/scalatex/book/indepth/SemanticDifferences.scalatex b/book/src/main/scalatex/book/indepth/SemanticDifferences.scalatex
index ebfd1db..96f3929 100644
--- a/book/src/main/scalatex/book/indepth/SemanticDifferences.scalatex
+++ b/book/src/main/scalatex/book/indepth/SemanticDifferences.scalatex
@@ -1,6 +1,6 @@
@import BookData._
@p
- Although Scala.js tries very hard to maintain compatibility with Scala-JVM, there are some parts where the two platforms differs. This can be roughly grouped into two things: differences in the libraries available,and differences in the language itself. This chapter will cover both of these facets.
+ Although Scala.js tries very hard to maintain compatibility with Scala-JVM, there are some parts where the two platforms differs. This can be roughly grouped into two things: differences in the libraries available, and differences in the language itself. This chapter will cover both of these facets.
@sect{Language Differences}
@sect{Floats are Doubles}
diff --git a/examples/crossBuilds/clientserver b/examples/crossBuilds/clientserver
deleted file mode 160000
-Subproject 8d199942e6ad4c927b825c493c69067d9474a8f
diff --git a/examples/crossBuilds/clientserver/Procfile b/examples/crossBuilds/clientserver/Procfile
new file mode 100644
index 0000000..59ff8a8
--- /dev/null
+++ b/examples/crossBuilds/clientserver/Procfile
@@ -0,0 +1 @@
+web: server/target/universal/stage/bin/server
diff --git a/examples/crossBuilds/clientserver/build.sbt b/examples/crossBuilds/clientserver/build.sbt
new file mode 100644
index 0000000..048df8a
--- /dev/null
+++ b/examples/crossBuilds/clientserver/build.sbt
@@ -0,0 +1,38 @@
+import NativePackagerKeys._
+import utest.jsrunner.JsCrossBuild
+import scalajs.sbtplugin.ScalaJSPlugin._
+import ScalaJSKeys._
+val sharedSettings = Seq(
+ unmanagedSourceDirectories in Compile +=
+ baseDirectory.value / "shared" / "main" / "scala",
+ libraryDependencies ++= Seq(
+ "com.scalatags" %%% "scalatags" % "0.4.2",
+ "com.lihaoyi" %%% "upickle" % "0.2.5"
+ ),
+ scalaVersion := "2.11.4"
+)
+
+lazy val client = project.in(file("client"))
+ .settings(scalaJSSettings:_*)
+ .settings(sharedSettings:_*)
+ .settings(
+ libraryDependencies ++= Seq(
+ "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6"
+ )
+)
+
+lazy val server = project.in(file("server"))
+ .settings(sharedSettings:_*)
+ .settings(packageArchetype.java_application:_*)
+ .settings(
+ libraryDependencies ++= Seq(
+ "io.spray" %% "spray-can" % "1.3.2",
+ "io.spray" %% "spray-routing" % "1.3.2",
+ "com.typesafe.akka" %% "akka-actor" % "2.3.6"
+ ),
+ (resources in Compile) += {
+ (fastOptJS in (client, Compile)).value
+ (artifactPath in (client, Compile, fastOptJS)).value
+ }
+)
+
diff --git a/examples/crossBuilds/clientserver/client/shared/main/scala/simple/FileData.scala b/examples/crossBuilds/clientserver/client/shared/main/scala/simple/FileData.scala
new file mode 100644
index 0000000..d3d2f91
--- /dev/null
+++ b/examples/crossBuilds/clientserver/client/shared/main/scala/simple/FileData.scala
@@ -0,0 +1,3 @@
+package simple
+
+case class FileData(name: String, size: Long) \ No newline at end of file
diff --git a/examples/crossBuilds/clientserver/client/src/main/scala/simple/Client.scala b/examples/crossBuilds/clientserver/client/src/main/scala/simple/Client.scala
new file mode 100644
index 0000000..9b3eda1
--- /dev/null
+++ b/examples/crossBuilds/clientserver/client/src/main/scala/simple/Client.scala
@@ -0,0 +1,36 @@
+package simple
+
+import scalatags.JsDom.all._
+import scalajs.concurrent.JSExecutionContext.Implicits.runNow
+import org.scalajs.dom
+import dom.extensions.Ajax
+import scalajs.js.annotation.JSExport
+
+@JSExport
+object Client extends{
+ @JSExport
+ def main(container: dom.HTMLDivElement) = {
+ val inputBox = input.render
+ val outputBox = ul.render
+ def update() = Ajax.post("/ajax/list", inputBox.value).foreach{ xhr =>
+ val data = upickle.read[Seq[FileData]](xhr.responseText)
+ outputBox.innerHTML = ""
+ for(FileData(name, size) <- data){
+ outputBox.appendChild(
+ li(
+ b(name), " - ", size, " bytes"
+ ).render
+ )
+ }
+ }
+ inputBox.onkeyup = (e: dom.Event) => update()
+ update()
+ container.appendChild(
+ div(
+ h1("File Search"),
+ inputBox,
+ outputBox
+ ).render
+ )
+ }
+} \ No newline at end of file
diff --git a/examples/crossBuilds/clientserver/project/build.properties b/examples/crossBuilds/clientserver/project/build.properties
new file mode 100644
index 0000000..748703f
--- /dev/null
+++ b/examples/crossBuilds/clientserver/project/build.properties
@@ -0,0 +1 @@
+sbt.version=0.13.7
diff --git a/examples/crossBuilds/clientserver/project/build.sbt b/examples/crossBuilds/clientserver/project/build.sbt
new file mode 100644
index 0000000..c24e2b0
--- /dev/null
+++ b/examples/crossBuilds/clientserver/project/build.sbt
@@ -0,0 +1,6 @@
+/*project/build.sbt*/
+addSbtPlugin("org.scala-lang.modules.scalajs" % "scalajs-sbt-plugin" % "0.5.5")
+
+addSbtPlugin("com.lihaoyi" % "utest-js-plugin" % "0.2.4")
+
+addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.7.4")
diff --git a/examples/crossBuilds/clientserver/server/shared b/examples/crossBuilds/clientserver/server/shared
new file mode 120000
index 0000000..f32be42
--- /dev/null
+++ b/examples/crossBuilds/clientserver/server/shared
@@ -0,0 +1 @@
+../client/shared \ No newline at end of file
diff --git a/examples/crossBuilds/clientserver/server/src/main/scala/simple/Page.scala b/examples/crossBuilds/clientserver/server/src/main/scala/simple/Page.scala
new file mode 100644
index 0000000..d657290
--- /dev/null
+++ b/examples/crossBuilds/clientserver/server/src/main/scala/simple/Page.scala
@@ -0,0 +1,21 @@
+package simple
+import scalatags.Text.all._
+
+object Page{
+ val boot =
+ "Client().main(document.getElementById('contents'))"
+ val skeleton =
+ html(
+ head(
+ script(src:="/client-fastopt.js"),
+ link(
+ rel:="stylesheet",
+ href:="https://cdnjs.cloudflare.com/ajax/libs/pure/0.5.0/pure-min.css"
+ )
+ ),
+ body(
+ onload:=boot,
+ div(id:="contents")
+ )
+ )
+}
diff --git a/examples/crossBuilds/clientserver/server/src/main/scala/simple/Server.scala b/examples/crossBuilds/clientserver/server/src/main/scala/simple/Server.scala
new file mode 100644
index 0000000..e9038b5
--- /dev/null
+++ b/examples/crossBuilds/clientserver/server/src/main/scala/simple/Server.scala
@@ -0,0 +1,46 @@
+package simple
+
+import akka.actor.ActorSystem
+import spray.http.{HttpEntity, MediaTypes}
+import spray.routing.SimpleRoutingApp
+
+import scala.util.Properties
+
+object Server extends SimpleRoutingApp{
+ def main(args: Array[String]): Unit = {
+ implicit val system = ActorSystem()
+ val port = Properties.envOrElse("PORT", "8080").toInt
+ startServer("0.0.0.0", port = port){
+ get{
+ pathSingleSlash{
+ complete{
+ HttpEntity(
+ MediaTypes.`text/html`,
+ Page.skeleton.render
+ )
+ }
+ } ~
+ getFromResourceDirectory("")
+ } ~
+ post{
+ path("ajax" / "list"){
+ extract(_.request.entity.asString) { e =>
+ complete {
+ upickle.write(list(e))
+ }
+ }
+ }
+ }
+ }
+ }
+ def list(path: String) = {
+ val (dir, last) = path.splitAt(path.lastIndexOf("/") + 1)
+ val files =
+ Option(new java.io.File("./" + dir).listFiles())
+ .toSeq.flatten
+ for{
+ f <- files
+ if f.getName.startsWith(last)
+ } yield FileData(f.getName, f.length())
+ }
+} \ No newline at end of file