summaryrefslogtreecommitdiff
path: root/examples/demos/ScrollMenu.scala
blob: ccab4e9d9a0150f83466c14505a08f0fe91a5ecb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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)
  }
}