Home | History | Annotate | Download | only in js
      1 var navBarIsFixed = false;
      2 $(document).ready(function() {
      3   // init the fullscreen toggle click event
      4   $('#nav-swap .fullscreen').click(function(){
      5     if ($(this).hasClass('disabled')) {
      6       toggleFullscreen(true);
      7     } else {
      8       toggleFullscreen(false);
      9     }
     10   });
     11   
     12   // initialize the divs with custom scrollbars
     13   $('.scroll-pane').jScrollPane( {verticalGutter:0} );
     14   
     15   // add HRs below all H2s (except for a few other h2 variants)
     16   $('h2').not('#qv h2').not('#tb h2').not('#devdoc-nav h2').css({marginBottom:0}).after('<hr/>');
     17   
     18   // set search's onkeyup handler here so we can show suggestions even while search results are visible
     19   $("#search_autocomplete").keyup(function() {return search_changed(event, false, '/')});
     20 
     21   // set up the search close button
     22   $('.search .close').click(function() {
     23     $searchInput = $('#search_autocomplete');
     24     $searchInput.attr('value', '');
     25     $(this).addClass("hide");
     26     $("#search-container").removeClass('active');
     27     $("#search_autocomplete").blur();
     28     search_focus_changed($searchInput.get(), false);  // see search_autocomplete.js
     29     hideResults();  // see search_autocomplete.js
     30   });
     31   $('.search').click(function() {
     32     if (!$('#search_autocomplete').is(":focused")) {
     33         $('#search_autocomplete').focus();
     34     }
     35   });
     36 
     37   // Set up quicknav
     38   var quicknav_open = false;  
     39   $("#btn-quicknav").click(function() {
     40     if (quicknav_open) {
     41       $(this).removeClass('active');
     42       quicknav_open = false;
     43       collapse();
     44     } else {
     45       $(this).addClass('active');
     46       quicknav_open = true;
     47       expand();
     48     }
     49   })
     50   
     51   var expand = function() {
     52    $('#header-wrap').addClass('quicknav');
     53    $('#quicknav').stop().show().animate({opacity:'1'});
     54   }
     55   
     56   var collapse = function() {
     57     $('#quicknav').stop().animate({opacity:'0'}, 100, function() {
     58       $(this).hide();
     59       $('#header-wrap').removeClass('quicknav');
     60     });
     61   }
     62   
     63   
     64   //Set up search
     65   $("#search_autocomplete").focus(function() {
     66     $("#search-container").addClass('active');
     67   })
     68   $("#search-container").mouseover(function() {
     69     $("#search-container").addClass('active');
     70     $("#search_autocomplete").focus();
     71   })
     72   $("#search-container").mouseout(function() {
     73     if ($("#search_autocomplete").is(":focus")) return;
     74     if ($("#search_autocomplete").val() == '') {
     75       setTimeout(function(){
     76         $("#search-container").removeClass('active');
     77         $("#search_autocomplete").blur();
     78       },250);
     79     }
     80   })
     81   $("#search_autocomplete").blur(function() {
     82     if ($("#search_autocomplete").val() == '') {
     83       $("#search-container").removeClass('active');
     84     }
     85   })
     86 
     87     
     88   // prep nav expandos
     89   var pagePath = document.location.pathname;
     90   // account for intl docs by removing the intl/*/ path
     91   if (pagePath.indexOf("/intl/") == 0) {
     92     pagePath = pagePath.substr(pagePath.indexOf("/",6)); // start after intl/ to get last /
     93   }
     94   
     95   if (pagePath.indexOf(SITE_ROOT) == 0) {
     96     if (pagePath == '' || pagePath.charAt(pagePath.length - 1) == '/') {
     97       pagePath += 'index.html';
     98     }
     99   }
    100 
    101   if (SITE_ROOT.match(/\.\.\//) || SITE_ROOT == '') {
    102     // If running locally, SITE_ROOT will be a relative path, so account for that by
    103     // finding the relative URL to this page. This will allow us to find links on the page
    104     // leading back to this page.
    105     var pathParts = pagePath.split('/');
    106     var relativePagePathParts = [];
    107     var upDirs = (SITE_ROOT.match(/(\.\.\/)+/) || [''])[0].length / 3;
    108     for (var i = 0; i < upDirs; i++) {
    109       relativePagePathParts.push('..');
    110     }
    111     for (var i = 0; i < upDirs; i++) {
    112       relativePagePathParts.push(pathParts[pathParts.length - (upDirs - i) - 1]);
    113     }
    114     relativePagePathParts.push(pathParts[pathParts.length - 1]);
    115     pagePath = relativePagePathParts.join('/');
    116   } else {
    117     // Otherwise the page path is already an absolute URL
    118   }
    119 
    120   // select current page in sidenav and set up prev/next links if they exist
    121   var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]');
    122   if ($selNavLink.length) {
    123     $selListItem = $selNavLink.closest('li');
    124 
    125     $selListItem.addClass('selected');
    126     $selListItem.closest('li.nav-section').addClass('expanded');
    127     $selListItem.closest('li.nav-section').children('ul').show();
    128     $selListItem.closest('li.nav-section').parent().closest('li.nav-section').addClass('expanded');
    129     $selListItem.closest('li.nav-section').parent().closest('ul').show();
    130     
    131     
    132   //  $selListItem.closest('li.nav-section').closest('li.nav-section').addClass('expanded');
    133   //  $selListItem.closest('li.nav-section').closest('li.nav-section').children('ul').show();  
    134 
    135     // set up prev links
    136     var $prevLink = [];
    137     var $prevListItem = $selListItem.prev('li');
    138     
    139     var crossBoundaries = ($("body.design").length > 0) || ($("body.guide").length > 0) ? true : false; // navigate across topic boundaries only in design docs
    140     if ($prevListItem.length) {
    141       if ($prevListItem.hasClass('nav-section')) {
    142         if (crossBoundaries) {
    143           // jump to last topic of previous section
    144           $prevLink = $prevListItem.find('a:last');
    145         }
    146       } else {
    147         // jump to previous topic in this section
    148         $prevLink = $prevListItem.find('a:eq(0)');
    149       }
    150     } else {
    151       // jump to this section's index page (if it exists)
    152       var $parentListItem = $selListItem.parents('li');
    153       $prevLink = $selListItem.parents('li').find('a');
    154       
    155       // except if cross boundaries aren't allowed, and we're at the top of a section already (and there's another parent)
    156       if (!crossBoundaries && $parentListItem.hasClass('nav-section') && $selListItem.hasClass('nav-section')) {
    157         $prevLink = [];
    158       }
    159     }
    160 
    161     if ($prevLink.length) {
    162       var prevHref = $prevLink.attr('href');
    163       if (prevHref == SITE_ROOT + 'index.html') {
    164         // Don't show Previous when it leads to the homepage
    165       } else {
    166         $('.prev-page-link').attr('href', $prevLink.attr('href')).removeClass("hide");
    167       }
    168     } 
    169 
    170     // set up next links
    171     var $nextLink = [];
    172     var startCourse = false;
    173     var startClass = false;
    174     var training = $(".next-class-link").length; // decides whether to provide "next class" link
    175     var isCrossingBoundary = false;
    176     
    177     if ($selListItem.hasClass('nav-section')) {
    178       // we're on an index page, jump to the first topic
    179       $nextLink = $selListItem.find('ul').find('a:eq(0)');
    180 
    181       // if there aren't any children, go to the next section (required for About pages)
    182       if($nextLink.length == 0) {
    183         $nextLink = $selListItem.next('li').find('a');
    184       }
    185       
    186       // Handle some Training specialties
    187       if ($selListItem.parent().is("#nav") && $(".start-course-link").length) {
    188         // this means we're at the very top of the TOC hierarchy
    189         startCourse = true;
    190       } else if ($(".start-class-link").length) {
    191         // this means this page has children but is not at the top (it's a class, not a course)
    192         startClass = true;
    193       }
    194     } else {
    195       // jump to the next topic in this section (if it exists)
    196       $nextLink = $selListItem.next('li').find('a:eq(0)');
    197       if (!$nextLink.length) {
    198         if (crossBoundaries || training) {
    199           // no more topics in this section, jump to the first topic in the next section
    200           $nextLink = $selListItem.parents('li:eq(0)').next('li.nav-section').find('a:eq(0)');
    201           isCrossingBoundary = true;
    202         }
    203       }
    204     }
    205     if ($nextLink.length) {
    206       if (startCourse || startClass) {
    207         if (startCourse) {
    208           $('.start-course-link').attr('href', $nextLink.attr('href')).removeClass("hide");
    209         } else {
    210           $('.start-class-link').attr('href', $nextLink.attr('href')).removeClass("hide");
    211         }
    212         // if there's no training bar (below the start button), then we need to add a bottom border to button
    213         if (!$("#tb").length) {
    214           $('.start-course-link').css({'border-bottom':'1px solid #DADADA'});
    215           $('.start-class-link').css({'border-bottom':'1px solid #DADADA'});
    216         }
    217       } else if (training && isCrossingBoundary) {
    218         $('.content-footer.next-class').show();
    219         $('.next-page-link').attr('href','').removeClass("hide").addClass("disabled").click(function() {
    220               return false;
    221             });
    222         $('.next-class-link').attr('href',$nextLink.attr('href')).removeClass("hide").append($nextLink.html());
    223         $('.next-class-link').find('.new').empty();
    224       } else {
    225         $('.next-page-link').attr('href', $nextLink.attr('href')).removeClass("hide");
    226       }
    227     }
    228     
    229   }
    230 
    231 
    232 
    233   // Set up expand/collapse behavior
    234   $('#nav li.nav-section .nav-section-header').click(function() {
    235     var section = $(this).closest('li.nav-section');
    236     if (section.hasClass('expanded')) {
    237     /* hide me */
    238     //  if (section.hasClass('selected') || section.find('li').hasClass('selected')) {
    239    //   /* but not if myself or my descendents are selected */
    240    //     return;
    241     //  }
    242       section.children('ul').slideUp(250, function() {
    243         section.closest('li').removeClass('expanded');
    244         resizeNav();
    245       });
    246     } else {
    247     /* show me */
    248       // first hide all other siblings
    249       var $others = $('li.nav-section.expanded', $(this).closest('ul'));
    250       $others.removeClass('expanded').children('ul').slideUp(250);
    251       
    252       // now expand me
    253       section.closest('li').addClass('expanded');
    254       section.children('ul').slideDown(250, function() {
    255         resizeNav();
    256       });
    257     }
    258   });
    259   
    260   $(".scroll-pane").scroll(function(event) {
    261       event.preventDefault();
    262       return false;
    263   });
    264 
    265   /* Resize nav height when window height changes */
    266   $(window).resize(function() {
    267     var stylesheet = $('link[rel="stylesheet"][title="fullscreen"]');
    268     setNavBarLeftPos(); // do this even if sidenav isn't fixed because it could become fixed
    269     // make sidenav behave when resizing the window and side-scolling is a concern
    270     if (navBarIsFixed) {
    271       if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) {
    272         updateSideNavPosition();
    273       } else {
    274         updateSidenavFullscreenWidth();
    275       }
    276     }
    277     resizeNav();
    278   });
    279 
    280 
    281   // Set up fixed navbar
    282   var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll
    283   $(window).scroll(function(event) {
    284     if (event.target.nodeName == "DIV") {
    285       // Dump scroll event if the target is a DIV, because that means the event is coming
    286       // from a scrollable div and so there's no need to make adjustments to our layout
    287       return;
    288     }
    289     var scrollTop = $(window).scrollTop();    
    290     var headerHeight = $('#header').outerHeight();
    291     var subheaderHeight = $('#nav-x').outerHeight();
    292     var searchResultHeight = $('#searchResults').is(":visible") ? $('#searchResults').outerHeight() : 0;
    293     var totalHeaderHeight = headerHeight + subheaderHeight + searchResultHeight;
    294     var navBarShouldBeFixed = scrollTop > totalHeaderHeight;
    295    
    296     var scrollLeft = $(window).scrollLeft();
    297     // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match
    298     if (navBarIsFixed && (scrollLeft != prevScrollLeft)) {
    299       updateSideNavPosition();
    300       prevScrollLeft = scrollLeft;
    301     }
    302     
    303     // Don't continue if the header is sufficently far away (to avoid intensive resizing that slows scrolling)
    304     if (navBarIsFixed && navBarShouldBeFixed) {
    305       return;
    306     }
    307     
    308     if (navBarIsFixed != navBarShouldBeFixed) {
    309       if (navBarShouldBeFixed) {
    310         // make it fixed
    311         var width = $('#devdoc-nav').width();
    312         var margin = $('#devdoc-nav').parent().css('margin');
    313         $('#devdoc-nav')
    314             .addClass('fixed')
    315             .css({'width':width+'px','margin':margin})
    316             .prependTo('#body-content');
    317         // add neato "back to top" button
    318         $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'});
    319         
    320         // update the sidenaav position for side scrolling
    321         updateSideNavPosition();
    322       } else {
    323         // make it static again
    324         $('#devdoc-nav')
    325             .removeClass('fixed')
    326             .css({'width':'auto','margin':''})
    327             .prependTo('#side-nav');
    328         $('#devdoc-nav a.totop').hide();
    329       }
    330       navBarIsFixed = navBarShouldBeFixed;
    331     } 
    332     
    333     resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance reasons
    334   });
    335 
    336   
    337   var navBarLeftPos;
    338   if ($('#devdoc-nav').length) {
    339     setNavBarLeftPos();
    340   }
    341 
    342 
    343   // Stop expand/collapse behavior when clicking on nav section links (since we're navigating away
    344   // from the page)
    345   $('.nav-section-header').find('a:eq(0)').click(function(evt) {
    346     window.location.href = $(this).attr('href');
    347     return false;
    348   });
    349 
    350   // Set up play-on-hover <video> tags.
    351   $('video.play-on-hover').bind('click', function(){
    352     $(this).get(0).load(); // in case the video isn't seekable
    353     $(this).get(0).play();
    354   });
    355 
    356   // Set up tooltips
    357   var TOOLTIP_MARGIN = 10;
    358   $('acronym').each(function() {
    359     var $target = $(this);
    360     var $tooltip = $('<div>')
    361         .addClass('tooltip-box')
    362         .text($target.attr('title'))
    363         .hide()
    364         .appendTo('body');
    365     $target.removeAttr('title');
    366 
    367     $target.hover(function() {
    368       // in
    369       var targetRect = $target.offset();
    370       targetRect.width = $target.width();
    371       targetRect.height = $target.height();
    372 
    373       $tooltip.css({
    374         left: targetRect.left,
    375         top: targetRect.top + targetRect.height + TOOLTIP_MARGIN
    376       });
    377       $tooltip.addClass('below');
    378       $tooltip.show();
    379     }, function() {
    380       // out
    381       $tooltip.hide();
    382     });
    383   });
    384 
    385   // Set up <h2> deeplinks
    386   $('h2').click(function() {
    387     var id = $(this).attr('id');
    388     if (id) {
    389       document.location.hash = id;
    390     }
    391   });
    392 
    393   //Loads the +1 button
    394   var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    395   po.src = 'https://apis.google.com/js/plusone.js';
    396   var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
    397 
    398 
    399   // Revise the sidenav widths to make room for the scrollbar 
    400   // which avoids the visible width from changing each time the bar appears
    401   var $sidenav = $("#side-nav");
    402   var sidenav_width = parseInt($sidenav.innerWidth());
    403     
    404   $("#devdoc-nav  #nav").css("width", sidenav_width - 4 + "px"); // 4px is scrollbar width
    405 
    406 
    407   $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller
    408   
    409   if ($(".scroll-pane").length > 1) {
    410     // Check if there's a user preference for the panel heights
    411     var cookieHeight = readCookie("reference_height");
    412     if (cookieHeight) {
    413       restoreHeight(cookieHeight);
    414     }
    415   }
    416   
    417   resizeNav();
    418 
    419 
    420 });
    421 
    422 
    423 
    424   function toggleFullscreen(enable) {
    425     var delay = 20;
    426     var enabled = false;
    427     var stylesheet = $('link[rel="stylesheet"][title="fullscreen"]');
    428     if (enable) {
    429       // Currently NOT USING fullscreen; enable fullscreen
    430       stylesheet.removeAttr('disabled');
    431       $('#nav-swap .fullscreen').removeClass('disabled');
    432       $('#devdoc-nav').css({left:''});
    433       setTimeout(updateSidenavFullscreenWidth,delay); // need to wait a moment for css to switch
    434       enabled = true;
    435     } else {
    436       // Currently USING fullscreen; disable fullscreen
    437       stylesheet.attr('disabled', 'disabled');
    438       $('#nav-swap .fullscreen').addClass('disabled');
    439       setTimeout(updateSidenavFixedWidth,delay); // need to wait a moment for css to switch
    440       enabled = false;
    441     }
    442     writeCookie("fullscreen", enabled, null, null);
    443     setNavBarLeftPos();
    444     resizeNav(delay);
    445     setTimeout(initSidenavHeightResize,delay);
    446   }
    447 
    448   
    449   function setNavBarLeftPos() {
    450     navBarLeftPos = $('#body-content').offset().left;
    451   }
    452 
    453 
    454   function updateSideNavPosition() {
    455     var newLeft = $(window).scrollLeft() - navBarLeftPos;
    456     $('#devdoc-nav').css({left: -newLeft});
    457     $('#devdoc-nav .totop').css({left: -(newLeft - parseInt($('#side-nav').css('margin-left')))});
    458   }
    459