navtree.js 14.5 KB
Newer Older
1 2
var SYNCONMSG = 'click to disable panel synchronisation';
var SYNCOFFMSG = 'click to enable panel synchronisation';
Dimitri van Heesch's avatar
Dimitri van Heesch committed
3
var navTreeSubIndices = new Array();
4

5 6 7 8
function getData(varName)
{
  var i = varName.lastIndexOf('/');
  var n = i>=0 ? varName.substring(i+1) : varName;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
9
  return eval(n.replace(/\-/g,'_'));
10 11 12 13 14 15 16
}

function stripPath(uri)
{
  return uri.substring(uri.lastIndexOf('/')+1);
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
17 18 19 20 21 22 23 24
function stripPath2(uri)
{
  var i = uri.lastIndexOf('/');
  var s = uri.substring(i+1);
  var m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/);
  return m ? uri.substring(i-6) : s;
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
25 26
function localStorageSupported()
{
27 28 29 30 31 32
  try {
    return 'localStorage' in window && window['localStorage'] !== null && window.localStorage.getItem;
  }
  catch(e) {
    return false;
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
33 34
}

35

Dimitri van Heesch's avatar
Dimitri van Heesch committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
function storeLink(link)
{
  if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) {
      window.localStorage.setItem('navpath',link);
  }
}

function deleteLink()
{
  if (localStorageSupported()) {
    window.localStorage.setItem('navpath','');
  } 
}

function cachedLink()
{
  if (localStorageSupported()) {
    return window.localStorage.getItem('navpath');
  } else {
    return '';
  }
}

59 60 61 62 63 64 65 66
function getScript(scriptName,func,show)
{
  var head = document.getElementsByTagName("head")[0]; 
  var script = document.createElement('script');
  script.id = scriptName;
  script.type = 'text/javascript';
  script.onload = func; 
  script.src = scriptName+'.js'; 
67
  if ($.browser.msie && $.browser.version<=8) { 
68
    // script.onload does not work with older versions of IE
69 70 71 72
    script.onreadystatechange = function() {
      if (script.readyState=='complete' || script.readyState=='loaded') { 
        func(); if (show) showRoot(); 
      }
73
    }
74
  }
75 76 77
  head.appendChild(script); 
}

78 79
function createIndent(o,domNode,node,level)
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
80 81 82 83
  var level=-1;
  var n = node;
  while (n.parentNode) { level++; n=n.parentNode; }
  if (node.childrenData) {
84 85 86 87 88
    var imgNode = document.createElement("img");
    imgNode.style.paddingLeft=(16*level).toString()+'px';
    imgNode.width  = 16;
    imgNode.height = 22;
    imgNode.border = 0;
89 90 91
    node.plus_img = imgNode;
    node.expandToggle = document.createElement("a");
    node.expandToggle.href = "javascript:void(0)";
92 93
    node.expandToggle.onclick = function() {
      if (node.expanded) {
94
        $(node.getChildrenUL()).slideUp("fast");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
95
        node.plus_img.src = node.relpath+"ftv2pnode.png";
96
        node.expanded = false;
97
      } else {
98
        expandNode(o, node, false, false);
99 100 101 102
      }
    }
    node.expandToggle.appendChild(imgNode);
    domNode.appendChild(node.expandToggle);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
103
    imgNode.src = node.relpath+"ftv2pnode.png";
104
  } else {
105 106 107 108
    var span = document.createElement("span");
    span.style.display = 'inline-block';
    span.style.width   = 16*(level+1)+'px';
    span.style.height  = '22px';
109
    span.innerHTML = '&#160;';
110
    domNode.appendChild(span);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
111
  } 
112 113
}

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
var animationInProgress = false;

