aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--html/haddock-util.js109
-rw-r--r--html/haddock.css7
-rw-r--r--src/Haddock/Backends/Html.hs16
3 files changed, 120 insertions, 12 deletions
diff --git a/html/haddock-util.js b/html/haddock-util.js
index fe471453..ddc7f6d0 100644
--- a/html/haddock-util.js
+++ b/html/haddock-util.js
@@ -4,17 +4,21 @@ function toggle(button,id)
var n = document.getElementById(id).style;
if (n.display == "none")
{
- button.src = "minus.gif";
- n.display = "block";
+ button.src = "minus.gif";
+ n.display = "block";
}
else
{
- button.src = "plus.gif";
- n.display = "none";
+ button.src = "plus.gif";
+ n.display = "none";
}
}
+var max_results = 50;
+var shown_range = null;
+var last_search = null;
+
function quick_search()
{
perform_search(false);
@@ -29,14 +33,101 @@ function full_search()
function perform_search(full)
{
var text = document.getElementById("searchbox").value.toLowerCase();
+ if (text == last_search && !full) return;
+ last_search = text;
+
var table = document.getElementById("indexlist");
+ var status = document.getElementById("searchmsg");
var children = table.firstChild.childNodes;
- for (var i = 0; i < children.length; i++)
+
+ // first figure out the first node with the prefix
+ var first = bisect(-1);
+ var last = (first == -1 ? -1 : bisect(1));
+
+ if (first == -1)
+ {
+ table.className = "";
+ status.innerHTML = "No results found, displaying all";
+ }
+ else if (first == 0 && last == children.length - 1)
+ {
+ table.className = "";
+ status.innerHTML = "";
+ }
+ else if (last - first >= max_results && !full)
+ {
+ table.className = "";
+ status.innerHTML = "More than " + max_results + ", press Search to display";
+ }
+ else
+ {
+ // decide what you need to clear/show
+ if (shown_range)
+ setclass(shown_range[0], shown_range[1], "indexrow");
+ setclass(first, last, "indexshow");
+ shown_range = [first, last];
+ table.className = "indexsearch";
+ status.innerHTML = "";
+ }
+
+
+ function setclass(first, last, status)
{
- var c = children[i];
- var s = c.firstChild.firstChild.data;
- var show = s.toLowerCase().indexOf(text) != -1;
+ for (var i = first; i <= last; i++)
+ {
+ children[i].className = status;
+ }
+ }
+
+
+ // do a binary search, treating 0 as ...
+ // return either -1 (no 0's found) or location of most far match
+ function bisect(dir)
+ {
+ var first = 0, finish = children.length - 1;
+ var mid, success = false;
+
+ while (finish - first > 3)
+ {
+ mid = Math.floor((finish + first) / 2);
+
+ var i = checkitem(mid);
+ if (i == 0) i = dir;
+ if (i == -1)
+ finish = mid;
+ else
+ first = mid;
+ }
+ var a = (dir == 1 ? first : finish);
+ var b = (dir == 1 ? finish : first);
+ for (var i = b; i != a - dir; i -= dir)
+ {
+ if (checkitem(i) == 0) return i;
+ }
+ return -1;
+ }
- c.style.display = (show ? "" : "none");
+
+ // from an index, decide what the result is
+ // 0 = match, -1 is lower, 1 is higher
+ function checkitem(i)
+ {
+ var s = getitem(i).toLowerCase().substr(0, text.length);
+ if (s == text) return 0;
+ else return (s > text ? -1 : 1);
+ }
+
+
+ // from an index, get its string
+ // this abstracts over alternates
+ function getitem(i)
+ {
+ for ( ; i >= 0; i--)
+ {
+ var s = children[i].firstChild.firstChild.data;
+ if (s.indexOf(' ') == -1)
+ return s;
+ }
+ return ""; // should never be reached
}
}
diff --git a/html/haddock.css b/html/haddock.css
index 14085bbe..26695270 100644
--- a/html/haddock.css
+++ b/html/haddock.css
@@ -141,6 +141,13 @@ TD.pkg {
padding-left: 10px
}
+TABLE.indexsearch TR.indexrow {
+ display: none;
+}
+TABLE.indexsearch TR.indexshow {
+ display: table-row;
+}
+
TD.indexentry {
vertical-align: top;
padding-right: 10px
diff --git a/src/Haddock/Backends/Html.hs b/src/Haddock/Backends/Html.hs
index 10bf794a..051f71a6 100644
--- a/src/Haddock/Backends/Html.hs
+++ b/src/Haddock/Backends/Html.hs
@@ -448,10 +448,20 @@ ppHtmlIndex odir doctitle maybe_package maybe_html_help_format
search_box = tda [colspan 2, thestyle "padding-top:5px;"] << search
where
search :: Html
- search = "Search: " +++ input ! [identifier "searchbox", strAttr "onkeyup" "quick_search()"] +++ " " +++ input ! [value "Search", thetype "button", onclick "full_search()"]
+ search = "Search: " +++ input ! [identifier "searchbox", strAttr "onkeyup" "quick_search()"]
+ +++ " " +++ input ! [value "Search", thetype "button", onclick "full_search()"]
+ +++ " " +++ thespan ! [identifier "searchmsg"] << " "
- index_html = td << table ! [identifier "indexlist", cellpadding 0, cellspacing 5] <<
- aboves (map indexElt index)
+ index_html = td << setTrClass (table ! [identifier "indexlist", cellpadding 0, cellspacing 5] <<
+ aboves (map indexElt index))
+
+ setTrClass :: Html -> Html
+ setTrClass (Html xs) = Html $ map f xs
+ where
+ f (HtmlTag name attrs inner)
+ | map toUpper name == "TR" = HtmlTag name (theclass "indexrow":attrs) inner
+ | otherwise = HtmlTag name attrs (setTrClass inner)
+ f x = x
index :: [(String, Map GHC.Name [(Module,Bool)])]
index = sortBy cmp (Map.toAscList full_index)