SearchBar.scala 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package com.weEat.modules
  2. import org.scalajs.dom.raw.Event
  3. import scala.concurrent.duration._
  4. import scala.concurrent.{ExecutionContext,Future,Promise}
  5. import scala.scalajs.js.timers.{clearTimeout, setTimeout}
  6. import mhtml.Rx
  7. import mhtml.future.syntax._
  8. import scala.util.Try
  9. import cats.implicits._
  10. import mhtml.implicits.cats._
  11. import cats.Traverse._
  12. import scala.xml.{Node,Elem,UnprefixedAttribute}
  13. import com.weEat.modules._
  14. import com.weEat.util.MHtmlHelpers._
  15. case class SearchBar[T](
  16. searchFn: (String) => Future[T],
  17. minLength: Int = 3,
  18. delay: FiniteDuration = 500 milliseconds
  19. )(implicit val ec: ExecutionContext = ExecutionContext.global) extends Module {
  20. // TODO: Refactor these out into utility classes
  21. def setTimeoutResult[T](delay: FiniteDuration)(body: => T) = {
  22. val promise = Promise[T]()
  23. setTimeout(delay) {
  24. promise.success(body)
  25. }
  26. promise.future
  27. }
  28. implicit class RxRxFlattener[T](outer: Rx[Rx[T]]) {
  29. def flatten = outer.flatMap(identity)
  30. }
  31. private val (_render, _inputTerm) =
  32. (<input type="text" class="form-control input-sm" />).value()
  33. val render = _render
  34. val searchTerm = _inputTerm.map[Option[String]](Some(_))
  35. .keepIf(_.map(_.length >= minLength).getOrElse(false))(None)
  36. .dropRepeats.impure.sharing
  37. // Nested futures give us a hellish type web to unweave
  38. val result: Rx[Option[Try[T]]] = searchTerm.flatMap({ term =>
  39. term.map({ termAtStart =>
  40. setTimeoutResult(delay) {
  41. searchTerm.map({ termAfterDelay =>
  42. if (Some(termAtStart) == termAfterDelay)
  43. searchFn(termAtStart).toRx
  44. else
  45. Rx(None)
  46. }).flatten
  47. }.toRx.map(
  48. _.map(
  49. _.sequence[Rx, Option[Try[T]]].map(
  50. _.flatSequence[Option, T]
  51. )
  52. )
  53. ).map(_.flatSequence[Rx, Try[T]]).flatten
  54. }).flatSequence[Rx, Try[T]]
  55. }).impure.sharing
  56. }