| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- package com.weEat.modules
- import org.scalajs.dom.raw.Event
- import scala.concurrent.duration._
- import scala.concurrent.{ExecutionContext,Future,Promise}
- import scala.scalajs.js.timers.{clearTimeout, setTimeout}
- import mhtml.Rx
- import mhtml.future.syntax._
- import scala.util.Try
- import cats.implicits._
- import mhtml.implicits.cats._
- import cats.Traverse._
- import scala.xml.{Node,Elem,UnprefixedAttribute}
- import com.weEat.modules._
- import com.weEat.util.MHtmlHelpers._
- case class SearchBar[T](
- searchFn: (String) => Future[T],
- minLength: Int = 3,
- delay: FiniteDuration = 500 milliseconds
- )(implicit val ec: ExecutionContext = ExecutionContext.global) extends Module {
- // TODO: Refactor these out into utility classes
- def setTimeoutResult[T](delay: FiniteDuration)(body: => T) = {
- val promise = Promise[T]()
- setTimeout(delay) {
- promise.success(body)
- }
- promise.future
- }
- implicit class RxRxFlattener[T](outer: Rx[Rx[T]]) {
- def flatten = outer.flatMap(identity)
- }
- private val (_render, _inputTerm) =
- (<input type="text" class="form-control input-sm" />).value()
- val render = _render
- val searchTerm = _inputTerm.map[Option[String]](Some(_))
- .keepIf(_.map(_.length >= minLength).getOrElse(false))(None)
- .dropRepeats.impure.sharing
- // Nested futures give us a hellish type web to unweave
- val result: Rx[Option[Try[T]]] = searchTerm.flatMap({ term =>
- term.map({ termAtStart =>
- setTimeoutResult(delay) {
- searchTerm.map({ termAfterDelay =>
- if (Some(termAtStart) == termAfterDelay)
- searchFn(termAtStart).toRx
- else
- Rx(None)
- }).flatten
- }.toRx.map(
- _.map(
- _.sequence[Rx, Option[Try[T]]].map(
- _.flatSequence[Option, T]
- )
- )
- ).map(_.flatSequence[Rx, Try[T]]).flatten
- }).flatSequence[Rx, Try[T]]
- }).impure.sharing
- }
|