From c7a6380fdf37010d43d62a7db0a882d7ccc68d96 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 14 Nov 2014 14:28:51 -0800 Subject: WIP after getting rid of react.js, still doesn't work --- book/src/main/resources/css/side-menu.css | 19 ++-- book/src/main/scala/book/Book.scala | 2 +- build.sbt | 4 +- examples/demos/Controller.scala | 144 ++++++++++++------------------ 4 files changed, 72 insertions(+), 97 deletions(-) diff --git a/book/src/main/resources/css/side-menu.css b/book/src/main/resources/css/side-menu.css index e5d014c..c9babca 100755 --- a/book/src/main/resources/css/side-menu.css +++ b/book/src/main/resources/css/side-menu.css @@ -310,19 +310,26 @@ code{ .header-link{ opacity: 0.05; } -.menu-item-list > li { - height: 43px; -} -.menu-item-list > li.hide{ +.menu-item-list li.hide > ul{ height: 0px; overflow: hidden; + opacity: 0; } -#menu .menu-item-list > li.pure-menu-selected > a{ + +#menu .menu-item-list li.selected > a{ border-left: 2px solid white; } -#menu .menu-item-list > li.lined > a{ +#menu .menu-item-list li.lined > a{ border-left: 2px solid white; } + +.pure-menu li > ul{ + position:relative; + visibility:visible; + left: 0px; + top: 0px; +} + /*Workaround for bug in highlight.js IDEA theme*/ .hljs-tag, .hljs-symbol{ background: none; diff --git a/book/src/main/scala/book/Book.scala b/book/src/main/scala/book/Book.scala index 857bf37..cd10205 100644 --- a/book/src/main/scala/book/Book.scala +++ b/book/src/main/scala/book/Book.scala @@ -26,7 +26,7 @@ object Book { "META-INF/resources/webjars/font-awesome/4.2.0/fonts/fontawesome-webfont.woff", "META-INF/resources/webjars/react/0.11.1/react.min.js", "css/side-menu.css", - "example-opt.js", + "example-fastopt.js", "webpage/weather.js", "favicon.svg", "favicon.png" diff --git a/build.sbt b/build.sbt index 8bb2856..e0b9f22 100644 --- a/build.sbt +++ b/build.sbt @@ -44,8 +44,8 @@ lazy val book = Project( "com.lihaoyi" %%% "upickle" % "0.2.5" ), (resources in Compile) += { - (fullOptJS in (demos, Compile)).value - (artifactPath in (demos, Compile, fullOptJS)).value + (fastOptJS in (demos, Compile)).value + (artifactPath in (demos, Compile, fastOptJS)).value }, (unmanagedResourceDirectories in Compile) ++= (unmanagedResourceDirectories in (demos, Compile)).value, diff --git a/examples/demos/Controller.scala b/examples/demos/Controller.scala index 6e7df42..b9d8d56 100644 --- a/examples/demos/Controller.scala +++ b/examples/demos/Controller.scala @@ -4,12 +4,10 @@ import scala.scalajs.js.annotation.JSExport import org.scalajs.dom import org.scalajs.dom.extensions._ import scala.collection.mutable -import japgolly.scalajs.react._ // React - -import vdom.ReactVDom.all._ // Scalatags html & css (div, h1, textarea, etc.) - +import scalatags.JsDom.all._ case class Tree[T](name: T, children: Vector[Tree[T]]) + @JSExport object Controller{ @@ -21,7 +19,10 @@ object Controller{ el.className = el.className + " " + cls } def removeClass(el: dom.HTMLElement, cls: String) = { - el.className = el.className.split(' ').filter(_ != cls).mkString(" ") + el.className = el.className.split(' ') + .iterator + .filter(_ != cls) + .mkString(" ") } def toggleClass(el: dom.HTMLElement, cls: String) = { val frags = el.className.split(' ') @@ -33,19 +34,25 @@ object Controller{ val structure = upickle.readJs[Tree[String]](upickle.json.readJs(data)) var i = 0 - def recurse(t: Tree[String], depth: Int): Tree[(Tag, Int)] = { + def recurse(t: Tree[String], depth: Int): Tree[(dom.HTMLElement, Int)] = { val curr = - li(paddingLeft := s"${depth * 15}px")( + li(paddingLeft := "15px")( a( t.name, - href:=munge("#"+t.name), + href:="#"+munge(t.name), cls:="menu-item" ) ) val originalI = i i += 1 val children = t.children.map(recurse(_, depth + 1)) - Tree(curr -> originalI, children) + Tree( + ( + curr(ul(children.map(_.name._1))).render, + originalI + ), + children + ) } val Seq(main, menu, layout, menuLink) = Seq( @@ -55,12 +62,12 @@ object Controller{ val snippets = dom.document.getElementsByClassName("highlight-me") snippets.foreach(js.Dynamic.global.hljs.highlightBlock(_)) - + 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 = { - def offset(el: dom.HTMLElement, parent: dom.HTMLElement): Double = { - if (el == parent) 0 - else el.offsetTop + offset(el.offsetParent.asInstanceOf[dom.HTMLElement], parent) - } + val menuItems = { def rec(current: Tree[String]): Seq[String] = { current.name +: current.children.flatMap(rec) @@ -73,10 +80,17 @@ object Controller{ .toVector } + val domTrees = recurse(structure, 0).children - val menuBar = React.renderComponent( - Menu(recurse(structure, 0)), - menu + 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) + ) + ).render ) menuLink.onclick = (e: dom.MouseEvent) => { toggleClass(layout, "active") @@ -84,28 +98,35 @@ object Controller{ toggleClass(menuLink, "active") } - var x = -1 - def start() = - x = dom.setTimeout(() => { - x = -1 - val threshold = main.scrollTop + main.clientHeight + var scrolling = false - var index = 0 - while(index < headers.length && index >= 0){ - index += 1 - if (headers(index) > threshold) index *= -1 - } - index = -index - menuBar.setState(index) + def start() ={ + scrolling = false + val threshold = main.scrollTop + main.clientHeight + println("") + def walkTree(tree: Tree[(dom.HTMLElement, Int)]): Unit = { + val Tree((menuItem, index), children) = tree + val before = headers(index) < threshold - }, 100) + val next = children.lastOption + .fold(index)(_.name._2) - main.onscroll = (e: dom.UIEvent) => { - if (x != -1){ - dom.clearTimeout(x) - s + val win = before && headers.lift(next + 1).getOrElse(999999.0) > threshold + + if (win){ + removeClass(menuItem, "hide") + addClass(menuItem, "selected") + tree.children.foreach(walkTree) + }else{ + addClass(menuItem, "hide") + removeClass(menuItem, "selected") + } } - start() + domTrees.map(walkTree) + } + main.onscroll = (e: dom.UIEvent) => if (!scrolling){ + scrolling = true + dom.requestAnimationFrame((d: Double) => start()) } } def isElementInViewport(el: dom.HTMLElement) = { @@ -114,57 +135,4 @@ object Controller{ } - - val Menu = ReactComponentB[Tree[(Tag, Int)]]("Menu") - .getInitialState(_ => 0) - .render{ (structure, _, index) => - - val contentList = { - var i = 0 - val winArray = new js.Array[Boolean](0) - def rec1(current: Tree[(Tag, Int)]): Unit = { - val initialI = i - i += 1 - current.children.foreach(rec1) - winArray(current.name._2) = i >= index && initialI < index - } - - val output = new js.Array[Tag](0) - def rec(current: Tree[(Tag, Int)], - classes: String): Unit = { - - - val winIndex = current.children.indexWhere { x => - winArray(x.name._2) - } - val (before, after) = current.children.splitAt(winIndex) - - val (tag, currIndex) = current.name - - val win = winArray(currIndex) - - val frag = tag( - cls:=classes + (if (win) " pure-menu-selected" else "") - ) - - output.push(frag) - - before.foreach(rec(_, "lined")) - after.foreach(rec(_, if (!win) "hide" else "")) - } - rec1(structure) - rec(structure, "") - output - } - - val frag = div(cls:="pure-menu pure-menu-open")( - a(cls:="pure-menu-heading", href:="#")( - "Contents" - ), - ul(cls:="menu-item-list")( - contentList.drop(1):_* - ) - ) - frag - }.build } \ No newline at end of file -- cgit v1.2.3