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