text: // © 2009–2010 EPFL/LAMP
  // code by Gilles Dubochet with contributions by Johannes Rudolph and "spiros"
  
  var topLevelTemplates = undefined;
  var topLevelPackages = undefined;
  
  var scheduler = undefined;
  var domCache = undefined;
  
  var kindFilterState = undefined;
  var focusFilterState = undefined;
  
  $(document).ready(function() {
  
      // workaround for IE's iframe sizing lack of smartness
      if($.browser.msie) {
          function fixIFrame() {
              $('iframe').height($(window).height() )
          }
          $('iframe').bind("load",fixIFrame)
          $('iframe').bind("resize",fixIFrame)
      }
  
      scheduler = new Scheduler();
      scheduler.addLabel("init", 1);
      scheduler.addLabel("focus", 2);
      scheduler.addLabel("kind", 3);
      scheduler.addLabel("filter", 4);
  
      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;
          }
      }
  
      domCache = new DomCache();
      domCache.update();
  
      prepareEntityList();
  
      configureTextFilter();
      configureKindFilter();
      configureEntityList();
  
  });
  
  function configureEntityList() {
      kindFilterSync();
      configureHideFilter();
      configureFocusFilter();
      textFilter();
  }
  
  /* 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");
      }
  }
  
  /* 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 the text filter  */
  function configureTextFilter() {
      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
                  input.attr("value", "");
              }
              textFilter();
          });
          input.focus(function(event) { input.select(); });
      });
  }
  
  // Filters all focused templates and packages. This function should be made less-blocking.
  //   @param query The string of the query
  function textFilter() {
      scheduler.clear("filter");
      scheduler.add("filter", function() {
          var query = $("#textfilter input").attr("value")
          var queryRegExp;
          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
              queryRegExp = new RegExp(query, "i");
          }
          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 {
                      $(this).addClass("hide");
                      $(this).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();
              }
          });
      });
  }
  
  /* Configures the hide tool by adding the hide link to all packages. */
  function configureHideFilter() {
      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", packhide).hide();
                  packhide.text("show");
              }
              else {
                  $("~ 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", function() {
          focusFilterState = null;
          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();
                      $("#kindfilter").show();
                      resizeFilterBlock();
                      focusFilterState = null;
                      configureEntityList();
                  });
              });
              $("#focusfilter").hide();
              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 */
  function focusFilter(package) {
      scheduler.add("focus", function() {
          scheduler.clear("filter");
          var currentFocus = package.attr("title");
          $("#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();
          $("#kindfilter").hide();
          resizeFilterBlock();
          focusFilterState = package;
          kindFilterSync();
      });
  }
  
  function configureKindFilter() {
      scheduler.add("init", function() {
          kindFilterState = "all";
          $("#filter").append("<div id='kindfilter'><a>display packages only</a></div>");
          $("#kindfilter > a").click(function(event) { kindFilter("packs"); });
          resizeFilterBlock();
      });
  }
  
  function kindFilter(kind) {
      if (kind == "packs") {
          kindFilterState = "packs";
          kindFilterSync();
          $("#kindfilter > a").replaceWith("<a>display all entities</a>");
          $("#kindfilter > a").click(function(event) { kindFilter("all"); });
      }
      else {
          kindFilterState = "all";
          kindFilterSync();
          $("#kindfilter > a").replaceWith("<a>display packages only</a>");
          $("#kindfilter > a").click(function(event) { kindFilter("packs"); });
      }
  }
  
  /* Applies the kind filter. */
  function kindFilterSync() {
      scheduler.add("kind", function () {
          if (kindFilterState == "all" || focusFilterState != null)
              scheduler.addForAll("kind", domCache.packs, function(pack0) {
                  $("> ol.templates", pack0).show();
              });
          else
              scheduler.addForAll("kind", domCache.packs, function(pack0) {
                  $("> ol.templates", pack0).hide();
              });
          textFilter();
      });
  }
  
  function resizeFilterBlock() {
      $("#tpl").css("top", $("#filter").outerHeight(true));
  }
  