From 70f9164e167398d75f99130a5325a3411215feb5 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 15 Nov 2014 15:59:38 -0800 Subject: works --- book/src/main/resources/css/side-menu.css | 18 +++--- book/src/main/scala/book/Utils.scala | 36 +++++------ .../src/main/scala/scrollmenu/Controller.scala | 49 +------------- .../src/main/scala/scrollmenu/ScrollMenu.scala | 74 +++++++++++++++++++--- .../src/test/scala/torimatomeru/SyntaxTest.scala | 18 ++++++ 5 files changed, 110 insertions(+), 85 deletions(-) create mode 100644 scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala diff --git a/book/src/main/resources/css/side-menu.css b/book/src/main/resources/css/side-menu.css index 00b351d..fbb2b26 100755 --- a/book/src/main/resources/css/side-menu.css +++ b/book/src/main/resources/css/side-menu.css @@ -32,13 +32,6 @@ Add transition to containers so they can push in and out. -o-transition: all 0.2s ease-out; transition: all 0.2s ease-out; } -.menu-item-list li > ul{ - -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; -} /* This is the parent `
` that contains the menu and the content area. @@ -319,14 +312,19 @@ code{ overflow: hidden; } - #menu .menu-item-list li.selected > a{ border-left: 2px solid white; } -#menu .menu-item-list li.lined > a{ - border-left: 2px solid white; + +.menu-item-list li > a{ + -webkit-transition: background-color 0.2s ease-out; + -moz-transition: background-color 0.2s ease-out; + -ms-transition: background-color 0.2s ease-out; + -o-transition: background-color 0.2s ease-out; + transition: background-color 0.2s ease-out; } +/*Override stuff from pure =/ it's not doing what I want*/ .pure-menu li > ul{ position:relative; visibility:visible; diff --git a/book/src/main/scala/book/Utils.scala b/book/src/main/scala/book/Utils.scala index ad41d18..6770e31 100644 --- a/book/src/main/scala/book/Utils.scala +++ b/book/src/main/scala/book/Utils.scala @@ -83,27 +83,21 @@ object lnk{ a(name, href:=url) } object dom{ - class MdnThing(name: String = toString) extends Frag{ - def render = lnk.apply(name, "https://developer.mozilla.org/en-US/docs/Web/API/" + name).render - def applyTo(t: Builder) = t.addChild(render) - } - class MdnEvent extends Frag { - def render = lnk.apply(toString, "https://developer.mozilla.org/en-US/docs/Web/Events/" + toString).render - def applyTo(t: Builder) = t.addChild(render) - } - object CanvasRenderingContext2D extends MdnThing() - object HTMLCanvasElement extends MdnThing() - object Element extends MdnThing() - object HTMLElement extends MdnThing() - object HTMLInputElement extends MdnThing() - object HTMLSpanElement extends MdnThing() - object XMLHttpRequest extends MdnThing() - object getElementById extends MdnThing("document.getElementById") - object setInterval extends MdnThing("WindowTimers.setInterval") - object mousedown extends MdnThing - object mouseup extends MdnThing - object onclick extends MdnThing - object onkeyup extends MdnThing + def mdnThing(name: String) = lnk(name, "https://developer.mozilla.org/en-US/docs/Web/API/" + name) + def mdnEvent(name: String) = lnk(name, "https://developer.mozilla.org/en-US/docs/Web/Events/" + name) + val CanvasRenderingContext2D = mdnThing("CanvasRenderingContext2D") + val HTMLCanvasElement = mdnThing("HTMLCanvasElement") + val Element = mdnThing("Element") + val HTMLElement = mdnThing("HTMLElement") + val HTMLInputElement = mdnThing("HTMLInputElement") + val HTMLSpanElement = mdnThing("HTMLSpanElement") + val XMLHttpRequest = mdnThing("XMLHttpRequest") + val getElementById = mdnThing("document.getElementById") + val setInterval = mdnThing("WindowTimers.setInterval") + val mousedown = mdnEvent("mousedown") + val mouseup = mdnEvent("mouseup") + val onclick = mdnEvent("onclick") + val onkeyup = mdnEvent("onkeyup") val JSONparse = lnk("Json.parse", "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse") } object scala{ diff --git a/examples/demos/src/main/scala/scrollmenu/Controller.scala b/examples/demos/src/main/scala/scrollmenu/Controller.scala index 1fcb68c..de120c6 100644 --- a/examples/demos/src/main/scala/scrollmenu/Controller.scala +++ b/examples/demos/src/main/scala/scrollmenu/Controller.scala @@ -20,28 +20,6 @@ object Controller{ def main(data: scala.scalajs.js.Any) = { val structure = upickle.readJs[Tree[String]](upickle.json.readJs(data)) - var i = 0 - def recurse(t: Tree[String], depth: Int): Tree[MenuNode] = { - val curr = - li( - a( - t.value, - href:="#"+munge(t.value), - cls:="menu-item" - ) - ) - val originalI = i - i += 1 - val children = t.children.map(recurse(_, depth + 1)) - Tree( - MenuNode( - curr(ul(paddingLeft := "15px",children.map(_.value.frag))).render, - originalI, - if (children.length > 0) children.map(_.value.end).max else originalI + 1 - ), - children - ) - } val Seq(main, menu, layout, menuLink) = Seq( "main", "menu", "layout", "menuLink" @@ -50,26 +28,8 @@ 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 = { - - val menuItems = { - def rec(current: Tree[String]): Seq[String] = { - current.value +: current.children.flatMap(rec) - } - rec(structure).tail - } - menuItems.map(munge) - .map(dom.document.getElementById) - .map(offset(_, main)) - .toVector - } - val domTrees = structure.children.map(recurse(_, 0)) - val scrollSpy = new ScrollSpy(headers, domTrees) + val scrollSpy = new ScrollSpy(structure, main) menu.appendChild( div(cls:="pure-menu pure-menu-open")( @@ -77,7 +37,7 @@ object Controller{ "Contents" ), ul(cls:="menu-item-list")( - domTrees.map(_.value.frag) + scrollSpy.domTrees.map(_.value.frag) ) ).render ) @@ -92,8 +52,5 @@ object Controller{ scrollSpy(main.scrollTop + main.clientHeight) } } - def isElementInViewport(el: dom.HTMLElement) = { - val rect = el.getBoundingClientRect() - rect.top >= 0 && rect.bottom <= dom.innerHeight - } + } diff --git a/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala b/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala index 9c0fbd2..7b238f4 100644 --- a/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala +++ b/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala @@ -2,6 +2,8 @@ package scrollmenu import org.scalajs.dom +import scalatags.JsDom.all._ + case class Tree[T](value: T, children: Vector[Tree[T]]) case class MenuNode(frag: dom.HTMLElement, start: Int, end: Int) @@ -10,18 +12,69 @@ case class MenuNode(frag: dom.HTMLElement, start: Int, end: Int) * High performance scrollspy to work keep the left menu bar in sync. * Lots of sketchy imperative code in order to maximize performance. */ -class ScrollSpy(headers: Vector[Double], domTrees: Seq[Tree[MenuNode]]){ - var scrolling = false - def apply(threshold: Double) = if (!scrolling){ +class ScrollSpy(structure: Tree[String], main: dom.HTMLElement){ + val (headers, domTrees) = { + var i = 0 + def recurse(t: Tree[String], depth: Int): Tree[MenuNode] = { + val curr = + li( + a( + t.value, + href:="#"+Controller.munge(t.value), + cls:="menu-item" + ) + ) + val originalI = i + i += 1 + val children = t.children.map(recurse(_, depth + 1)) + Tree( + MenuNode( + curr(ul(paddingLeft := "15px",children.map(_.value.frag))).render, + originalI, + if (children.length > 0) children.map(_.value.end).max else originalI + 1 + ), + children + ) + } + 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 = { + val menuItems = { + def rec(current: Tree[String]): Seq[String] = { + current.value +: current.children.flatMap(rec) + } + rec(structure).tail + } + menuItems.map(Controller.munge) + .map(dom.document.getElementById) + .map(offset(_, main)) + .toVector + } + val domTrees = structure.children.map(recurse(_, 0)) + (headers, domTrees) + } + + + private[this] var scrolling = false + def apply(threshold: => Double) = if (!scrolling){ scrolling = true - dom.requestAnimationFrame((d: Double) => start(threshold)) + dom.setTimeout(() => start(threshold), 200) } - def start(threshold: Double) = { + private[this] def start(threshold: Double) = { scrolling = false + def scroll(el: dom.HTMLElement) = { + val rect = el.getBoundingClientRect() + if (rect.top <= 0) + el.scrollIntoView(true) + else if (rect.bottom > dom.innerHeight) + el.scrollIntoView(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 Tree(MenuNode(menuItem, start, end), children) = tree + val before = headers(start) < threshold + val after = (end >= headers.length) || headers(end) > threshold val win = before && after if (win){ menuItem.classList.remove("hide") @@ -34,7 +87,10 @@ class ScrollSpy(headers: Vector[Double], domTrees: Seq[Tree[MenuNode]]){ winFound = winFound | newWinFound } if (!winFound) { + // This means it's the leaf element, because it won but there + // aren't any children which won, so it must be the actual leaf tree.children.foreach(_.value.frag.classList.remove("selected")) + scroll(menuItem) } menuItem.children(0).classList.add("pure-menu-selected") }else{ @@ -46,4 +102,6 @@ class ScrollSpy(headers: Vector[Double], domTrees: Seq[Tree[MenuNode]]){ } domTrees.map(walkTree) } + + } \ No newline at end of file diff --git a/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala b/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala new file mode 100644 index 0000000..8d5a0d8 --- /dev/null +++ b/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala @@ -0,0 +1,18 @@ +package torimatomeru +import utest._ +import utest.framework.Test +import utest.util.Tree + +object SyntaxTest extends TestSuite{ + def check[T](input: String, parse: ScalaSyntax => scala.util.Try[T], expected: T) = { + val parsed = parse(new ScalaSyntax(input)).get + assert(parsed == expected) + } + def tests = TestSuite{ + + "omg" - check( + """if (true) () else ()""", + _.IfCFlow.run(), () + ) + } +} -- cgit v1.2.3