function gotoAnchor(anchor,aname,updateLocation)
{
  var pos, docContent = $('#doc-content');
  if (anchor.parent().attr('class')=='memItemLeft' ||
      anchor.parent().attr('class')=='fieldtype' ||
      anchor.parent().is(':header')) 
  {
    pos = anchor.parent().position().top;
  } else if (anchor.position()) {
    pos = anchor.position().top;
  }
  if (pos) {
    var dist = Math.abs(Math.min(
               pos-docContent.offset().top,
               docContent[0].scrollHeight-
               docContent.height()-docContent.scrollTop()));
    animationInProgress=true;
    docContent.animate({
      scrollTop: pos + docContent.scrollTop() - docContent.offset().top
    },Math.max(50,Math.min(500,dist)),function(){
      if (updateLocation) window.location.href=aname;
      animationInProgress=false;
    });
  }
}

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
function newNode(o, po, text, link, childrenData, lastNode)
{
  var node = new Object();
  node.children = Array();
  node.childrenData = childrenData;
  node.depth = po.depth + 1;
  node.relpath = po.relpath;
  node.isLast = lastNode;

  node.li = document.createElement("li");
  po.getChildrenUL().appendChild(node.li);
  node.parentNode = po;

  node.itemDiv = document.createElement("div");
  node.itemDiv.className = "item";

  node.labelSpan = document.createElement("span");
  node.labelSpan.className = "label";

  createIndent(o,node.itemDiv,node,0);
  node.itemDiv.appendChild(node.labelSpan);
  node.li.appendChild(node.itemDiv);

  var a = document.createElement("a");
  node.labelSpan.appendChild(a);
  node.label = document.createTextNode(text);
168
  node.expanded = false;
169
  a.appendChild(node.label);
170 171 172 173 174 175 176 177
  if (link) {
    var url;
    if (link.substring(0,1)=='^') {
      url = link.substring(1);
      link = url;
    } else {
      url = node.relpath+link;
    }
178
    a.className = stripPath(link.replace('#',':'));
179
    if (link.indexOf('#')!=-1) {
180 181 182
      var aname = '#'+link.split('#')[1];
      var srcPage = stripPath($(location).attr('pathname'));
      var targetPage = stripPath(link.split('#')[0]);
183
      a.href = srcPage!=targetPage ? url : "javascript:void(0)"; 
184
      a.onclick = function(){
Dimitri van Heesch's avatar
Dimitri van Heesch committed
185
        storeLink(link);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
186 187 188 189 190 191 192
        if (!$(a).parent().parent().hasClass('selected'))
        {
          $('.item').removeClass('selected');
          $('.item').removeAttr('id');
          $(a).parent().parent().addClass('selected');
          $(a).parent().parent().attr('id','selected');
        }
193 194
        var anchor = $(aname);
        gotoAnchor(anchor,aname,true);
195
      };
196 197
    } else {
      a.href = url;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
198
      a.onclick = function() { storeLink(link); }
199
    }
200
  } else {
201 202 203 204 205 206 207 208 209
    if (childrenData != null) 
    {
      a.className = "nolink";
      a.href = "javascript:void(0)";
      a.onclick = node.expandToggle.onclick;
    }
  }

  node.childrenUL = null;
210 211
  node.getChildrenUL = function() {
    if (!node.childrenUL) {
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
      node.childrenUL = document.createElement("ul");
      node.childrenUL.className = "children_ul";
      node.childrenUL.style.display = "none";
      node.li.appendChild(node.childrenUL);
    }
    return node.childrenUL;
  };

  return node;
}

function showRoot()
{
  var headerHeight = $("#top").height();
  var footerHeight = $("#nav-path").height();
  var windowHeight = $(window).height() - headerHeight - footerHeight;
228 229
  (function (){ // retry until we can scroll to the selected item
    try {
230
      var navtree=$('#nav-tree');
231 232 233 234 235
      navtree.scrollTo('#selected',0,{offset:-windowHeight/2});
    } catch (err) {
      setTimeout(arguments.callee, 0);
    }
  })();
236 237
}

238
function expandNode(o, node, imm, showRoot)
239
{
240 241
  if (node.childrenData && !node.expanded) {
    if (typeof(node.childrenData)==='string') {
242 243 244 245 246
      var varName    = node.childrenData;
      getScript(node.relpath+varName,function(){
        node.childrenData = getData(varName);
        expandNode(o, node, imm, showRoot);
      }, showRoot);
247 248
    } else {
      if (!node.childrenVisited) {
249
        getNode(o, node);
250 251
      } if (imm || ($.browser.msie && $.browser.version>8)) { 
        // somehow slideDown jumps to the start of tree for IE9 :-(
252
        $(node.getChildrenUL()).show();
253
      } else {
254 255
        $(node.getChildrenUL()).slideDown("fast");
      }
256
      if (node.isLast) {
257
        node.plus_img.src = node.relpath+"ftv2mlastnode.png";
258
      } else {
259 260 261
        node.plus_img.src = node.relpath+"ftv2mnode.png";
      }
      node.expanded = true;
262
    }
263 264 265
  }
}

266 267 268 269 270 271 272
function glowEffect(n,duration)
{
  n.addClass('glow').delay(duration).queue(function(next){
    $(this).removeClass('glow');next();
  });
}

