aboutsummaryrefslogtreecommitdiff
path: root/latest/api/lib/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'latest/api/lib/index.js')
-rw-r--r--latest/api/lib/index.js567
1 files changed, 567 insertions, 0 deletions
diff --git a/latest/api/lib/index.js b/latest/api/lib/index.js
new file mode 100644
index 0000000..3d9cf8d
--- /dev/null
+++ b/latest/api/lib/index.js
@@ -0,0 +1,567 @@
+// © 2009–2010 EPFL/LAMP
+// code by Gilles Dubochet with contributions by Johannes Rudolph, "spiros" and Marcin Kubala
+
+var topLevelTemplates = undefined;
+var topLevelPackages = undefined;
+
+var scheduler = undefined;
+
+var kindFilterState = undefined;
+var focusFilterState = undefined;
+
+var title = $(document).attr('title');
+
+var lastFragment = "";
+
+$(document).ready(function() {
+ $('body').layout({
+ west__size: '20%',
+ center__maskContents: true
+ });
+ $('#browser').layout({
+ center__paneSelector: ".ui-west-center"
+ //,center__initClosed:true
+ ,north__paneSelector: ".ui-west-north"
+ });
+ $('iframe').bind("load", function(){
+ try {
+ var subtitle = $(this).contents().find('title').text();
+ $(document).attr('title', (title ? title + " - " : "") + subtitle);
+ } catch (e) {
+ // Chrome doesn't allow reading the iframe's contents when
+ // used on the local file system.
+ }
+ setUrlFragmentFromFrameSrc();
+ });
+
+ // 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("filter", 4);
+
+ prepareEntityList();
+
+ configureTextFilter();
+ configureKindFilter();
+ configureEntityList();
+
+ setFrameSrcFromUrlFragment();
+
+ // If the url fragment changes, adjust the src of iframe "template".
+ $(window).bind('hashchange', function() {
+ if(lastFragment != window.location.hash) {
+ lastFragment = window.location.hash;
+ setFrameSrcFromUrlFragment();
+ }
+ });
+});
+
+// Set the iframe's src according to the fragment of the current url.
+// fragment = "#scala.Either" => iframe url = "scala/Either.html"
+// fragment = "#scala.Either@isRight:Boolean" => iframe url = "scala/Either.html#isRight:Boolean"
+// fragment = "#scalaz.iteratee.package@>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" => iframe url = "scalaz/iteratee/package.html#>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]"
+function setFrameSrcFromUrlFragment() {
+
+ function extractLoc(fragment) {
+ var loc = fragment.split('@')[0].replace(/\./g, "/");
+ if (loc.indexOf(".html") < 0) {
+ loc += ".html";
+ }
+ return loc;
+ }
+
+ function extractMemberSig(fragment) {
+ var splitIdx = fragment.indexOf('@');
+ if (splitIdx < 0) {
+ return;
+ }
+ return fragment.substr(splitIdx + 1);
+ }
+
+ var fragment = location.hash.slice(1);
+ if (fragment) {
+ var locWithMemeberSig = extractLoc(fragment);
+ var memberSig = extractMemberSig(fragment);
+ if (memberSig) {
+ locWithMemeberSig += "#" + memberSig;
+ }
+ frames["template"].location.replace(location.protocol + locWithMemeberSig);
+ } else {
+ console.log("empty fragment detected");
+ frames["template"].location.replace("package.html");
+ }
+}
+
+// Set the url fragment according to the src of the iframe "template".
+// iframe url = "scala/Either.html" => url fragment = "#scala.Either"
+// iframe url = "scala/Either.html#isRight:Boolean" => url fragment = "#scala.Either@isRight:Boolean"
+// iframe url = "scalaz/iteratee/package.html#>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" => fragment = "#scalaz.iteratee.package@>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]"
+function setUrlFragmentFromFrameSrc() {
+ try {
+ var commonLength = location.pathname.lastIndexOf("/");
+ var frameLocation = frames["template"].location;
+ var relativePath = frameLocation.pathname.slice(commonLength + 1);
+
+ if(!relativePath || frameLocation.pathname.indexOf("/") < 0)
+ return;
+
+ // Add #, remove ".html" and replace "/" with "."
+ fragment = "#" + relativePath.replace(/\.html$/, "").replace(/\//g, ".");
+
+ // Add the frame's hash after an @
+ if(frameLocation.hash) fragment += ("@" + frameLocation.hash.slice(1));
+
+ // Use replace to not add history items
+ lastFragment = fragment;
+ location.replace(fragment);
+ }
+ catch(e) {
+ // Chrome doesn't allow reading the iframe's location when
+ // used on the local file system.
+ }
+}
+
+var Index = {};
+
+(function (ns) {
+ function openLink(t, type) {
+ var href;
+ if (type == 'object') {
+ href = t['object'];
+ } else {
+ href = t['class'] || t['trait'] || t['case class'] || t['type'];
+ }
+ return [
+ '<a class="tplshow" target="template" href="',
+ href,
+ '"><img width="13" height="13" class="',
+ type,
+ ' icon" src="lib/',
+ type,
+ '.png" />'
+ ].join('');
+ }
+
+ function createPackageHeader(pack) {
+ return [
+ '<li class="pack">',
+ '<a class="packfocus">focus</a><a class="packhide">hide</a>',
+ '<a class="tplshow" target="template" href="',
+ pack.replace(/\./g, '/'),
+ '/package.html">',
+ pack,
+ '</a></li>'
+ ].join('');
+ };
+
+ function createListItem(template) {
+ var inner = '';
+
+
+ if (template.object) {
+ inner += openLink(template, 'object');
+ }
+
+ if (template['class'] || template['trait'] || template['case class'] || template['type']) {
+ inner += (inner == '') ?
+ '<div class="placeholder" />' : '</a>';
+ inner += openLink(template, template['trait'] ? 'trait' : template['type'] ? 'type' : 'class');
+ } else {
+ inner += '<div class="placeholder"/>';
+ }
+
+ return [
+ '<li>',
+ inner,
+ '<span class="tplLink">',
+ template.name.replace(/^.*\./, ''),
+ '</span></a></li>'
+ ].join('');
+ }
+
+
+ ns.createPackageTree = function (pack, matched, focused) {
+ var html = $.map(matched, function (child, i) {
+ return createListItem(child);
+ }).join('');
+
+ var header;
+ if (focused && pack == focused) {
+ header = '';
+ } else {
+ header = createPackageHeader(pack);
+ }
+
+ return [
+ '<ol class="packages">',
+ header,
+ '<ol class="templates">',
+ html,
+ '</ol></ol>'
+ ].join('');
+ }
+
+ ns.keys = function (obj) {
+ var result = [];
+ var key;
+ for (key in obj) {
+ result.push(key);
+ }
+ return result;
+ }
+
+ var hiddenPackages = {};
+
+ function subPackages(pack) {
+ return $.grep($('#tpl ol.packages'), function (element, index) {
+ var pack = $('li.pack > .tplshow', element).text();
+ return pack.indexOf(pack + '.') == 0;
+ });
+ }
+
+ ns.hidePackage = function (ol) {
+ var selected = $('li.pack > .tplshow', ol).text();
+ hiddenPackages[selected] = true;
+
+ $('ol.templates', ol).hide();
+
+ $.each(subPackages(selected), function (index, element) {
+ $(element).hide();
+ });
+ }
+
+ ns.showPackage = function (ol, state) {
+ var selected = $('li.pack > .tplshow', ol).text();
+ hiddenPackages[selected] = false;
+
+ $('ol.templates', ol).show();
+
+ $.each(subPackages(selected), function (index, element) {
+ $(element).show();
+
+ // When the filter is in "packs" state,
+ // we don't want to show the `.templates`
+ var key = $('li.pack > .tplshow', element).text();
+ if (hiddenPackages[key] || state == 'packs') {
+ $('ol.templates', element).hide();
+ }
+ });
+ }
+
+})(Index);
+
+function configureEntityList() {
+ kindFilterSync();
+ configureHideFilter();
+ configureFocusFilter();
+ textFilter();
+}
+
+/* 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 typeIcon = $("#library > img.type");
+ var objectIcon = $("#library > img.object");
+ var packageIcon = $("#library > img.package");
+
+ $('#tpl li.pack > a.tplshow').attr("target", "template");
+ $('#tpl li.pack').each(function () {
+ $("span.class", this).each(function() { $(this).replaceWith(classIcon.clone()); });
+ $("span.trait", this).each(function() { $(this).replaceWith(traitIcon.clone()); });
+ $("span.type", this).each(function() { $(this).replaceWith(typeIcon.clone()); });
+ $("span.object", this).each(function() { $(this).replaceWith(objectIcon.clone()); });
+ $("span.package", this).each(function() { $(this).replaceWith(packageIcon.clone()); });
+ });
+ $('#tpl li.pack')
+ .prepend("<a class='packhide'>hide</a>")
+ .prepend("<a class='packfocus'>focus</a>");
+}
+
+/* Handles all key presses while scrolling around with keyboard shortcuts in left panel */
+function keyboardScrolldownLeftPane() {
+ scheduler.add("init", function() {
+ $("#textfilter input").blur();
+ var $items = $("#tpl li");
+ $items.first().addClass('selected');
+
+ $(window).bind("keydown", function(e) {
+ var $old = $items.filter('.selected'),
+ $new;
+
+ switch ( e.keyCode ) {
+
+ case 9: // tab
+ $old.removeClass('selected');
+ break;
+
+ case 13: // enter
+ $old.removeClass('selected');
+ var $url = $old.children().filter('a:last').attr('href');
+ $("#template").attr("src",$url);
+ break;
+
+ case 27: // escape
+ $old.removeClass('selected');
+ $(window).unbind(e);
+ $("#textfilter input").focus();
+
+ break;
+
+ case 38: // up
+ $new = $old.prev();
+
+ if (!$new.length) {
+ $new = $old.parent().prev();
+ }
+
+ if ($new.is('ol') && $new.children(':last').is('ol')) {
+ $new = $new.children().children(':last');
+ } else if ($new.is('ol')) {
+ $new = $new.children(':last');
+ }
+
+ break;
+
+ case 40: // down
+ $new = $old.next();
+ if (!$new.length) {
+ $new = $old.parent().parent().next();
+ }
+ if ($new.is('ol')) {
+ $new = $new.children(':first');
+ }
+ break;
+ }
+
+ if ($new.is('li')) {
+ $old.removeClass('selected');
+ $new.addClass('selected');
+ } else if (e.keyCode == 38) {
+ $(window).unbind(e);
+ $("#textfilter input").focus();
+ }
+ });
+ });
+}
+
+/* Configures the text filter */
+function configureTextFilter() {
+ scheduler.add("init", function() {
+ $("#textfilter").append("<span class='pre'/><span class='input'><input id='index-input' type='text' accesskey='/'/></span><span class='post'/>");
+ var input = $("#textfilter input");
+ resizeFilterBlock();
+ input.bind('keyup', function(event) {
+ if (event.keyCode == 27) { // escape
+ input.attr("value", "");
+ }
+ if (event.keyCode == 40) { // down arrow
+ $(window).unbind("keydown");
+ keyboardScrolldownLeftPane();
+ return false;
+ }
+ textFilter();
+ });
+ input.bind('keydown', function(event) {
+ if (event.keyCode == 9) { // tab
+ $("#template").contents().find("#mbrsel-input").focus();
+ input.attr("value", "");
+ return false;
+ }
+ textFilter();
+ });
+ input.focus(function(event) { input.select(); });
+ });
+ scheduler.add("init", function() {
+ $("#textfilter > .post").click(function(){
+ $("#textfilter input").attr("value", "");
+ textFilter();
+ });
+ });
+}
+
+function compilePattern(query) {
+ var escaped = query.replace(/([\.\*\+\?\|\(\)\[\]\\])/g, '\\$1');
+
+ if (query.toLowerCase() != query) {
+ // Regexp that matches CamelCase subbits: "BiSe" is
+ // "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ...
+ return new RegExp(escaped.replace(/([A-Z])/g,"[a-z]*$1"));
+ }
+ else { // if query is all lower case make a normal case insensitive search
+ return new RegExp(escaped, "i");
+ }
+}
+
+// Filters all focused templates and packages. This function should be made less-blocking.
+// @param query The string of the query
+function textFilter() {
+ var query = $("#textfilter input").attr("value") || '';
+ var queryRegExp = compilePattern(query);
+
+ if ((typeof textFilter.lastQuery === "undefined") || (textFilter.lastQuery !== query)) {
+
+ textFilter.lastQuery = query;
+
+ scheduler.clear("filter");
+
+ $('#tpl').html('');
+
+ var index = 0;
+
+ var searchLoop = function () {
+ var packages = Index.keys(Index.PACKAGES).sort();
+
+ while (packages[index]) {
+ var pack = packages[index];
+ var children = Index.PACKAGES[pack];
+ index++;
+
+ if (focusFilterState) {
+ if (pack == focusFilterState ||
+ pack.indexOf(focusFilterState + '.') == 0) {
+ ;
+ } else {
+ continue;
+ }
+ }
+
+ var matched = $.grep(children, function (child, i) {
+ return queryRegExp.test(child.name);
+ });
+
+ if (matched.length > 0) {
+ $('#tpl').append(Index.createPackageTree(pack, matched,
+ focusFilterState));
+ scheduler.add('filter', searchLoop);
+ return;
+ }
+ }
+
+ $('#tpl a.packfocus').click(function () {
+ focusFilter($(this).parent().parent());
+ });
+ configureHideFilter();
+ };
+
+ scheduler.add('filter', searchLoop);
+ }
+}
+
+/* Configures the hide tool by adding the hide link to all packages. */
+function configureHideFilter() {
+ $('#tpl li.pack a.packhide').click(function () {
+ var packhide = $(this)
+ var action = packhide.text();
+
+ var ol = $(this).parent().parent();
+
+ if (action == "hide") {
+ Index.hidePackage(ol);
+ packhide.text("show");
+ }
+ else {
+ Index.showPackage(ol, kindFilterState);
+ 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) {
+ textFilter();
+
+ $("#focusfilter").hide();
+ $("#kindfilter").show();
+ resizeFilterBlock();
+ focusFilterState = null;
+ });
+ $("#focusfilter").hide();
+ resizeFilterBlock();
+ }
+ });
+ scheduler.add("init", function() {
+ $('#tpl li.pack a.packfocus').click(function () {
+ 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.clear("filter");
+
+ var currentFocus = $('li.pack > .tplshow', package).text();
+ $("#focusfilter > .focuscoll").empty();
+ $("#focusfilter > .focuscoll").append(currentFocus);
+
+ $("#focusfilter").show();
+ $("#kindfilter").hide();
+ resizeFilterBlock();
+ focusFilterState = currentFocus;
+ kindFilterSync();
+
+ textFilter();
+}
+
+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() {
+ if (kindFilterState == "all" || focusFilterState != null) {
+ $("#tpl a.packhide").text('hide');
+ $("#tpl ol.templates").show();
+ } else {
+ $("#tpl a.packhide").text('show');
+ $("#tpl ol.templates").hide();
+ }
+}
+
+function resizeFilterBlock() {
+ $("#tpl").css("top", $("#filter").outerHeight(true));
+}