source: Dev/branches/play-2.0.1/documentation/api/scala/lib/index.js @ 322

Last change on this file since 322 was 322, checked in by hendrikvanantwerpen, 13 years ago

Added Play! framework and application with Jena dependency. Working on
the basic things now (login/register), after that start implementing
our data model.

File size: 15.5 KB
Line 
1// © 2009–2010 EPFL/LAMP
2// code by Gilles Dubochet with contributions by Johannes Rudolph and "spiros"
3
4var topLevelTemplates = undefined;
5var topLevelPackages = undefined;
6
7var scheduler = undefined;
8
9var kindFilterState = undefined;
10var focusFilterState = undefined;
11
12var title = $(document).attr('title');
13
14var lastHash = "";
15
16$(document).ready(function() {
17    $('body').layout({ west__size: '20%' });
18    $('#browser').layout({     
19        center__paneSelector: ".ui-west-center"
20        //,center__initClosed:true
21        ,north__paneSelector: ".ui-west-north"
22    });
23    $('iframe').bind("load", function(){
24        var subtitle = $(this).contents().find('title').text();
25        $(document).attr('title', (title ? title + " - " : "") + subtitle);
26       
27        setUrlFragmentFromFrameSrc();
28    });
29
30    // workaround for IE's iframe sizing lack of smartness
31    if($.browser.msie) {
32        function fixIFrame() {
33            $('iframe').height($(window).height() )
34        }
35        $('iframe').bind("load",fixIFrame)
36        $('iframe').bind("resize",fixIFrame)
37    }
38
39    scheduler = new Scheduler();
40    scheduler.addLabel("init", 1);
41    scheduler.addLabel("focus", 2);
42    scheduler.addLabel("filter", 4);
43
44    prepareEntityList();
45
46    configureTextFilter();
47    configureKindFilter();
48    configureEntityList();
49
50    setFrameSrcFromUrlFragment();
51
52    // If the url fragment changes, adjust the src of iframe "template".
53    $(window).bind('hashchange', function() {
54      if(lastFragment != window.location.hash) {
55        lastFragment = window.location.hash;
56        setFrameSrcFromUrlFragment();
57      }
58    });
59});
60
61// Set the iframe's src according to the fragment of the current url.
62// fragment = "#scala.Either" => iframe url = "scala/Either.html"
63// fragment = "#scala.Either@isRight:Boolean" => iframe url = "scala/Either.html#isRight:Boolean"
64function setFrameSrcFromUrlFragment() {
65  var fragment = location.hash.slice(1);
66  if(fragment) {
67    var loc = fragment.split("@")[0].replace(/\./g, "/");
68    if(loc.indexOf(".html") < 0) loc += ".html";
69    if(fragment.indexOf('@') > 0) loc += ("#" + fragment.split("@", 2)[1]);
70    frames["template"].location.replace(loc);
71  }
72  else
73    frames["template"].location.replace("package.html");
74}
75
76// Set the url fragment according to the src of the iframe "template".
77// iframe url = "scala/Either.html"  =>  url fragment = "#scala.Either"
78// iframe url = "scala/Either.html#isRight:Boolean"  =>  url fragment = "#scala.Either@isRight:Boolean"
79function setUrlFragmentFromFrameSrc() {
80  try {
81    var commonLength = location.pathname.lastIndexOf("/");
82    var frameLocation = frames["template"].location;
83    var relativePath = frameLocation.pathname.slice(commonLength + 1);
84   
85    if(!relativePath || frameLocation.pathname.indexOf("/") < 0)
86      return;
87   
88    // Add #, remove ".html" and replace "/" with "."
89    fragment = "#" + relativePath.replace(/\.html$/, "").replace(/\//g, ".");
90   
91    // Add the frame's hash after an @
92    if(frameLocation.hash) fragment += ("@" + frameLocation.hash.slice(1));
93 
94    // Use replace to not add history items
95    lastFragment = fragment;
96    location.replace(fragment);
97  }
98  catch(e) {
99    // Chrome doesn't allow reading the iframe's location when
100    // used on the local file system.
101  }
102}
103
104var Index = {};
105
106(function (ns) {
107    function openLink(t, type) {
108        var href;
109        if (type == 'object') {
110            href = t['object'];
111        } else {
112            href = t['class'] || t['trait'] || t['case class'];
113        }
114        return [
115            '<a class="tplshow" target="template" href="',
116            href,
117            '"><img width="13" height="13" class="',
118            type,
119            ' icon" src="lib/',
120            type,
121            '.png" />'
122        ].join('');
123    }
124
125    function createPackageHeader(pack) {
126        return [
127            '<li class="pack">',
128            '<a class="packfocus">focus</a><a class="packhide">hide</a>',
129            '<a class="tplshow" target="template" href="',
130            pack.replace(/\./g, '/'),
131            '/package.html">',
132            pack,
133            '</a></li>'
134        ].join('');
135    };
136
137    function createListItem(template) {
138        var inner = '';
139
140
141        if (template.object) {
142            inner += openLink(template, 'object');
143        }
144
145        if (template['class'] || template['trait'] || template['case class']) {
146            inner += (inner == '') ?
147                '<div class="placeholder" />' : '</a>';
148            inner += openLink(template, template['trait'] ? 'trait' : 'class');
149        } else {
150            inner += '<div class="placeholder"/>';
151        }
152
153        return [
154            '<li>',
155            inner,
156            '<span class="tplLink">',
157            template.name.replace(/^.*\./, ''),
158            '</span></a></li>'
159        ].join('');
160    }
161
162
163    ns.createPackageTree = function (pack, matched, focused) {
164        var html = $.map(matched, function (child, i) {
165            return createListItem(child);
166        }).join('');
167
168        var header;
169        if (focused && pack == focused) {
170            header = '';
171        } else {
172            header = createPackageHeader(pack);
173        }
174
175        return [
176            '<ol class="packages">',
177            header,
178            '<ol class="templates">',
179            html,
180            '</ol></ol>'
181        ].join('');
182    }
183
184    ns.keys = function (obj) {
185        var result = [];
186        var key;
187        for (key in obj) {
188            result.push(key);
189        }
190        return result;
191    }
192
193    var hiddenPackages = {};
194
195    function subPackages(pack) {
196        return $.grep($('#tpl ol.packages'), function (element, index) {
197            var pack = $('li.pack > .tplshow', element).text();
198            return pack.indexOf(pack + '.') == 0;
199        });
200    }
201
202    ns.hidePackage = function (ol) {
203        var selected = $('li.pack > .tplshow', ol).text();
204        hiddenPackages[selected] = true;
205
206        $('ol.templates', ol).hide();
207
208        $.each(subPackages(selected), function (index, element) {
209            $(element).hide();
210        });
211    }
212
213    ns.showPackage = function (ol, state) {
214        var selected = $('li.pack > .tplshow', ol).text();
215        hiddenPackages[selected] = false;
216
217        $('ol.templates', ol).show();
218
219        $.each(subPackages(selected), function (index, element) {
220            $(element).show();
221
222            // When the filter is in "packs" state,
223            // we don't want to show the `.templates`
224            var key = $('li.pack > .tplshow', element).text();
225            if (hiddenPackages[key] || state == 'packs') {
226                $('ol.templates', element).hide();
227            }
228        });
229    }
230
231})(Index);
232
233function configureEntityList() {
234    kindFilterSync();
235    configureHideFilter();
236    configureFocusFilter();
237    textFilter();
238}
239
240/* Updates the list of entities (i.e. the content of the #tpl element) from the raw form generated by Scaladoc to a
241   form suitable for display. In particular, it adds class and object etc. icons, and it configures links to open in
242   the right frame. Furthermore, it sets the two reference top-level entities lists (topLevelTemplates and
243   topLevelPackages) to serve as reference for resetting the list when needed.
244   Be advised: this function should only be called once, on page load. */
245function prepareEntityList() {
246    var classIcon = $("#library > img.class");
247    var traitIcon = $("#library > img.trait");
248    var objectIcon = $("#library > img.object");
249    var packageIcon = $("#library > img.package");
250
251    $('#tpl li.pack > a.tplshow').attr("target", "template");
252    $('#tpl li.pack').each(function () {
253        $("span.class", this).each(function() { $(this).replaceWith(classIcon.clone()); });
254        $("span.trait", this).each(function() { $(this).replaceWith(traitIcon.clone()); });
255        $("span.object", this).each(function() { $(this).replaceWith(objectIcon.clone()); });
256        $("span.package", this).each(function() { $(this).replaceWith(packageIcon.clone()); });
257    });
258    $('#tpl li.pack')
259        .prepend("<a class='packhide'>hide</a>")
260        .prepend("<a class='packfocus'>focus</a>");
261}
262
263/* Configures the text filter  */
264function configureTextFilter() {
265    scheduler.add("init", function() {
266        $("#filter").append("<div id='textfilter'><span class='pre'/><span class='input'><input type='text' accesskey='/'/></span><span class='post'/></div>");
267        printAlphabet();
268        var input = $("#textfilter input");
269        resizeFilterBlock();
270        input.bind("keyup", function(event) {
271            if (event.keyCode == 27) { // escape
272                input.attr("value", "");
273            }
274            textFilter();
275        });
276        input.focus(function(event) { input.select(); });
277    });
278    scheduler.add("init", function() {
279        $("#textfilter > .post").click(function(){
280            $("#textfilter input").attr("value", "");
281            textFilter();
282        });
283    });
284}
285
286function compilePattern(query) {
287    var escaped = query.replace(/([\.\*\+\?\|\(\)\[\]\\])/g, '\\$1');
288
289    if (query.toLowerCase() != query) {
290        // Regexp that matches CamelCase subbits: "BiSe" is
291        // "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ...
292        return new RegExp(escaped.replace(/([A-Z])/g,"[a-z]*$1"));
293    }
294    else { // if query is all lower case make a normal case insensitive search
295        return new RegExp(escaped, "i");
296    }
297}
298
299// Filters all focused templates and packages. This function should be made less-blocking.
300//   @param query The string of the query
301function textFilter() {
302    scheduler.clear("filter");
303
304    $('#tpl').html('');
305
306    var query = $("#textfilter input").attr("value") || '';
307    var queryRegExp = compilePattern(query);
308
309    var index = 0;
310
311    var searchLoop = function () {
312        var packages = Index.keys(Index.PACKAGES).sort();
313
314        while (packages[index]) {
315            var pack = packages[index];
316            var children = Index.PACKAGES[pack];
317            index++;
318
319            if (focusFilterState) {
320                if (pack == focusFilterState ||
321                    pack.indexOf(focusFilterState + '.') == 0) {
322                    ;
323                } else {
324                    continue;
325                }
326            }
327
328            var matched = $.grep(children, function (child, i) {
329                return queryRegExp.test(child.name);
330            });
331
332            if (matched.length > 0) {
333                $('#tpl').append(Index.createPackageTree(pack, matched,
334                                                         focusFilterState));
335                scheduler.add('filter', searchLoop);
336                return;
337            }
338        }
339
340        $('#tpl a.packfocus').click(function () {
341            focusFilter($(this).parent().parent());
342        });
343        configureHideFilter();
344    };
345   
346    scheduler.add('filter', searchLoop);
347}
348
349/* Configures the hide tool by adding the hide link to all packages. */
350function configureHideFilter() {
351    $('#tpl li.pack a.packhide').click(function () {
352        var packhide = $(this)
353        var action = packhide.text();
354
355        var ol = $(this).parent().parent();
356
357        if (action == "hide") {
358            Index.hidePackage(ol);
359            packhide.text("show");
360        }
361        else {
362            Index.showPackage(ol, kindFilterState);
363            packhide.text("hide");
364        }
365        return false;
366    });
367}
368
369/* Configures the focus tool by adding the focus bar in the filter box (initially hidden), and by adding the focus
370   link to all packages. */
371function configureFocusFilter() {
372    scheduler.add("init", function() {
373        focusFilterState = null;
374        if ($("#focusfilter").length == 0) {
375            $("#filter").append("<div id='focusfilter'>focused on <span class='focuscoll'></span> <a class='focusremove'><img class='icon' src='lib/remove.png'/></a></div>");
376            $("#focusfilter > .focusremove").click(function(event) {
377                textFilter();
378
379                $("#focusfilter").hide();
380                $("#kindfilter").show();
381                resizeFilterBlock();
382                focusFilterState = null;
383            });
384            $("#focusfilter").hide();
385            resizeFilterBlock();
386        }
387    });
388    scheduler.add("init", function() {
389        $('#tpl li.pack a.packfocus').click(function () {
390            focusFilter($(this).parent());
391            return false;
392        });
393    });
394}
395
396/* Focuses the entity index on a specific package. To do so, it will copy the sub-templates and sub-packages of the
397   focuses package into the top-level templates and packages position of the index. The original top-level
398     @param package The <li> element that corresponds to the package in the entity index */
399function focusFilter(package) {
400    scheduler.clear("filter");
401
402    var currentFocus = $('li.pack > .tplshow', package).text();
403    $("#focusfilter > .focuscoll").empty();
404    $("#focusfilter > .focuscoll").append(currentFocus);
405
406    $("#focusfilter").show();
407    $("#kindfilter").hide();
408    resizeFilterBlock();
409    focusFilterState = currentFocus;
410    kindFilterSync();
411
412    textFilter();
413}
414
415function configureKindFilter() {
416    scheduler.add("init", function() {
417        kindFilterState = "all";
418        $("#filter").append("<div id='kindfilter'><a>display packages only</a></div>");
419        $("#kindfilter > a").click(function(event) { kindFilter("packs"); });
420        resizeFilterBlock();
421    });
422}
423
424function kindFilter(kind) {
425    if (kind == "packs") {
426        kindFilterState = "packs";
427        kindFilterSync();
428        $("#kindfilter > a").replaceWith("<a>display all entities</a>");
429        $("#kindfilter > a").click(function(event) { kindFilter("all"); });
430    }
431    else {
432        kindFilterState = "all";
433        kindFilterSync();
434        $("#kindfilter > a").replaceWith("<a>display packages only</a>");
435        $("#kindfilter > a").click(function(event) { kindFilter("packs"); });
436    }
437}
438
439/* Applies the kind filter. */
440function kindFilterSync() {
441    if (kindFilterState == "all" || focusFilterState != null) {
442        $("#tpl a.packhide").text('hide');
443        $("#tpl ol.templates").show();
444    } else {
445        $("#tpl a.packhide").text('show');
446        $("#tpl ol.templates").hide();
447    }
448}
449
450function resizeFilterBlock() {
451    $("#tpl").css("top", $("#filter").outerHeight(true));
452}
453
454function printAlphabet() {
455    $("#filter").append("<div id='letters'><a target='template' href='index/index-%23.html'>#</a><a target='template' href='index/index-a.html'>A</a><a target='template' href='index/index-b.html'>B</a><a target='template' href='index/index-c.html'>C</a><a target='template' href='index/index-d.html'>D</a><a target='template' href='index/index-e.html'>E</a><a target='template' href='index/index-f.html'>F</a><a target='template' href='index/index-g.html'>G</a><a target='template' href='index/index-h.html'>H</a><a target='template' href='index/index-i.html'>I</a><a target='template' href='index/index-j.html'>J</a><a target='template' href='index/index-k.html'>K</a><a target='template' href='index/index-l.html'>L</a><a target='template' href='index/index-m.html'>M</a><a target='template' href='index/index-n.html'>N</a><a target='template' href='index/index-o.html'>O</a><a target='template' href='index/index-p.html'>P</a><a target='template' href='index/index-q.html'>Q</a><a target='template' href='index/index-r.html'>R</a><a target='template' href='index/index-s.html'>S</a><a target='template' href='index/index-t.html'>T</a><a target='template' href='index/index-u.html'>U</a><a target='template' href='index/index-v.html'>V</a><a target='template' href='index/index-w.html'>W</a><a target='template' href='index/index-x.html'>X</a><a target='template' href='index/index-y.html'>Y</a><a target='template' href='index/index-z.html'>Z</a></div>");
456}
457
Note: See TracBrowser for help on using the repository browser.