e310bc9d0ea2ff1678baa4634fb3b83fc2048fa1
[platform/upstream/doxygen.git] / templates / html / navtree.js
1 /*
2  @licstart  The following is the entire license notice for the
3  JavaScript code in this file.
4
5  Copyright (C) 1997-2017 by Dimitri van Heesch
6
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
16
17  You should have received a copy of the GNU General Public License along
18  with this program; if not, write to the Free Software Foundation, Inc.,
19  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21  @licend  The above is the entire license notice
22  for the JavaScript code in this file
23  */
24 var navTreeSubIndices = new Array();
25 var arrowDown = '▼';
26 var arrowRight = '▶';
27
28 function getData(varName)
29 {
30   var i = varName.lastIndexOf('/');
31   var n = i>=0 ? varName.substring(i+1) : varName;
32   return eval(n.replace(/\-/g,'_'));
33 }
34
35 function stripPath(uri)
36 {
37   return uri.substring(uri.lastIndexOf('/')+1);
38 }
39
40 function stripPath2(uri)
41 {
42   var i = uri.lastIndexOf('/');
43   var s = uri.substring(i+1);
44   var m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/);
45   return m ? uri.substring(i-6) : s;
46 }
47
48 function hashValue()
49 {
50   return $(location).attr('hash').substring(1).replace(/[^\w\-]/g,'');
51 }
52
53 function hashUrl()
54 {
55   return '#'+hashValue();
56 }
57
58 function pathName()
59 {
60   return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]/g, '');
61 }
62
63 function localStorageSupported()
64 {
65   try {
66     return 'localStorage' in window && window['localStorage'] !== null && window.localStorage.getItem;
67   }
68   catch(e) {
69     return false;
70   }
71 }
72
73
74 function storeLink(link)
75 {
76   if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) {
77       window.localStorage.setItem('navpath',link);
78   }
79 }
80
81 function deleteLink()
82 {
83   if (localStorageSupported()) {
84     window.localStorage.setItem('navpath','');
85   }
86 }
87
88 function cachedLink()
89 {
90   if (localStorageSupported()) {
91     return window.localStorage.getItem('navpath');
92   } else {
93     return '';
94   }
95 }
96
97 function getScript(scriptName,func,show)
98 {
99   var head = document.getElementsByTagName("head")[0];
100   var script = document.createElement('script');
101   script.id = scriptName;
102   script.type = 'text/javascript';
103   script.onload = func;
104   script.src = scriptName+'.js';
105   if ($.browser.msie && $.browser.version<=8) {
106     // script.onload does not work with older versions of IE
107     script.onreadystatechange = function() {
108       if (script.readyState=='complete' || script.readyState=='loaded') {
109         func(); if (show) showRoot();
110       }
111     }
112   }
113   head.appendChild(script);
114 }
115
116 function createIndent(o,domNode,node,level)
117 {
118   var level=-1;
119   var n = node;
120   while (n.parentNode) { level++; n=n.parentNode; }
121   if (node.childrenData) {
122     var imgNode = document.createElement("span");
123     imgNode.className = 'arrow';
124     imgNode.style.paddingLeft=(16*level).toString()+'px';
125     imgNode.innerHTML=arrowRight;
126     node.plus_img = imgNode;
127     node.expandToggle = document.createElement("a");
128     node.expandToggle.href = "javascript:void(0)";
129     node.expandToggle.onclick = function() {
130       if (node.expanded) {
131         $(node.getChildrenUL()).slideUp("fast");
132         node.plus_img.innerHTML=arrowRight;
133         node.expanded = false;
134       } else {
135         expandNode(o, node, false, false);
136       }
137     }
138     node.expandToggle.appendChild(imgNode);
139     domNode.appendChild(node.expandToggle);
140   } else {
141     var span = document.createElement("span");
142     span.className = 'arrow';
143     span.style.width   = 16*(level+1)+'px';
144     span.innerHTML = '&#160;';
145     domNode.appendChild(span);
146   }
147 }
148
149 var animationInProgress = false;
150
151 function gotoAnchor(anchor,aname,updateLocation)
152 {
153   var pos, docContent = $('#doc-content');
154   var ancParent = $(anchor.parent());
155   if (ancParent.hasClass('memItemLeft') ||
156       ancParent.hasClass('fieldname') ||
157       ancParent.hasClass('fieldtype') ||
158       ancParent.is(':header'))
159   {
160     pos = ancParent.position().top;
161   } else if (anchor.position()) {
162     pos = anchor.position().top;
163   }
164   if (pos) {
165     var dist = Math.abs(Math.min(
166                pos-docContent.offset().top,
167                docContent[0].scrollHeight-
168                docContent.height()-docContent.scrollTop()));
169     animationInProgress=true;
170     docContent.animate({
171       scrollTop: pos + docContent.scrollTop() - docContent.offset().top
172     },Math.max(50,Math.min(500,dist)),function(){
173       if (updateLocation) window.location.href=aname;
174       animationInProgress=false;
175     });
176   }
177 }
178
179 function newNode(o, po, text, link, childrenData, lastNode)
180 {
181   var node = new Object();
182   node.children = Array();
183   node.childrenData = childrenData;
184   node.depth = po.depth + 1;
185   node.relpath = po.relpath;
186   node.isLast = lastNode;
187
188   node.li = document.createElement("li");
189   po.getChildrenUL().appendChild(node.li);
190   node.parentNode = po;
191
192   node.itemDiv = document.createElement("div");
193   node.itemDiv.className = "item";
194
195   node.labelSpan = document.createElement("span");
196   node.labelSpan.className = "label";
197
198   createIndent(o,node.itemDiv,node,0);
199   node.itemDiv.appendChild(node.labelSpan);
200   node.li.appendChild(node.itemDiv);
201
202   var a = document.createElement("a");
203   node.labelSpan.appendChild(a);
204   node.label = document.createTextNode(text);
205   node.expanded = false;
206   a.appendChild(node.label);
207   if (link) {
208     var url;
209     if (link.substring(0,1)=='^') {
210       url = link.substring(1);
211       link = url;
212     } else {
213       url = node.relpath+link;
214     }
215     a.className = stripPath(link.replace('#',':'));
216     if (link.indexOf('#')!=-1) {
217       var aname = '#'+link.split('#')[1];
218       var srcPage = stripPath(pathName());
219       var targetPage = stripPath(link.split('#')[0]);
220       a.href = srcPage!=targetPage ? url : "javascript:void(0)";
221       a.onclick = function(){
222         storeLink(link);
223         if (!$(a).parent().parent().hasClass('selected'))
224         {
225           $('.item').removeClass('selected');
226           $('.item').removeAttr('id');
227           $(a).parent().parent().addClass('selected');
228           $(a).parent().parent().attr('id','selected');
229         }
230         var anchor = $(aname);
231         gotoAnchor(anchor,aname,true);
232       };
233     } else {
234       a.href = url;
235       a.onclick = function() { storeLink(link); }
236     }
237   } else {
238     if (childrenData != null)
239     {
240       a.className = "nolink";
241       a.href = "javascript:void(0)";
242       a.onclick = node.expandToggle.onclick;
243     }
244   }
245
246   node.childrenUL = null;
247   node.getChildrenUL = function() {
248     if (!node.childrenUL) {
249       node.childrenUL = document.createElement("ul");
250       node.childrenUL.className = "children_ul";
251       node.childrenUL.style.display = "none";
252       node.li.appendChild(node.childrenUL);
253     }
254     return node.childrenUL;
255   };
256
257   return node;
258 }
259
260 function showRoot()
261 {
262   var headerHeight = $("#top").height();
263   var footerHeight = $("#nav-path").height();
264   var windowHeight = $(window).height() - headerHeight - footerHeight;
265   (function (){ // retry until we can scroll to the selected item
266     try {
267       var navtree=$('#nav-tree');
268       navtree.scrollTo('#selected',0,{offset:-windowHeight/2});
269     } catch (err) {
270       setTimeout(arguments.callee, 0);
271     }
272   })();
273 }
274
275 function expandNode(o, node, imm, showRoot)
276 {
277   if (node.childrenData && !node.expanded) {
278     if (typeof(node.childrenData)==='string') {
279       var varName    = node.childrenData;
280       getScript(node.relpath+varName,function(){
281         node.childrenData = getData(varName);
282         expandNode(o, node, imm, showRoot);
283       }, showRoot);
284     } else {
285       if (!node.childrenVisited) {
286         getNode(o, node);
287       } if (imm || ($.browser.msie && $.browser.version>8)) {
288         // somehow slideDown jumps to the start of tree for IE9 :-(
289         $(node.getChildrenUL()).show();
290       } else {
291         $(node.getChildrenUL()).slideDown("fast");
292       }
293       node.plus_img.innerHTML = arrowDown;
294       node.expanded = true;
295     }
296   }
297 }
298
299 function glowEffect(n,duration)
300 {
301   n.addClass('glow').delay(duration).queue(function(next){
302     $(this).removeClass('glow');next();
303   });
304 }
305
306 function highlightAnchor()
307 {
308   var aname = hashUrl();
309   var anchor = $(aname);
310   if (anchor.parent().attr('class')=='memItemLeft'){
311     var rows = $('.memberdecls tr[class$="'+hashValue()+'"]');
312     glowEffect(rows.children(),300); // member without details
313   } else if (anchor.parent().attr('class')=='fieldname'){
314     glowEffect(anchor.parent().parent(),1000); // enum value
315   } else if (anchor.parent().attr('class')=='fieldtype'){
316     glowEffect(anchor.parent().parent(),1000); // struct field
317   } else if (anchor.parent().is(":header")) {
318     glowEffect(anchor.parent(),1000); // section header
319   } else {
320     glowEffect(anchor.next(),1000); // normal member
321   }
322   gotoAnchor(anchor,aname,false);
323 }
324
325 function selectAndHighlight(hash,n)
326 {
327   var a;
328   if (hash) {
329     var link=stripPath(pathName())+':'+hash.substring(1);
330     a=$('.item a[class$="'+link+'"]');
331   }
332   if (a && a.length) {
333     a.parent().parent().addClass('selected');
334     a.parent().parent().attr('id','selected');
335     highlightAnchor();
336   } else if (n) {
337     $(n.itemDiv).addClass('selected');
338     $(n.itemDiv).attr('id','selected');
339   }
340   if ($('#nav-tree-contents .item:first').hasClass('selected')) {
341     $('#nav-sync').css('top','30px');
342   } else {
343     $('#nav-sync').css('top','5px');
344   }
345   showRoot();
346 }
347
348 function showNode(o, node, index, hash)
349 {
350   if (node && node.childrenData) {
351     if (typeof(node.childrenData)==='string') {
352       var varName    = node.childrenData;
353       getScript(node.relpath+varName,function(){
354         node.childrenData = getData(varName);
355         showNode(o,node,index,hash);
356       },true);
357     } else {
358       if (!node.childrenVisited) {
359         getNode(o, node);
360       }
361       $(node.getChildrenUL()).css({'display':'block'});
362       node.plus_img.innerHTML = arrowDown;
363       node.expanded = true;
364       var n = node.children[o.breadcrumbs[index]];
365       if (index+1<o.breadcrumbs.length) {
366         showNode(o,n,index+1,hash);
367       } else {
368         if (typeof(n.childrenData)==='string') {
369           var varName = n.childrenData;
370           getScript(n.relpath+varName,function(){
371             n.childrenData = getData(varName);
372             node.expanded=false;
373             showNode(o,node,index,hash); // retry with child node expanded
374           },true);
375         } else {
376           var rootBase = stripPath(o.toroot.replace(/\..+$/, ''));
377           if (rootBase=="index" || rootBase=="pages" || rootBase=="search") {
378             expandNode(o, n, true, true);
379           }
380           selectAndHighlight(hash,n);
381         }
382       }
383     }
384   } else {
385     selectAndHighlight(hash);
386   }
387 }
388
389 function removeToInsertLater(element) {
390   var parentNode = element.parentNode;
391   var nextSibling = element.nextSibling;
392   parentNode.removeChild(element);
393   return function() {
394     if (nextSibling) {
395       parentNode.insertBefore(element, nextSibling);
396     } else {
397       parentNode.appendChild(element);
398     }
399   };
400 }
401
402 function getNode(o, po)
403 {
404   var insertFunction = removeToInsertLater(po.li);
405   po.childrenVisited = true;
406   var l = po.childrenData.length-1;
407   for (var i in po.childrenData) {
408     var nodeData = po.childrenData[i];
409     po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2],
410       i==l);
411   }
412   insertFunction();
413 }
414
415 function gotoNode(o,subIndex,root,hash,relpath)
416 {
417   var nti = navTreeSubIndices[subIndex][root+hash];
418   o.breadcrumbs = $.extend(true, [], nti ? nti : navTreeSubIndices[subIndex][root]);
419   if (!o.breadcrumbs && root!=NAVTREE[0][1]) { // fallback: show index
420     navTo(o,NAVTREE[0][1],"",relpath);
421     $('.item').removeClass('selected');
422     $('.item').removeAttr('id');
423   }
424   if (o.breadcrumbs) {
425     o.breadcrumbs.unshift(0); // add 0 for root node
426     showNode(o, o.node, 0, hash);
427   }
428 }
429
430 function navTo(o,root,hash,relpath)
431 {
432   var link = cachedLink();
433   if (link) {
434     var parts = link.split('#');
435     root = parts[0];
436     if (parts.length>1) hash = '#'+parts[1].replace(/[^\w\-]/g,'');
437     else hash='';
438   }
439   if (hash.match(/^#l\d+$/)) {
440     var anchor=$('a[name='+hash.substring(1)+']');
441     glowEffect(anchor.parent(),1000); // line number
442     hash=''; // strip line number anchors
443   }
444   var url=root+hash;
445   var i=-1;
446   while (NAVTREEINDEX[i+1]<=url) i++;
447   if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index
448   if (navTreeSubIndices[i]) {
449     gotoNode(o,i,root,hash,relpath)
450   } else {
451     getScript(relpath+'navtreeindex'+i,function(){
452       navTreeSubIndices[i] = eval('NAVTREEINDEX'+i);
453       if (navTreeSubIndices[i]) {
454         gotoNode(o,i,root,hash,relpath);
455       }
456     },true);
457   }
458 }
459
460 function showSyncOff(n,relpath)
461 {
462     n.html('<img src="'+relpath+'sync_off.png" title="'+SYNCOFFMSG+'"/>');
463 }
464
465 function showSyncOn(n,relpath)
466 {
467     n.html('<img src="'+relpath+'sync_on.png" title="'+SYNCONMSG+'"/>');
468 }
469
470 function toggleSyncButton(relpath)
471 {
472   var navSync = $('#nav-sync');
473   if (navSync.hasClass('sync')) {
474     navSync.removeClass('sync');
475     showSyncOff(navSync,relpath);
476     storeLink(stripPath2(pathName())+hashUrl());
477   } else {
478     navSync.addClass('sync');
479     showSyncOn(navSync,relpath);
480     deleteLink();
481   }
482 }
483
484 function initNavTree(toroot,relpath)
485 {
486   var o = new Object();
487   o.toroot = toroot;
488   o.node = new Object();
489   o.node.li = document.getElementById("nav-tree-contents");
490   o.node.childrenData = NAVTREE;
491   o.node.children = new Array();
492   o.node.childrenUL = document.createElement("ul");
493   o.node.getChildrenUL = function() { return o.node.childrenUL; };
494   o.node.li.appendChild(o.node.childrenUL);
495   o.node.depth = 0;
496   o.node.relpath = relpath;
497   o.node.expanded = false;
498   o.node.isLast = true;
499   o.node.plus_img = document.createElement("span");
500   o.node.plus_img.className = 'arrow';
501   o.node.plus_img.innerHTML = arrowRight;
502
503   if (localStorageSupported()) {
504     var navSync = $('#nav-sync');
505     if (cachedLink()) {
506       showSyncOff(navSync,relpath);
507       navSync.removeClass('sync');
508     } else {
509       showSyncOn(navSync,relpath);
510     }
511     navSync.click(function(){ toggleSyncButton(relpath); });
512   }
513
514   $(window).load(function(){
515     navTo(o,toroot,hashUrl(),relpath);
516     showRoot();
517   });
518
519   $(window).bind('hashchange', function(){
520      if (window.location.hash && window.location.hash.length>1){
521        var a;
522        if ($(location).attr('hash')){
523          var clslink=stripPath(pathName())+':'+hashValue();
524          a=$('.item a[class$="'+clslink.replace(/</g,'\\3c ')+'"]');
525        }
526        if (a==null || !$(a).parent().parent().hasClass('selected')){
527          $('.item').removeClass('selected');
528          $('.item').removeAttr('id');
529        }
530        var link=stripPath2(pathName());
531        navTo(o,link,hashUrl(),relpath);
532      } else if (!animationInProgress) {
533        $('#doc-content').scrollTop(0);
534        $('.item').removeClass('selected');
535        $('.item').removeAttr('id');
536        navTo(o,toroot,hashUrl(),relpath);
537      }
538   })
539 }
540 /* @license-end */