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