diff options
-rw-r--r-- | html/haddock-util.js | 109 | ||||
-rw-r--r-- | html/haddock.css | 7 | ||||
-rw-r--r-- | src/Haddock/Backends/Html.hs | 16 |
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) |