diff options
Diffstat (limited to 'dottydoc/js/src')
-rw-r--r-- | dottydoc/js/src/DottyDoc.scala | 2 | ||||
-rw-r--r-- | dottydoc/js/src/Search.scala | 115 | ||||
-rw-r--r-- | dottydoc/js/src/html/EntityLayout.scala | 2 | ||||
-rw-r--r-- | dottydoc/js/src/html/Member.scala | 4 | ||||
-rw-r--r-- | dottydoc/js/src/model/entities.scala | 50 |
5 files changed, 134 insertions, 39 deletions
diff --git a/dottydoc/js/src/DottyDoc.scala b/dottydoc/js/src/DottyDoc.scala index 5773e6a19..d33648e49 100644 --- a/dottydoc/js/src/DottyDoc.scala +++ b/dottydoc/js/src/DottyDoc.scala @@ -18,7 +18,7 @@ import html.EntityLayout hljs.initHighlightingOnLoad() val searchInput = document.getElementById("search").asInstanceOf[dom.html.Input] - searchInput.onkeyup = Search(searchInput) + searchInput.onkeyup = new Search(searchInput).search() } } diff --git a/dottydoc/js/src/Search.scala b/dottydoc/js/src/Search.scala index 0683c5d95..6625e3c78 100644 --- a/dottydoc/js/src/Search.scala +++ b/dottydoc/js/src/Search.scala @@ -2,33 +2,120 @@ package dotty.tools.dottydoc package js import scala.scalajs.{ js => sjs } -import sjs.timers._ -import org.scalajs.dom +import sjs.timers.setTimeout +import scalatags.JsDom.all._ +import org.scalajs.dom.html.{ Input, Div } +import org.scalajs.dom.{ document, Event } +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future -object Search { +import js.model._ +import js.model.ops._ + +class Search(val input: Input) { private var isSearching = false - def apply(input: dom.html.Input) = considerSearch(input) + private val mainDiv = document + .getElementById("entity-container") + .asInstanceOf[Div] + private val resultsDiv = document + .getElementById("search-results") + .asInstanceOf[Div] + + /** Search result ADTs */ + private case class PackageResults(matching: Stream[Package], nonMatching: Stream[Package]) + private object PackageResults { + def empty = PackageResults(Stream.empty, Stream.empty) + } - def considerSearch(input: dom.html.Input): dom.Event => Unit = { e => - val query = input.value + /** Entry point into search, will consider whether to start searching or not, + * then call `performSearch` + */ + def search(): Event => Unit = { e => + val query = input.value.trim if (query.length > 2) setTimeout(200) { if (!isSearching) { isSearching = true - performSearch(query) + performSearch(query.toLowerCase).map { _ => isSearching = false } } } + else if (query.length == 0) + hideSearchDiv() } - def performSearch(query: String): Unit = { - println(s"searching for $query...") + private def performSearch(query: String): Future[Unit] = + for (PackageResults(matching, nonMatching) <- searchPackages(query)) yield { + // Clear old results, add new result categories add close button + resultsDiv.innerHTML = "" + val toplevelRes = div(id := "toplevel-results").render + val methodRes = div(id := "method-results").render + val closeButton = button( + id := "close-button", + onclick := { _: Event => + resetInput() + hideSearchDiv() + }, + cls := "mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored", + i(cls := "material-icons", "clear") + ).render + + resultsDiv.appendChild(toplevelRes) + resultsDiv.appendChild(methodRes) + resultsDiv.appendChild(closeButton) + + // Add all matching toplevel entities + matching + .toStream + .sortBy(_.name) + .map(createPackageCard) + .foreach(toplevelRes.appendChild) + + // Hide entity and show results instead + showSearchDiv() + } + + private def searchPackages(query: String): Future[PackageResults] = Future { + EntityIndex.packages.values.foldLeft(PackageResults.empty) { (acc, p) => + val matchingMembers = p.members.collect { + case x if (x.name.toLowerCase.contains(query) && x.kind != "package") => x + } + + println("We found all matching members maybe") + sjs.Dynamic.global.console.log(p) - val matchingPackages = EntityIndex.packages.values.collect { - case x if x.name.startsWith(query) => x + if (p.name.toLowerCase.contains(query) || matchingMembers.nonEmpty) + acc.copy(matching = p.withMembers(matchingMembers) #:: acc.matching) + else acc } + } + + private def createPackageCard(pack: Package): Div = div( + cls := "mdl-card mdl-shadow--2dp package-result", + div(cls := "mdl-card__title", h2(cls := "mdl-card__title-text", pack.name)), + ul(pack.members.map(createEntityLi).toList) + ).render + + private def createEntityLi(e: Entity) = li( + a( + href := toRoot + e.path.mkString("", "/", ".html"), + e.kind + " " + e.name + ) + ) + + private def toRoot = "../" * (EntityIndex.currentEntity.path.length - 1) + + private def resetInput() = { + input.value = "" + input.parentElement.className = input.parentElement.className.replaceAll("is-dirty", "") + } + + private def showSearchDiv() = { + mainDiv.style.display = "none" + resultsDiv.style.display = "block" + } - println("Found matching packages: ") - matchingPackages.map(_.name).foreach(println) - isSearching = false + private def hideSearchDiv() = { + resultsDiv.style.display = "none" + mainDiv.style.display = "block" } } diff --git a/dottydoc/js/src/html/EntityLayout.scala b/dottydoc/js/src/html/EntityLayout.scala index fcb0cd5e0..9a1076a16 100644 --- a/dottydoc/js/src/html/EntityLayout.scala +++ b/dottydoc/js/src/html/EntityLayout.scala @@ -5,7 +5,7 @@ package html import scalatags.JsDom.all._ import org.scalajs.dom import org.scalajs.dom.html.{Anchor, Div} -import model._ +import dotty.tools.dottydoc.model._ case class EntityLayout(entity: Entity) extends MemberLayout { def html = div( diff --git a/dottydoc/js/src/html/Member.scala b/dottydoc/js/src/html/Member.scala index ff16631c5..c4989e762 100644 --- a/dottydoc/js/src/html/Member.scala +++ b/dottydoc/js/src/html/Member.scala @@ -8,8 +8,8 @@ import org.scalajs.dom import org.scalajs.dom.html.{Anchor, Div} trait MemberLayout { - import model._ - import comment._ + import dotty.tools.dottydoc.model._ + import dotty.tools.dottydoc.model.comment._ def member(m: Entity, parent: Entity) = { def toggleBetween(short: Div, and: Div): Unit = diff --git a/dottydoc/js/src/model/entities.scala b/dottydoc/js/src/model/entities.scala index 2710a5392..4a4984a34 100644 --- a/dottydoc/js/src/model/entities.scala +++ b/dottydoc/js/src/model/entities.scala @@ -4,6 +4,7 @@ package js package model import scala.scalajs.{ js => sjs } +import sjs.annotation.ScalaJSDefined /** This file defines the interface for which to interact with the searchable * index. To use the normal operations available on the traits on the JVM: @@ -17,47 +18,47 @@ import scala.scalajs.{ js => sjs } * interface, this is simply due to the fact that they're not necessary for * search - YET. They could be added, for instance `comment` is missing. */ -@sjs.native -trait Entity extends sjs.Any { - val kind: String = sjs.native +@ScalaJSDefined +trait Entity extends sjs.Object { + val kind: String - val name: String = sjs.native + val name: String - val path: sjs.Array[String] = sjs.native + val path: sjs.Array[String] } -@sjs.native -trait Members extends sjs.Any { - val members: sjs.Array[Entity] = sjs.native +@ScalaJSDefined +trait Members extends sjs.Object { + val members: sjs.Array[Entity] } -@sjs.native -trait Modifiers extends sjs.Any { - val modifiers: sjs.Array[String] = sjs.native +@ScalaJSDefined +trait Modifiers extends sjs.Object { + val modifiers: sjs.Array[String] } -@sjs.native +@ScalaJSDefined trait Package extends Entity with Members -@sjs.native +@ScalaJSDefined trait Class extends Entity with Members with Modifiers -@sjs.native -trait CaseClass extends Entity with Members with Modifiers +@ScalaJSDefined +trait CaseClass extends Class -@sjs.native -trait Object extends Class with Modifiers +@ScalaJSDefined +trait Object extends Class -@sjs.native +@ScalaJSDefined trait Trait extends Class -@sjs.native +@ScalaJSDefined trait Def extends Entity with Modifiers -@sjs.native +@ScalaJSDefined trait Val extends Def -@sjs.native +@ScalaJSDefined trait Var extends Def object ops { @@ -70,5 +71,12 @@ object ops { case x if EntitiesWithMembers contains x.kind => x.asInstanceOf[Entity with Members] } + + def withMembers(mbrs: sjs.Array[Entity]): Package = new Package { + val kind = p.kind + val name = p.name + val path = p.path + val members = mbrs + } } } |