diff options
author | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2010-02-11 13:55:34 +0000 |
---|---|---|
committer | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2010-02-11 13:55:34 +0000 |
commit | a78bf650be7cc82e43907d1bbf966b3d802fc301 (patch) | |
tree | 841f40d822d2a33cd05570909f7d1d06676abfc7 | |
parent | c37cb5ad1d8977ebbd9a559a884d7115df980a53 (diff) | |
download | scala-a78bf650be7cc82e43907d1bbf966b3d802fc301.tar.gz scala-a78bf650be7cc82e43907d1bbf966b3d802fc301.tar.bz2 scala-a78bf650be7cc82e43907d1bbf966b3d802fc301.zip |
[scaladoc] Fixed popup content lookup so that i...
[scaladoc] Fixed popup content lookup so that it works on all browsers.
Speed-up in entity index search (according to jQuery manual, observed
no notable difference). Some small aesthetic cleanups in the way index
initialization and filtering behaves. No review.
5 files changed, 146 insertions, 140 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala index 786bb5d11d..135696a869 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala @@ -37,15 +37,8 @@ class Index(modelRoot: Package) extends HtmlPage { <img class='package icon' src='lib/package.png'/> </div> <div id="browser"> - <div id="filter"> - <div id="textfilter"> - <input type="text" accesskey="/"/> - </div> - <div id="focusfilter"> - focus on <span class="focuscoll"></span> <a class="focusremove">(remove)</a> - </div> - </div> - <div class="wu" id="tpl">{ + <div id="filter"></div> + <div class="pack" id="tpl">{ def isExcluded(dtpl: DocTemplateEntity) = { val qname = dtpl.qualifiedName (qname.startsWith("scala.Tuple") || qname.startsWith("scala.Product") || qname.startsWith("scala.Function")) && @@ -79,7 +72,7 @@ class Index(modelRoot: Package) extends HtmlPage { }</ol> <ol class="packages"> { for (sp <- pack.packages sortBy (_.name.toLowerCase)) yield - <li class="wu" title={ sp.qualifiedName }>{ packageElem(sp) }</li> + <li class="pack" title={ sp.qualifiedName }>{ packageElem(sp) }</li> }</ol> </xml:group> } diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css index 84855d0d1a..fc759867a4 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css @@ -99,7 +99,7 @@ h1 { right: 0; left: 0; bottom: 0; - top: 0; + top: 5px; position: absolute; display: block; } diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js index e70b1a0725..09e298e98a 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js @@ -1,10 +1,11 @@ // © 2009–2010 EPFL/LAMP // code by Gilles Dubochet with contributions by Johannes Rudolph and "spiros" -var topLevelTemplates = null; -var topLevelPackages = null; +var topLevelTemplates = undefined; +var topLevelPackages = undefined; var scheduler = undefined; +var domCache = undefined; $(document).ready(function() { @@ -13,13 +14,20 @@ $(document).ready(function() { scheduler.addLabel("focus", 7); scheduler.addLabel("filter", 10); - // Saves a pointer to top-level templates and packages (used to regain top-level focus after removing - // a focusing filter). - topLevelTemplates = $("#tpl > ol.templates").clone(); - topLevelPackages = $("#tpl > ol.packages").clone(); + scheduler.addForAll = function(labelName, elems, fn) { + var idx = 0; + var elem = undefined; + while (idx < elems.length) { + elem = elems[idx]; + scheduler.add(labelName, function(elem0) { fn(elem0); }, undefined, [elem]); + idx = idx + 1; + } + } - // Hides unavailable tools - $("#focusfilter").hide(); + domCache = new DomCache(); + domCache.update(); + + prepareEntityList(); configureTextFilter(); configureEntityList(); @@ -27,52 +35,61 @@ $(document).ready(function() { }); function configureEntityList() { - resizeFilterBlock(); - redirectEntityLinks(); - setEntityIcons(); configureHideFilter(); configureFocusFilter(); - resizeFilterBlock(); textFilter(); } -// Configure behaviour: links open in right frame -function redirectEntityLinks() { - $(".wu").each(function() { - scheduler.add("init", this, function() { - $("> h3 a.tplshow", this).add("> .templates a.tplshow", this).attr("target", "template"); - }); - }); +/* The DomCache class holds a series of pointers to interesting parts of the page's DOM tree. Generally, any DOM + accessor should be reduced to the context of a relevant entity from the cache. This is crucial to maintaining + decent performance of the page. */ +function DomCache() { + var cache = this; + this.packs = undefined; + this.liPacks = undefined; + this.update = function() { + cache.packs = $(".pack"); + cache.liPacks = cache.packs.filter("li"); + } } -// Configure layout: replace text by icons when necessary -function setEntityIcons() { - var classIcon = $("#library img.class"); - var traitIcon = $("#library img.trait"); - var objectIcon = $("#library img.object"); - var packageIcon = $("#library img.package"); - $("#tpl ol.templates").each(function() { - scheduler.add("init", this, function() { - $("> li span.class", this).each(function() { $(this).replaceWith(classIcon.clone()); }); - $("> li span.trait", this).each(function() { $(this).replaceWith(traitIcon.clone()); }); - $("> li span.object", this).each(function() { $(this).replaceWith(objectIcon.clone()); }); - $("> li span.package", this).each(function() { $(this).replaceWith(packageIcon.clone()); }); - }); - }); +/* Updates the list of entities (i.e. the content of the #tpl element) from the raw form generated by Scaladoc to a + form suitable for display. In particular, it adds class and object etc. icons, and it configures links to open in + the right frame. Furthermore, it sets the two reference top-level entities lists (topLevelTemplates and + topLevelPackages) to serve as reference for resetting the list when needed. + Be advised: this function should only be called once, on page load. */ +function prepareEntityList() { + var classIcon = $("#library > img.class"); + var traitIcon = $("#library > img.trait"); + var objectIcon = $("#library > img.object"); + var packageIcon = $("#library > img.package"); + scheduler.addForAll("init", domCache.packs, function(pack) { + var packTemplates = $("> ol.templates > li", pack); + $("> h3 > a.tplshow", pack).add("> a.tplshow", packTemplates).attr("target", "template"); + $("span.class", packTemplates).each(function() { $(this).replaceWith(classIcon.clone()); }); + $("span.trait", packTemplates).each(function() { $(this).replaceWith(traitIcon.clone()); }); + $("span.object", packTemplates).each(function() { $(this).replaceWith(objectIcon.clone()); }); + $("span.package", packTemplates).each(function() { $(this).replaceWith(packageIcon.clone()); }); + }); + scheduler.add("init", function() { + topLevelTemplates = $("#tpl > ol.templates").clone(); + topLevelPackages = $("#tpl > ol.packages").clone(); + }); } -// Configures behaviour: text filter filters +/* Configures the text filter */ function configureTextFilter() { - scheduler.add("init", this, function() { - $("#textfilter input").bind("keyup", function(event) { + scheduler.add("init", function() { + $("#filter").append("<div id='textfilter'><input type='text' accesskey='/'/></div>"); + var input = $("#textfilter > input"); + resizeFilterBlock(); + input.bind("keyup", function(event) { if (event.keyCode == 27) { // escape - $("#textfilter input").attr("value", ""); + input.attr("value", ""); } textFilter(); }); - $("#textfilter input").focus(function(event) { - $("#textfilter input").select(); - }); + input.focus(function(event) { input.select(); }); }); } @@ -80,122 +97,121 @@ function configureTextFilter() { // @param query The string of the query function textFilter() { scheduler.clear("filter"); - scheduler.add("filter", this, function() { + scheduler.add("filter", function() { var query = $("#textfilter input").attr("value") var queryRegExp; - if (query.toLowerCase() != query) + if (query.toLowerCase() != query) { // Regexp that matches CamelCase subbits: "BiSe" is // "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ... queryRegExp = new RegExp(query.replace(/([A-Z])/g,"[a-z]*$1")); - else - // if query is all lower case make a normal case insensitive search + } + else { // if query is all lower case make a normal case insensitive search queryRegExp = new RegExp(query, "i"); - - $(".wu").each(function() { - var pack = $(this); - scheduler.add("filter", this, function() { - $("> ol.templates > li", pack).each(function(){ - var item = $(this).attr("title"); - if (item == "" || queryRegExp.test(item)) { - $(this).show(); - $(this).removeClass("hide"); - } - else { - $(this).addClass("hide"); - $(this).hide(); - } - }); - if ($("> ol > li:not(.hide)", pack).length > 0) { - pack.show(); - pack.removeClass("hide"); + } + scheduler.addForAll("filter", domCache.packs, function(pack0) { + var pack = $(pack0); + $("> ol.templates > li", pack).each(function(){ + var item = $(this).attr("title"); + if (item == "" || queryRegExp.test(item)) { + $(this).show(); + $(this).removeClass("hide"); } else { - pack.addClass("hide"); - pack.hide(); - }; - if ($("> ol.templates > li:not(.hide)", pack).length > 0) { - $("> h3", pack).show(); - $("> .packhide", pack).show(); - $("> .packfocus", pack).show(); + $(this).addClass("hide"); + $(this).hide(); } - else { - $("> h3", pack).hide(); - $("> .packhide", pack).hide(); - $("> .packfocus", pack).hide(); - }; }); + if ($("> ol > li:not(.hide)", pack).length > 0) { + pack.show(); + pack.removeClass("hide"); + } + else { + pack.addClass("hide"); + pack.hide(); + } + if ($("> ol.templates > li:not(.hide)", pack).length > 0) { + $("> h3", pack).show(); + $("> .packhide", pack).show(); + $("> .packfocus", pack).show(); + } + else { + $("> h3", pack).hide(); + $("> .packhide", pack).hide(); + $("> .packfocus", pack).hide(); + } }); - }); } -// Configure behaviour and layout: add focus and hide links on packages +/* Configures the hide tool by adding the hide link to all packages. */ function configureHideFilter() { - scheduler.add("init", this, function() { - $("#tpl .packages > li").prepend("<a class='packhide'>hide</a>"); - - // Configures the hide links of packages - $("#tpl .packages > li > a.packhide").click(function(event){ - var action = $(this).text(); + scheduler.addForAll("init", domCache.liPacks, function(pack) { + $(pack).prepend("<a class='packhide'>hide</a>"); + $("> a.packhide", pack).click(function(event) { + var packhide = $(this) + var action = packhide.text(); if (action == "hide") { - $("~ ol", $(this)).hide(); - $(this).text("show"); + $("~ ol", packhide).hide(); + packhide.text("show"); } else { - $("~ ol", $(this)).show(); - $(this).text("hide"); + $("~ ol", packhide).show(); + packhide.text("hide"); } return false; }); }); } +/* Configures the focus tool by adding the focus bar in the filter box (initially hidden), and by adding the focus + link to all packages. */ function configureFocusFilter() { - scheduler.add("init", this, function() { - // Configures the focus links of packages - $("#focusfilter .focusremove").replaceWith("<img class='focusremove icon' src='lib/remove.png'/>"); - $("#tpl .packages > li").prepend("<a class='packfocus'>focus</a>"); - $("#tpl .packages > li > a.packfocus").click(function(event){ - focusFilter($(this).parent()); - return false; - }); - $("#focusfilter .focusremove").click(function(event){ - scheduler.clear("filter"); - $("#tpl > ol.templates").replaceWith(topLevelTemplates.clone()); - $("#tpl > ol.packages").replaceWith(topLevelPackages.clone()); + scheduler.add("init", function() { + if ($("#focusfilter").length == 0) { + $("#filter").append("<div id='focusfilter'>focused on <span class='focuscoll'></span> <a class='focusremove'><img class='icon' src='lib/remove.png'/></a></div>"); + $("#focusfilter > .focusremove").click(function(event) { + scheduler.clear("filter"); + scheduler.add("focus", function() { + $("#tpl > ol.templates").replaceWith(topLevelTemplates.clone()); + $("#tpl > ol.packages").replaceWith(topLevelPackages.clone()); + domCache.update(); + $("#focusfilter").hide(); + resizeFilterBlock(); + configureEntityList(); + }); + }); $("#focusfilter").hide(); - configureEntityList(); + resizeFilterBlock(); + } + }); + scheduler.addForAll("init", domCache.liPacks, function(pack) { + $(pack).prepend("<a class='packfocus'>focus</a>"); + $("> a.packfocus", pack).click(function(event) { + focusFilter($(this).parent()); return false; }); }); } -// Focuses the entity index on a specific package. To do so, it will copy the sub-templates and sub-packages of the -// focuses package into the top-level templates and packages position of the index. The original top-level -// @param package The <li> element that corresponds to the package in the entity index +/* Focuses the entity index on a specific package. To do so, it will copy the sub-templates and sub-packages of the + focuses package into the top-level templates and packages position of the index. The original top-level + @param package The <li> element that corresponds to the package in the entity index */ function focusFilter(package) { - scheduler.add("focus", this, function() { - + scheduler.add("focus", function() { scheduler.clear("filter"); - var currentFocus = package.attr("title"); - - $("#focusfilter .focuscoll").empty(); - $("#focusfilter .focuscoll").append(currentFocus); - - var templates = $(" > ol.templates", package); - var packages = $(" > ol.packages", package); - - $("#tpl > ol.templates").replaceWith(templates); - $("#tpl > ol.packages").replaceWith(packages); - + $("#focusfilter > .focuscoll").empty(); + $("#focusfilter > .focuscoll").append(currentFocus); + var packTemplates = $("> ol.templates", package); + var packPackages = $("> ol.packages", package); + $("#tpl > ol.templates").replaceWith(packTemplates); + $("#tpl > ol.packages").replaceWith(packPackages); + domCache.update(); $("#focusfilter").show(); resizeFilterBlock(); }); } function resizeFilterBlock() { - scheduler.add("init", this, function() { - $("#tpl").css("top", $("#filter").outerHeight(true)); - }); + $("#tpl").css("top", $("#filter").outerHeight(true)); } diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/scheduler.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/scheduler.js index d9fb8a453c..51d8ae8cc3 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/scheduler.js +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/scheduler.js @@ -3,7 +3,7 @@ function Scheduler() { var scheduler = this; - var resolution = 1; + var resolution = 0; this.timeout = undefined; this.queues = new Array(0); // an array of work pacakges indexed by index in the labels table. this.labels = new Array(0); // an indexed array of labels indexed by priority. This should be short. @@ -34,12 +34,13 @@ function Scheduler() { } return fn; } - this.add = function(labelName, self, fn) { + this.add = function(labelName, fn, self, args) { var doWork = function() { scheduler.timeout = setTimeout(function() { var work = scheduler.nextWork(); if (work != undefined) { - work[1].call(work[0]); + //alert(work[0]); + work[0].apply(work[1], work[2]); doWork(); } else { @@ -50,14 +51,10 @@ function Scheduler() { var idx = 0; while (idx < scheduler.labels.length && scheduler.labels[idx].name != labelName) { idx = idx + 1; } if (idx < scheduler.queues.length && scheduler.labels[idx].name == labelName) { - scheduler.queues[idx].push([self, fn]); - if (scheduler.timeout == undefined) { - doWork(); - } - } - else { - throw("queue for add is non existant"); + scheduler.queues[idx].push([fn, self, args]); + if (scheduler.timeout == undefined) doWork(); } + else throw("queue for add is non existant"); } this.clear = function(labelName) { var idx = 0; diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js index e69a055951..4ff278e80b 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js @@ -37,7 +37,7 @@ $(document).ready(function(){ tip: "#tooltip", position:"top center", onBeforeShow: function(ev) { - $(this.getTip()).text($(ev.srcElement).attr("name")); + $(this.getTip()).text(this.getTrigger().attr("name")); } }); $("#template div.fullcomment").hide(); |