From 670415277f57b90546c5fdcf66c35e2199b722b1 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 26 Nov 2014 08:10:56 -0800 Subject: Refactored scrollMenu to be waaay simpler --- book/src/main/resources/css/side-menu.css | 16 ++--- .../src/main/scala/scrollmenu/Controller.scala | 3 +- .../src/main/scala/scrollmenu/ScrollMenu.scala | 79 +++++++++++----------- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/book/src/main/resources/css/side-menu.css b/book/src/main/resources/css/side-menu.css index b8e36c6..cc23949 100755 --- a/book/src/main/resources/css/side-menu.css +++ b/book/src/main/resources/css/side-menu.css @@ -307,21 +307,15 @@ code{ overflow: hidden; height: 0px; } -.collapsed.menu-item-list li > ul{ - opacity: 1; - overflow: hidden; +.collapsed.menu-item-list .hide li > a{ + background: none; } -#menu .collapsed.menu-item-list li.selected > a{ +#menu .menu-item-list li.selected{ 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; +#menu .menu-item-list .hide li.selected{ + border-left: none; } /*Override stuff from pure =/ it's not doing what I want*/ diff --git a/examples/demos/src/main/scala/scrollmenu/Controller.scala b/examples/demos/src/main/scala/scrollmenu/Controller.scala index 7fd8c90..3e498c6 100644 --- a/examples/demos/src/main/scala/scrollmenu/Controller.scala +++ b/examples/demos/src/main/scala/scrollmenu/Controller.scala @@ -31,7 +31,7 @@ object Controller{ val scrollSpy = new ScrollSpy(structure, main) val list = ul(cls := "menu-item-list collapsed")( - scrollSpy.domTrees.map(_.value.frag) + scrollSpy.domTrees.value.frag ).render def updateScroll() = scrollSpy() @@ -51,6 +51,7 @@ object Controller{ expandIcon.classList.toggle("fa-caret-down") expandIcon.classList.toggle("fa-caret-up") list.classList.toggle("collapsed") + list.classList.toggle("expanded") scrollSpy.clean = !scrollSpy.clean updateScroll() } diff --git a/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala b/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala index 1938c67..19d69f4 100644 --- a/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala +++ b/examples/demos/src/main/scala/scrollmenu/ScrollMenu.scala @@ -17,7 +17,7 @@ class ScrollSpy(structure: Tree[String], main: dom.HTMLElement, var clean: Boolean = false){ val (headers, domTrees) = { - var i = 0 + var i = -1 def recurse(t: Tree[String], depth: Int): Tree[MenuNode] = { val curr = li( @@ -32,7 +32,7 @@ class ScrollSpy(structure: Tree[String], val children = t.children.map(recurse(_, depth + 1)) Tree( MenuNode( - curr(ul(paddingLeft := "15px",children.map(_.value.frag))).render, + curr(ul(marginLeft := "15px",children.map(_.value.frag))).render, Controller.munge(t.value), originalI, if (children.length > 0) children.map(_.value.end).max else originalI + 1 @@ -56,7 +56,7 @@ class ScrollSpy(structure: Tree[String], .map(offset(_, main)) .toVector } - val domTrees = structure.children.map(recurse(_, 0)) + val domTrees = recurse(structure, 0) (headers, domTrees) } @@ -68,7 +68,7 @@ class ScrollSpy(structure: Tree[String], dom.requestAnimationFrame((d: Double) => start()) } } - private[this] var previousId = "" + private[this] var previousWin: MenuNode = null private[this] def start() = { scrolling = false def scroll(el: dom.Element) = { @@ -78,44 +78,47 @@ class ScrollSpy(structure: Tree[String], else if (rect.top > dom.innerHeight) el.scrollIntoView(false) } - def walkTree(tree: Tree[MenuNode]): Boolean = { - val Tree(MenuNode(menuItem, itemId, start, end), children) = tree - val before = headers(start) <= main.scrollTop - val after = (end >= headers.length) || headers(end) > main.scrollTop - - 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) { - if (previousId != itemId){ - previousId = itemId - // 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.children(0)) + val scrollTop = main.scrollTop + def walkIndex(tree: Tree[MenuNode]): List[Tree[MenuNode]] = { + val t @ Tree(m, children) = tree + val win = if(m.start == -1) true + else { + val before = headers(m.start) <= scrollTop + val after = (m.end >= headers.length) || headers(m.end) > scrollTop + before && after + } + val childIndexes = children.map(walkIndex) + val childWin = childIndexes.indexWhere(_ != null) + if (childWin != -1) t :: childIndexes(childWin) + else if (win) Nil + else null + } - dom.history.replaceState(null, null, "#" + itemId) - } + val winPath = walkIndex(domTrees) + val winItem = winPath.last.value + def walkTree(tree: Tree[MenuNode], indices: List[Tree[MenuNode]]): Unit = { + for(item <- indices){ + item.value.frag.classList.remove("hide") + item.value.frag.classList.remove("selected") + item.value.frag.children(0).classList.add("pure-menu-selected") + for(child <- item.children){ + val childFrag = child.value.frag + childFrag.children(0).classList.remove("pure-menu-selected") + childFrag.classList.add("hide") + if (child.value.start < winItem.start) childFrag.classList.add("selected") + else childFrag.classList.remove("selected") } - menuItem.children(0).classList.add("pure-menu-selected") - }else{ - if(clean) tree.children.map(walkTree) - menuItem.children(0).classList.remove("pure-menu-selected") - menuItem.classList.add("hide") - menuItem.classList.remove("selected") } - win + } - domTrees.map(walkTree) + + if (winItem != previousWin){ + scroll(winItem.frag.children(0)) + dom.history.replaceState(null, null, "#" + winItem.id) + previousWin = winItem + walkTree(domTrees, winPath) + } + } -- cgit v1.2.3