| // ?? 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("org/apache/ignite/scalar/scalar$.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)); |
| } |