blob: 195c9e5f06ced5de21b495d84a19ec5ea30c3568 [file] [log] [blame]
Robert Lya4d2d0e2013-04-09 11:26:12 -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 isMobile = false; // true if mobile, so we can adjust some layout
9
10var basePath = getBaseUri(location.pathname);
11var SITE_ROOT = toRoot + basePath.substring(1,basePath.indexOf("/",1));
12var GOOGLE_DATA; // combined data for google service apis, used for search suggest
Robert Lyc942e872013-05-07 12:09:01 -070013
Robert Lya4d2d0e2013-04-09 11:26:12 -070014
15/****** ON LOAD SET UP STUFF *********/
16
17var navBarIsFixed = false;
18$(document).ready(function() {
19
20 // load json file for Android API search suggestions
21 $.getScript(toRoot + 'reference/lists.js');
22 // load json files for Google services API suggestions
23 $.getScript(toRoot + 'reference/gcm_lists.js', function(data, textStatus, jqxhr) {
24 // once the GCM json (GCM_DATA) is loaded, load the GMS json (GMS_DATA) and merge the data
25 if(jqxhr.status === 200) {
26 $.getScript(toRoot + 'reference/gms_lists.js', function(data, textStatus, jqxhr) {
27 if(jqxhr.status === 200) {
28 // combine GCM and GMS data
29 GOOGLE_DATA = GMS_DATA;
30 var start = GOOGLE_DATA.length;
31 for (var i=0; i<GCM_DATA.length; i++) {
32 GOOGLE_DATA.push({id:start+i, label:GCM_DATA[i].label,
33 link:GCM_DATA[i].link, type:GCM_DATA[i].type});
34 }
35 }
36 });
37 }
38 });
39
40 // layout hosted on devsite is special
41 if (devsite) {
42 // move the lang selector into the overflow menu
43 $("#moremenu .mid div.header:last").after($("#language").detach());
44 }
45
46 // init the fullscreen toggle click event
47 $('#nav-swap .fullscreen').click(function(){
48 if ($(this).hasClass('disabled')) {
49 toggleFullscreen(true);
50 } else {
51 toggleFullscreen(false);
52 }
53 });
Robert Lyc942e872013-05-07 12:09:01 -070054
Robert Lya4d2d0e2013-04-09 11:26:12 -070055 // initialize the divs with custom scrollbars
56 $('.scroll-pane').jScrollPane( {verticalGutter:0} );
Robert Lyc942e872013-05-07 12:09:01 -070057
Robert Lya4d2d0e2013-04-09 11:26:12 -070058 // add HRs below all H2s (except for a few other h2 variants)
59 $('h2').not('#qv h2').not('#tb h2').not('.sidebox h2').not('#devdoc-nav h2').not('h2.norule').css({marginBottom:0}).after('<hr/>');
Robert Lyc942e872013-05-07 12:09:01 -070060
61 // set search's onkeyup handler here so we can show suggestions
Robert Lya4d2d0e2013-04-09 11:26:12 -070062 // even while search results are visible
63 $("#search_autocomplete").keyup(function() {return search_changed(event, false, toRoot)});
64
65 // set up the search close button
66 $('.search .close').click(function() {
67 $searchInput = $('#search_autocomplete');
68 $searchInput.attr('value', '');
69 $(this).addClass("hide");
70 $("#search-container").removeClass('active');
71 $("#search_autocomplete").blur();
72 search_focus_changed($searchInput.get(), false); // see search_autocomplete.js
73 hideResults(); // see search_autocomplete.js
74 });
75 $('.search').click(function() {
76 if (!$('#search_autocomplete').is(":focus")) {
77 $('#search_autocomplete').focus();
78 }
79 });
80
81 // Set up quicknav
Robert Lyc942e872013-05-07 12:09:01 -070082 var quicknav_open = false;
Robert Lya4d2d0e2013-04-09 11:26:12 -070083 $("#btn-quicknav").click(function() {
84 if (quicknav_open) {
85 $(this).removeClass('active');
86 quicknav_open = false;
87 collapse();
88 } else {
89 $(this).addClass('active');
90 quicknav_open = true;
91 expand();
92 }
93 })
Robert Lyc942e872013-05-07 12:09:01 -070094
Robert Lya4d2d0e2013-04-09 11:26:12 -070095 var expand = function() {
96 $('#header-wrap').addClass('quicknav');
97 $('#quicknav').stop().show().animate({opacity:'1'});
98 }
Robert Lyc942e872013-05-07 12:09:01 -070099
Robert Lya4d2d0e2013-04-09 11:26:12 -0700100 var collapse = function() {
101 $('#quicknav').stop().animate({opacity:'0'}, 100, function() {
102 $(this).hide();
103 $('#header-wrap').removeClass('quicknav');
104 });
105 }
Robert Lyc942e872013-05-07 12:09:01 -0700106
107
Robert Lya4d2d0e2013-04-09 11:26:12 -0700108 //Set up search
109 $("#search_autocomplete").focus(function() {
110 $("#search-container").addClass('active');
111 })
112 $("#search-container").mouseover(function() {
113 $("#search-container").addClass('active');
114 $("#search_autocomplete").focus();
115 })
116 $("#search-container").mouseout(function() {
117 if ($("#search_autocomplete").is(":focus")) return;
118 if ($("#search_autocomplete").val() == '') {
119 setTimeout(function(){
120 $("#search-container").removeClass('active');
121 $("#search_autocomplete").blur();
122 },250);
123 }
124 })
125 $("#search_autocomplete").blur(function() {
126 if ($("#search_autocomplete").val() == '') {
127 $("#search-container").removeClass('active');
128 }
129 })
130
Robert Lyc942e872013-05-07 12:09:01 -0700131
Robert Lya4d2d0e2013-04-09 11:26:12 -0700132 // prep nav expandos
133 var pagePath = document.location.pathname;
134 // account for intl docs by removing the intl/*/ path
135 if (pagePath.indexOf("/intl/") == 0) {
136 pagePath = pagePath.substr(pagePath.indexOf("/",6)); // start after intl/ to get last /
137 }
138
139 if (pagePath.indexOf(SITE_ROOT) == 0) {
140 if (pagePath == '' || pagePath.charAt(pagePath.length - 1) == '/') {
141 pagePath += 'index.html';
142 }
143 }
144
145 if (SITE_ROOT.match(/\.\.\//) || SITE_ROOT == '') {
146 // If running locally, SITE_ROOT will be a relative path, so account for that by
147 // finding the relative URL to this page. This will allow us to find links on the page
148 // leading back to this page.
149 var pathParts = pagePath.split('/');
150 var relativePagePathParts = [];
151 var upDirs = (SITE_ROOT.match(/(\.\.\/)+/) || [''])[0].length / 3;
152 for (var i = 0; i < upDirs; i++) {
153 relativePagePathParts.push('..');
154 }
155 for (var i = 0; i < upDirs; i++) {
156 relativePagePathParts.push(pathParts[pathParts.length - (upDirs - i) - 1]);
157 }
158 relativePagePathParts.push(pathParts[pathParts.length - 1]);
159 pagePath = relativePagePathParts.join('/');
160 } else {
161 // Otherwise the page path is already an absolute URL
162 }
163
164 // Highlight the header tabs...
165 // highlight Design tab
166 if ($("body").hasClass("design")) {
167 $("#header li.design a").addClass("selected");
168
169 // highlight Develop tab
170 } else if ($("body").hasClass("develop") || $("body").hasClass("google")) {
171 $("#header li.develop a").addClass("selected");
172
173 // In Develop docs, also highlight appropriate sub-tab
174 var rootDir = pagePath.substring(1,pagePath.indexOf('/', 1));
175 if (rootDir == "training") {
176 $("#nav-x li.training a").addClass("selected");
177 } else if (rootDir == "guide") {
178 $("#nav-x li.guide a").addClass("selected");
179 } else if (rootDir == "reference") {
180 // If the root is reference, but page is also part of Google Services, select Google
181 if ($("body").hasClass("google")) {
182 $("#nav-x li.google a").addClass("selected");
183 } else {
184 $("#nav-x li.reference a").addClass("selected");
185 }
186 } else if ((rootDir == "tools") || (rootDir == "sdk")) {
187 $("#nav-x li.tools a").addClass("selected");
188 } else if ($("body").hasClass("google")) {
189 $("#nav-x li.google a").addClass("selected");
190 }
191
192 // highlight Distribute tab
193 } else if ($("body").hasClass("distribute")) {
194 $("#header li.distribute a").addClass("selected");
195 }
196
197
198 // select current page in sidenav and header, and set up prev/next links if they exist
199 var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]');
200 var $selListItem;
201 if ($selNavLink.length) {
202
203 // Find this page's <li> in sidenav and set selected
204 $selListItem = $selNavLink.closest('li');
205 $selListItem.addClass('selected');
Robert Lyc942e872013-05-07 12:09:01 -0700206
Robert Lya4d2d0e2013-04-09 11:26:12 -0700207 // Traverse up the tree and expand all parent nav-sections
208 $selNavLink.parents('li.nav-section').each(function() {
209 $(this).addClass('expanded');
210 $(this).children('ul').show();
211 });
212
213 // set up prev links
214 var $prevLink = [];
215 var $prevListItem = $selListItem.prev('li');
Robert Lyc942e872013-05-07 12:09:01 -0700216
Robert Lya4d2d0e2013-04-09 11:26:12 -0700217 var crossBoundaries = ($("body.design").length > 0) || ($("body.guide").length > 0) ? true :
218false; // navigate across topic boundaries only in design docs
219 if ($prevListItem.length) {
220 if ($prevListItem.hasClass('nav-section')) {
221 // jump to last topic of previous section
222 $prevLink = $prevListItem.find('a:last');
223 } else if (!$selListItem.hasClass('nav-section')) {
224 // jump to previous topic in this section
225 $prevLink = $prevListItem.find('a:eq(0)');
226 }
227 } else {
228 // jump to this section's index page (if it exists)
229 var $parentListItem = $selListItem.parents('li');
230 $prevLink = $selListItem.parents('li').find('a');
Robert Lyc942e872013-05-07 12:09:01 -0700231
Robert Lya4d2d0e2013-04-09 11:26:12 -0700232 // except if cross boundaries aren't allowed, and we're at the top of a section already
233 // (and there's another parent)
Robert Lyc942e872013-05-07 12:09:01 -0700234 if (!crossBoundaries && $parentListItem.hasClass('nav-section')
Robert Lya4d2d0e2013-04-09 11:26:12 -0700235 && $selListItem.hasClass('nav-section')) {
236 $prevLink = [];
237 }
238 }
239
240 // set up next links
241 var $nextLink = [];
242 var startClass = false;
243 var training = $(".next-class-link").length; // decides whether to provide "next class" link
244 var isCrossingBoundary = false;
Robert Lyc942e872013-05-07 12:09:01 -0700245
Robert Lya4d2d0e2013-04-09 11:26:12 -0700246 if ($selListItem.hasClass('nav-section')) {
247 // we're on an index page, jump to the first topic
248 $nextLink = $selListItem.find('ul:eq(0)').find('a:eq(0)');
249
250 // if there aren't any children, go to the next section (required for About pages)
251 if($nextLink.length == 0) {
252 $nextLink = $selListItem.next('li').find('a');
253 } else if ($('.topic-start-link').length) {
254 // as long as there's a child link and there is a "topic start link" (we're on a landing)
255 // then set the landing page "start link" text to be the first doc title
256 $('.topic-start-link').text($nextLink.text().toUpperCase());
257 }
Robert Lyc942e872013-05-07 12:09:01 -0700258
Robert Lya4d2d0e2013-04-09 11:26:12 -0700259 // If the selected page has a description, then it's a class or article homepage
260 if ($selListItem.find('a[description]').length) {
261 // this means we're on a class landing page
262 startClass = true;
263 }
264 } else {
265 // jump to the next topic in this section (if it exists)
266 $nextLink = $selListItem.next('li').find('a:eq(0)');
267 if (!$nextLink.length) {
268 isCrossingBoundary = true;
269 // no more topics in this section, jump to the first topic in the next section
270 $nextLink = $selListItem.parents('li:eq(0)').next('li.nav-section').find('a:eq(0)');
271 if (!$nextLink.length) { // Go up another layer to look for next page (lesson > class > course)
272 $nextLink = $selListItem.parents('li:eq(1)').next('li.nav-section').find('a:eq(0)');
273 }
274 }
275 }
276
277 if (startClass) {
278 $('.start-class-link').attr('href', $nextLink.attr('href')).removeClass("hide");
279
Robert Lyc942e872013-05-07 12:09:01 -0700280 // if there's no training bar (below the start button),
Robert Lya4d2d0e2013-04-09 11:26:12 -0700281 // then we need to add a bottom border to button
282 if (!$("#tb").length) {
283 $('.start-class-link').css({'border-bottom':'1px solid #DADADA'});
284 }
285 } else if (isCrossingBoundary && !$('body.design').length) { // Design always crosses boundaries
286 $('.content-footer.next-class').show();
287 $('.next-page-link').attr('href','')
288 .removeClass("hide").addClass("disabled")
289 .click(function() { return false; });
Robert Lyc942e872013-05-07 12:09:01 -0700290
Robert Lya4d2d0e2013-04-09 11:26:12 -0700291 $('.next-class-link').attr('href',$nextLink.attr('href'))
292 .removeClass("hide").append($nextLink.html());
293 $('.next-class-link').find('.new').empty();
294 } else {
295 $('.next-page-link').attr('href', $nextLink.attr('href')).removeClass("hide");
296 }
297
298 if (!startClass && $prevLink.length) {
299 var prevHref = $prevLink.attr('href');
300 if (prevHref == SITE_ROOT + 'index.html') {
301 // Don't show Previous when it leads to the homepage
302 } else {
303 $('.prev-page-link').attr('href', $prevLink.attr('href')).removeClass("hide");
304 }
Robert Lyc942e872013-05-07 12:09:01 -0700305 }
Robert Lya4d2d0e2013-04-09 11:26:12 -0700306
307 // If this is a training 'article', there should be no prev/next nav
308 // ... if the grandparent is the "nav" ... and it has no child list items...
309 if (training && $selListItem.parents('ul').eq(1).is('[id="nav"]') &&
310 !$selListItem.find('li').length) {
311 $('.next-page-link,.prev-page-link').attr('href','').addClass("disabled")
312 .click(function() { return false; });
313 }
Robert Lyc942e872013-05-07 12:09:01 -0700314
Robert Lya4d2d0e2013-04-09 11:26:12 -0700315 }
316//If auto-toc div is present, generate the automated TOC
317if ($("#auto-toc").is('*')) {
318 var previous = $(this); //needs to be not null first time through loop
319 var toc = "";
320 $("#jd-content").find("h2, h3").not(':first-child').each(function(i) { // have to skip the first h2, which is "In this Document" with not:first-child
321 var current = $(this);
322 if(current.is("h3") && previous.is("h2")){ //need nested ols for h3s
323 toc+="<ol>";
324 }
325 else if(current.is("h2") && previous.is("h3")){ //close up the nested ol
Robert Lyc942e872013-05-07 12:09:01 -0700326 toc+="</ol>";
Robert Lya4d2d0e2013-04-09 11:26:12 -0700327 }
328 toc+="<li><a href='#" + current[0].id + "'>" +
329 current.html() + "</a></li>";
330
331 previous = current; //keep track of previous element next time through loop
332 });
333 $("#auto-toc").append(toc); //append to the div
334}
Robert Lyc942e872013-05-07 12:09:01 -0700335
Robert Lya4d2d0e2013-04-09 11:26:12 -0700336 // Set up the course landing pages for Training with class names and descriptions
337 if ($('body.trainingcourse').length) {
338 var $classLinks = $selListItem.find('ul li a').not('#nav .nav-section .nav-section ul a');
339 var $classDescriptions = $classLinks.attr('description');
Robert Lyc942e872013-05-07 12:09:01 -0700340
Robert Lya4d2d0e2013-04-09 11:26:12 -0700341 var $olClasses = $('<ol class="class-list"></ol>');
342 var $liClass;
343 var $imgIcon;
344 var $h2Title;
345 var $pSummary;
346 var $olLessons;
347 var $liLesson;
348 $classLinks.each(function(index) {
349 $liClass = $('<li></li>');
350 $h2Title = $('<a class="title" href="'+$(this).attr('href')+'"><h2>' + $(this).html()+'</h2><span></span></a>');
351 $pSummary = $('<p class="description">' + $(this).attr('description') + '</p>');
Robert Lyc942e872013-05-07 12:09:01 -0700352
Robert Lya4d2d0e2013-04-09 11:26:12 -0700353 $olLessons = $('<ol class="lesson-list"></ol>');
Robert Lyc942e872013-05-07 12:09:01 -0700354
Robert Lya4d2d0e2013-04-09 11:26:12 -0700355 $lessons = $(this).closest('li').find('ul li a');
Robert Lyc942e872013-05-07 12:09:01 -0700356
Robert Lya4d2d0e2013-04-09 11:26:12 -0700357 if ($lessons.length) {
358 $imgIcon = $('<img src="'+toRoot+'assets/images/resource-tutorial.png" alt=""/>');
359 $lessons.each(function(index) {
360 $olLessons.append('<li><a href="'+$(this).attr('href')+'">' + $(this).html()+'</a></li>');
361 });
362 } else {
363 $imgIcon = $('<img src="'+toRoot+'assets/images/resource-article.png" alt=""/>');
364 $pSummary.addClass('article');
365 }
366
367 $liClass.append($h2Title).append($imgIcon).append($pSummary).append($olLessons);
368 $olClasses.append($liClass);
369 });
370 $('.jd-descr').append($olClasses);
371 }
372
373
374
375
376 // Set up expand/collapse behavior
377 $('#nav li.nav-section .nav-section-header').click(function() {
378 var section = $(this).closest('li.nav-section');
379 if (section.hasClass('expanded')) {
380 /* hide me */
381 // if (section.hasClass('selected') || section.find('li').hasClass('selected')) {
382 // /* but not if myself or my descendents are selected */
383 // return;
384 // }
385 section.children('ul').slideUp(250, function() {
386 section.closest('li').removeClass('expanded');
387 resizeNav();
388 });
389 } else {
390 /* show me */
391 // first hide all other siblings
392 var $others = $('li.nav-section.expanded', $(this).closest('ul'));
393 $others.removeClass('expanded').children('ul').slideUp(250);
Robert Lyc942e872013-05-07 12:09:01 -0700394
Robert Lya4d2d0e2013-04-09 11:26:12 -0700395 // now expand me
396 section.closest('li').addClass('expanded');
397 section.children('ul').slideDown(250, function() {
398 resizeNav();
399 });
400 }
401 });
Robert Lyc942e872013-05-07 12:09:01 -0700402
Robert Lya4d2d0e2013-04-09 11:26:12 -0700403 $(".scroll-pane").scroll(function(event) {
404 event.preventDefault();
405 return false;
406 });
407
408 /* Resize nav height when window height changes */
409 $(window).resize(function() {
410 if ($('#side-nav').length == 0) return;
411 var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]');
412 setNavBarLeftPos(); // do this even if sidenav isn't fixed because it could become fixed
413 // make sidenav behave when resizing the window and side-scolling is a concern
414 if (navBarIsFixed) {
415 if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) {
416 updateSideNavPosition();
417 } else {
418 updateSidenavFullscreenWidth();
419 }
420 }
421 resizeNav();
422 });
423
424
425 // Set up fixed navbar
426 var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll
427 $(window).scroll(function(event) {
428 if ($('#side-nav').length == 0) return;
429 if (event.target.nodeName == "DIV") {
430 // Dump scroll event if the target is a DIV, because that means the event is coming
431 // from a scrollable div and so there's no need to make adjustments to our layout
432 return;
433 }
Robert Lyc942e872013-05-07 12:09:01 -0700434 var scrollTop = $(window).scrollTop();
Robert Lya4d2d0e2013-04-09 11:26:12 -0700435 var headerHeight = $('#header').outerHeight();
436 var subheaderHeight = $('#nav-x').outerHeight();
Robert Lyc942e872013-05-07 12:09:01 -0700437 var searchResultHeight = $('#searchResults').is(":visible") ?
Robert Lya4d2d0e2013-04-09 11:26:12 -0700438 $('#searchResults').outerHeight() : 0;
439 var totalHeaderHeight = headerHeight + subheaderHeight + searchResultHeight;
440 // we set the navbar fixed when the scroll position is beyond the height of the site header...
441 var navBarShouldBeFixed = scrollTop > totalHeaderHeight;
442 // ... except if the document content is shorter than the sidenav height.
443 // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing)
444 if ($("#doc-col").height() < $("#side-nav").height()) {
445 navBarShouldBeFixed = false;
446 }
Robert Lyc942e872013-05-07 12:09:01 -0700447
Robert Lya4d2d0e2013-04-09 11:26:12 -0700448 var scrollLeft = $(window).scrollLeft();
449 // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match
450 if (navBarIsFixed && (scrollLeft != prevScrollLeft)) {
451 updateSideNavPosition();
452 prevScrollLeft = scrollLeft;
453 }
Robert Lyc942e872013-05-07 12:09:01 -0700454
455 // Don't continue if the header is sufficently far away
Robert Lya4d2d0e2013-04-09 11:26:12 -0700456 // (to avoid intensive resizing that slows scrolling)
457 if (navBarIsFixed && navBarShouldBeFixed) {
458 return;
459 }
Robert Lyc942e872013-05-07 12:09:01 -0700460
Robert Lya4d2d0e2013-04-09 11:26:12 -0700461 if (navBarIsFixed != navBarShouldBeFixed) {
462 if (navBarShouldBeFixed) {
463 // make it fixed
464 var width = $('#devdoc-nav').width();
465 $('#devdoc-nav')
466 .addClass('fixed')
467 .css({'width':width+'px'})
468 .prependTo('#body-content');
469 // add neato "back to top" button
470 $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'});
Robert Lyc942e872013-05-07 12:09:01 -0700471
Robert Lya4d2d0e2013-04-09 11:26:12 -0700472 // update the sidenaav position for side scrolling
473 updateSideNavPosition();
474 } else {
475 // make it static again
476 $('#devdoc-nav')
477 .removeClass('fixed')
478 .css({'width':'auto','margin':''})
479 .prependTo('#side-nav');
480 $('#devdoc-nav a.totop').hide();
481 }
482 navBarIsFixed = navBarShouldBeFixed;
Robert Lyc942e872013-05-07 12:09:01 -0700483 }
484
Robert Lya4d2d0e2013-04-09 11:26:12 -0700485 resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance
486 });
487
Robert Lyc942e872013-05-07 12:09:01 -0700488
Robert Lya4d2d0e2013-04-09 11:26:12 -0700489 var navBarLeftPos;
490 if ($('#devdoc-nav').length) {
491 setNavBarLeftPos();
492 }
493
494
495 // Stop expand/collapse behavior when clicking on nav section links (since we're navigating away
496 // from the page)
497 $('.nav-section-header').find('a:eq(0)').click(function(evt) {
498 window.location.href = $(this).attr('href');
499 return false;
500 });
501
502 // Set up play-on-hover <video> tags.
503 $('video.play-on-hover').bind('click', function(){
504 $(this).get(0).load(); // in case the video isn't seekable
505 $(this).get(0).play();
506 });
507
508 // Set up tooltips
509 var TOOLTIP_MARGIN = 10;
510 $('acronym,.tooltip-link').each(function() {
511 var $target = $(this);
512 var $tooltip = $('<div>')
513 .addClass('tooltip-box')
514 .append($target.attr('title'))
515 .hide()
516 .appendTo('body');
517 $target.removeAttr('title');
518
519 $target.hover(function() {
520 // in
521 var targetRect = $target.offset();
522 targetRect.width = $target.width();
523 targetRect.height = $target.height();
524
525 $tooltip.css({
526 left: targetRect.left,
527 top: targetRect.top + targetRect.height + TOOLTIP_MARGIN
528 });
529 $tooltip.addClass('below');
530 $tooltip.show();
531 }, function() {
532 // out
533 $tooltip.hide();
534 });
535 });
536
537 // Set up <h2> deeplinks
538 $('h2').click(function() {
539 var id = $(this).attr('id');
540 if (id) {
541 document.location.hash = id;
542 }
543 });
544
545 //Loads the +1 button
546 var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
547 po.src = 'https://apis.google.com/js/plusone.js';
548 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
549
550
Robert Lyc942e872013-05-07 12:09:01 -0700551 // Revise the sidenav widths to make room for the scrollbar
Robert Lya4d2d0e2013-04-09 11:26:12 -0700552 // which avoids the visible width from changing each time the bar appears
553 var $sidenav = $("#side-nav");
554 var sidenav_width = parseInt($sidenav.innerWidth());
Robert Lyc942e872013-05-07 12:09:01 -0700555
Robert Lya4d2d0e2013-04-09 11:26:12 -0700556 $("#devdoc-nav #nav").css("width", sidenav_width - 4 + "px"); // 4px is scrollbar width
557
558
559 $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller
Robert Lyc942e872013-05-07 12:09:01 -0700560
Robert Lya4d2d0e2013-04-09 11:26:12 -0700561 if ($(".scroll-pane").length > 1) {
562 // Check if there's a user preference for the panel heights
563 var cookieHeight = readCookie("reference_height");
564 if (cookieHeight) {
565 restoreHeight(cookieHeight);
566 }
567 }
Robert Lyc942e872013-05-07 12:09:01 -0700568
Robert Lya4d2d0e2013-04-09 11:26:12 -0700569 resizeNav();
570
571 /* init the language selector based on user cookie for lang */
572 loadLangPref();
573 changeNavLang(getLangPref());
574
575 /* setup event handlers to ensure the overflow menu is visible while picking lang */
576 $("#language select")
577 .mousedown(function() {
578 $("div.morehover").addClass("hover"); })
579 .blur(function() {
580 $("div.morehover").removeClass("hover"); });
581
582 /* some global variable setup */
583 resizePackagesNav = $("#resize-packages-nav");
584 classesNav = $("#classes-nav");
585 devdocNav = $("#devdoc-nav");
586
587 var cookiePath = "";
588 if (location.href.indexOf("/reference/") != -1) {
589 cookiePath = "reference_";
590 } else if (location.href.indexOf("/guide/") != -1) {
591 cookiePath = "guide_";
592 } else if (location.href.indexOf("/tools/") != -1) {
593 cookiePath = "tools_";
594 } else if (location.href.indexOf("/training/") != -1) {
595 cookiePath = "training_";
596 } else if (location.href.indexOf("/design/") != -1) {
597 cookiePath = "design_";
598 } else if (location.href.indexOf("/distribute/") != -1) {
599 cookiePath = "distribute_";
600 }
601
602});
603// END of the onload event
604
605
606
607function toggleFullscreen(enable) {
608 var delay = 20;
609 var enabled = true;
610 var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]');
611 if (enable) {
612 // Currently NOT USING fullscreen; enable fullscreen
613 stylesheet.removeAttr('disabled');
614 $('#nav-swap .fullscreen').removeClass('disabled');
615 $('#devdoc-nav').css({left:''});
616 setTimeout(updateSidenavFullscreenWidth,delay); // need to wait a moment for css to switch
617 enabled = true;
618 } else {
619 // Currently USING fullscreen; disable fullscreen
620 stylesheet.attr('disabled', 'disabled');
621 $('#nav-swap .fullscreen').addClass('disabled');
622 setTimeout(updateSidenavFixedWidth,delay); // need to wait a moment for css to switch
623 enabled = false;
624 }
625 writeCookie("fullscreen", enabled, null, null);
626 setNavBarLeftPos();
627 resizeNav(delay);
628 updateSideNavPosition();
629 setTimeout(initSidenavHeightResize,delay);
630}
631
632
633function setNavBarLeftPos() {
634 navBarLeftPos = $('#body-content').offset().left;
635}
636
637
638function updateSideNavPosition() {
639 var newLeft = $(window).scrollLeft() - navBarLeftPos;
640 $('#devdoc-nav').css({left: -newLeft});
641 $('#devdoc-nav .totop').css({left: -(newLeft - parseInt($('#side-nav').css('margin-left')))});
642}
Robert Lyc942e872013-05-07 12:09:01 -0700643
Robert Lya4d2d0e2013-04-09 11:26:12 -0700644
645
646
647
648
649
650
651// TODO: use $(document).ready instead
652function addLoadEvent(newfun) {
653 var current = window.onload;
654 if (typeof window.onload != 'function') {
655 window.onload = newfun;
656 } else {
657 window.onload = function() {
658 current();
659 newfun();
660 }
661 }
662}
663
664var agent = navigator['userAgent'].toLowerCase();
665// If a mobile phone, set flag and do mobile setup
666if ((agent.indexOf("mobile") != -1) || // android, iphone, ipod
667 (agent.indexOf("blackberry") != -1) ||
668 (agent.indexOf("webos") != -1) ||
669 (agent.indexOf("mini") != -1)) { // opera mini browsers
670 isMobile = true;
671}
672
673
674addLoadEvent( function() {
675 $("pre:not(.no-pretty-print)").addClass("prettyprint");
676 prettyPrint();
677} );
678
679
680
681
682/* ######### RESIZE THE SIDENAV HEIGHT ########## */
683
684function resizeNav(delay) {
685 var $nav = $("#devdoc-nav");
686 var $window = $(window);
687 var navHeight;
Robert Lyc942e872013-05-07 12:09:01 -0700688
Robert Lya4d2d0e2013-04-09 11:26:12 -0700689 // Get the height of entire window and the total header height.
690 // Then figure out based on scroll position whether the header is visible
691 var windowHeight = $window.height();
692 var scrollTop = $window.scrollTop();
693 var headerHeight = $('#header').outerHeight();
694 var subheaderHeight = $('#nav-x').outerHeight();
695 var headerVisible = (scrollTop < (headerHeight + subheaderHeight));
Robert Lyc942e872013-05-07 12:09:01 -0700696
697 // get the height of space between nav and top of window.
Robert Lya4d2d0e2013-04-09 11:26:12 -0700698 // Could be either margin or top position, depending on whether the nav is fixed.
Robert Lyc942e872013-05-07 12:09:01 -0700699 var topMargin = (parseInt($nav.css('margin-top')) || parseInt($nav.css('top'))) + 1;
Robert Lya4d2d0e2013-04-09 11:26:12 -0700700 // add 1 for the #side-nav bottom margin
Robert Lyc942e872013-05-07 12:09:01 -0700701
Robert Lya4d2d0e2013-04-09 11:26:12 -0700702 // Depending on whether the header is visible, set the side nav's height.
703 if (headerVisible) {
704 // The sidenav height grows as the header goes off screen
705 navHeight = windowHeight - (headerHeight + subheaderHeight - scrollTop) - topMargin;
706 } else {
707 // Once header is off screen, the nav height is almost full window height
708 navHeight = windowHeight - topMargin;
709 }
Robert Lyc942e872013-05-07 12:09:01 -0700710
711
712
Robert Lya4d2d0e2013-04-09 11:26:12 -0700713 $scrollPanes = $(".scroll-pane");
714 if ($scrollPanes.length > 1) {
715 // subtract the height of the api level widget and nav swapper from the available nav height
716 navHeight -= ($('#api-nav-header').outerHeight(true) + $('#nav-swap').outerHeight(true));
Robert Lyc942e872013-05-07 12:09:01 -0700717
Robert Lya4d2d0e2013-04-09 11:26:12 -0700718 $("#swapper").css({height:navHeight + "px"});
719 if ($("#nav-tree").is(":visible")) {
720 $("#nav-tree").css({height:navHeight});
721 }
Robert Lyc942e872013-05-07 12:09:01 -0700722
723 var classesHeight = navHeight - parseInt($("#resize-packages-nav").css("height")) - 10 + "px";
Robert Lya4d2d0e2013-04-09 11:26:12 -0700724 //subtract 10px to account for drag bar
Robert Lyc942e872013-05-07 12:09:01 -0700725
726 // if the window becomes small enough to make the class panel height 0,
Robert Lya4d2d0e2013-04-09 11:26:12 -0700727 // then the package panel should begin to shrink
728 if (parseInt(classesHeight) <= 0) {
729 $("#resize-packages-nav").css({height:navHeight - 10}); //subtract 10px for drag bar
730 $("#packages-nav").css({height:navHeight - 10});
731 }
Robert Lyc942e872013-05-07 12:09:01 -0700732
Robert Lya4d2d0e2013-04-09 11:26:12 -0700733 $("#classes-nav").css({'height':classesHeight, 'margin-top':'10px'});
734 $("#classes-nav .jspContainer").css({height:classesHeight});
Robert Lyc942e872013-05-07 12:09:01 -0700735
736
Robert Lya4d2d0e2013-04-09 11:26:12 -0700737 } else {
738 $nav.height(navHeight);
739 }
Robert Lyc942e872013-05-07 12:09:01 -0700740
Robert Lya4d2d0e2013-04-09 11:26:12 -0700741 if (delay) {
742 updateFromResize = true;
743 delayedReInitScrollbars(delay);
744 } else {
745 reInitScrollbars();
746 }
Robert Lyc942e872013-05-07 12:09:01 -0700747
Robert Lya4d2d0e2013-04-09 11:26:12 -0700748}
749
750var updateScrollbars = false;
751var updateFromResize = false;
752
753/* Re-initialize the scrollbars to account for changed nav size.
754 * This method postpones the actual update by a 1/4 second in order to optimize the
755 * scroll performance while the header is still visible, because re-initializing the
756 * scroll panes is an intensive process.
757 */
758function delayedReInitScrollbars(delay) {
759 // If we're scheduled for an update, but have received another resize request
760 // before the scheduled resize has occured, just ignore the new request
761 // (and wait for the scheduled one).
762 if (updateScrollbars && updateFromResize) {
763 updateFromResize = false;
764 return;
765 }
Robert Lyc942e872013-05-07 12:09:01 -0700766
Robert Lya4d2d0e2013-04-09 11:26:12 -0700767 // We're scheduled for an update and the update request came from this method's setTimeout
768 if (updateScrollbars && !updateFromResize) {
769 reInitScrollbars();
770 updateScrollbars = false;
771 } else {
772 updateScrollbars = true;
773 updateFromResize = false;
774 setTimeout('delayedReInitScrollbars()',delay);
775 }
776}
777
778/* Re-initialize the scrollbars to account for changed nav size. */
779function reInitScrollbars() {
780 var pane = $(".scroll-pane").each(function(){
781 var api = $(this).data('jsp');
782 if (!api) { setTimeout(reInitScrollbars,300); return;}
783 api.reinitialise( {verticalGutter:0} );
Robert Lyc942e872013-05-07 12:09:01 -0700784 });
Robert Lya4d2d0e2013-04-09 11:26:12 -0700785 $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller
786}
787
788
789/* Resize the height of the nav panels in the reference,
790 * and save the new size to a cookie */
791function saveNavPanels() {
792 var basePath = getBaseUri(location.pathname);
793 var section = basePath.substring(1,basePath.indexOf("/",1));
794 writeCookie("height", resizePackagesNav.css("height"), section, null);
795}
796
797
798
799function restoreHeight(packageHeight) {
800 $("#resize-packages-nav").height(packageHeight);
801 $("#packages-nav").height(packageHeight);
802 // var classesHeight = navHeight - packageHeight;
803 // $("#classes-nav").css({height:classesHeight});
804 // $("#classes-nav .jspContainer").css({height:classesHeight});
805}
806
807
808
809/* ######### END RESIZE THE SIDENAV HEIGHT ########## */
810
811
812
813
814
Robert Lyc942e872013-05-07 12:09:01 -0700815/** Scroll the jScrollPane to make the currently selected item visible
Robert Lya4d2d0e2013-04-09 11:26:12 -0700816 This is called when the page finished loading. */
817function scrollIntoView(nav) {
818 var $nav = $("#"+nav);
819 var element = $nav.jScrollPane({/* ...settings... */});
820 var api = element.data('jsp');
821
822 if ($nav.is(':visible')) {
823 var $selected = $(".selected", $nav);
824 if ($selected.length == 0) return;
Robert Lyc942e872013-05-07 12:09:01 -0700825
Robert Lya4d2d0e2013-04-09 11:26:12 -0700826 var selectedOffset = $selected.position().top;
Robert Lyc942e872013-05-07 12:09:01 -0700827 if (selectedOffset + 90 > $nav.height()) { // add 90 so that we scroll up even
Robert Lya4d2d0e2013-04-09 11:26:12 -0700828 // if the current item is close to the bottom
829 api.scrollTo(0, selectedOffset - ($nav.height() / 4), false); // scroll the item into view
830 // to be 1/4 of the way from the top
831 }
832 }
833}
834
835
836
837
838
839
840/* Show popup dialogs */
841function showDialog(id) {
842 $dialog = $("#"+id);
843 $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>');
844 $dialog.wrapInner('<div/>');
845 $dialog.removeClass("hide");
846}
847
848
849
850
851
852/* ######### COOKIES! ########## */
853
854function readCookie(cookie) {
855 var myCookie = cookie_namespace+"_"+cookie+"=";
856 if (document.cookie) {
857 var index = document.cookie.indexOf(myCookie);
858 if (index != -1) {
859 var valStart = index + myCookie.length;
860 var valEnd = document.cookie.indexOf(";", valStart);
861 if (valEnd == -1) {
862 valEnd = document.cookie.length;
863 }
864 var val = document.cookie.substring(valStart, valEnd);
865 return val;
866 }
867 }
868 return 0;
869}
870
871function writeCookie(cookie, val, section, expiration) {
872 if (val==undefined) return;
873 section = section == null ? "_" : "_"+section+"_";
874 if (expiration == null) {
875 var date = new Date();
876 date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
877 expiration = date.toGMTString();
878 }
Robert Lyc942e872013-05-07 12:09:01 -0700879 var cookieValue = cookie_namespace + section + cookie + "=" + val
Robert Lya4d2d0e2013-04-09 11:26:12 -0700880 + "; expires=" + expiration+"; path=/";
881 document.cookie = cookieValue;
882}
883
884/* ######### END COOKIES! ########## */
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910/*
911
912REMEMBER THE PREVIOUS PAGE FOR EACH TAB
913
914function loadLast(cookiePath) {
915 var location = window.location.href;
916 if (location.indexOf("/"+cookiePath+"/") != -1) {
917 return true;
918 }
919 var lastPage = readCookie(cookiePath + "_lastpage");
920 if (lastPage) {
921 window.location = lastPage;
922 return false;
923 }
924 return true;
925}
926
927
928
929$(window).unload(function(){
930 var path = getBaseUri(location.pathname);
931 if (path.indexOf("/reference/") != -1) {
932 writeCookie("lastpage", path, "reference", null);
933 } else if (path.indexOf("/guide/") != -1) {
934 writeCookie("lastpage", path, "guide", null);
935 } else if ((path.indexOf("/resources/") != -1) || (path.indexOf("/training/") != -1)) {
936 writeCookie("lastpage", path, "resources", null);
937 }
938});
939
940*/
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955function toggle(obj, slide) {
956 var ul = $("ul:first", obj);
957 var li = ul.parent();
958 if (li.hasClass("closed")) {
959 if (slide) {
960 ul.slideDown("fast");
961 } else {
962 ul.show();
963 }
964 li.removeClass("closed");
965 li.addClass("open");
966 $(".toggle-img", li).attr("title", "hide pages");
967 } else {
968 ul.slideUp("fast");
969 li.removeClass("open");
970 li.addClass("closed");
971 $(".toggle-img", li).attr("title", "show pages");
972 }
973}
974
975
976
977
978
979function buildToggleLists() {
980 $(".toggle-list").each(
981 function(i) {
982 $("div:first", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>");
983 $(this).addClass("closed");
984 });
985}
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018/* REFERENCE NAV SWAP */
1019
1020
1021function getNavPref() {
1022 var v = readCookie('reference_nav');
1023 if (v != NAV_PREF_TREE) {
1024 v = NAV_PREF_PANELS;
1025 }
1026 return v;
1027}
1028
1029function chooseDefaultNav() {
1030 nav_pref = getNavPref();
1031 if (nav_pref == NAV_PREF_TREE) {
1032 $("#nav-panels").toggle();
1033 $("#panel-link").toggle();
1034 $("#nav-tree").toggle();
1035 $("#tree-link").toggle();
1036 }
1037}
1038
1039function swapNav() {
1040 if (nav_pref == NAV_PREF_TREE) {
1041 nav_pref = NAV_PREF_PANELS;
1042 } else {
1043 nav_pref = NAV_PREF_TREE;
1044 init_default_navtree(toRoot);
1045 }
1046 var date = new Date();
1047 date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
1048 writeCookie("nav", nav_pref, "reference", date.toGMTString());
1049
1050 $("#nav-panels").toggle();
1051 $("#panel-link").toggle();
1052 $("#nav-tree").toggle();
1053 $("#tree-link").toggle();
Robert Lyc942e872013-05-07 12:09:01 -07001054
Robert Lya4d2d0e2013-04-09 11:26:12 -07001055 resizeNav();
1056
1057 // Gross nasty hack to make tree view show up upon first swap by setting height manually
1058 $("#nav-tree .jspContainer:visible")
1059 .css({'height':$("#nav-tree .jspContainer .jspPane").height() +'px'});
1060 // Another nasty hack to make the scrollbar appear now that we have height
1061 resizeNav();
Robert Lyc942e872013-05-07 12:09:01 -07001062
Robert Lya4d2d0e2013-04-09 11:26:12 -07001063 if ($("#nav-tree").is(':visible')) {
1064 scrollIntoView("nav-tree");
1065 } else {
1066 scrollIntoView("packages-nav");
1067 scrollIntoView("classes-nav");
1068 }
1069}
1070
1071
1072
1073/* ############################################ */
1074/* ########## LOCALIZATION ############ */
1075/* ############################################ */
1076
1077function getBaseUri(uri) {
1078 var intlUrl = (uri.substring(0,6) == "/intl/");
1079 if (intlUrl) {
1080 base = uri.substring(uri.indexOf('intl/')+5,uri.length);
1081 base = base.substring(base.indexOf('/')+1, base.length);
1082 //alert("intl, returning base url: /" + base);
1083 return ("/" + base);
1084 } else {
1085 //alert("not intl, returning uri as found.");
1086 return uri;
1087 }
1088}
1089
1090function requestAppendHL(uri) {
1091//append "?hl=<lang> to an outgoing request (such as to blog)
1092 var lang = getLangPref();
1093 if (lang) {
1094 var q = 'hl=' + lang;
1095 uri += '?' + q;
1096 window.location = uri;
1097 return false;
1098 } else {
1099 return true;
1100 }
1101}
1102
1103
1104function changeNavLang(lang) {
1105 var $links = $("#devdoc-nav,#header,#nav-x,.training-nav-top,.content-footer").find("a["+lang+"-lang]");
1106 $links.each(function(i){ // for each link with a translation
1107 var $link = $(this);
1108 if (lang != "en") { // No need to worry about English, because a language change invokes new request
1109 // put the desired language from the attribute as the text
1110 $link.text($link.attr(lang+"-lang"))
1111 }
1112 });
1113}
1114
1115function changeLangPref(lang, submit) {
1116 var date = new Date();
Robert Lyc942e872013-05-07 12:09:01 -07001117 expires = date.toGMTString(date.setTime(date.getTime()+(10*365*24*60*60*1000)));
Robert Lya4d2d0e2013-04-09 11:26:12 -07001118 // keep this for 50 years
1119 //alert("expires: " + expires)
1120 writeCookie("pref_lang", lang, null, expires);
1121
1122 // ####### TODO: Remove this condition once we're stable on devsite #######
1123 // This condition is only needed if we still need to support legacy GAE server
1124 if (devsite) {
1125 // Switch language when on Devsite server
1126 if (submit) {
1127 $("#setlang").submit();
1128 }
1129 } else {
1130 // Switch language when on legacy GAE server
1131 if (submit) {
1132 window.location = getBaseUri(location.pathname);
1133 }
1134 }
1135}
1136
1137function loadLangPref() {
1138 var lang = readCookie("pref_lang");
1139 if (lang != 0) {
1140 $("#language").find("option[value='"+lang+"']").attr("selected",true);
1141 }
1142}
1143
1144function getLangPref() {
1145 var lang = $("#language").find(":selected").attr("value");
1146 if (!lang) {
1147 lang = readCookie("pref_lang");
1148 }
1149 return (lang != 0) ? lang : 'en';
1150}
1151
1152/* ########## END LOCALIZATION ############ */
1153
1154
1155
1156
1157
1158
1159/* Used to hide and reveal supplemental content, such as long code samples.
1160 See the companion CSS in android-developer-docs.css */
1161function toggleContent(obj) {
1162 var div = $(obj.parentNode.parentNode);
1163 var toggleMe = $(".toggle-content-toggleme",div);
1164 if (div.hasClass("closed")) { // if it's closed, open it
1165 toggleMe.slideDown();
1166 $(".toggle-content-text", obj).toggle();
1167 div.removeClass("closed").addClass("open");
Robert Lyc942e872013-05-07 12:09:01 -07001168 $(".toggle-content-img", div).attr("title", "hide").attr("src", toRoot
Robert Lya4d2d0e2013-04-09 11:26:12 -07001169 + "assets/images/triangle-opened.png");
1170 } else { // if it's open, close it
1171 toggleMe.slideUp('fast', function() { // Wait until the animation is done before closing arrow
1172 $(".toggle-content-text", obj).toggle();
1173 div.removeClass("open").addClass("closed");
Robert Lyc942e872013-05-07 12:09:01 -07001174 $(".toggle-content-img", div).attr("title", "show").attr("src", toRoot
Robert Lya4d2d0e2013-04-09 11:26:12 -07001175 + "assets/images/triangle-closed.png");
1176 });
1177 }
1178 return false;
1179}
1180
1181
1182/* New version of expandable content */
1183function toggleExpandable(link,id) {
1184 if($(id).is(':visible')) {
1185 $(id).slideUp();
1186 $(link).removeClass('expanded');
1187 } else {
1188 $(id).slideDown();
1189 $(link).addClass('expanded');
1190 }
1191}
1192
1193function hideExpandable(ids) {
1194 $(ids).slideUp();
1195 $(ids).prev('h4').find('a.expandable').removeClass('expanded');
1196}
1197
1198
1199
1200
1201
Robert Lyc942e872013-05-07 12:09:01 -07001202/*
Robert Lya4d2d0e2013-04-09 11:26:12 -07001203 * Slideshow 1.0
1204 * Used on /index.html and /develop/index.html for carousel
1205 *
1206 * Sample usage:
1207 * HTML -
1208 * <div class="slideshow-container">
1209 * <a href="" class="slideshow-prev">Prev</a>
1210 * <a href="" class="slideshow-next">Next</a>
1211 * <ul>
1212 * <li class="item"><img src="images/marquee1.jpg"></li>
1213 * <li class="item"><img src="images/marquee2.jpg"></li>
1214 * <li class="item"><img src="images/marquee3.jpg"></li>
1215 * <li class="item"><img src="images/marquee4.jpg"></li>
1216 * </ul>
1217 * </div>
1218 *
1219 * <script type="text/javascript">
1220 * $('.slideshow-container').dacSlideshow({
1221 * auto: true,
1222 * btnPrev: '.slideshow-prev',
1223 * btnNext: '.slideshow-next'
1224 * });
1225 * </script>
1226 *
1227 * Options:
1228 * btnPrev: optional identifier for previous button
1229 * btnNext: optional identifier for next button
1230 * btnPause: optional identifier for pause button
1231 * auto: whether or not to auto-proceed
1232 * speed: animation speed
1233 * autoTime: time between auto-rotation
1234 * easing: easing function for transition
1235 * start: item to select by default
1236 * scroll: direction to scroll in
1237 * pagination: whether or not to include dotted pagination
1238 *
1239 */
1240
1241 (function($) {
1242 $.fn.dacSlideshow = function(o) {
Robert Lyc942e872013-05-07 12:09:01 -07001243
Robert Lya4d2d0e2013-04-09 11:26:12 -07001244 //Options - see above
1245 o = $.extend({
1246 btnPrev: null,
1247 btnNext: null,
1248 btnPause: null,
1249 auto: true,
1250 speed: 500,
1251 autoTime: 12000,
1252 easing: null,
1253 start: 0,
1254 scroll: 1,
1255 pagination: true
1256
1257 }, o || {});
Robert Lyc942e872013-05-07 12:09:01 -07001258
1259 //Set up a carousel for each
Robert Lya4d2d0e2013-04-09 11:26:12 -07001260 return this.each(function() {
1261
1262 var running = false;
1263 var animCss = o.vertical ? "top" : "left";
1264 var sizeCss = o.vertical ? "height" : "width";
1265 var div = $(this);
1266 var ul = $("ul", div);
1267 var tLi = $("li", ul);
Robert Lyc942e872013-05-07 12:09:01 -07001268 var tl = tLi.size();
Robert Lya4d2d0e2013-04-09 11:26:12 -07001269 var timer = null;
1270
1271 var li = $("li", ul);
1272 var itemLength = li.size();
1273 var curr = o.start;
1274
1275 li.css({float: o.vertical ? "none" : "left"});
1276 ul.css({margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1"});
1277 div.css({position: "relative", "z-index": "2", left: "0px"});
1278
1279 var liSize = o.vertical ? height(li) : width(li);
1280 var ulSize = liSize * itemLength;
1281 var divSize = liSize;
1282
1283 li.css({width: li.width(), height: li.height()});
1284 ul.css(sizeCss, ulSize+"px").css(animCss, -(curr*liSize));
1285
1286 div.css(sizeCss, divSize+"px");
Robert Lyc942e872013-05-07 12:09:01 -07001287
Robert Lya4d2d0e2013-04-09 11:26:12 -07001288 //Pagination
1289 if (o.pagination) {
1290 var pagination = $("<div class='pagination'></div>");
1291 var pag_ul = $("<ul></ul>");
1292 if (tl > 1) {
1293 for (var i=0;i<tl;i++) {
1294 var li = $("<li>"+i+"</li>");
1295 pag_ul.append(li);
1296 if (i==o.start) li.addClass('active');
1297 li.click(function() {
1298 go(parseInt($(this).text()));
1299 })
1300 }
1301 pagination.append(pag_ul);
1302 div.append(pagination);
1303 }
1304 }
Robert Lyc942e872013-05-07 12:09:01 -07001305
Robert Lya4d2d0e2013-04-09 11:26:12 -07001306 //Previous button
1307 if(o.btnPrev)
1308 $(o.btnPrev).click(function(e) {
1309 e.preventDefault();
1310 return go(curr-o.scroll);
1311 });
1312
1313 //Next button
1314 if(o.btnNext)
1315 $(o.btnNext).click(function(e) {
1316 e.preventDefault();
1317 return go(curr+o.scroll);
1318 });
1319
1320 //Pause button
1321 if(o.btnPause)
1322 $(o.btnPause).click(function(e) {
1323 e.preventDefault();
1324 if ($(this).hasClass('paused')) {
1325 startRotateTimer();
1326 } else {
1327 pauseRotateTimer();
1328 }
1329 });
Robert Lyc942e872013-05-07 12:09:01 -07001330
Robert Lya4d2d0e2013-04-09 11:26:12 -07001331 //Auto rotation
1332 if(o.auto) startRotateTimer();
Robert Lyc942e872013-05-07 12:09:01 -07001333
Robert Lya4d2d0e2013-04-09 11:26:12 -07001334 function startRotateTimer() {
1335 clearInterval(timer);
1336 timer = setInterval(function() {
1337 if (curr == tl-1) {
1338 go(0);
1339 } else {
Robert Lyc942e872013-05-07 12:09:01 -07001340 go(curr+o.scroll);
1341 }
Robert Lya4d2d0e2013-04-09 11:26:12 -07001342 }, o.autoTime);
1343 $(o.btnPause).removeClass('paused');
1344 }
1345
1346 function pauseRotateTimer() {
1347 clearInterval(timer);
1348 $(o.btnPause).addClass('paused');
1349 }
1350
1351 //Go to an item
1352 function go(to) {
1353 if(!running) {
1354
1355 if(to<0) {
1356 to = itemLength-1;
1357 } else if (to>itemLength-1) {
1358 to = 0;
1359 }
1360 curr = to;
1361
1362 running = true;
1363
1364 ul.animate(
1365 animCss == "left" ? { left: -(curr*liSize) } : { top: -(curr*liSize) } , o.speed, o.easing,
1366 function() {
1367 running = false;
1368 }
1369 );
1370
1371 $(o.btnPrev + "," + o.btnNext).removeClass("disabled");
1372 $( (curr-o.scroll<0 && o.btnPrev)
1373 ||
1374 (curr+o.scroll > itemLength && o.btnNext)
1375 ||
1376 []
1377 ).addClass("disabled");
1378
Robert Lyc942e872013-05-07 12:09:01 -07001379
Robert Lya4d2d0e2013-04-09 11:26:12 -07001380 var nav_items = $('li', pagination);
1381 nav_items.removeClass('active');
1382 nav_items.eq(to).addClass('active');
Robert Lyc942e872013-05-07 12:09:01 -07001383
Robert Lya4d2d0e2013-04-09 11:26:12 -07001384
1385 }
1386 if(o.auto) startRotateTimer();
1387 return false;
1388 };
1389 });
1390 };
1391
1392 function css(el, prop) {
1393 return parseInt($.css(el[0], prop)) || 0;
1394 };
1395 function width(el) {
1396 return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
1397 };
1398 function height(el) {
1399 return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
1400 };
1401
1402 })(jQuery);
1403
1404
Robert Lyc942e872013-05-07 12:09:01 -07001405/*
Robert Lya4d2d0e2013-04-09 11:26:12 -07001406 * dacSlideshow 1.0
1407 * Used on develop/index.html for side-sliding tabs
1408 *
1409 * Sample usage:
1410 * HTML -
1411 * <div class="slideshow-container">
1412 * <a href="" class="slideshow-prev">Prev</a>
1413 * <a href="" class="slideshow-next">Next</a>
1414 * <ul>
1415 * <li class="item"><img src="images/marquee1.jpg"></li>
1416 * <li class="item"><img src="images/marquee2.jpg"></li>
1417 * <li class="item"><img src="images/marquee3.jpg"></li>
1418 * <li class="item"><img src="images/marquee4.jpg"></li>
1419 * </ul>
1420 * </div>
1421 *
1422 * <script type="text/javascript">
1423 * $('.slideshow-container').dacSlideshow({
1424 * auto: true,
1425 * btnPrev: '.slideshow-prev',
1426 * btnNext: '.slideshow-next'
1427 * });
1428 * </script>
1429 *
1430 * Options:
1431 * btnPrev: optional identifier for previous button
1432 * btnNext: optional identifier for next button
1433 * auto: whether or not to auto-proceed
1434 * speed: animation speed
1435 * autoTime: time between auto-rotation
1436 * easing: easing function for transition
1437 * start: item to select by default
1438 * scroll: direction to scroll in
1439 * pagination: whether or not to include dotted pagination
1440 *
1441 */
1442 (function($) {
1443 $.fn.dacTabbedList = function(o) {
Robert Lyc942e872013-05-07 12:09:01 -07001444
Robert Lya4d2d0e2013-04-09 11:26:12 -07001445 //Options - see above
1446 o = $.extend({
1447 speed : 250,
1448 easing: null,
1449 nav_id: null,
1450 frame_id: null
1451 }, o || {});
Robert Lyc942e872013-05-07 12:09:01 -07001452
1453 //Set up a carousel for each
Robert Lya4d2d0e2013-04-09 11:26:12 -07001454 return this.each(function() {
1455
1456 var curr = 0;
1457 var running = false;
1458 var animCss = "margin-left";
1459 var sizeCss = "width";
1460 var div = $(this);
Robert Lyc942e872013-05-07 12:09:01 -07001461
Robert Lya4d2d0e2013-04-09 11:26:12 -07001462 var nav = $(o.nav_id, div);
1463 var nav_li = $("li", nav);
Robert Lyc942e872013-05-07 12:09:01 -07001464 var nav_size = nav_li.size();
Robert Lya4d2d0e2013-04-09 11:26:12 -07001465 var frame = div.find(o.frame_id);
1466 var content_width = $(frame).find('ul').width();
1467 //Buttons
1468 $(nav_li).click(function(e) {
1469 go($(nav_li).index($(this)));
1470 })
Robert Lyc942e872013-05-07 12:09:01 -07001471
Robert Lya4d2d0e2013-04-09 11:26:12 -07001472 //Go to an item
1473 function go(to) {
1474 if(!running) {
1475 curr = to;
1476 running = true;
1477
1478 frame.animate({ 'margin-left' : -(curr*content_width) }, o.speed, o.easing,
1479 function() {
1480 running = false;
1481 }
1482 );
1483
Robert Lyc942e872013-05-07 12:09:01 -07001484
Robert Lya4d2d0e2013-04-09 11:26:12 -07001485 nav_li.removeClass('active');
1486 nav_li.eq(to).addClass('active');
Robert Lyc942e872013-05-07 12:09:01 -07001487
Robert Lya4d2d0e2013-04-09 11:26:12 -07001488
1489 }
1490 return false;
1491 };
1492 });
1493 };
1494
1495 function css(el, prop) {
1496 return parseInt($.css(el[0], prop)) || 0;
1497 };
1498 function width(el) {
1499 return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
1500 };
1501 function height(el) {
1502 return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
1503 };
1504
1505 })(jQuery);
1506
1507
1508
1509
1510
1511/* ######################################################## */
1512/* ################ SEARCH SUGGESTIONS ################## */
1513/* ######################################################## */
1514
1515
1516
1517var gSelectedIndex = -1;
1518var gMatches = new Array();
1519var gLastText = "";
1520var gInitialized = false;
1521var ROW_COUNT_FRAMEWORK = 20; // max number of results in list
1522var gListLength = 0;
1523
1524
1525var gGoogleMatches = new Array();
1526var ROW_COUNT_GOOGLE = 15; // max number of results in list
1527var gGoogleListLength = 0;
1528
1529function set_item_selected($li, selected)
1530{
1531 if (selected) {
1532 $li.attr('class','jd-autocomplete jd-selected');
1533 } else {
1534 $li.attr('class','jd-autocomplete');
1535 }
1536}
1537
1538function set_item_values(toroot, $li, match)
1539{
1540 var $link = $('a',$li);
1541 $link.html(match.__hilabel || match.label);
1542 $link.attr('href',toroot + match.link);
1543}
1544
1545function new_suggestion() {
1546 var $list = $("#search_filtered");
1547 var $li = $("<li class='jd-autocomplete'></li>");
1548 $list.append($li);
1549
1550 $li.mousedown(function() {
1551 window.location = this.firstChild.getAttribute("href");
1552 });
1553 $li.mouseover(function() {
1554 $('#search_filtered li').removeClass('jd-selected');
1555 $(this).addClass('jd-selected');
1556 gSelectedIndex = $('#search_filtered li').index(this);
1557 });
1558 $li.append('<a></a>');
1559 $li.attr('class','show-item');
1560 return $li;
1561}
1562
1563function sync_selection_table(toroot)
1564{
1565 var $list = $("#search_filtered");
1566 var $li; //list item jquery object
1567 var i; //list item iterator
Robert Lyc942e872013-05-07 12:09:01 -07001568
Robert Lya4d2d0e2013-04-09 11:26:12 -07001569 // reset the list
1570 $("li",$list).remove();
1571
1572 //if we have results, make the table visible and initialize result info
1573 if ((gMatches.length > 0) || (gGoogleMatches.length > 0)) {
1574 // reveal suggestion list
1575 $('#search_filtered_div').removeClass('no-display');
1576 var listIndex = 0; // list index position
1577
1578 // ########### ANDROID RESULTS #############
1579 if (gMatches.length > 0) {
1580
1581 // determine android results to show
1582 gListLength = gMatches.length < ROW_COUNT_FRAMEWORK ?
1583 gMatches.length : ROW_COUNT_FRAMEWORK;
1584 for (i=0; i<gListLength; i++) {
1585 var $li = new_suggestion();
1586 set_item_values(toroot, $li, gMatches[i]);
1587 set_item_selected($li, i == gSelectedIndex);
1588 }
1589 }
1590
1591 // ########### GOOGLE RESULTS #############
1592 if (gGoogleMatches.length > 0) {
1593 // show header for list
1594 $list.append("<li class='header'>in Google Services:</li>");
1595
1596 // determine google results to show
1597 gGoogleListLength = gGoogleMatches.length < ROW_COUNT_GOOGLE ? gGoogleMatches.length : ROW_COUNT_GOOGLE;
1598 for (i=0; i<gGoogleListLength; i++) {
1599 var $li = new_suggestion();
1600 set_item_values(toroot, $li, gGoogleMatches[i]);
1601 set_item_selected($li, i == gSelectedIndex);
1602 }
1603 }
1604
1605 //if we have no results, hide the table
1606 } else {
1607 $('#search_filtered_div').addClass('no-display');
1608 }
1609}
1610
1611function search_changed(e, kd, toroot)
1612{
1613 var search = document.getElementById("search_autocomplete");
1614 var text = search.value.replace(/(^ +)|( +$)/g, '');
Robert Lyc942e872013-05-07 12:09:01 -07001615
Robert Lya4d2d0e2013-04-09 11:26:12 -07001616 // show/hide the close button
1617 if (text != '') {
1618 $(".search .close").removeClass("hide");
1619 } else {
1620 $(".search .close").addClass("hide");
1621 }
1622
1623 // 13 = enter
1624 if (e.keyCode == 13) {
1625 $('#search_filtered_div').addClass('no-display');
1626 if (!$('#search_filtered_div').hasClass('no-display') || (gSelectedIndex < 0)) {
1627 if ($("#searchResults").is(":hidden") && (search.value != "")) {
1628 // if results aren't showing (and text not empty), return true to allow search to execute
1629 return true;
1630 } else {
1631 // otherwise, results are already showing, so allow ajax to auto refresh the results
1632 // and ignore this Enter press to avoid the reload.
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001633 // return false;
1634 //
1635 // For now, we're not using AJAX so we respond to every Enter.
1636 return true;
Robert Lya4d2d0e2013-04-09 11:26:12 -07001637 }
1638 } else if (kd && gSelectedIndex >= 0) {
1639 window.location = $("a",$('#search_filtered li')[gSelectedIndex]).attr("href");
1640 return false;
1641 }
1642 }
1643 // 38 -- arrow up
1644 else if (kd && (e.keyCode == 38)) {
1645 if ($($("#search_filtered li")[gSelectedIndex-1]).hasClass("header")) {
1646 $('#search_filtered_div li').removeClass('jd-selected');
1647 gSelectedIndex--;
1648 $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
1649 }
1650 if (gSelectedIndex >= 0) {
1651 $('#search_filtered_div li').removeClass('jd-selected');
1652 gSelectedIndex--;
1653 $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
1654 }
1655 return false;
1656 }
1657 // 40 -- arrow down
1658 else if (kd && (e.keyCode == 40)) {
1659 if ($($("#search_filtered li")[gSelectedIndex+1]).hasClass("header")) {
1660 $('#search_filtered_div li').removeClass('jd-selected');
1661 gSelectedIndex++;
1662 $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
1663 }
1664 if ((gSelectedIndex < $("ul#search_filtered li").length-1) ||
1665 ($($("#search_filtered li")[gSelectedIndex+1]).hasClass("header"))) {
1666 $('#search_filtered_div li').removeClass('jd-selected');
1667 gSelectedIndex++;
1668 $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
1669 }
1670 return false;
1671 }
1672 // if key-up event and not arrow down/up,
1673 // read the search query and add suggestsions to gMatches
1674 else if (!kd && (e.keyCode != 40) && (e.keyCode != 38)) {
1675 gMatches = new Array();
1676 matchedCount = 0;
1677 gGoogleMatches = new Array();
1678 matchedCountGoogle = 0;
1679 gSelectedIndex = -1;
1680
1681 // Search for Android matches
1682 for (var i=0; i<DATA.length; i++) {
1683 var s = DATA[i];
1684 if (text.length != 0 &&
1685 s.label.toLowerCase().indexOf(text.toLowerCase()) != -1) {
1686 gMatches[matchedCount] = s;
1687 matchedCount++;
1688 }
1689 }
1690 rank_autocomplete_results(text, gMatches);
1691 for (var i=0; i<gMatches.length; i++) {
1692 var s = gMatches[i];
1693 }
1694
1695
1696 // Search for Google matches
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001697 /*
1698 * Commented this out because GOOGLE_DATA not defined for us and code
1699 * causes an error. This probably has to do with the missing
1700 * gms_lists.js file in SAC. TODO figure it all out.
1701 *
Robert Lya4d2d0e2013-04-09 11:26:12 -07001702 for (var i=0; i<GOOGLE_DATA.length; i++) {
1703 var s = GOOGLE_DATA[i];
1704 if (text.length != 0 &&
1705 s.label.toLowerCase().indexOf(text.toLowerCase()) != -1) {
1706 gGoogleMatches[matchedCountGoogle] = s;
1707 matchedCountGoogle++;
1708 }
1709 }
1710 rank_autocomplete_results(text, gGoogleMatches);
1711 for (var i=0; i<gGoogleMatches.length; i++) {
1712 var s = gGoogleMatches[i];
1713 }
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001714 */
Robert Lya4d2d0e2013-04-09 11:26:12 -07001715
1716 highlight_autocomplete_result_labels(text);
1717 sync_selection_table(toroot);
1718
1719
1720 return true; // allow the event to bubble up to the search api
1721 }
1722}
1723
1724/* Order the result list based on match quality */
1725function rank_autocomplete_results(query, matches) {
1726 query = query || '';
1727 if (!matches || !matches.length)
1728 return;
1729
1730 // helper function that gets the last occurence index of the given regex
1731 // in the given string, or -1 if not found
1732 var _lastSearch = function(s, re) {
1733 if (s == '')
1734 return -1;
1735 var l = -1;
1736 var tmp;
1737 while ((tmp = s.search(re)) >= 0) {
1738 if (l < 0) l = 0;
1739 l += tmp;
1740 s = s.substr(tmp + 1);
1741 }
1742 return l;
1743 };
1744
1745 // helper function that counts the occurrences of a given character in
1746 // a given string
1747 var _countChar = function(s, c) {
1748 var n = 0;
1749 for (var i=0; i<s.length; i++)
1750 if (s.charAt(i) == c) ++n;
1751 return n;
1752 };
1753
1754 var queryLower = query.toLowerCase();
1755 var queryAlnum = (queryLower.match(/\w+/) || [''])[0];
1756 var partPrefixAlnumRE = new RegExp('\\b' + queryAlnum);
1757 var partExactAlnumRE = new RegExp('\\b' + queryAlnum + '\\b');
1758
1759 var _resultScoreFn = function(result) {
1760 // scores are calculated based on exact and prefix matches,
1761 // and then number of path separators (dots) from the last
1762 // match (i.e. favoring classes and deep package names)
1763 var score = 1.0;
1764 var labelLower = result.label.toLowerCase();
1765 var t;
1766 t = _lastSearch(labelLower, partExactAlnumRE);
1767 if (t >= 0) {
1768 // exact part match
1769 var partsAfter = _countChar(labelLower.substr(t + 1), '.');
1770 score *= 200 / (partsAfter + 1);
1771 } else {
1772 t = _lastSearch(labelLower, partPrefixAlnumRE);
1773 if (t >= 0) {
1774 // part prefix match
1775 var partsAfter = _countChar(labelLower.substr(t + 1), '.');
1776 score *= 20 / (partsAfter + 1);
1777 }
1778 }
1779
1780 return score;
1781 };
1782
1783 for (var i=0; i<matches.length; i++) {
1784 matches[i].__resultScore = _resultScoreFn(matches[i]);
1785 }
1786
1787 matches.sort(function(a,b){
1788 var n = b.__resultScore - a.__resultScore;
1789 if (n == 0) // lexicographical sort if scores are the same
1790 n = (a.label < b.label) ? -1 : 1;
1791 return n;
1792 });
1793}
1794
1795/* Add emphasis to part of string that matches query */
1796function highlight_autocomplete_result_labels(query) {
1797 query = query || '';
1798 if ((!gMatches || !gMatches.length) && (!gGoogleMatches || !gGoogleMatches.length))
1799 return;
1800
1801 var queryLower = query.toLowerCase();
1802 var queryAlnumDot = (queryLower.match(/[\w\.]+/) || [''])[0];
1803 var queryRE = new RegExp(
1804 '(' + queryAlnumDot.replace(/\./g, '\\.') + ')', 'ig');
1805 for (var i=0; i<gMatches.length; i++) {
1806 gMatches[i].__hilabel = gMatches[i].label.replace(
1807 queryRE, '<b>$1</b>');
1808 }
1809 for (var i=0; i<gGoogleMatches.length; i++) {
1810 gGoogleMatches[i].__hilabel = gGoogleMatches[i].label.replace(
1811 queryRE, '<b>$1</b>');
1812 }
1813}
1814
1815function search_focus_changed(obj, focused)
1816{
Robert Lyc942e872013-05-07 12:09:01 -07001817 if (!focused) {
Robert Lya4d2d0e2013-04-09 11:26:12 -07001818 if(obj.value == ""){
1819 $(".search .close").addClass("hide");
1820 }
1821 document.getElementById("search_filtered_div").className = "no-display";
1822 }
1823}
1824
1825function submit_search() {
1826 var query = document.getElementById('search_autocomplete').value;
1827 location.hash = 'q=' + query;
1828 loadSearchResults();
1829 $("#searchResults").slideDown('slow');
1830 return false;
1831}
1832
1833
1834function hideResults() {
1835 $("#searchResults").slideUp();
1836 $(".search .close").addClass("hide");
1837 location.hash = '';
Robert Lyc942e872013-05-07 12:09:01 -07001838
Robert Lya4d2d0e2013-04-09 11:26:12 -07001839 $("#search_autocomplete").val("").blur();
Robert Lyc942e872013-05-07 12:09:01 -07001840
Robert Lya4d2d0e2013-04-09 11:26:12 -07001841 // reset the ajax search callback to nothing, so results don't appear unless ENTER
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001842 // searchControl.setSearchStartingCallback(this, function(control, searcher, query) {});
Robert Lya4d2d0e2013-04-09 11:26:12 -07001843 return false;
1844}
1845
1846
Robert Lya4d2d0e2013-04-09 11:26:12 -07001847/* ########################################################## */
1848/* ################ CUSTOM SEARCH ENGINE ################## */
1849/* ########################################################## */
1850
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001851// TODO, add localized search.
1852function getLangPref() {
1853 return "en";
1854}
1855
1856// Package of functions that does custom search, from DAC redesign.
1857(function($) {
1858 var LANG;
1859
1860 function getSearchLang() {
1861 if (!LANG) {
1862 LANG = getLangPref();
1863
1864 // Fix zh-cn to be zh-CN.
1865 LANG = LANG.replace(/-\w+/, function(m) { return m.toUpperCase(); });
1866 }
1867 return LANG;
1868 }
1869
1870 function customSearch(query, start) {
1871 var searchParams = {
1872 // Keys for SAC
1873 cx:'016258643462168859875:qqpm8fiwgc0',
1874 key: 'AIzaSyBOWHD3JAF6Q9LIJ4NiahGAF70W7iDAI9M',
1875
1876 // Keys for DAC
1877 // cx: '000521750095050289010:zpcpi1ea4s8',
1878 // key: 'AIzaSyCFhbGnjW06dYwvRCU8h_zjdpS4PYYbEe8',
1879
1880 q: query,
1881 start: start || 1,
1882 num: 6,
1883 hl: getSearchLang(),
1884 fields: 'queries,items(pagemap,link,title,htmlSnippet,formattedUrl)'
1885 };
1886
1887 return $.get('https://content.googleapis.com/customsearch/v1?' + $.param(searchParams));
1888 }
1889
1890 function renderResults(el, results) {
1891 if (!results.items) {
1892 el.append($('<div>').text('No results'));
1893 return;
1894 }
1895
1896 for (var i = 0; i < results.items.length; i++) {
1897 var item = results.items[i];
1898 // No thumbnail images in SAC.
1899 // var hasImage = item.pagemap && item.pagemap.cse_thumbnail;
1900 var sectionMatch = item.link.match(/source\.android\.com\/(\w*)/);
1901 var section = (sectionMatch && sectionMatch[1]) || 'blog';
1902
1903 var entry = $('<div>').addClass('dac-custom-search-entry cols');
1904
1905// No thumbnail images in SAC.
1906// if (hasImage) {
1907// var image = item.pagemap.cse_thumbnail[0];
1908// entry.append($('<div>').addClass('col-1of6')
1909// .append($('<div>').addClass('dac-custom-search-image').css('background-image', 'url(' + image.src + ')')));
1910// }
1911// entry.append($('<div>').addClass(hasImage ? 'col-5of6' : 'col-6of6')
1912 entry.append($('<div>')
1913 .append($('<p>').addClass('dac-custom-search-section').text(section))
1914 .append(
1915 $('<a>').text(item.title).attr('href', item.link).wrap('<h2>').parent().addClass('dac-custom-search-title')
1916 )
1917 .append($('<p>').addClass('dac-custom-search-snippet').html(item.htmlSnippet.replace(/<br>/g, '')))
1918 .append($('<a>').addClass('dac-custom-search-link').text(item.formattedUrl).attr('href', item.link)));
1919
1920 el.append(entry);
1921 }
1922
1923 if (results.queries.nextPage) {
1924 var loadMoreButton = $('<button id="dac-custom-search-load-more">')
1925 .addClass('dac-custom-search-load-more')
1926 .text('Load more')
1927 .click(function() {
1928 loadMoreResults(el, results);
1929 });
1930
1931 el.append(loadMoreButton);
1932 }
1933 }
1934
1935 function loadMoreResults(el, results) {
1936 var query = results.queries.request.searchTerms;
1937 var start = results.queries.nextPage.startIndex;
1938 var loadMoreButton = el.find('#dac-custom-search-load-more');
1939
1940 loadMoreButton.text('Loading more...');
1941
1942 customSearch(query, start).then(function(results) {
1943 loadMoreButton.remove();
1944 renderResults(el, results);
1945 });
1946 }
1947
1948 $.fn.customSearch = function(query) {
1949 var el = $(this);
1950
1951 customSearch(query).then(function(results) {
1952 el.empty();
1953 renderResults(el, results);
1954 });
1955 };
1956})(jQuery);
1957
Robert Lya4d2d0e2013-04-09 11:26:12 -07001958
1959function loadSearchResults() {
Robert Lya4d2d0e2013-04-09 11:26:12 -07001960
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001961 // Draw the search results box
1962 //searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);
1963 $(searchResults).append('<div class="leftSearchControl"></div>');
Robert Lya4d2d0e2013-04-09 11:26:12 -07001964
1965
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001966 // Refresh the url and search title
1967 var query = document.getElementById('search_autocomplete').value || getQuery(location.hash);
1968 updateResultTitle(query);
1969 location.hash = 'q=' + query;
Robert Lya4d2d0e2013-04-09 11:26:12 -07001970
1971 // get query and execute the search
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001972 //searchControl.execute(decodeURI(getQuery(location.hash)));
1973 $(leftSearchControl).customSearch(getQuery(location.hash));
Robert Lya4d2d0e2013-04-09 11:26:12 -07001974
1975 document.getElementById("search_autocomplete").focus();
1976 addTabListeners();
1977}
1978// End of loadSearchResults
1979
1980google.setOnLoadCallback(function(){
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08001981
1982 var query = decodeURI(getQuery(location.hash));
1983 if (location.hash.indexOf("q=") == -1 || query == '') {
Robert Lya4d2d0e2013-04-09 11:26:12 -07001984 // if there's no query in the url, don't search and make sure results are hidden
1985 $('#searchResults').hide();
1986 return;
1987 } else {
1988 // first time loading search results for this page
1989 $('#searchResults').slideDown('slow');
1990 $(".search .close").removeClass("hide");
1991 loadSearchResults();
1992 }
1993}, true);
1994
1995// when an event on the browser history occurs (back, forward, load) requery hash and do search
1996$(window).hashchange( function(){
1997 // Exit if the hash isn't a search query or there's an error in the query
1998 if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) {
1999 // If the results pane is open, close it.
2000 if (!$("#searchResults").is(":hidden")) {
2001 hideResults();
2002 }
2003 return;
2004 }
2005
2006 // Otherwise, we have a search to do
2007 var query = decodeURI(getQuery(location.hash));
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08002008 //searchControl.execute(query);
2009 $('#leftSearchControl').customSearch(query);
Robert Lya4d2d0e2013-04-09 11:26:12 -07002010 $('#searchResults').slideDown('slow');
2011 $("#search_autocomplete").focus();
2012 $(".search .close").removeClass("hide");
2013
2014 updateResultTitle(query);
2015});
2016
2017function updateResultTitle(query) {
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08002018 $("#searchTitle").html("Results for <em>" + (query) + "</em>");
2019// For some reason, the escapeHTML function wasn't working for me. TODO fix
2020// this by copying in a comparable library function.
2021// $("#searchTitle").html("Results for <em>" + escapeHTML(query) + "</em>");
Robert Lya4d2d0e2013-04-09 11:26:12 -07002022}
2023
2024// forcefully regain key-up event control (previously jacked by search api)
2025$("#search_autocomplete").keyup(function(event) {
2026 return search_changed(event, false, toRoot);
2027});
2028
2029// add event listeners to each tab so we can track the browser history
2030function addTabListeners() {
2031 var tabHeaders = $(".gsc-tabHeader");
2032 for (var i = 0; i < tabHeaders.length; i++) {
2033 $(tabHeaders[i]).attr("id",i).click(function() {
2034 /*
2035 // make a copy of the page numbers for the search left pane
2036 setTimeout(function() {
2037 // remove any residual page numbers
2038 $('#searchResults .gsc-tabsArea .gsc-cursor-box.gs-bidi-start-align').remove();
Robert Lyc942e872013-05-07 12:09:01 -07002039 // move the page numbers to the left position; make a clone,
Robert Lya4d2d0e2013-04-09 11:26:12 -07002040 // because the element is drawn to the DOM only once
Robert Lyc942e872013-05-07 12:09:01 -07002041 // and because we're going to remove it (previous line),
2042 // we need it to be available to move again as the user navigates
Robert Lya4d2d0e2013-04-09 11:26:12 -07002043 $('#searchResults .gsc-webResult .gsc-cursor-box.gs-bidi-start-align:visible')
2044 .clone().appendTo('#searchResults .gsc-tabsArea');
2045 }, 200);
2046 */
2047 });
2048 }
2049 setTimeout(function(){$(tabHeaders[0]).click()},200);
2050}
2051
2052
2053function getQuery(hash) {
2054 var queryParts = hash.split('=');
2055 return queryParts[1];
2056}
2057
2058/* returns the given string with all HTML brackets converted to entities
2059 TODO: move this to the site's JS library */
2060function escapeHTML(string) {
2061 return string.replace(/</g,"&lt;")
2062 .replace(/>/g,"&gt;");
2063}
2064
2065
Robert Lya4d2d0e2013-04-09 11:26:12 -07002066/* ######################################################## */
2067/* ################# JAVADOC REFERENCE ################### */
2068/* ######################################################## */
2069
2070/* Initialize some droiddoc stuff, but only if we're in the reference */
2071if (location.pathname.indexOf("/reference")) {
2072 if(!location.pathname.indexOf("/reference-gms/packages.html")
2073 && !location.pathname.indexOf("/reference-gcm/packages.html")
2074 && !location.pathname.indexOf("/reference/com/google") == 0) {
2075 $(document).ready(function() {
2076 // init available apis based on user pref
2077 changeApiLevel();
2078 initSidenavHeightResize()
2079 });
2080 }
2081}
2082
2083var API_LEVEL_COOKIE = "api_level";
2084var minLevel = 1;
2085var maxLevel = 1;
2086
2087/******* SIDENAV DIMENSIONS ************/
Robert Lyc942e872013-05-07 12:09:01 -07002088
Robert Lya4d2d0e2013-04-09 11:26:12 -07002089 function initSidenavHeightResize() {
2090 // Change the drag bar size to nicely fit the scrollbar positions
2091 var $dragBar = $(".ui-resizable-s");
2092 $dragBar.css({'width': $dragBar.parent().width() - 5 + "px"});
Robert Lyc942e872013-05-07 12:09:01 -07002093
2094 $( "#resize-packages-nav" ).resizable({
Robert Lya4d2d0e2013-04-09 11:26:12 -07002095 containment: "#nav-panels",
2096 handles: "s",
2097 alsoResize: "#packages-nav",
2098 resize: function(event, ui) { resizeNav(); }, /* resize the nav while dragging */
2099 stop: function(event, ui) { saveNavPanels(); } /* once stopped, save the sizes to cookie */
2100 });
Robert Lyc942e872013-05-07 12:09:01 -07002101
Robert Lya4d2d0e2013-04-09 11:26:12 -07002102 }
Robert Lyc942e872013-05-07 12:09:01 -07002103
Robert Lya4d2d0e2013-04-09 11:26:12 -07002104function updateSidenavFixedWidth() {
2105 if (!navBarIsFixed) return;
2106 $('#devdoc-nav').css({
2107 'width' : $('#side-nav').css('width'),
2108 'margin' : $('#side-nav').css('margin')
2109 });
2110 $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'});
Robert Lyc942e872013-05-07 12:09:01 -07002111
Robert Lya4d2d0e2013-04-09 11:26:12 -07002112 initSidenavHeightResize();
2113}
2114
2115function updateSidenavFullscreenWidth() {
2116 if (!navBarIsFixed) return;
2117 $('#devdoc-nav').css({
2118 'width' : $('#side-nav').css('width'),
2119 'margin' : $('#side-nav').css('margin')
2120 });
2121 $('#devdoc-nav .totop').css({'left': 'inherit'});
Robert Lyc942e872013-05-07 12:09:01 -07002122
Robert Lya4d2d0e2013-04-09 11:26:12 -07002123 initSidenavHeightResize();
2124}
2125
2126function buildApiLevelSelector() {
2127 maxLevel = SINCE_DATA.length;
2128 var userApiLevel = parseInt(readCookie(API_LEVEL_COOKIE));
2129 userApiLevel = userApiLevel == 0 ? maxLevel : userApiLevel; // If there's no cookie (zero), use the max by default
2130
2131 minLevel = parseInt($("#doc-api-level").attr("class"));
2132 // Handle provisional api levels; the provisional level will always be the highest possible level
2133 // Provisional api levels will also have a length; other stuff that's just missing a level won't,
2134 // so leave those kinds of entities at the default level of 1 (for example, the R.styleable class)
2135 if (isNaN(minLevel) && minLevel.length) {
2136 minLevel = maxLevel;
2137 }
2138 var select = $("#apiLevelSelector").html("").change(changeApiLevel);
2139 for (var i = maxLevel-1; i >= 0; i--) {
2140 var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
2141 // if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
2142 select.append(option);
2143 }
2144
2145 // get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true)
2146 var selectedLevelItem = $("#apiLevelSelector option[value='"+userApiLevel+"']").get(0);
Gina Dimino8cc3a9e2015-12-14 13:44:19 -08002147// Another piece of functionality that we don't use that produces an error.
2148// TODO figure it all out.
2149// selectedLevelItem.setAttribute('selected',true);
Robert Lya4d2d0e2013-04-09 11:26:12 -07002150}
2151
2152function changeApiLevel() {
2153 maxLevel = SINCE_DATA.length;
2154 var selectedLevel = maxLevel;
2155
2156 selectedLevel = parseInt($("#apiLevelSelector option:selected").val());
2157 toggleVisisbleApis(selectedLevel, "body");
2158
2159 var date = new Date();
2160 date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
2161 var expiration = date.toGMTString();
2162 writeCookie(API_LEVEL_COOKIE, selectedLevel, null, expiration);
2163
2164 if (selectedLevel < minLevel) {
2165 var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
2166 $("#naMessage").show().html("<div><p><strong>This " + thing
2167 + " requires API level " + minLevel + " or higher.</strong></p>"
2168 + "<p>This document is hidden because your selected API level for the documentation is "
2169 + selectedLevel + ". You can change the documentation API level with the selector "
2170 + "above the left navigation.</p>"
2171 + "<p>For more information about specifying the API level your app requires, "
2172 + "read <a href='" + toRoot + "training/basics/supporting-devices/platforms.html'"
2173 + ">Supporting Different Platform Versions</a>.</p>"
2174 + "<input type='button' value='OK, make this page visible' "
2175 + "title='Change the API level to " + minLevel + "' "
2176 + "onclick='$(\"#apiLevelSelector\").val(\"" + minLevel + "\");changeApiLevel();' />"
2177 + "</div>");
2178 } else {
2179 $("#naMessage").hide();
2180 }
2181}
2182
2183function toggleVisisbleApis(selectedLevel, context) {
2184 var apis = $(".api",context);
2185 apis.each(function(i) {
2186 var obj = $(this);
2187 var className = obj.attr("class");
2188 var apiLevelIndex = className.lastIndexOf("-")+1;
2189 var apiLevelEndIndex = className.indexOf(" ", apiLevelIndex);
2190 apiLevelEndIndex = apiLevelEndIndex != -1 ? apiLevelEndIndex : className.length;
2191 var apiLevel = className.substring(apiLevelIndex, apiLevelEndIndex);
2192 if (apiLevel.length == 0) { // for odd cases when the since data is actually missing, just bail
2193 return;
2194 }
2195 apiLevel = parseInt(apiLevel);
2196
2197 // Handle provisional api levels; if this item's level is the provisional one, set it to the max
2198 var selectedLevelNum = parseInt(selectedLevel)
2199 var apiLevelNum = parseInt(apiLevel);
2200 if (isNaN(apiLevelNum)) {
2201 apiLevelNum = maxLevel;
2202 }
2203
2204 // Grey things out that aren't available and give a tooltip title
2205 if (apiLevelNum > selectedLevelNum) {
2206 obj.addClass("absent").attr("title","Requires API Level \""
2207 + apiLevel + "\" or higher");
Robert Lyc942e872013-05-07 12:09:01 -07002208 }
Robert Lya4d2d0e2013-04-09 11:26:12 -07002209 else obj.removeClass("absent").removeAttr("title");
2210 });
2211}
2212
2213
2214
2215
2216/* ################# SIDENAV TREE VIEW ################### */
2217
2218function new_node(me, mom, text, link, children_data, api_level)
2219{
2220 var node = new Object();
2221 node.children = Array();
2222 node.children_data = children_data;
2223 node.depth = mom.depth + 1;
2224
2225 node.li = document.createElement("li");
2226 mom.get_children_ul().appendChild(node.li);
2227
2228 node.label_div = document.createElement("div");
2229 node.label_div.className = "label";
2230 if (api_level != null) {
2231 $(node.label_div).addClass("api");
2232 $(node.label_div).addClass("api-level-"+api_level);
2233 }
2234 node.li.appendChild(node.label_div);
2235
2236 if (children_data != null) {
2237 node.expand_toggle = document.createElement("a");
2238 node.expand_toggle.href = "javascript:void(0)";
2239 node.expand_toggle.onclick = function() {
2240 if (node.expanded) {
2241 $(node.get_children_ul()).slideUp("fast");
2242 node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
2243 node.expanded = false;
2244 } else {
2245 expand_node(me, node);
2246 }
2247 };
2248 node.label_div.appendChild(node.expand_toggle);
2249
2250 node.plus_img = document.createElement("img");
2251 node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
2252 node.plus_img.className = "plus";
2253 node.plus_img.width = "8";
2254 node.plus_img.border = "0";
2255 node.expand_toggle.appendChild(node.plus_img);
2256
2257 node.expanded = false;
2258 }
2259
2260 var a = document.createElement("a");
2261 node.label_div.appendChild(a);
2262 node.label = document.createTextNode(text);
2263 a.appendChild(node.label);
2264 if (link) {
2265 a.href = me.toroot + link;
2266 } else {
2267 if (children_data != null) {
2268 a.className = "nolink";
2269 a.href = "javascript:void(0)";
2270 a.onclick = node.expand_toggle.onclick;
2271 // This next line shouldn't be necessary. I'll buy a beer for the first
2272 // person who figures out how to remove this line and have the link
2273 // toggle shut on the first try. --joeo@android.com
2274 node.expanded = false;
2275 }
2276 }
Robert Lyc942e872013-05-07 12:09:01 -07002277
Robert Lya4d2d0e2013-04-09 11:26:12 -07002278
2279 node.children_ul = null;
2280 node.get_children_ul = function() {
2281 if (!node.children_ul) {
2282 node.children_ul = document.createElement("ul");
2283 node.children_ul.className = "children_ul";
2284 node.children_ul.style.display = "none";
2285 node.li.appendChild(node.children_ul);
2286 }
2287 return node.children_ul;
2288 };
2289
2290 return node;
2291}
2292
2293
2294
2295
2296function expand_node(me, node)
2297{
2298 if (node.children_data && !node.expanded) {
2299 if (node.children_visited) {
2300 $(node.get_children_ul()).slideDown("fast");
2301 } else {
2302 get_node(me, node);
2303 if ($(node.label_div).hasClass("absent")) {
2304 $(node.get_children_ul()).addClass("absent");
Robert Lyc942e872013-05-07 12:09:01 -07002305 }
Robert Lya4d2d0e2013-04-09 11:26:12 -07002306 $(node.get_children_ul()).slideDown("fast");
2307 }
2308 node.plus_img.src = me.toroot + "assets/images/triangle-opened-small.png";
2309 node.expanded = true;
2310
2311 // perform api level toggling because new nodes are new to the DOM
2312 var selectedLevel = $("#apiLevelSelector option:selected").val();
2313 toggleVisisbleApis(selectedLevel, "#side-nav");
2314 }
2315}
2316
2317function get_node(me, mom)
2318{
2319 mom.children_visited = true;
2320 for (var i in mom.children_data) {
2321 var node_data = mom.children_data[i];
2322 mom.children[i] = new_node(me, mom, node_data[0], node_data[1],
2323 node_data[2], node_data[3]);
2324 }
2325}
2326
2327function this_page_relative(toroot)
2328{
2329 var full = document.location.pathname;
2330 var file = "";
2331 if (toroot.substr(0, 1) == "/") {
2332 if (full.substr(0, toroot.length) == toroot) {
2333 return full.substr(toroot.length);
2334 } else {
2335 // the file isn't under toroot. Fail.
2336 return null;
2337 }
2338 } else {
2339 if (toroot != "./") {
2340 toroot = "./" + toroot;
2341 }
2342 do {
2343 if (toroot.substr(toroot.length-3, 3) == "../" || toroot == "./") {
2344 var pos = full.lastIndexOf("/");
2345 file = full.substr(pos) + file;
2346 full = full.substr(0, pos);
2347 toroot = toroot.substr(0, toroot.length-3);
2348 }
2349 } while (toroot != "" && toroot != "/");
2350 return file.substr(1);
2351 }
2352}
2353
2354function find_page(url, data)
2355{
2356 var nodes = data;
2357 var result = null;
2358 for (var i in nodes) {
2359 var d = nodes[i];
2360 if (d[1] == url) {
2361 return new Array(i);
2362 }
2363 else if (d[2] != null) {
2364 result = find_page(url, d[2]);
2365 if (result != null) {
2366 return (new Array(i).concat(result));
2367 }
2368 }
2369 }
2370 return null;
2371}
2372
2373function init_default_navtree(toroot) {
2374 init_navtree("tree-list", toroot, NAVTREE_DATA);
Robert Lyc942e872013-05-07 12:09:01 -07002375
Robert Lya4d2d0e2013-04-09 11:26:12 -07002376 // perform api level toggling because because the whole tree is new to the DOM
2377 var selectedLevel = $("#apiLevelSelector option:selected").val();
2378 toggleVisisbleApis(selectedLevel, "#side-nav");
2379}
2380
2381function init_navtree(navtree_id, toroot, root_nodes)
2382{
2383 var me = new Object();
2384 me.toroot = toroot;
2385 me.node = new Object();
2386
2387 me.node.li = document.getElementById(navtree_id);
2388 me.node.children_data = root_nodes;
2389 me.node.children = new Array();
2390 me.node.children_ul = document.createElement("ul");
2391 me.node.get_children_ul = function() { return me.node.children_ul; };
2392 //me.node.children_ul.className = "children_ul";
2393 me.node.li.appendChild(me.node.children_ul);
2394 me.node.depth = 0;
2395
2396 get_node(me, me.node);
2397
2398 me.this_page = this_page_relative(toroot);
2399 me.breadcrumbs = find_page(me.this_page, root_nodes);
2400 if (me.breadcrumbs != null && me.breadcrumbs.length != 0) {
2401 var mom = me.node;
2402 for (var i in me.breadcrumbs) {
2403 var j = me.breadcrumbs[i];
2404 mom = mom.children[j];
2405 expand_node(me, mom);
2406 }
2407 mom.label_div.className = mom.label_div.className + " selected";
2408 addLoadEvent(function() {
2409 scrollIntoView("nav-tree");
2410 });
2411 }
2412}
2413
2414/* TODO: eliminate redundancy with non-google functions */
2415function init_google_navtree(navtree_id, toroot, root_nodes)
2416{
2417 var me = new Object();
2418 me.toroot = toroot;
2419 me.node = new Object();
2420
2421 me.node.li = document.getElementById(navtree_id);
2422 me.node.children_data = root_nodes;
2423 me.node.children = new Array();
2424 me.node.children_ul = document.createElement("ul");
2425 me.node.get_children_ul = function() { return me.node.children_ul; };
2426 //me.node.children_ul.className = "children_ul";
2427 me.node.li.appendChild(me.node.children_ul);
2428 me.node.depth = 0;
2429
2430 get_google_node(me, me.node);
2431
2432}
2433
2434function new_google_node(me, mom, text, link, children_data, api_level)
2435{
2436 var node = new Object();
2437 var child;
2438 node.children = Array();
2439 node.children_data = children_data;
2440 node.depth = mom.depth + 1;
2441 node.get_children_ul = function() {
2442 if (!node.children_ul) {
Robert Lyc942e872013-05-07 12:09:01 -07002443 node.children_ul = document.createElement("ul");
2444 node.children_ul.className = "tree-list-children";
Robert Lya4d2d0e2013-04-09 11:26:12 -07002445 node.li.appendChild(node.children_ul);
2446 }
2447 return node.children_ul;
2448 };
2449 node.li = document.createElement("li");
2450
2451 mom.get_children_ul().appendChild(node.li);
Robert Lyc942e872013-05-07 12:09:01 -07002452
2453
Robert Lya4d2d0e2013-04-09 11:26:12 -07002454 if(link) {
2455 child = document.createElement("a");
2456
2457 }
2458 else {
2459 child = document.createElement("span");
2460 child.className = "tree-list-subtitle";
2461
2462 }
2463 if (children_data != null) {
2464 node.li.className="nav-section";
2465 node.label_div = document.createElement("div");
Robert Lyc942e872013-05-07 12:09:01 -07002466 node.label_div.className = "nav-section-header-ref";
Robert Lya4d2d0e2013-04-09 11:26:12 -07002467 node.li.appendChild(node.label_div);
2468 get_google_node(me, node);
2469 node.label_div.appendChild(child);
2470 }
2471 else {
2472 node.li.appendChild(child);
2473 }
2474 if(link) {
2475 child.href = me.toroot + link;
2476 }
2477 node.label = document.createTextNode(text);
2478 child.appendChild(node.label);
2479
2480 node.children_ul = null;
2481
2482 return node;
2483}
2484
2485function get_google_node(me, mom)
2486{
2487 mom.children_visited = true;
2488 var linkText;
2489 for (var i in mom.children_data) {
2490 var node_data = mom.children_data[i];
2491 linkText = node_data[0];
2492
2493 if(linkText.match("^"+"com.google.android")=="com.google.android"){
2494 linkText = linkText.substr(19, linkText.length);
2495 }
2496 else if(linkText.match("^"+"com.android")=="com.android"){
2497 linkText = linkText.substr(12, linkText.length);
2498 }
2499 mom.children[i] = new_google_node(me, mom, linkText, node_data[1],
2500 node_data[2], node_data[3]);
2501 }
2502}
2503function showGoogleRefTree() {
2504 init_default_google_navtree(toRoot);
2505 init_default_gcm_navtree(toRoot);
2506 resizeNav();
2507}
2508
2509
2510function showTradefedRefTree() {
2511 init_default_tradefed_navtree(toRoot);
2512 resizeNav();
2513}
2514
2515function init_default_google_navtree(toroot) {
2516 init_google_navtree("gms-tree-list", toroot, GMS_NAVTREE_DATA);
2517}
2518
2519function init_default_gcm_navtree(toroot) {
2520 init_google_navtree("gcm-tree-list", toroot, GCM_NAVTREE_DATA);
2521}
2522
2523function init_default_tradefed_navtree(toroot) {
2524 init_google_navtree("tradefed-tree-list", toroot, NAVTREE_DATA);
2525}
2526
2527/* TOGGLE INHERITED MEMBERS */
2528
2529/* Toggle an inherited class (arrow toggle)
2530 * @param linkObj The link that was clicked.
2531 * @param expand 'true' to ensure it's expanded. 'false' to ensure it's closed.
2532 * 'null' to simply toggle.
2533 */
2534function toggleInherited(linkObj, expand) {
2535 var base = linkObj.getAttribute("id");
2536 var list = document.getElementById(base + "-list");
2537 var summary = document.getElementById(base + "-summary");
2538 var trigger = document.getElementById(base + "-trigger");
2539 var a = $(linkObj);
2540 if ( (expand == null && a.hasClass("closed")) || expand ) {
2541 list.style.display = "none";
2542 summary.style.display = "block";
2543 trigger.src = toRoot + "assets/images/triangle-opened.png";
2544 a.removeClass("closed");
2545 a.addClass("opened");
2546 } else if ( (expand == null && a.hasClass("opened")) || (expand == false) ) {
2547 list.style.display = "block";
2548 summary.style.display = "none";
2549 trigger.src = toRoot + "assets/images/triangle-closed.png";
2550 a.removeClass("opened");
2551 a.addClass("closed");
2552 }
2553 return false;
2554}
2555
2556/* Toggle all inherited classes in a single table (e.g. all inherited methods)
2557 * @param linkObj The link that was clicked.
2558 * @param expand 'true' to ensure it's expanded. 'false' to ensure it's closed.
2559 * 'null' to simply toggle.
2560 */
2561function toggleAllInherited(linkObj, expand) {
2562 var a = $(linkObj);
2563 var table = $(a.parent().parent().parent()); // ugly way to get table/tbody
2564 var expandos = $(".jd-expando-trigger", table);
2565 if ( (expand == null && a.text() == "[Expand]") || expand ) {
2566 expandos.each(function(i) {
2567 toggleInherited(this, true);
2568 });
2569 a.text("[Collapse]");
2570 } else if ( (expand == null && a.text() == "[Collapse]") || (expand == false) ) {
2571 expandos.each(function(i) {
2572 toggleInherited(this, false);
2573 });
2574 a.text("[Expand]");
2575 }
2576 return false;
2577}
2578
2579/* Toggle all inherited members in the class (link in the class title)
2580 */
2581function toggleAllClassInherited() {
2582 var a = $("#toggleAllClassInherited"); // get toggle link from class title
2583 var toggles = $(".toggle-all", $("#body-content"));
2584 if (a.text() == "[Expand All]") {
2585 toggles.each(function(i) {
2586 toggleAllInherited(this, true);
2587 });
2588 a.text("[Collapse All]");
2589 } else {
2590 toggles.each(function(i) {
2591 toggleAllInherited(this, false);
2592 });
2593 a.text("[Expand All]");
2594 }
2595 return false;
2596}
2597
2598/* Expand all inherited members in the class. Used when initiating page search */
2599function ensureAllInheritedExpanded() {
2600 var toggles = $(".toggle-all", $("#body-content"));
2601 toggles.each(function(i) {
2602 toggleAllInherited(this, true);
2603 });
2604 $("#toggleAllClassInherited").text("[Collapse All]");
2605}
2606
2607
2608/* HANDLE KEY EVENTS
2609 * - Listen for Ctrl+F (Cmd on Mac) and expand all inherited members (to aid page search)
2610 */
2611var agent = navigator['userAgent'].toLowerCase();
2612var mac = agent.indexOf("macintosh") != -1;
2613
2614$(document).keydown( function(e) {
2615var control = mac ? e.metaKey && !e.ctrlKey : e.ctrlKey; // get ctrl key
2616 if (control && e.which == 70) { // 70 is "F"
2617 ensureAllInheritedExpanded();
2618 }
2619});