aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/reading/Route.scala
blob: c1f993e39507be2f350c1268bb34f530c6c4e2dd (plain)
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package reading

import org.scalajs.dom
import scala.scalajs.js.URIUtils

import rx.Var

import reading.models.{ Filter, FilterKind }

sealed trait Route

object Route {
  case class Books(filters: Seq[Filter]) extends Route

  val current: Var[Route] = Var(parse(dom.window.location.hash))

  dom.window.onpopstate = (e: dom.raw.PopStateEvent) => {
    current() = parse(dom.window.location.hash)
  }

  def parse(hash: String): Route =
    pathAndParams(hash) match {
      case ("books" :: Nil, params) => {
        val filters = params.flatMap { param =>
          param.split("=") match {
            case Array(kind, nonFormattedName) =>
              for {
                kind <- FilterKind.withNameOption(kind)
                filter <- Filter(kind, nonFormattedName)
              } yield filter
            case _ => None
          }
        }
        Books(filters)
      }
      case _ =>
        Books(Nil)
    }

  def pathAndParams(hash: String): (List[String], List[String]) = {
    def splitPath(path: String) = path.split("/").drop(1).toList
    URIUtils.decodeURI(hash.drop(1)).split('?') match {
      case Array(path) => (splitPath(path), Nil)
      case Array(path, params) => (splitPath(path), params.split("&").toList)
    }
  }

  def url(route: Route): String = {
    val hash = route match {
      case Books(filters) => "/books" ++ (if (filters.nonEmpty) filters.map(filter => s"${filter.kind}=${filter.nonFormattedName}").mkString("?", "&", "") else "")
      case _ => "/books"
    }
    dom.window.location.origin + dom.window.location.pathname + "#" + URIUtils.encodeURI(hash)
  }

  def goTo(route: Route): Unit = {
    push(route)
    current() = route
  }

  def push(route: Route): Unit = {
    dom.window.history.pushState(null, "", url(route));
  }
}