From 7f33cb682200a501e0a48ab2fbad688317d80754 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 12 Nov 2014 22:22:16 -0800 Subject: Commit before trying out scala-js-react --- book/src/main/resources/css/side-menu.css | 26 +++++-- examples/demos/Controller.scala | 110 ++++++++++++++++++++++-------- examples/demos/build.sbt | 6 +- 3 files changed, 108 insertions(+), 34 deletions(-) diff --git a/book/src/main/resources/css/side-menu.css b/book/src/main/resources/css/side-menu.css index 8bded91..8a9e25e 100755 --- a/book/src/main/resources/css/side-menu.css +++ b/book/src/main/resources/css/side-menu.css @@ -25,13 +25,21 @@ Add transition to containers so they can push in and out. */ #layout, #menu, -.menu-link { +.menu-link,{ -webkit-transition: all 0.2s ease-out; -moz-transition: all 0.2s ease-out; -ms-transition: all 0.2s ease-out; -o-transition: all 0.2s ease-out; transition: all 0.2s ease-out; } +.hide, +.menu-item-list > li{ + -webkit-transition: height 0.2s ease-out; + -moz-transition: height 0.2s ease-out; + -ms-transition: height 0.2s ease-out; + -o-transition: height 0.2s ease-out; + transition: height 0.2s ease-out; +} /* This is the parent `
` that contains the menu and the content area. @@ -302,11 +310,19 @@ code{ .header-link{ opacity: 0.05; } -.hide{ - display: none; +.menu-item-list > li { + height: 43px; +} +.menu-item-list > li.hide{ + height: 0px; + overflow: hidden; +} +#menu .menu-item-list > li.pure-menu-selected > a{ + border-left: 2px solid white; +} +#menu .menu-item-list > li.lined > a{ + border-left: 2px solid white; } - - /*Workaround for bug in highlight.js IDEA theme*/ .hljs-tag, .hljs-symbol{ background: none; diff --git a/examples/demos/Controller.scala b/examples/demos/Controller.scala index 81bcdb4..0936776 100644 --- a/examples/demos/Controller.scala +++ b/examples/demos/Controller.scala @@ -6,7 +6,16 @@ import org.scalajs.dom.extensions._ import scala.collection.mutable import scalatags.JsDom.all._ -case class Tree[T](name: T, children: Seq[Tree[T]]) +object Renderer{ + import japgolly.scalajs.react._ // React + import vdom.ReactVDom._ // Scalatags → React virtual DOM + import vdom.ReactVDom.all._ // Scalatags html & css (div, h1, textarea, etc.) + + val Menu = ReactComponentB[Int]("Menu").render{ p => + + }.build +} +case class Tree[T](name: T, children: Vector[Tree[T]]) @JSExport object Controller{ @@ -14,7 +23,6 @@ object Controller{ name.replace(" ", "") } def addClass(el: dom.HTMLElement, cls: String) = { - println("Adding Class " + cls) removeClass(el, cls) el.className = el.className + " " + cls } @@ -47,10 +55,10 @@ object Controller{ val frag = li( + paddingLeft := s"${depth * 15}px", a( current.name, href:="#"+munge(current.name), - paddingLeft := s"${depth * 15}px", cls:=myCls ) ).render @@ -90,7 +98,7 @@ object Controller{ menuItems.map(munge) .map(dom.document.getElementById) .map(offset(_, main)) - .toArray + .toVector } scrollSpy(main, headers, contentList, contentTree) @@ -108,14 +116,11 @@ object Controller{ * noticeable jerky */ def scrollSpy(main: dom.HTMLElement, - headers: Seq[Double], - contentList: Seq[dom.HTMLElement], + headers: Vector[Double], + contentList: Vector[dom.HTMLElement], contentTree: Tree[dom.HTMLElement]) = { - def isElementInViewport(el: dom.HTMLElement) = { - val rect = el.getBoundingClientRect() - rect.top >= 0 && rect.bottom <= dom.innerHeight - } + var scrolling = false var lastIndex = -1 @@ -128,25 +133,10 @@ object Controller{ index += 1 if (headers(index) > threshold) index *= -1 } - index = -index - 1 - if (index != lastIndex){ - if (!isElementInViewport(contentList(index))) { - contentList(index).scrollIntoView(lastIndex > index) - } - def rec(curr: Tree[dom.HTMLElement]): Boolean = { - if (curr.children.map(rec).contains(true) || - curr.name == contentList(index)){ - addClass(curr.name, "pure-menu-selected") - curr.children.map(_.name).foreach(removeClass(_, "hide")) - true - }else{ - removeClass(curr.name, "pure-menu-selected") - addClass(curr.name, "hide") - false - } - } - rec(contentTree) + index = -index + if (index != lastIndex){ + updateSideBar(lastIndex, index, contentList, contentTree) lastIndex = index } } @@ -158,4 +148,68 @@ object Controller{ } } } + def isElementInViewport(el: dom.HTMLElement) = { + val rect = el.getBoundingClientRect() + rect.top >= 0 && rect.bottom <= dom.innerHeight + } + val lastShown = new js.Array[dom.HTMLElement](0) + val lastLined = new js.Array[dom.HTMLElement](0) + def updateSideBar(lastIndex: Int, + index: Int, + contentList: Vector[dom.HTMLElement], + contentTree: Tree[dom.HTMLElement]) = { + + println(s"MOVING $lastIndex -> $index") + if (!isElementInViewport(contentList(index))) { + contentList(index).scrollIntoView(lastIndex > index) + } + val shown = new js.Array[dom.HTMLElement](0) + val lined = new js.Array[dom.HTMLElement](0) + /** + * Makes two passes over the children list; once to determine if + * the current element is a parent of the current header, and another + * to mark all the children of the current element with the correct + * CSS classes. + */ + def rec(curr: Tree[dom.HTMLElement]): Boolean = { + + var found = false + var i = 0 + var j = 0 + while (j < curr.children.length){ + val x = curr.children(j) + j+= 1 + val f = rec(x) + found |= f + if (!found) i += 1 + } + + if (found || curr.name == contentList(index)){ + var j = 0 + while (j < curr.children.length){ + val x = curr.children(j) + if (found && i > 0){ + lined.push(x.name) + i -= 1 + } + + j+= 1 + shown.push(x.name) + } + lined.push(curr.name) + true + }else false + + } + rec(contentTree) + for(el <- contentList){ + if (shown.indexOf(el) != -1) removeClass(el, "hide") + else addClass(el, "hide") + + if (lined.indexOf(el) == -1) removeClass(el, "lined") + else addClass(el, "lined") + } + if (lastIndex != -1) removeClass(contentList(lastIndex), "pure-menu-selected") + addClass(contentList(index), "pure-menu-selected") + } } diff --git a/examples/demos/build.sbt b/examples/demos/build.sbt index 5374c30..9be4d4d 100644 --- a/examples/demos/build.sbt +++ b/examples/demos/build.sbt @@ -1,3 +1,5 @@ +import scala.scalajs.sbtplugin.ScalaJSPlugin.ScalaJSKeys.jsDependencies + scalaJSSettings name := "Example" @@ -6,7 +8,9 @@ version := "0.1-SNAPSHOT" scalaVersion := "2.11.4" -libraryDependencies += "com.scalarx" %%% "scalarx" % "0.2.6" +libraryDependencies += "com.github.japgolly.scalajs-react" %%% "core" % "0.5.1" + +jsDependencies += "org.webjars" % "react" % "0.11.1" / "react-with-addons.js" commonJSName "React" libraryDependencies += "com.lihaoyi" %%% "upickle" % "0.2.5" -- cgit v1.2.3