1var classesNav; 2var devdocNav; 3var sidenav; 4var cookie_namespace = 'android_developer'; 5var NAV_PREF_TREE = "tree"; 6var NAV_PREF_PANELS = "panels"; 7var nav_pref; 8var toRoot; 9var isMobile = false; // true if mobile, so we can adjust some layout 10 11 12/****** ON LOAD SET UP STUFF *********/ 13 14var navBarIsFixed = false; 15$(document).ready(function() { 16 // init the fullscreen toggle click event 17 $('#nav-swap .fullscreen').click(function(){ 18 if ($(this).hasClass('disabled')) { 19 toggleFullscreen(true); 20 } else { 21 toggleFullscreen(false); 22 } 23 }); 24 25 // initialize the divs with custom scrollbars 26 $('.scroll-pane').jScrollPane( {verticalGutter:0} ); 27 28 // add HRs below all H2s (except for a few other h2 variants) 29 $('h2').not('#qv h2').not('#tb h2').not('#devdoc-nav h2').css({marginBottom:0}).after('<hr/>'); 30 31 // set search's onkeyup handler here so we can show suggestions 32 // even while search results are visible 33 $("#search_autocomplete").keyup(function() {return search_changed(event, false, '/')}); 34 35 // set up the search close button 36 $('.search .close').click(function() { 37 $searchInput = $('#search_autocomplete'); 38 $searchInput.attr('value', ''); 39 $(this).addClass("hide"); 40 $("#search-container").removeClass('active'); 41 $("#search_autocomplete").blur(); 42 search_focus_changed($searchInput.get(), false); // see search_autocomplete.js 43 hideResults(); // see search_autocomplete.js 44 }); 45 $('.search').click(function() { 46 if (!$('#search_autocomplete').is(":focused")) { 47 $('#search_autocomplete').focus(); 48 } 49 }); 50 51 // Set up quicknav 52 var quicknav_open = false; 53 $("#btn-quicknav").click(function() { 54 if (quicknav_open) { 55 $(this).removeClass('active'); 56 quicknav_open = false; 57 collapse(); 58 } else { 59 $(this).addClass('active'); 60 quicknav_open = true; 61 expand(); 62 } 63 }) 64 65 var expand = function() { 66 $('#header-wrap').addClass('quicknav'); 67 $('#quicknav').stop().show().animate({opacity:'1'}); 68 } 69 70 var collapse = function() { 71 $('#quicknav').stop().animate({opacity:'0'}, 100, function() { 72 $(this).hide(); 73 $('#header-wrap').removeClass('quicknav'); 74 }); 75 } 76 77 78 //Set up search 79 $("#search_autocomplete").focus(function() { 80 $("#search-container").addClass('active'); 81 }) 82 $("#search-container").mouseover(function() { 83 $("#search-container").addClass('active'); 84 $("#search_autocomplete").focus(); 85 }) 86 $("#search-container").mouseout(function() { 87 if ($("#search_autocomplete").is(":focus")) return; 88 if ($("#search_autocomplete").val() == '') { 89 setTimeout(function(){ 90 $("#search-container").removeClass('active'); 91 $("#search_autocomplete").blur(); 92 },250); 93 } 94 }) 95 $("#search_autocomplete").blur(function() { 96 if ($("#search_autocomplete").val() == '') { 97 $("#search-container").removeClass('active'); 98 } 99 }) 100 101 102 // prep nav expandos 103 var pagePath = document.location.pathname; 104 // account for intl docs by removing the intl/*/ path 105 if (pagePath.indexOf("/intl/") == 0) { 106 pagePath = pagePath.substr(pagePath.indexOf("/",6)); // start after intl/ to get last / 107 } 108 109 if (pagePath.indexOf(SITE_ROOT) == 0) { 110 if (pagePath == '' || pagePath.charAt(pagePath.length - 1) == '/') { 111 pagePath += 'index.html'; 112 } 113 } 114 115 if (SITE_ROOT.match(/\.\.\//) || SITE_ROOT == '') { 116 // If running locally, SITE_ROOT will be a relative path, so account for that by 117 // finding the relative URL to this page. This will allow us to find links on the page 118 // leading back to this page. 119 var pathParts = pagePath.split('/'); 120 var relativePagePathParts = []; 121 var upDirs = (SITE_ROOT.match(/(\.\.\/)+/) || [''])[0].length / 3; 122 for (var i = 0; i < upDirs; i++) { 123 relativePagePathParts.push('..'); 124 } 125 for (var i = 0; i < upDirs; i++) { 126 relativePagePathParts.push(pathParts[pathParts.length - (upDirs - i) - 1]); 127 } 128 relativePagePathParts.push(pathParts[pathParts.length - 1]); 129 pagePath = relativePagePathParts.join('/'); 130 } else { 131 // Otherwise the page path is already an absolute URL 132 } 133 134 // select current page in sidenav and set up prev/next links if they exist 135 var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]'); 136 if ($selNavLink.length) { 137 $selListItem = $selNavLink.closest('li'); 138 139 $selListItem.addClass('selected'); 140 $selListItem.closest('li.nav-section').addClass('expanded'); 141 $selListItem.closest('li.nav-section').children('ul').show(); 142 $selListItem.closest('li.nav-section').parent().closest('li.nav-section').addClass('expanded'); 143 $selListItem.closest('li.nav-section').parent().closest('ul').show(); 144 145 146 // $selListItem.closest('li.nav-section').closest('li.nav-section').addClass('expanded'); 147 // $selListItem.closest('li.nav-section').closest('li.nav-section').children('ul').show(); 148 149 // set up prev links 150 var $prevLink = []; 151 var $prevListItem = $selListItem.prev('li'); 152 153 var crossBoundaries = ($("body.design").length > 0) || ($("body.guide").length > 0) ? true : 154false; // navigate across topic boundaries only in design docs 155 if ($prevListItem.length) { 156 if ($prevListItem.hasClass('nav-section')) { 157 if (crossBoundaries) { 158 // jump to last topic of previous section 159 $prevLink = $prevListItem.find('a:last'); 160 } 161 } else { 162 // jump to previous topic in this section 163 $prevLink = $prevListItem.find('a:eq(0)'); 164 } 165 } else { 166 // jump to this section's index page (if it exists) 167 var $parentListItem = $selListItem.parents('li'); 168 $prevLink = $selListItem.parents('li').find('a'); 169 170 // except if cross boundaries aren't allowed, and we're at the top of a section already 171 // (and there's another parent) 172 if (!crossBoundaries && $parentListItem.hasClass('nav-section') 173 && $selListItem.hasClass('nav-section')) { 174 $prevLink = []; 175 } 176 } 177 178 if ($prevLink.length) { 179 var prevHref = $prevLink.attr('href'); 180 if (prevHref == SITE_ROOT + 'index.html') { 181 // Don't show Previous when it leads to the homepage 182 } else { 183 $('.prev-page-link').attr('href', $prevLink.attr('href')).removeClass("hide"); 184 } 185 } 186 187 // set up next links 188 var $nextLink = []; 189 var startCourse = false; 190 var startClass = false; 191 var training = $(".next-class-link").length; // decides whether to provide "next class" link 192 var isCrossingBoundary = false; 193 194 if ($selListItem.hasClass('nav-section')) { 195 // we're on an index page, jump to the first topic 196 $nextLink = $selListItem.find('ul').find('a:eq(0)'); 197 198 // if there aren't any children, go to the next section (required for About pages) 199 if($nextLink.length == 0) { 200 $nextLink = $selListItem.next('li').find('a'); 201 } 202 203 // Handle some Training specialties 204 if ($selListItem.parent().is("#nav") && $(".start-course-link").length) { 205 // this means we're at the very top of the TOC hierarchy 206 startCourse = true; 207 } else if ($(".start-class-link").length) { 208 // this means this page has children but is not at the top (it's a class, not a course) 209 startClass = true; 210 } 211 } else { 212 // jump to the next topic in this section (if it exists) 213 $nextLink = $selListItem.next('li').find('a:eq(0)'); 214 if (!$nextLink.length) { 215 if (crossBoundaries || training) { 216 // no more topics in this section, jump to the first topic in the next section 217 $nextLink = $selListItem.parents('li:eq(0)').next('li.nav-section').find('a:eq(0)'); 218 isCrossingBoundary = true; 219 } 220 } 221 } 222 if ($nextLink.length) { 223 if (startCourse || startClass) { 224 if (startCourse) { 225 $('.start-course-link').attr('href', $nextLink.attr('href')).removeClass("hide"); 226 } else { 227 $('.start-class-link').attr('href', $nextLink.attr('href')).removeClass("hide"); 228 } 229 // if there's no training bar (below the start button), 230 // then we need to add a bottom border to button 231 if (!$("#tb").length) { 232 $('.start-course-link').css({'border-bottom':'1px solid #DADADA'}); 233 $('.start-class-link').css({'border-bottom':'1px solid #DADADA'}); 234 } 235 } else if (training && isCrossingBoundary) { 236 $('.content-footer.next-class').show(); 237 $('.next-page-link').attr('href','') 238 .removeClass("hide").addClass("disabled") 239 .click(function() { return false; }); 240 241 $('.next-class-link').attr('href',$nextLink.attr('href')) 242 .removeClass("hide").append($nextLink.html()); 243 $('.next-class-link').find('.new').empty(); 244 } else { 245 $('.next-page-link').attr('href', $nextLink.attr('href')).removeClass("hide"); 246 } 247 } 248 249 } 250 251 252 253 // Set up expand/collapse behavior 254 $('#nav li.nav-section .nav-section-header').click(function() { 255 var section = $(this).closest('li.nav-section'); 256 if (section.hasClass('expanded')) { 257 /* hide me */ 258 // if (section.hasClass('selected') || section.find('li').hasClass('selected')) { 259 // /* but not if myself or my descendents are selected */ 260 // return; 261 // } 262 section.children('ul').slideUp(250, function() { 263 section.closest('li').removeClass('expanded'); 264 resizeNav(); 265 }); 266 } else { 267 /* show me */ 268 // first hide all other siblings 269 var $others = $('li.nav-section.expanded', $(this).closest('ul')); 270 $others.removeClass('expanded').children('ul').slideUp(250); 271 272 // now expand me 273 section.closest('li').addClass('expanded'); 274 section.children('ul').slideDown(250, function() { 275 resizeNav(); 276 }); 277 } 278 }); 279 280 $(".scroll-pane").scroll(function(event) { 281 event.preventDefault(); 282 return false; 283 }); 284 285 /* Resize nav height when window height changes */ 286 $(window).resize(function() { 287 if ($('#side-nav').length == 0) return; 288 var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]'); 289 setNavBarLeftPos(); // do this even if sidenav isn't fixed because it could become fixed 290 // make sidenav behave when resizing the window and side-scolling is a concern 291 if (navBarIsFixed) { 292 if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) { 293 updateSideNavPosition(); 294 } else { 295 updateSidenavFullscreenWidth(); 296 } 297 } 298 resizeNav(); 299 }); 300 301 302 // Set up fixed navbar 303 var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll 304 $(window).scroll(function(event) { 305 if ($('#side-nav').length == 0) return; 306 if (event.target.nodeName == "DIV") { 307 // Dump scroll event if the target is a DIV, because that means the event is coming 308 // from a scrollable div and so there's no need to make adjustments to our layout 309 return; 310 } 311 var scrollTop = $(window).scrollTop(); 312 var headerHeight = $('#header').outerHeight(); 313 var subheaderHeight = $('#nav-x').outerHeight(); 314 var searchResultHeight = $('#searchResults').is(":visible") ? 315 $('#searchResults').outerHeight() : 0; 316 var totalHeaderHeight = headerHeight + subheaderHeight + searchResultHeight; 317 var navBarShouldBeFixed = scrollTop > totalHeaderHeight; 318 319 var scrollLeft = $(window).scrollLeft(); 320 // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match 321 if (navBarIsFixed && (scrollLeft != prevScrollLeft)) { 322 updateSideNavPosition(); 323 prevScrollLeft = scrollLeft; 324 } 325 326 // Don't continue if the header is sufficently far away 327 // (to avoid intensive resizing that slows scrolling) 328 if (navBarIsFixed && navBarShouldBeFixed) { 329 return; 330 } 331 332 if (navBarIsFixed != navBarShouldBeFixed) { 333 if (navBarShouldBeFixed) { 334 // make it fixed 335 var width = $('#devdoc-nav').width(); 336 $('#devdoc-nav') 337 .addClass('fixed') 338 .css({'width':width+'px'}) 339 .prependTo('#body-content'); 340 // add neato "back to top" button 341 $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'}); 342 343 // update the sidenaav position for side scrolling 344 updateSideNavPosition(); 345 } else { 346 // make it static again 347 $('#devdoc-nav') 348 .removeClass('fixed') 349 .css({'width':'auto','margin':''}) 350 .prependTo('#side-nav'); 351 $('#devdoc-nav a.totop').hide(); 352 } 353 navBarIsFixed = navBarShouldBeFixed; 354 } 355 356 resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance 357 }); 358 359 360 var navBarLeftPos; 361 if ($('#devdoc-nav').length) { 362 setNavBarLeftPos(); 363 } 364 365 366 // Stop expand/collapse behavior when clicking on nav section links (since we're navigating away 367 // from the page) 368 $('.nav-section-header').find('a:eq(0)').click(function(evt) { 369 window.location.href = $(this).attr('href'); 370 return false; 371 }); 372 373 // Set up play-on-hover <video> tags. 374 $('video.play-on-hover').bind('click', function(){ 375 $(this).get(0).load(); // in case the video isn't seekable 376 $(this).get(0).play(); 377 }); 378 379 // Set up tooltips 380 var TOOLTIP_MARGIN = 10; 381 $('acronym').each(function() { 382 var $target = $(this); 383 var $tooltip = $('<div>') 384 .addClass('tooltip-box') 385 .text($target.attr('title')) 386 .hide() 387 .appendTo('body'); 388 $target.removeAttr('title'); 389 390 $target.hover(function() { 391 // in 392 var targetRect = $target.offset(); 393 targetRect.width = $target.width(); 394 targetRect.height = $target.height(); 395 396 $tooltip.css({ 397 left: targetRect.left, 398 top: targetRect.top + targetRect.height + TOOLTIP_MARGIN 399 }); 400 $tooltip.addClass('below'); 401 $tooltip.show(); 402 }, function() { 403 // out 404 $tooltip.hide(); 405 }); 406 }); 407 408 // Set up <h2> deeplinks 409 $('h2').click(function() { 410 var id = $(this).attr('id'); 411 if (id) { 412 document.location.hash = id; 413 } 414 }); 415 416 //Loads the +1 button 417 var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; 418 po.src = 'https://apis.google.com/js/plusone.js'; 419 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); 420 421 422 // Revise the sidenav widths to make room for the scrollbar 423 // which avoids the visible width from changing each time the bar appears 424 var $sidenav = $("#side-nav"); 425 var sidenav_width = parseInt($sidenav.innerWidth()); 426 427 $("#devdoc-nav #nav").css("width", sidenav_width - 4 + "px"); // 4px is scrollbar width 428 429 430 $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller 431 432 if ($(".scroll-pane").length > 1) { 433 // Check if there's a user preference for the panel heights 434 var cookieHeight = readCookie("reference_height"); 435 if (cookieHeight) { 436 restoreHeight(cookieHeight); 437 } 438 } 439 440 resizeNav(); 441 442 443}); 444 445 446 447function toggleFullscreen(enable) { 448 var delay = 20; 449 var enabled = true; 450 var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]'); 451 if (enable) { 452 // Currently NOT USING fullscreen; enable fullscreen 453 stylesheet.removeAttr('disabled'); 454 $('#nav-swap .fullscreen').removeClass('disabled'); 455 $('#devdoc-nav').css({left:''}); 456 setTimeout(updateSidenavFullscreenWidth,delay); // need to wait a moment for css to switch 457 enabled = true; 458 } else { 459 // Currently USING fullscreen; disable fullscreen 460 stylesheet.attr('disabled', 'disabled'); 461 $('#nav-swap .fullscreen').addClass('disabled'); 462 setTimeout(updateSidenavFixedWidth,delay); // need to wait a moment for css to switch 463 enabled = false; 464 } 465 writeCookie("fullscreen", enabled, null, null); 466 setNavBarLeftPos(); 467 resizeNav(delay); 468 updateSideNavPosition(); 469 setTimeout(initSidenavHeightResize,delay); 470} 471 472 473function setNavBarLeftPos() { 474 navBarLeftPos = $('#body-content').offset().left; 475} 476 477 478function updateSideNavPosition() { 479 var newLeft = $(window).scrollLeft() - navBarLeftPos; 480 $('#devdoc-nav').css({left: -newLeft}); 481 $('#devdoc-nav .totop').css({left: -(newLeft - parseInt($('#side-nav').css('margin-left')))}); 482} 483 484 485 486 487 488 489 490 491// TODO: use $(document).ready instead 492function addLoadEvent(newfun) { 493 var current = window.onload; 494 if (typeof window.onload != 'function') { 495 window.onload = newfun; 496 } else { 497 window.onload = function() { 498 current(); 499 newfun(); 500 } 501 } 502} 503 504var agent = navigator['userAgent'].toLowerCase(); 505// If a mobile phone, set flag and do mobile setup 506if ((agent.indexOf("mobile") != -1) || // android, iphone, ipod 507 (agent.indexOf("blackberry") != -1) || 508 (agent.indexOf("webos") != -1) || 509 (agent.indexOf("mini") != -1)) { // opera mini browsers 510 isMobile = true; 511} 512 513 514/* loads the lists.js file to the page. 515Loading this in the head was slowing page load time */ 516addLoadEvent( function() { 517 var lists = document.createElement("script"); 518 lists.setAttribute("type","text/javascript"); 519 lists.setAttribute("src", toRoot+"reference/lists.js"); 520 document.getElementsByTagName("head")[0].appendChild(lists); 521} ); 522 523 524addLoadEvent( function() { 525 $("pre:not(.no-pretty-print)").addClass("prettyprint"); 526 prettyPrint(); 527} ); 528 529function setToRoot(root) { 530 toRoot = root; 531 // note: toRoot also used by carousel.js 532} 533 534function init() { 535 //resizeNav(); 536 537 resizePackagesNav = $("#resize-packages-nav"); 538 classesNav = $("#classes-nav"); 539 devdocNav = $("#devdoc-nav"); 540 541 var cookiePath = ""; 542 if (location.href.indexOf("/reference/") != -1) { 543 cookiePath = "reference_"; 544 } else if (location.href.indexOf("/guide/") != -1) { 545 cookiePath = "guide_"; 546 } else if (location.href.indexOf("/tools/") != -1) { 547 cookiePath = "tools_"; 548 } else if (location.href.indexOf("/training/") != -1) { 549 cookiePath = "training_"; 550 } else if (location.href.indexOf("/design/") != -1) { 551 cookiePath = "design_"; 552 } else if (location.href.indexOf("/distribute/") != -1) { 553 cookiePath = "distribute_"; 554 } 555} 556 557 558 559/* ######### RESIZE THE SIDENAV HEIGHT ########## */ 560 561function resizeNav(delay) { 562 var $nav = $("#devdoc-nav"); 563 var $window = $(window); 564 var navHeight; 565 566 // Get the height of entire window and the total header height. 567 // Then figure out based on scroll position whether the header is visible 568 var windowHeight = $window.height(); 569 var scrollTop = $window.scrollTop(); 570 var headerHeight = $('#header').outerHeight(); 571 var subheaderHeight = $('#nav-x').outerHeight(); 572 var headerVisible = (scrollTop < (headerHeight + subheaderHeight)); 573 574 // get the height of space between nav and top of window. 575 // Could be either margin or top position, depending on whether the nav is fixed. 576 var topMargin = (parseInt($nav.css('margin-top')) || parseInt($nav.css('top'))) + 1; 577 // add 1 for the #side-nav bottom margin 578 579 // Depending on whether the header is visible, set the side nav's height. 580 if (headerVisible) { 581 // The sidenav height grows as the header goes off screen 582 navHeight = windowHeight - (headerHeight + subheaderHeight - scrollTop) - topMargin; 583 } else { 584 // Once header is off screen, the nav height is almost full window height 585 navHeight = windowHeight - topMargin; 586 } 587 588 589 590 $scrollPanes = $(".scroll-pane"); 591 if ($scrollPanes.length > 1) { 592 // subtract the height of the api level widget and nav swapper from the available nav height 593 navHeight -= ($('#api-nav-header').outerHeight(true) + $('#nav-swap').outerHeight(true)); 594 595 $("#swapper").css({height:navHeight + "px"}); 596 if ($("#nav-tree").is(":visible")) { 597 $("#nav-tree").css({height:navHeight}); 598 } 599 600 var classesHeight = navHeight - parseInt($("#resize-packages-nav").css("height")) - 10 + "px"; 601 //subtract 10px to account for drag bar 602 603 // if the window becomes small enough to make the class panel height 0, 604 // then the package panel should begin to shrink 605 if (parseInt(classesHeight) <= 0) { 606 $("#resize-packages-nav").css({height:navHeight - 10}); //subtract 10px for drag bar 607 $("#packages-nav").css({height:navHeight - 10}); 608 } 609 610 $("#classes-nav").css({'height':classesHeight, 'margin-top':'10px'}); 611 $("#classes-nav .jspContainer").css({height:classesHeight}); 612 613 614 } else { 615 $nav.height(navHeight); 616 } 617 618 if (delay) { 619 updateFromResize = true; 620 delayedReInitScrollbars(delay); 621 } else { 622 reInitScrollbars(); 623 } 624 625} 626 627var updateScrollbars = false; 628var updateFromResize = false; 629 630/* Re-initialize the scrollbars to account for changed nav size. 631 * This method postpones the actual update by a 1/4 second in order to optimize the 632 * scroll performance while the header is still visible, because re-initializing the 633 * scroll panes is an intensive process. 634 */ 635function delayedReInitScrollbars(delay) { 636 // If we're scheduled for an update, but have received another resize request 637 // before the scheduled resize has occured, just ignore the new request 638 // (and wait for the scheduled one). 639 if (updateScrollbars && updateFromResize) { 640 updateFromResize = false; 641 return; 642 } 643 644 // We're scheduled for an update and the update request came from this method's setTimeout 645 if (updateScrollbars && !updateFromResize) { 646 reInitScrollbars(); 647 updateScrollbars = false; 648 } else { 649 updateScrollbars = true; 650 updateFromResize = false; 651 setTimeout('delayedReInitScrollbars()',delay); 652 } 653} 654 655/* Re-initialize the scrollbars to account for changed nav size. */ 656function reInitScrollbars() { 657 var pane = $(".scroll-pane").each(function(){ 658 var api = $(this).data('jsp'); 659 if (!api) { setTimeout(reInitScrollbars,300); return;} 660 api.reinitialise( {verticalGutter:0} ); 661 }); 662 $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller 663} 664 665 666/* Resize the height of the nav panels in the reference, 667 * and save the new size to a cookie */ 668function saveNavPanels() { 669 var basePath = getBaseUri(location.pathname); 670 var section = basePath.substring(1,basePath.indexOf("/",1)); 671 writeCookie("height", resizePackagesNav.css("height"), section, null); 672} 673 674 675 676function restoreHeight(packageHeight) { 677 $("#resize-packages-nav").height(packageHeight); 678 $("#packages-nav").height(packageHeight); 679 // var classesHeight = navHeight - packageHeight; 680 // $("#classes-nav").css({height:classesHeight}); 681 // $("#classes-nav .jspContainer").css({height:classesHeight}); 682} 683 684 685 686/* ######### END RESIZE THE SIDENAV HEIGHT ########## */ 687 688 689 690 691 692/** Scroll the jScrollPane to make the currently selected item visible 693 This is called when the page finished loading. */ 694function scrollIntoView(nav) { 695 var $nav = $("#"+nav); 696 var element = $nav.jScrollPane({/* ...settings... */}); 697 var api = element.data('jsp'); 698 699 if ($nav.is(':visible')) { 700 var $selected = $(".selected", $nav); 701 if ($selected.length == 0) return; 702 703 var selectedOffset = $selected.position().top; 704 if (selectedOffset + 90 > $nav.height()) { // add 90 so that we scroll up even 705 // if the current item is close to the bottom 706 api.scrollTo(0, selectedOffset - ($nav.height() / 4), false); // scroll the item into view 707 // to be 1/4 of the way from the top 708 } 709 } 710} 711 712 713 714 715 716 717/* Show popup dialogs */ 718function showDialog(id) { 719 $dialog = $("#"+id); 720 $dialog.prepend('<div class="box-border"><div class="top"> <div class="left"></div> <div class="right"></div></div><div class="bottom"> <div class="left"></div> <div class="right"></div> </div> </div>'); 721 $dialog.wrapInner('<div/>'); 722 $dialog.removeClass("hide"); 723} 724 725 726 727 728 729/* ######### COOKIES! ########## */ 730 731function readCookie(cookie) { 732 var myCookie = cookie_namespace+"_"+cookie+"="; 733 if (document.cookie) { 734 var index = document.cookie.indexOf(myCookie); 735 if (index != -1) { 736 var valStart = index + myCookie.length; 737 var valEnd = document.cookie.indexOf(";", valStart); 738 if (valEnd == -1) { 739 valEnd = document.cookie.length; 740 } 741 var val = document.cookie.substring(valStart, valEnd); 742 return val; 743 } 744 } 745 return 0; 746} 747 748function writeCookie(cookie, val, section, expiration) { 749 if (val==undefined) return; 750 section = section == null ? "_" : "_"+section+"_"; 751 if (expiration == null) { 752 var date = new Date(); 753 date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week 754 expiration = date.toGMTString(); 755 } 756 var cookieValue = cookie_namespace + section + cookie + "=" + val 757 + "; expires=" + expiration+"; path=/"; 758 document.cookie = cookieValue; 759} 760 761/* ######### END COOKIES! ########## */ 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787/* 788 789REMEMBER THE PREVIOUS PAGE FOR EACH TAB 790 791function loadLast(cookiePath) { 792 var location = window.location.href; 793 if (location.indexOf("/"+cookiePath+"/") != -1) { 794 return true; 795 } 796 var lastPage = readCookie(cookiePath + "_lastpage"); 797 if (lastPage) { 798 window.location = lastPage; 799 return false; 800 } 801 return true; 802} 803 804 805 806$(window).unload(function(){ 807 var path = getBaseUri(location.pathname); 808 if (path.indexOf("/reference/") != -1) { 809 writeCookie("lastpage", path, "reference", null); 810 } else if (path.indexOf("/guide/") != -1) { 811 writeCookie("lastpage", path, "guide", null); 812 } else if ((path.indexOf("/resources/") != -1) || (path.indexOf("/training/") != -1)) { 813 writeCookie("lastpage", path, "resources", null); 814 } 815}); 816 817*/ 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832function toggle(obj, slide) { 833 var ul = $("ul:first", obj); 834 var li = ul.parent(); 835 if (li.hasClass("closed")) { 836 if (slide) { 837 ul.slideDown("fast"); 838 } else { 839 ul.show(); 840 } 841 li.removeClass("closed"); 842 li.addClass("open"); 843 $(".toggle-img", li).attr("title", "hide pages"); 844 } else { 845 ul.slideUp("fast"); 846 li.removeClass("open"); 847 li.addClass("closed"); 848 $(".toggle-img", li).attr("title", "show pages"); 849 } 850} 851 852 853 854 855 856function buildToggleLists() { 857 $(".toggle-list").each( 858 function(i) { 859 $("div:first", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>"); 860 $(this).addClass("closed"); 861 }); 862} 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895/* REFERENCE NAV SWAP */ 896 897 898function getNavPref() { 899 var v = readCookie('reference_nav'); 900 if (v != NAV_PREF_TREE) { 901 v = NAV_PREF_PANELS; 902 } 903 return v; 904} 905 906function chooseDefaultNav() { 907 nav_pref = getNavPref(); 908 if (nav_pref == NAV_PREF_TREE) { 909 $("#nav-panels").toggle(); 910 $("#panel-link").toggle(); 911 $("#nav-tree").toggle(); 912 $("#tree-link").toggle(); 913 } 914} 915 916function swapNav() { 917 if (nav_pref == NAV_PREF_TREE) { 918 nav_pref = NAV_PREF_PANELS; 919 } else { 920 nav_pref = NAV_PREF_TREE; 921 init_default_navtree(toRoot); 922 } 923 var date = new Date(); 924 date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years 925 writeCookie("nav", nav_pref, "reference", date.toGMTString()); 926 927 $("#nav-panels").toggle(); 928 $("#panel-link").toggle(); 929 $("#nav-tree").toggle(); 930 $("#tree-link").toggle(); 931 932 resizeNav(); 933 934 // Gross nasty hack to make tree view show up upon first swap by setting height manually 935 $("#nav-tree .jspContainer:visible") 936 .css({'height':$("#nav-tree .jspContainer .jspPane").height() +'px'}); 937 // Another nasty hack to make the scrollbar appear now that we have height 938 resizeNav(); 939 940 if ($("#nav-tree").is(':visible')) { 941 scrollIntoView("nav-tree"); 942 } else { 943 scrollIntoView("packages-nav"); 944 scrollIntoView("classes-nav"); 945 } 946} 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972/* ########## LOCALIZATION ############ */ 973 974function getBaseUri(uri) { 975 var intlUrl = (uri.substring(0,6) == "/intl/"); 976 if (intlUrl) { 977 base = uri.substring(uri.indexOf('intl/')+5,uri.length); 978 base = base.substring(base.indexOf('/')+1, base.length); 979 //alert("intl, returning base url: /" + base); 980 return ("/" + base); 981 } else { 982 //alert("not intl, returning uri as found."); 983 return uri; 984 } 985} 986 987function requestAppendHL(uri) { 988//append "?hl=<lang> to an outgoing request (such as to blog) 989 var lang = getLangPref(); 990 if (lang) { 991 var q = 'hl=' + lang; 992 uri += '?' + q; 993 window.location = uri; 994 return false; 995 } else { 996 return true; 997 } 998} 999 1000 1001function changeTabLang(lang) { 1002 var nodes = $("#header-tabs").find("."+lang); 1003 for (i=0; i < nodes.length; i++) { // for each node in this language 1004 var node = $(nodes[i]); 1005 node.siblings().css("display","none"); // hide all siblings 1006 if (node.not(":empty").length != 0) { //if this languages node has a translation, show it 1007 node.css("display","inline"); 1008 } else { //otherwise, show English instead 1009 node.css("display","none"); 1010 node.siblings().filter(".en").css("display","inline"); 1011 } 1012 } 1013} 1014 1015function changeNavLang(lang) { 1016 var nodes = $("#devdoc-nav").find("."+lang); 1017 for (i=0; i < nodes.length; i++) { // for each node in this language 1018 var node = $(nodes[i]); 1019 node.siblings().css("display","none"); // hide all siblings 1020 if (node.not(":empty").length != 0) { // if this languages node has a translation, show it 1021 node.css("display","inline"); 1022 } else { // otherwise, show English instead 1023 node.css("display","none"); 1024 node.siblings().filter(".en").css("display","inline"); 1025 } 1026 } 1027} 1028 1029function changeDocLang(lang) { 1030 changeTabLang(lang); 1031 changeNavLang(lang); 1032} 1033 1034function changeLangPref(lang, refresh) { 1035 var date = new Date(); 1036 expires = date.toGMTString(date.setTime(date.getTime()+(10*365*24*60*60*1000))); 1037 // keep this for 50 years 1038 //alert("expires: " + expires) 1039 writeCookie("pref_lang", lang, null, expires); 1040 changeDocLang(lang); 1041 if (refresh) { 1042 l = getBaseUri(location.pathname); 1043 window.location = l; 1044 } 1045} 1046 1047function loadLangPref() { 1048 var lang = readCookie("pref_lang"); 1049 if (lang != 0) { 1050 $("#language").find("option[value='"+lang+"']").attr("selected",true); 1051 } 1052} 1053 1054function getLangPref() { 1055 var lang = $("#language").find(":selected").attr("value"); 1056 if (!lang) { 1057 lang = readCookie("pref_lang"); 1058 } 1059 return (lang != 0) ? lang : 'en'; 1060} 1061 1062/* ########## END LOCALIZATION ############ */ 1063 1064 1065 1066 1067 1068 1069/* Used to hide and reveal supplemental content, such as long code samples. 1070 See the companion CSS in android-developer-docs.css */ 1071function toggleContent(obj) { 1072 var div = $(obj.parentNode.parentNode); 1073 var toggleMe = $(".toggle-content-toggleme",div); 1074 if (div.hasClass("closed")) { // if it's closed, open it 1075 toggleMe.slideDown(); 1076 $(".toggle-content-text", obj).toggle(); 1077 div.removeClass("closed").addClass("open"); 1078 $(".toggle-content-img", div).attr("title", "hide").attr("src", toRoot 1079 + "assets/images/triangle-opened.png"); 1080 } else { // if it's open, close it 1081 toggleMe.slideUp('fast', function() { // Wait until the animation is done before closing arrow 1082 $(".toggle-content-text", obj).toggle(); 1083 div.removeClass("open").addClass("closed"); 1084 $(".toggle-content-img", div).attr("title", "show").attr("src", toRoot 1085 + "assets/images/triangle-closed.png"); 1086 }); 1087 } 1088 return false; 1089} 1090