var jQuery = (typeof(window) != 'undefined') ? window.jQuery : require('jquery'); // Sphinx theme nav state function ThemeNav () { var nav = { navBar: null, win: null, winScroll: false, winResize: false, linkScroll: false, winPosition: 0, winHeight: null, docHeight: null, isRunning: false }; nav.enable = function (withStickyNav) { var self = this; // TODO this can likely be removed once the theme javascript is broken // out from the RTD assets. This just ensures old projects that are // calling `enable()` get the sticky menu on by default. All other cals // to `enable` should include an argument for enabling the sticky menu. if (typeof(withStickyNav) == 'undefined') { withStickyNav = true; } if (self.isRunning) { // Only allow enabling nav logic once return; } self.isRunning = true; jQuery(function ($) { self.init($); self.reset(); self.win.on('hashchange', self.reset); if (withStickyNav) { // Set scroll monitor self.win.on('scroll', function () { if (!self.linkScroll) { if (!self.winScroll) { self.winScroll = true; requestAnimationFrame(function() { self.onScroll(); }); } } }); } // Set resize monitor self.win.on('resize', function () { if (!self.winResize) { self.winResize = true; requestAnimationFrame(function() { self.onResize(); }); } }); self.onResize(); }); }; // TODO remove this with a split in theme and Read the Docs JS logic as // well, it's only here to support 0.3.0 installs of our theme. nav.enableSticky = function() { this.enable(true); }; nav.init = function ($) { var doc = $(document), self = this; this.navBar = $('div.wy-side-scroll:first'); this.win = $(window); // Set up javascript UX bits $(document) // Shift nav in mobile when clicking the menu. .on('click', "[data-toggle='wy-nav-top']", function() { $("[data-toggle='wy-nav-shift']").toggleClass("shift"); $("[data-toggle='rst-versions']").toggleClass("shift"); }) // Nav menu link click operations .on('click', ".wy-menu-vertical .current ul li a", function() { var target = $(this); // Close menu when you click a link. $("[data-toggle='wy-nav-shift']").removeClass("shift"); $("[data-toggle='rst-versions']").toggleClass("shift"); // Handle dynamic display of l3 and l4 nav lists self.toggleCurrent(target); self.hashChange(); }) .on('click', "[data-toggle='rst-current-version']", function() { $("[data-toggle='rst-versions']").toggleClass("shift-up"); }) // Make tables responsive $("table.docutils:not(.field-list,.footnote,.citation)") .wrap("
"); // Add extra class to responsive tables that contain // footnotes or citations so that we can target them for styling $("table.docutils.footnote") .wrap("
"); $("table.docutils.citation") .wrap("
"); // Add expand links to all parents of nested ul $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () { var link = $(this); expand = $(''); expand.on('click', function (ev) { self.toggleCurrent(link); ev.stopPropagation(); return false; }); link.prepend(expand); }); }; nav.reset = function () { // Get anchor from URL and open up nested nav var anchor = encodeURI(window.location.hash) || '#'; try { var vmenu = $('.wy-menu-vertical'); var link = vmenu.find('[href="' + anchor + '"]'); if (link.length === 0) { // this link was not found in the sidebar. // Find associated id element, then its closest section // in the document and try with that one. var id_elt = $('.document [id="' + anchor.substring(1) + '"]'); var closest_section = id_elt.closest('div.section'); link = vmenu.find('[href="#' + closest_section.attr("id") + '"]'); if (link.length === 0) { // still not found in the sidebar. fall back to main section link = vmenu.find('[href="#"]'); } } // If we found a matching link then reset current and re-apply // otherwise retain the existing match if (link.length > 0) { $('.wy-menu-vertical .current') .removeClass('current') .attr('aria-expanded','false'); link.addClass('current') .attr('aria-expanded','true'); link.closest('li.toctree-l1') .parent() .addClass('current') .attr('aria-expanded','true'); for (let i = 1; i <= 10; i++) { link.closest('li.toctree-l' + i) .addClass('current') .attr('aria-expanded','true'); } link[0].scrollIntoView(); } } catch (err) { console.log("Error expanding nav for anchor", err); } }; nav.onScroll = function () { this.winScroll = false; var newWinPosition = this.win.scrollTop(), winBottom = newWinPosition + this.winHeight, navPosition = this.navBar.scrollTop(), newNavPosition = navPosition + (newWinPosition - this.winPosition); if (newWinPosition < 0 || winBottom > this.docHeight) { return; } this.navBar.scrollTop(newNavPosition); this.winPosition = newWinPosition; }; nav.onResize = function () { this.winResize = false; this.winHeight = this.win.height(); this.docHeight = $(document).height(); }; nav.hashChange = function () { this.linkScroll = true; this.win.one('hashchange', function () { this.linkScroll = false; }); }; nav.toggleCurrent = function (elem) { var parent_li = elem.closest('li'); parent_li .siblings('li.current') .removeClass('current') .attr('aria-expanded','false'); parent_li .siblings() .find('li.current') .removeClass('current') .attr('aria-expanded','false'); var children = parent_li.find('> ul li'); // Don't toggle terminal elements. if (children.length) { children .removeClass('current') .attr('aria-expanded','false'); parent_li .toggleClass('current') .attr('aria-expanded', function(i, old) { return old == 'true' ? 'false' : 'true'; }); } } return nav; }; _ThemeNav = ThemeNav(); if (typeof(window) != 'undefined') { window.SphinxRtdTheme = { Navigation: _ThemeNav, // TODO remove this once static assets are split up between the theme // and Read the Docs. For now, this patches 0.3.0 to be backwards // compatible with a pre-0.3.0 layout.html StickyNav: _ThemeNav, }; } // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel // https://gist.github.com/paulirish/1579671 // MIT license (function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }());