From 64b283eb61f2c20e39e4c55e8696522569420028 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 14 Nov 2014 15:44:54 -0800 Subject: lots of cleanip --- book/src/main/scala/book/Main.scala | 4 +-- book/src/main/scala/book/Utils.scala | 6 ++-- examples/demos/Controller.scala | 67 +++++++++--------------------------- examples/demos/ScrollMenu.scala | 50 +++++++++++++++++++++++++++ examples/demos/build.sbt | 4 +-- 5 files changed, 72 insertions(+), 59 deletions(-) create mode 100644 examples/demos/ScrollMenu.scala diff --git a/book/src/main/scala/book/Main.scala b/book/src/main/scala/book/Main.scala index 91360d5..da9bace 100644 --- a/book/src/main/scala/book/Main.scala +++ b/book/src/main/scala/book/Main.scala @@ -27,8 +27,8 @@ object Main { } val allNames = { - def rec(n: Node): Seq[String] = { - n.name +: n.children.flatMap(rec) + def rec(n: Tree[String]): Seq[String] = { + n.value +: n.children.flatMap(rec) } rec(sect.structure).toSet } diff --git a/book/src/main/scala/book/Utils.scala b/book/src/main/scala/book/Utils.scala index 07f462c..ad41d18 100644 --- a/book/src/main/scala/book/Utils.scala +++ b/book/src/main/scala/book/Utils.scala @@ -34,7 +34,7 @@ object sect{ (h6(_, _, _), None) ) - var structure = Node("root", mutable.Buffer.empty) + var structure = Tree[String]("root", mutable.Buffer.empty) val usedRefs = mutable.Set.empty[String] @@ -49,7 +49,7 @@ object sect{ } case class sect(name: String, subname: String = ""){ sect.indent += 1 - val newNode = Node(name, mutable.Buffer.empty) + val newNode = Tree[String](name, mutable.Buffer.empty) val (headerWrap, contentWrap) = sect.headers(sect.indent-1) sect.structure.children.append(newNode) val prev = sect.structure @@ -75,7 +75,7 @@ case class sect(name: String, subname: String = ""){ res } } -case class Node(name: String, children: mutable.Buffer[Node]) +case class Tree[T](value: T, children: mutable.Buffer[Tree[T]]) object lnk{ val usedLinks = mutable.Set.empty[String] def apply(name: String, url: String) = { diff --git a/examples/demos/Controller.scala b/examples/demos/Controller.scala index 9a11597..6fd7ac7 100644 --- a/examples/demos/Controller.scala +++ b/examples/demos/Controller.scala @@ -1,4 +1,4 @@ - +import acyclic.file import scala.scalajs.js import scala.scalajs.js.annotation.JSExport import org.scalajs.dom @@ -6,7 +6,7 @@ import org.scalajs.dom.extensions._ import scala.collection.mutable import scalatags.JsDom.all._ -case class Tree[T](name: T, children: Vector[Tree[T]]) + @JSExport object Controller{ @@ -20,12 +20,12 @@ object Controller{ val structure = upickle.readJs[Tree[String]](upickle.json.readJs(data)) var i = 0 - def recurse(t: Tree[String], depth: Int): Tree[(dom.HTMLElement, Int, Int)] = { + def recurse(t: Tree[String], depth: Int): Tree[MenuNode] = { val curr = li( a( - t.name, - href:="#"+munge(t.name), + t.value, + href:="#"+munge(t.value), cls:="menu-item" ) ) @@ -33,10 +33,10 @@ object Controller{ i += 1 val children = t.children.map(recurse(_, depth + 1)) Tree( - ( - curr(ul(paddingLeft := "15px",children.map(_.name._1))).render, + MenuNode( + curr(ul(paddingLeft := "15px",children.map(_.value.frag))).render, originalI, - if (children.length > 0) children.map(_.name._3).max else originalI + 1 + if (children.length > 0) children.map(_.value.end).max else originalI + 1 ), children ) @@ -57,7 +57,7 @@ object Controller{ val menuItems = { def rec(current: Tree[String]): Seq[String] = { - current.name +: current.children.flatMap(rec) + current.value +: current.children.flatMap(rec) } rec(structure).tail } @@ -68,15 +68,17 @@ object Controller{ } println(headers) - val domTrees = structure.children.map(recurse(_, 0)) + + val domTrees = structure.children.map(recurse(_, 0)) + val scrollSpy = new ScrollSpy(headers, domTrees) menu.appendChild( div(cls:="pure-menu pure-menu-open")( a(cls:="pure-menu-heading", href:="#")( "Contents" ), ul(cls:="menu-item-list")( - domTrees.map(_.name._1) + domTrees.map(_.value.frag) ) ).render ) @@ -86,50 +88,13 @@ object Controller{ menuLink.classList.toggle("active") } - var scrolling = false - var lastSelected: dom.HTMLElement = null - def start() ={ - scrolling = false - val threshold = main.scrollTop + main.clientHeight - def walkTree(tree: Tree[(dom.HTMLElement, Int, Int)]): Boolean = { - val Tree((menuItem, index, next), children) = tree - val before = headers(index) < threshold - val after = (next >= headers.length) || headers(next) > threshold - val win = before && after - if (win){ - menuItem.classList.remove("hide") - var winFound = false - for(c <- tree.children){ - val newWinFound = walkTree(c) - if (!winFound) c.name._1.classList.add("selected") - else c.name._1.classList.remove("selected") - winFound = winFound | newWinFound - } - if (!winFound) { - tree.children.foreach(_.name._1.classList.remove("selected")) - if (lastSelected != null) - lastSelected.children(0).classList.remove("pure-menu-selected") - menuItem.children(0).classList.add("pure-menu-selected") - lastSelected = menuItem - } - }else{ - menuItem.classList.add("hide") - menuItem.classList.remove("selected") - } - win - } - domTrees.map(walkTree) - } - main.onscroll = (e: dom.UIEvent) => if (!scrolling){ - scrolling = true - dom.requestAnimationFrame((d: Double) => start()) + main.onscroll = (e: dom.UIEvent) => { + scrollSpy(main.scrollTop + main.clientHeight) } } def isElementInViewport(el: dom.HTMLElement) = { val rect = el.getBoundingClientRect() rect.top >= 0 && rect.bottom <= dom.innerHeight } - - -} \ No newline at end of file +} diff --git a/examples/demos/ScrollMenu.scala b/examples/demos/ScrollMenu.scala new file mode 100644 index 0000000..ccab4e9 --- /dev/null +++ b/examples/demos/ScrollMenu.scala @@ -0,0 +1,50 @@ +import acyclic.file +import org.scalajs.dom + +case class Tree[T](value: T, children: Vector[Tree[T]]) + +case class MenuNode(frag: dom.HTMLElement, start: Int, end: Int) + +/** + * High performance scrollspy to + */ +class ScrollSpy(headers: Vector[Double], domTrees: Seq[Tree[MenuNode]]){ + var scrolling = false + var lastSelected: dom.HTMLElement = null + def apply(threshold: Double) = if (!scrolling){ + scrolling = true + dom.requestAnimationFrame((d: Double) => start(threshold)) + } + def start(threshold: Double) = { + scrolling = false + def walkTree(tree: Tree[MenuNode]): Boolean = { + val Tree(MenuNode(menuItem, index, next), children) = tree + val before = headers(index) < threshold + val after = (next >= headers.length) || headers(next) > threshold + val win = before && after + if (win){ + menuItem.classList.remove("hide") + var winFound = false + + for(c <- tree.children){ + val newWinFound = walkTree(c) + if (!winFound) c.value.frag.classList.add("selected") + else c.value.frag.classList.remove("selected") + winFound = winFound | newWinFound + } + if (!winFound) { + tree.children.foreach(_.value.frag.classList.remove("selected")) + if (lastSelected != null) + lastSelected.children(0).classList.remove("pure-menu-selected") + menuItem.children(0).classList.add("pure-menu-selected") + lastSelected = menuItem + } + }else{ + menuItem.classList.add("hide") + menuItem.classList.remove("selected") + } + win + } + domTrees.map(walkTree) + } +} \ No newline at end of file diff --git a/examples/demos/build.sbt b/examples/demos/build.sbt index 040f9fd..fb79984 100644 --- a/examples/demos/build.sbt +++ b/examples/demos/build.sbt @@ -8,9 +8,7 @@ version := "0.1-SNAPSHOT" scalaVersion := "2.11.4" -libraryDependencies += "com.github.japgolly.scalajs-react" %%% "core" % "0.5.1" - - +libraryDependencies += "com.lihaoyi" %% "acyclic" % "0.1.2" % "provided" libraryDependencies += "com.lihaoyi" %%% "upickle" % "0.2.5" -- cgit v1.2.3