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)); } }