summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-11-11 21:32:25 -0800
committerLi Haoyi <haoyi@dropbox.com>2014-11-11 21:32:25 -0800
commitdab933c342d755086253b1465a04caeeaa2af823 (patch)
tree62019986ef2becf02b9848ed983eadcd4837a5d2 /examples
parent43795c30a7295310b47885b3eacca9fd9af33343 (diff)
downloadhands-on-scala-js-dab933c342d755086253b1465a04caeeaa2af823.tar.gz
hands-on-scala-js-dab933c342d755086253b1465a04caeeaa2af823.tar.bz2
hands-on-scala-js-dab933c342d755086253b1465a04caeeaa2af823.zip
Pure Scala!
Diffstat (limited to 'examples')
-rw-r--r--examples/demos/Controller.scala130
-rw-r--r--examples/demos/build.sbt4
2 files changed, 134 insertions, 0 deletions
diff --git a/examples/demos/Controller.scala b/examples/demos/Controller.scala
new file mode 100644
index 0000000..d27c68e
--- /dev/null
+++ b/examples/demos/Controller.scala
@@ -0,0 +1,130 @@
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSExport
+import org.scalajs.dom
+import org.scalajs.dom.extensions._
+import scala.collection.mutable
+import scalatags.JsDom.all._
+import rx._
+import util.{Success, Failure}
+case class Node(name: String, children: mutable.Buffer[Node])
+@JSExport
+object Controller{
+
+ def munge(name: String) = {
+ name.replace(" ", "")
+ }
+ def toggleClass(el: dom.HTMLElement, cls: String) = {
+ val frags = el.className.split(' ')
+ if (!frags.contains(cls)) el.className = el.className + " " + cls
+ else el.className = el.className.split(' ').filter(_ != cls).mkString(" ")
+ }
+ @JSExport
+ def main(data: scala.scalajs.js.Any) = {
+
+ val structure = upickle.readJs[Node](upickle.json.readJs(data))
+
+ val main = dom.document.getElementById("main")
+ val menu = dom.document.getElementById("menu")
+
+ val layout = dom.document.getElementById("layout")
+ val menuLink = dom.document.getElementById("menuLink")
+ val snippets = dom.document.getElementsByClassName("highlight-me")
+
+ snippets.foreach(js.Dynamic.global.hljs.highlightBlock(_))
+
+ val contentBar = {
+ def rec(current: Node, depth: Int): Seq[dom.HTMLLIElement] = {
+ println("\t"*depth + current.name)
+ val myCls =
+ "menu-item" +
+ (if (depth == 1) " menu-item-divided" else "")
+
+ val frag =
+ li(
+ a(
+ current.name,
+ href:="#"+munge(current.name),
+ paddingLeft := s"${depth * 10 + 10}px",
+ cls:=myCls
+ )
+ ).render
+
+ frag +: current.children.flatMap(rec(_, depth + 1))
+ }
+ structure.children.flatMap(rec(_, 0))
+ }
+ def menuItems = {
+ def rec(current: Node): Seq[String] = {
+ current.name +: current.children.flatMap(rec)
+ }
+ rec(structure).tail
+ }
+ val frag = div(cls:="pure-menu pure-menu-open")(
+ a(cls:="pure-menu-heading", href:="#")(
+ "Contents"
+ ),
+ ul(cls:="menu-item-list")(
+ contentBar
+ )
+ )
+ menu.appendChild(frag.render)
+
+ def offset(el: dom.HTMLElement, parent: dom.HTMLElement): Double = {
+ if (el == parent) 0
+ else el.offsetTop + offset(el.offsetParent.asInstanceOf[dom.HTMLElement], parent)
+ }
+ val headers = menuItems.map(munge)
+ .map(dom.document.getElementById)
+ .map(offset(_, main))
+ .toArray
+
+ scrollSpy(main, headers, contentBar)
+
+ menuLink.onclick = (e: dom.MouseEvent) => {
+ toggleClass(layout, "active")
+ toggleClass(menu, "active")
+ toggleClass(menuLink, "active")
+ };
+ }
+
+
+
+ def scrollSpy(main: dom.HTMLElement,
+ headers: Seq[Double],
+ contentBar: Seq[dom.HTMLElement]) = {
+ def isElementInViewport(el: dom.HTMLElement) = {
+ val rect = el.getBoundingClientRect()
+ rect.top >= 0 && rect.bottom <= dom.innerHeight
+ }
+
+ var scrolling = false
+ var lastIndex = -1
+ def run() = {
+ scrolling = false
+ val threshold = main.scrollTop + main.clientHeight
+ var index = 0
+ while(index < headers.length && index >= 0){
+ index += 1
+ if (headers(index) > threshold) index *= -1
+ }
+ index = -index - 1
+ if (index != lastIndex){
+ if (!isElementInViewport(contentBar(index))) {
+ contentBar(index).scrollIntoView(lastIndex > index)
+ }
+ if (lastIndex != -1)
+ toggleClass(contentBar(lastIndex), "pure-menu-selected")
+ toggleClass(contentBar(index), "pure-menu-selected")
+ lastIndex = index
+ }
+ }
+ run()
+ main.onscroll = (e: dom.UIEvent) => {
+ if (!scrolling){
+ scrolling = true
+ dom.requestAnimationFrame((d: Double) => run())
+ }
+ }
+ }
+}
diff --git a/examples/demos/build.sbt b/examples/demos/build.sbt
index 20b9fca..5374c30 100644
--- a/examples/demos/build.sbt
+++ b/examples/demos/build.sbt
@@ -6,6 +6,10 @@ version := "0.1-SNAPSHOT"
scalaVersion := "2.11.4"
+libraryDependencies += "com.scalarx" %%% "scalarx" % "0.2.6"
+
+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