summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-11-20 02:07:02 -0800
committerLi Haoyi <haoyi@dropbox.com>2014-11-20 02:07:02 -0800
commit7ca2e125c17bd541340bce55623bd40cf88ce64f (patch)
tree9d79964209255e539fa83275466f9ea32c01db8d /examples
parentefc1b9cfd9c04b8d7f8cf0fb35e77bcb94a25a6e (diff)
downloadhands-on-scala-js-7ca2e125c17bd541340bce55623bd40cf88ce64f.tar.gz
hands-on-scala-js-7ca2e125c17bd541340bce55623bd40cf88ce64f.tar.bz2
hands-on-scala-js-7ca2e125c17bd541340bce55623bd40cf88ce64f.zip
Scala-async chapter works
Diffstat (limited to 'examples')
-rw-r--r--examples/demos/build.sbt6
-rw-r--r--examples/demos/src/main/scala/advanced/Async.scala120
-rw-r--r--examples/demos/src/main/scala/advanced/BasicRx.scala80
-rw-r--r--examples/demos/src/main/scala/advanced/Futures.scala13
-rw-r--r--examples/demos/src/main/scala/scrollmenu/Controller.scala3
5 files changed, 221 insertions, 1 deletions
diff --git a/examples/demos/build.sbt b/examples/demos/build.sbt
index fb79984..5b55829 100644
--- a/examples/demos/build.sbt
+++ b/examples/demos/build.sbt
@@ -14,4 +14,8 @@ libraryDependencies += "com.lihaoyi" %%% "upickle" % "0.2.5"
libraryDependencies += "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6"
-libraryDependencies += "com.scalatags" %%% "scalatags" % "0.4.2" \ No newline at end of file
+libraryDependencies += "com.scalatags" %%% "scalatags" % "0.4.2"
+
+libraryDependencies += "com.scalarx" %%% "scalarx" % "0.2.6"
+
+libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "0.9.2" \ No newline at end of file
diff --git a/examples/demos/src/main/scala/advanced/Async.scala b/examples/demos/src/main/scala/advanced/Async.scala
new file mode 100644
index 0000000..481e80e
--- /dev/null
+++ b/examples/demos/src/main/scala/advanced/Async.scala
@@ -0,0 +1,120 @@
+package advanced
+
+import org.scalajs.dom
+import concurrent._
+import async.Async._
+import scala.scalajs.js.annotation.JSExport
+import scalajs.concurrent.JSExecutionContext.Implicits.queue
+
+@JSExport
+object Async {
+ def init(canvas: dom.HTMLCanvasElement) = {
+ val renderer = canvas.getContext("2d")
+ .asInstanceOf[dom.CanvasRenderingContext2D]
+
+ canvas.style.backgroundColor = "#f8f8f8"
+ canvas.height = canvas.parentElement.clientHeight
+ canvas.width = canvas.parentElement.clientWidth
+
+ renderer.lineWidth = 5
+ renderer.strokeStyle = "red"
+ renderer.fillStyle = "cyan"
+ renderer
+ }
+ @JSExport
+ def main(canvas: dom.HTMLCanvasElement) = {
+ val renderer = init(canvas)
+ // async
+ def rect = canvas.getBoundingClientRect()
+
+ type ME = dom.MouseEvent
+ val mousemove =
+ Channel[ME](canvas.onmousemove = _)
+ val mouseup =
+ Channel[ME](canvas.onmouseup = _)
+ val mousedown =
+ Channel[ME](canvas.onmousedown = _)
+
+ async{
+ while(true){
+ val start = await(mousedown())
+ renderer.beginPath()
+ renderer.moveTo(
+ start.clientX - rect.left,
+ start.clientY - rect.top
+ )
+
+ var res = await(mousemove | mouseup)
+ while(res.`type` == "mousemove"){
+ renderer.lineTo(
+ res.clientX - rect.left,
+ res.clientY - rect.top
+ )
+ renderer.stroke()
+ res = await(mousemove | mouseup)
+ }
+
+ renderer.fill()
+ await(mouseup())
+ renderer.clearRect(0, 0, 1000, 1000)
+ }
+ }
+ }
+ @JSExport
+ def main0(canvas: dom.HTMLCanvasElement) = {
+ val renderer = init(canvas)
+ // traditional
+ def rect = canvas.getBoundingClientRect()
+
+ var dragState = 0
+
+ canvas.onmousemove ={(e: dom.MouseEvent) =>
+ if (dragState == 1) {
+ renderer.lineTo(
+ e.clientX - rect.left,
+ e.clientY - rect.top
+ )
+ renderer.stroke()
+ }
+ }
+ canvas.onmouseup = {(e: dom.MouseEvent) =>
+ if(dragState == 1) {
+ renderer.fill()
+ dragState = 2
+ }else if (dragState == 2){
+ renderer.clearRect(0, 0, 1000, 1000)
+ dragState = 0
+ }
+ }
+ canvas.onmousedown ={(e: dom.MouseEvent) =>
+ if (dragState == 0) {
+ dragState = 1
+ renderer.beginPath()
+ renderer.moveTo(
+ e.clientX - rect.left,
+ e.clientY - rect.top
+ )
+ }
+ }
+ }
+}
+
+case class Channel[T](init: (T => Unit) => Unit){
+ init(update)
+ private[this] var value: Promise[T] = null
+ def apply(): Future[T] = {
+ value = Promise[T]()
+ value.future
+ }
+ def update(t: T): Unit = {
+ if (value != null && !value.isCompleted) value.success(t)
+ }
+ def |(other: Channel[T]): Future[T] = {
+ val p = Promise[T]()
+ for{
+ f <- Seq(other(), this())
+ t <- f
+ } p.trySuccess(t)
+ p.future
+ }
+} \ No newline at end of file
diff --git a/examples/demos/src/main/scala/advanced/BasicRx.scala b/examples/demos/src/main/scala/advanced/BasicRx.scala
new file mode 100644
index 0000000..56b41b0
--- /dev/null
+++ b/examples/demos/src/main/scala/advanced/BasicRx.scala
@@ -0,0 +1,80 @@
+package advanced
+
+import org.scalajs.dom
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExport
+import rx._
+import scalatags.JsDom.all._
+
+@JSExport
+object BasicRx {
+ @JSExport
+ def main(container: dom.HTMLDivElement) = {
+ val txt = Var("")
+ val numChars = Rx{txt().length}
+ val numWords = Rx{
+ txt().split(' ')
+ .filter(_.length > 0)
+ .length
+ }
+
+ val avgWordLength = Rx{
+ txt().count(_ != ' ') * 1.0 / numWords()
+ }
+
+ val txtInput = textarea.render
+ txtInput.onkeyup = (e: dom.Event) => {
+ txt() = txtInput.value
+ }
+
+ container.appendChild(
+ div(
+ txtInput,
+ ul(
+ li("Chars: ", numChars),
+ li("Words: ", numWords),
+ li("Word Length: ", avgWordLength)
+ )
+ ).render
+ )
+ }
+ @JSExport
+ def main2(container: dom.HTMLDivElement) = {
+ val fruits = Seq(
+ "Apple", "Apricot", "Banana", "Cherry",
+ "Mango", "Mangosteen", "Mandarin",
+ "Grape", "Grapefruit", "Guava"
+ )
+ val query = Var("")
+ val txtInput = input.render
+ txtInput.onkeyup = (e: dom.Event) => {
+ query() = txtInput.value
+ }
+
+ val fragments =
+ for(fruit <- fruits) yield Rx {
+ val shown = fruit.toLowerCase
+ .startsWith(query())
+ if (shown) li(fruit)
+ else li(display := "none")
+ }
+
+ container.appendChild(
+ div(
+ txtInput,
+ ul(fragments)
+ ).render
+ )
+ }
+ implicit def rxFrag[T <% Frag](r: Rx[T]): Frag = {
+ def rSafe: dom.Node = span(r()).render
+ var last = rSafe
+ Obs(r, skipInitial = true){
+ val newLast = rSafe
+ js.Dynamic.global.last = last
+ last.parentNode.replaceChild(newLast, last)
+ last = newLast
+ }
+ last
+ }
+}
diff --git a/examples/demos/src/main/scala/advanced/Futures.scala b/examples/demos/src/main/scala/advanced/Futures.scala
new file mode 100644
index 0000000..4035fac
--- /dev/null
+++ b/examples/demos/src/main/scala/advanced/Futures.scala
@@ -0,0 +1,13 @@
+package advanced
+
+import org.scalajs.dom
+
+import scala.scalajs.js.annotation.JSExport
+
+@JSExport
+object Futures {
+ @JSExport
+ def main(container: dom.HTMLDivElement) = {
+
+ }
+}
diff --git a/examples/demos/src/main/scala/scrollmenu/Controller.scala b/examples/demos/src/main/scala/scrollmenu/Controller.scala
index 132a073..119b8d4 100644
--- a/examples/demos/src/main/scala/scrollmenu/Controller.scala
+++ b/examples/demos/src/main/scala/scrollmenu/Controller.scala
@@ -70,6 +70,9 @@ object Controller{
menu.appendChild(
div(cls:="pure-menu pure-menu-open")(
+ a(cls:="pure-menu-heading")(
+ "Contents"
+ ),
list
).render
)