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