blob: 0b0a3756ffce40240e337f2f677561d1efd8373f [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;
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}