273 274
function highlightAnchor()
{
275 276
  var aname = $(location).attr('hash');
  var anchor = $(aname);
277
  if (anchor.parent().attr('class')=='memItemLeft'){
278
    var rows = $('.memberdecls tr[class$="'+
279
               window.location.hash.substring(1).replace(/</g,'\\3c ')+'"]');
Dimitri van Heesch's avatar
Dimitri van Heesch committed
280 281 282
    glowEffect(rows.children(),300); // member without details
  } else if (anchor.parents().slice(2).prop('tagName')=='TR') {
    glowEffect(anchor.parents('div.memitem'),1000); // enum value
Dimitri van Heesch's avatar
Dimitri van Heesch committed
283 284
  } else if (anchor.parent().attr('class')=='fieldtype'){
    glowEffect(anchor.parent().parent(),1000); // struct field
285
  } else if (anchor.parent().is(":header")) {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
286
    glowEffect(anchor.parent(),1000); // section header
287
  } else {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
288
    glowEffect(anchor.next(),1000); // normal member
289
  }
290
  gotoAnchor(anchor,aname,false);
291 292
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
293
function selectAndHighlight(hash,n)
294 295
{
  var a;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
296 297
  if (hash) {
    var link=stripPath($(location).attr('pathname'))+':'+hash.substring(1);
298
    a=$('.item a[class$="'+link.replace(/</g,'\\3c ')+'"]');
299 300 301 302 303 304 305 306
  }
  if (a && a.length) {
    a.parent().parent().addClass('selected');
    a.parent().parent().attr('id','selected');
    highlightAnchor();
  } else if (n) {
    $(n.itemDiv).addClass('selected');
    $(n.itemDiv).attr('id','selected');
307
  }
308 309 310 311 312
  if ($('#nav-tree-contents .item:first').hasClass('selected')) {
    $('#nav-sync').css('top','30px');
  } else {
    $('#nav-sync').css('top','5px');
  }
313
  showRoot();
314 315
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
316
function showNode(o, node, index, hash)
317
{
318
  if (node && node.childrenData) {
319
    if (typeof(node.childrenData)==='string') {
320 321 322
      var varName    = node.childrenData;
      getScript(node.relpath+varName,function(){
        node.childrenData = getData(varName);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
323
        showNode(o,node,index,hash);
324
      },true);
325 326
    } else {
      if (!node.childrenVisited) {
327 328
        getNode(o, node);
      }
329
      $(node.getChildrenUL()).css({'display':'block'});
330
      if (node.isLast) {
331
        node.plus_img.src = node.relpath+"ftv2mlastnode.png";
332
      } else {
333 334 335 336
        node.plus_img.src = node.relpath+"ftv2mnode.png";
      }
      node.expanded = true;
      var n = node.children[o.breadcrumbs[index]];
337
      if (index+1<o.breadcrumbs.length) {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
338
        showNode(o,n,index+1,hash);
339 340
      } else {
        if (typeof(n.childrenData)==='string') {
341 342 343 344
          var varName = n.childrenData;
          getScript(n.relpath+varName,function(){
            n.childrenData = getData(varName);
            node.expanded=false;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
345
            showNode(o,node,index,hash); // retry with child node expanded
346
          },true);
347
        } else {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
348
          var rootBase = stripPath(o.toroot.replace(/\..+$/, ''));
Dimitri van Heesch's avatar
Dimitri van Heesch committed
349
          if (rootBase=="index" || rootBase=="pages" || rootBase=="search") {
350 351
            expandNode(o, n, true, true);
          }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
352
          selectAndHighlight(hash,n);
353 354
        }
      }
355
    }
356
  } else {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
357
    selectAndHighlight(hash);
358 359 360
  }
}

361 362 363 364 365 366 367 368 369 370 371 372 373
function removeToInsertLater(element) {
  var parentNode = element.parentNode;
  var nextSibling = element.nextSibling;
  parentNode.removeChild(element);
  return function() {
    if (nextSibling) {
      parentNode.insertBefore(element, nextSibling);
    } else {
      parentNode.appendChild(element);
    }
  };
}

374 375
function getNode(o, po)
{
376
  var insertFunction = removeToInsertLater(po.li);
377 378
  po.childrenVisited = true;
  var l = po.childrenData.length-1;
379
  for (var i in po.childrenData) {
380 381
    var nodeData = po.childrenData[i];
    po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2],
382
      i==l);
383
  }
384
  insertFunction();
385 386
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
387
function gotoNode(o,subIndex,root,hash,relpath)
388
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
389
  var nti = navTreeSubIndices[subIndex][root+hash];
Dimitri van Heesch's avatar
Dimitri van Heesch committed
390
  o.breadcrumbs = $.extend(true, [], nti ? nti : navTreeSubIndices[subIndex][root]);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
391 392 393 394 395 396
  if (!o.breadcrumbs && root!=NAVTREE[0][1]) { // fallback: show index
    navTo(o,NAVTREE[0][1],"",relpath);
    $('.item').removeClass('selected');
    $('.item').removeAttr('id');
  }
  if (o.breadcrumbs) {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
397
    o.breadcrumbs.unshift(0); // add 0 for root node
Dimitri van Heesch's avatar
Dimitri van Heesch committed
398
    showNode(o, o.node, 0, hash);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
399 400 401
  }
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
402
function navTo(o,root,hash,relpath)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
403
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
404 405 406 407 408 409 410
  var link = cachedLink();
  if (link) {
    var parts = link.split('#');
    root = parts[0];
    if (parts.length>1) hash = '#'+parts[1];
    else hash='';
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
411 412 413
  if (hash.match(/^#l\d+$/)) {
    var anchor=$('a[name='+hash.substring(1)+']');
    glowEffect(anchor.parent(),1000); // line number
Dimitri van Heesch's avatar
Dimitri van Heesch committed
414
    hash=''; // strip line number anchors
Dimitri van Heesch's avatar
Dimitri van Heesch committed
415
    //root=root.replace(/_source\./,'.'); // source link to doc link
Dimitri van Heesch's avatar
Dimitri van Heesch committed
416 417 418
  }
  var url=root+hash;
  var i=-1;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
419
  while (NAVTREEINDEX[i+1]<=url) i++;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
420
  if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index
Dimitri van Heesch's avatar
Dimitri van Heesch committed
421
  if (navTreeSubIndices[i]) {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
422
    gotoNode(o,i,root,hash,relpath)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
423 424 425 426
  } else {
    getScript(relpath+'navtreeindex'+i,function(){
      navTreeSubIndices[i] = eval('NAVTREEINDEX'+i);
      if (navTreeSubIndices[i]) {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
427
        gotoNode(o,i,root,hash,relpath);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
428 429 430
      }
    },true);
  }
431 432
}

433 434 435 436 437 438 439
function showSyncOff(n,relpath)
{
    n.html('<img src="'+relpath+'sync_off.png" title="'+SYNCOFFMSG+'"/>');
}

function showSyncOn(n,relpath)
{
440
    n.html('<img src="'+relpath+'sync_on.png" title="'+SYNCONMSG+'"/>');
441 442
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
443 444 445 446 447
function toggleSyncButton(relpath)
{
  var navSync = $('#nav-sync');
  if (navSync.hasClass('sync')) {
    navSync.removeClass('sync');
448
    showSyncOff(navSync,relpath);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
449 450 451
    storeLink(stripPath2($(location).attr('pathname'))+$(location).attr('hash'));
  } else {
    navSync.addClass('sync');
452
    showSyncOn(navSync,relpath);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
453 454 455 456
    deleteLink();
  }
}

457 458 459 460 461 462 463 464 465 466 467 468 469
function initNavTree(toroot,relpath)
{
  var o = new Object();
  o.toroot = toroot;
  o.node = new Object();
  o.node.li = document.getElementById("nav-tree-contents");
  o.node.childrenData = NAVTREE;
  o.node.children = new Array();
  o.node.childrenUL = document.createElement("ul");
  o.node.getChildrenUL = function() { return o.node.childrenUL; };
  o.node.li.appendChild(o.node.childrenUL);
  o.node.depth = 0;
  o.node.relpath = relpath;
470 471 472 473 474 475
  o.node.expanded = false;
  o.node.isLast = true;
  o.node.plus_img = document.createElement("img");
  o.node.plus_img.src = relpath+"ftv2pnode.png";
  o.node.plus_img.width = 16;
  o.node.plus_img.height = 22;
476

Dimitri van Heesch's avatar
Dimitri van Heesch committed
477 478 479
  if (localStorageSupported()) {
    var navSync = $('#nav-sync');
    if (cachedLink()) {
480
      showSyncOff(navSync,relpath);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
481 482
      navSync.removeClass('sync');
    } else {
483
      showSyncOn(navSync,relpath);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
484 485 486 487
    }
    navSync.click(function(){ toggleSyncButton(relpath); });
  }

488 489
  $(window).load(function(){
    navTo(o,toroot,window.location.hash,relpath);
490
    showRoot();
491
  });
492

493 494 495 496
  $(window).bind('hashchange', function(){
     if (window.location.hash && window.location.hash.length>1){
       var a;
       if ($(location).attr('hash')){
Dimitri van Heesch's avatar
Dimitri van Heesch committed
497 498
         var clslink=stripPath($(location).attr('pathname'))+':'+
                               $(location).attr('hash').substring(1);
499
         a=$('.item a[class$="'+clslink.replace(/</g,'\\3c ')+'"]');
500
       }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
501
       if (a==null || !$(a).parent().parent().hasClass('selected')){
502 503 504
         $('.item').removeClass('selected');
         $('.item').removeAttr('id');
       }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
505
       var link=stripPath2($(location).attr('pathname'));
Dimitri van Heesch's avatar
Dimitri van Heesch committed
506
       navTo(o,link,$(location).attr('hash'),relpath);
507 508 509 510 511
     } else if (!animationInProgress) {
       $('#doc-content').scrollTop(0);
       $('.item').removeClass('selected');
       $('.item').removeAttr('id');
       navTo(o,toroot,window.location.hash,relpath);
512 513
     }
  })
514 515
}