1var resizePackagesNav;
2var classesNav;
3var devdocNav;
4var sidenav;
5var content;
6var HEADER_HEIGHT = -1;
7var cookie_namespace = 'doclava_developer';
8var NAV_PREF_TREE = "tree";
9var NAV_PREF_PANELS = "panels";
10var nav_pref;
11var toRoot;
12var isMobile = false; // true if mobile, so we can adjust some layout
13var isIE6 = false; // true if IE6
14
15// TODO: use $(document).ready instead
16function addLoadEvent(newfun) {
17  var current = window.onload;
18  if (typeof window.onload != 'function') {
19    window.onload = newfun;
20  } else {
21    window.onload = function() {
22      current();
23      newfun();
24    }
25  }
26}
27
28var agent = navigator['userAgent'].toLowerCase();
29// If a mobile phone, set flag and do mobile setup
30if ((agent.indexOf("mobile") != -1) ||      // android, iphone, ipod
31    (agent.indexOf("blackberry") != -1) ||
32    (agent.indexOf("webos") != -1) ||
33    (agent.indexOf("mini") != -1)) {        // opera mini browsers
34  isMobile = true;
35  addLoadEvent(mobileSetup);
36// If not a mobile browser, set the onresize event for IE6, and others
37} else if (agent.indexOf("msie 6") != -1) {
38  isIE6 = true;
39  addLoadEvent(function() {
40    window.onresize = resizeAll;
41  });
42} else {
43  addLoadEvent(function() {
44    window.onresize = resizeHeight;
45  });
46}
47
48function mobileSetup() {
49  $("body").css({'overflow':'auto'});
50  $("html").css({'overflow':'auto'});
51  $("#body-content").css({'position':'relative', 'top':'0'});
52  $("#doc-content").css({'overflow':'visible', 'border-left':'3px solid #DDD'});
53  $("#side-nav").css({'padding':'0'});
54  $("#nav-tree").css({'overflow-y': 'auto'});
55}
56
57/* loads the lists.js file to the page.
58Loading this in the head was slowing page load time */
59addLoadEvent( function() {
60  var lists = document.createElement("script");
61  lists.setAttribute("type","text/javascript");
62  lists.setAttribute("src", toRoot+"reference/lists.js");
63  document.getElementsByTagName("head")[0].appendChild(lists);
64} );
65
66addLoadEvent( function() {
67  $("pre:not(.no-pretty-print)").addClass("prettyprint");
68  prettyPrint();
69} );
70
71function setToRoot(root) {
72  toRoot = root;
73  // note: toRoot also used by carousel.js
74}
75
76function restoreWidth(navWidth) {
77  var windowWidth = $(window).width() + "px";
78  content.css({marginLeft:parseInt(navWidth) + 6 + "px"}); //account for 6px-wide handle-bar
79
80  if (isIE6) {
81    content.css({width:parseInt(windowWidth) - parseInt(navWidth) - 6 + "px"}); // necessary in order for scrollbars to be visible
82  }
83
84  sidenav.css({width:navWidth});
85  resizePackagesNav.css({width:navWidth});
86  classesNav.css({width:navWidth});
87  $("#packages-nav").css({width:navWidth});
88}
89
90function restoreHeight(packageHeight) {
91  var windowHeight = ($(window).height() - HEADER_HEIGHT);
92  var swapperHeight = windowHeight - 13;
93  $("#swapper").css({height:swapperHeight + "px"});
94  sidenav.css({height:windowHeight + "px"});
95  content.css({height:windowHeight + "px"});
96  resizePackagesNav.css({maxHeight:swapperHeight + "px", height:packageHeight});
97  classesNav.css({height:swapperHeight - parseInt(packageHeight) + "px"});
98  $("#packages-nav").css({height:parseInt(packageHeight) - 6 + "px"}); //move 6px to give space for the resize handle
99  devdocNav.css({height:sidenav.css("height")});
100  $("#nav-tree").css({height:swapperHeight + "px"});
101}
102
103function readCookie(cookie) {
104  var myCookie = cookie_namespace+"_"+cookie+"=";
105  if (document.cookie) {
106    var index = document.cookie.indexOf(myCookie);
107    if (index != -1) {
108      var valStart = index + myCookie.length;
109      var valEnd = document.cookie.indexOf(";", valStart);
110      if (valEnd == -1) {
111        valEnd = document.cookie.length;
112      }
113      var val = document.cookie.substring(valStart, valEnd);
114      return val;
115    }
116  }
117  return 0;
118}
119
120function writeCookie(cookie, val, section, expiration) {
121  if (val==undefined) return;
122  section = section == null ? "_" : "_"+section+"_";
123  if (expiration == null) {
124    var date = new Date();
125    date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
126    expiration = date.toGMTString();
127  }
128  document.cookie = cookie_namespace + section + cookie + "=" + val + "; expires=" + expiration+"; path=/";
129}
130
131function getSection() {
132  if (location.href.indexOf("/reference/") != -1) {
133    return "reference";
134  } else if (location.href.indexOf("/guide/") != -1) {
135    return "guide";
136  } else if (location.href.indexOf("/resources/") != -1) {
137    return "resources";
138  }
139  var basePath = getBaseUri(location.pathname);
140  return basePath.substring(1,basePath.indexOf("/",1));
141}
142
143function init() {
144  HEADER_HEIGHT = $("#header").height()+3;
145  $("#side-nav").css({position:"absolute",left:0});
146  content = $("#doc-content");
147  resizePackagesNav = $("#resize-packages-nav");
148  classesNav = $("#classes-nav");
149  sidenav = $("#side-nav");
150  devdocNav = $("#devdoc-nav");
151
152  var cookiePath = getSection() + "_";
153
154  if (!isMobile) {
155    $("#resize-packages-nav").resizable({handles: "s", resize: function(e, ui) { resizePackagesHeight(); } });
156    $(".side-nav-resizable").resizable({handles: "e", resize: function(e, ui) { resizeWidth(); } });
157    var cookieWidth = readCookie(cookiePath+'width');
158    var cookieHeight = readCookie(cookiePath+'height');
159    if (cookieWidth) {
160      restoreWidth(cookieWidth);
161    } else if ($(".side-nav-resizable").length) {
162      resizeWidth();
163    }
164    if (cookieHeight) {
165      restoreHeight(cookieHeight);
166    } else {
167      resizeHeight();
168    }
169  }
170
171  if (devdocNav.length) { // only dev guide, resources, and sdk
172    tryPopulateResourcesNav();
173    highlightNav(location.href);
174  }
175}
176
177function highlightNav(fullPageName) {
178  var lastSlashPos = fullPageName.lastIndexOf("/");
179  var firstSlashPos;
180  if (fullPageName.indexOf("/guide/") != -1) {
181      firstSlashPos = fullPageName.indexOf("/guide/");
182    } else if (fullPageName.indexOf("/sdk/") != -1) {
183      firstSlashPos = fullPageName.indexOf("/sdk/");
184    } else {
185      firstSlashPos = fullPageName.indexOf("/resources/");
186    }
187  if (lastSlashPos == (fullPageName.length - 1)) { // if the url ends in slash (add 'index.html')
188    fullPageName = fullPageName + "index.html";
189  }
190  // First check if the exact URL, with query string and all, is in the navigation menu
191  var pathPageName = fullPageName.substr(firstSlashPos);
192  var link = $("#devdoc-nav a[href$='"+ pathPageName+"']");
193  if (link.length == 0) {
194    var htmlPos = fullPageName.lastIndexOf(".html", fullPageName.length);
195    pathPageName = fullPageName.slice(firstSlashPos, htmlPos + 5); // +5 advances past ".html"
196    link = $("#devdoc-nav a[href$='"+ pathPageName+"']");
197    if ((link.length == 0) && ((fullPageName.indexOf("/guide/") != -1) || (fullPageName.indexOf("/resources/") != -1))) {
198      // if there's no match, then let's backstep through the directory until we find an index.html page
199      // that matches our ancestor directories (only for dev guide and resources)
200      lastBackstep = pathPageName.lastIndexOf("/");
201      while (link.length == 0) {
202        backstepDirectory = pathPageName.lastIndexOf("/", lastBackstep);
203        link = $("#devdoc-nav a[href$='"+ pathPageName.slice(0, backstepDirectory + 1)+"index.html']");
204        lastBackstep = pathPageName.lastIndexOf("/", lastBackstep - 1);
205        if (lastBackstep == 0) break;
206      }
207    }
208  }
209
210  // add 'selected' to the <li> or <div> that wraps this <a>
211  link.parent().addClass('selected');
212
213  // if we're in a toggleable root link (<li class=toggle-list><div><a>)
214  if (link.parent().parent().hasClass('toggle-list')) {
215    toggle(link.parent().parent(), false); // open our own list
216    // then also check if we're in a third-level nested list that's toggleable
217    if (link.parent().parent().parent().is(':hidden')) {
218      toggle(link.parent().parent().parent().parent(), false); // open the super parent list
219    }
220  }
221  // if we're in a normal nav link (<li><a>) and the parent <ul> is hidden
222  else if (link.parent().parent().is(':hidden')) {
223    toggle(link.parent().parent().parent(), false); // open the parent list
224    // then also check if the parent list is also nested in a hidden list
225    if (link.parent().parent().parent().parent().is(':hidden')) {
226      toggle(link.parent().parent().parent().parent().parent(), false); // open the super parent list
227    }
228  }
229}
230
231/* Resize the height of the nav panels in the reference,
232 * and save the new size to a cookie */
233function resizePackagesHeight() {
234  var windowHeight = ($(window).height() - HEADER_HEIGHT);
235  var swapperHeight = windowHeight - 13; // move 13px for swapper link at the bottom
236  resizePackagesNav.css({maxHeight:swapperHeight + "px"});
237  classesNav.css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"});
238
239  $("#swapper").css({height:swapperHeight + "px"});
240  $("#packages-nav").css({height:parseInt(resizePackagesNav.css("height")) - 6 + "px"}); //move 6px for handle
241
242  var section = getSection();
243  writeCookie("height", resizePackagesNav.css("height"), section, null);
244}
245
246/* Resize the height of the side-nav and doc-content divs,
247 * which creates the frame effect */
248function resizeHeight() {
249  var docContent = $("#doc-content");
250
251  // Get the window height and always resize the doc-content and side-nav divs
252  var windowHeight = ($(window).height() - HEADER_HEIGHT);
253  docContent.css({height:windowHeight + "px"});
254  $("#side-nav").css({height:windowHeight + "px"});
255
256  var href = location.href;
257  // If in the reference docs, also resize the "swapper", "classes-nav", and "nav-tree"  divs
258  if (href.indexOf("/reference/") != -1) {
259    var swapperHeight = windowHeight - 13;
260    $("#swapper").css({height:swapperHeight + "px"});
261    $("#classes-nav").css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"});
262    $("#nav-tree").css({height:swapperHeight + "px"});
263
264  // If in the dev guide docs, also resize the "devdoc-nav" div
265  } else if (href.indexOf("/guide/") != -1) {
266    $("#devdoc-nav").css({height:sidenav.css("height")});
267  } else if (href.indexOf("/resources/") != -1) {
268    $("#devdoc-nav").css({height:sidenav.css("height")});
269  }
270
271  // Hide the "Go to top" link if there's no vertical scroll
272  if ( parseInt($("#jd-content").css("height")) <= parseInt(docContent.css("height")) ) {
273    $("a[href='#top']").css({'display':'none'});
274  } else {
275    $("a[href='#top']").css({'display':'inline'});
276  }
277}
278
279/* Resize the width of the "side-nav" and the left margin of the "doc-content" div,
280 * which creates the resizable side bar */
281function resizeWidth() {
282  var windowWidth = $(window).width() + "px";
283  if (sidenav.length) {
284    var sidenavWidth = sidenav.css("width");
285  } else {
286    var sidenavWidth = 0;
287  }
288  content.css({marginLeft:parseInt(sidenavWidth) + 6 + "px"}); //account for 6px-wide handle-bar
289
290  if (isIE6) {
291    content.css({width:parseInt(windowWidth) - parseInt(sidenavWidth) - 6 + "px"}); // necessary in order to for scrollbars to be visible
292  }
293
294  resizePackagesNav.css({width:sidenavWidth});
295  classesNav.css({width:sidenavWidth});
296  $("#packages-nav").css({width:sidenavWidth});
297
298  if ($(".side-nav-resizable").length) { // Must check if the nav is resizable because IE6 calls resizeWidth() from resizeAll() for all pages
299    var section = getSection();
300    writeCookie("width", sidenavWidth, section, null);
301  }
302}
303
304/* For IE6 only,
305 * because it can't properly perform auto width for "doc-content" div,
306 * avoiding this for all browsers provides better performance */
307function resizeAll() {
308  resizeHeight();
309  resizeWidth();
310}
311
312function getBaseUri(uri) {
313  var intlUrl = (uri.substring(0,6) == "/intl/");
314  if (intlUrl) {
315    base = uri.substring(uri.indexOf('intl/')+5,uri.length);
316    base = base.substring(base.indexOf('/')+1, base.length);
317      //alert("intl, returning base url: /" + base);
318    return ("/" + base);
319  } else {
320      //alert("not intl, returning uri as found.");
321    return uri;
322  }
323}
324
325function requestAppendHL(uri) {
326//append "?hl=<lang> to an outgoing request (such as to blog)
327  var lang = getLangPref();
328  if (lang) {
329    var q = 'hl=' + lang;
330    uri += '?' + q;
331    window.location = uri;
332    return false;
333  } else {
334    return true;
335  }
336}
337
338function loadLast(cookiePath) {
339  var location = window.location.href;
340  if (location.indexOf("/"+cookiePath+"/") != -1) {
341    return true;
342  }
343  var lastPage = readCookie(cookiePath + "_lastpage");
344  if (lastPage) {
345    window.location = lastPage;
346    return false;
347  }
348  return true;
349}
350
351$(window).unload(function(){
352  var path = getBaseUri(location.pathname);
353  if (path.indexOf("/reference/") != -1) {
354    writeCookie("lastpage", path, "reference", null);
355  } else if (path.indexOf("/guide/") != -1) {
356    writeCookie("lastpage", path, "guide", null);
357  } else if (path.indexOf("/resources/") != -1) {
358    writeCookie("lastpage", path, "resources", null);
359  }
360});
361
362function toggle(obj, slide) {
363  var ul = $("ul:first", obj);
364  var li = ul.parent();
365  if (li.hasClass("closed")) {
366    if (slide) {
367      ul.slideDown("fast");
368    } else {
369      ul.show();
370    }
371    li.removeClass("closed");
372    li.addClass("open");
373    $(".toggle-img", li).attr("title", "hide pages");
374  } else {
375    ul.slideUp("fast");
376    li.removeClass("open");
377    li.addClass("closed");
378    $(".toggle-img", li).attr("title", "show pages");
379  }
380}
381
382function buildToggleLists() {
383  $(".toggle-list").each(
384    function(i) {
385      $("div:first", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>");
386      $(this).addClass("closed");
387    });
388}
389
390function getNavPref() {
391  var v = readCookie('reference_nav');
392  if (v != NAV_PREF_TREE) {
393    v = NAV_PREF_PANELS;
394  }
395  return v;
396}
397
398function chooseDefaultNav() {
399  nav_pref = getNavPref();
400  if (nav_pref == NAV_PREF_TREE) {
401    $("#nav-panels").toggle();
402    $("#panel-link").toggle();
403    $("#nav-tree").toggle();
404    $("#tree-link").toggle();
405  }
406}
407
408function swapNav() {
409  if (nav_pref == NAV_PREF_TREE) {
410    nav_pref = NAV_PREF_PANELS;
411  } else {
412    nav_pref = NAV_PREF_TREE;
413    init_default_navtree(toRoot);
414  }
415  var date = new Date();
416  date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
417  writeCookie("nav", nav_pref, "reference", date.toGMTString());
418
419  $("#nav-panels").toggle();
420  $("#panel-link").toggle();
421  $("#nav-tree").toggle();
422  $("#tree-link").toggle();
423
424  if ($("#nav-tree").is(':visible')) scrollIntoView("nav-tree");
425  else {
426    scrollIntoView("packages-nav");
427    scrollIntoView("classes-nav");
428  }
429}
430
431function scrollIntoView(nav) {
432  var navObj = $("#"+nav);
433  if (navObj.is(':visible')) {
434    var selected = $(".selected", navObj);
435    if (selected.length == 0) return;
436    if (selected.is("div")) selected = selected.parent();
437
438    var scrolling = document.getElementById(nav);
439    var navHeight = navObj.height();
440    var offsetTop = selected.position().top;
441    if (selected.parent().parent().is(".toggle-list")) offsetTop += selected.parent().parent().position().top;
442    if(offsetTop > navHeight - 92) {
443      scrolling.scrollTop = offsetTop - navHeight + 92;
444    }
445  }
446}
447
448function changeTabLang(lang) {
449  var nodes = $("#header-tabs").find("."+lang);
450  for (i=0; i < nodes.length; i++) { // for each node in this language
451    var node = $(nodes[i]);
452    node.siblings().css("display","none"); // hide all siblings
453    if (node.not(":empty").length != 0) { //if this languages node has a translation, show it
454      node.css("display","inline");
455    } else { //otherwise, show English instead
456      node.css("display","none");
457      node.siblings().filter(".en").css("display","inline");
458    }
459  }
460}
461
462function changeNavLang(lang) {
463  var nodes = $("#side-nav").find("."+lang);
464  for (i=0; i < nodes.length; i++) { // for each node in this language
465    var node = $(nodes[i]);
466    node.siblings().css("display","none"); // hide all siblings
467    if (node.not(":empty").length != 0) { // if this languages node has a translation, show it
468      node.css("display","inline");
469    } else { // otherwise, show English instead
470      node.css("display","none");
471      node.siblings().filter(".en").css("display","inline");
472    }
473  }
474}
475
476function changeDocLang(lang) {
477  changeTabLang(lang);
478  changeNavLang(lang);
479}
480
481function changeLangPref(lang, refresh) {
482  var date = new Date();
483  expires = date.toGMTString(date.setTime(date.getTime()+(10*365*24*60*60*1000))); // keep this for 50 years
484  //alert("expires: " + expires)
485  writeCookie("pref_lang", lang, null, expires);
486  //changeDocLang(lang);
487  if (refresh) {
488    l = getBaseUri(location.pathname);
489    window.location = l;
490  }
491}
492
493function loadLangPref() {
494  var lang = readCookie("pref_lang");
495  if (lang != 0) {
496    $("#language").find("option[value='"+lang+"']").attr("selected",true);
497  }
498}
499
500function getLangPref() {
501  var lang = $("#language").find(":selected").attr("value");
502  if (!lang) {
503    lang = readCookie("pref_lang");
504  }
505  return (lang != 0) ? lang : 'en';
506}
507
508
509function toggleContent(obj) {
510  var button = $(obj);
511  var div = $(obj.parentNode);
512  var toggleMe = $(".toggle-content-toggleme",div);
513  if (button.hasClass("show")) {
514    toggleMe.slideDown();
515    button.removeClass("show").addClass("hide");
516  } else {
517    toggleMe.slideUp();
518    button.removeClass("hide").addClass("show");
519  }
520  $("span", button).toggle();
521}