|
| 1 | +// The MIT License (MIT) |
| 2 | + |
| 3 | +// Copyright (c) 2013-2018 Dave Snider, Read the Docs, Inc. & contributors |
| 4 | + |
| 5 | +// Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 6 | +// this software and associated documentation files (the "Software"), to deal in |
| 7 | +// the Software without restriction, including without limitation the rights to |
| 8 | +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| 9 | +// the Software, and to permit persons to whom the Software is furnished to do so, |
| 10 | +// subject to the following conditions: |
| 11 | + |
| 12 | +// The above copyright notice and this permission notice shall be included in all |
| 13 | +// copies or substantial portions of the Software. |
| 14 | + |
| 15 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| 17 | +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| 18 | +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| 19 | +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 20 | +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 21 | + |
| 22 | +// var jQuery = (typeof(window) != 'undefined') ? window.jQuery : require('jquery'); |
| 23 | + |
| 24 | +// Sphinx theme nav state |
| 25 | +function ThemeNav () { |
| 26 | + |
| 27 | + var nav = { |
| 28 | + navBar: null, |
| 29 | + win: null, |
| 30 | + winScroll: false, |
| 31 | + winResize: false, |
| 32 | + linkScroll: false, |
| 33 | + winPosition: 0, |
| 34 | + winHeight: null, |
| 35 | + docHeight: null, |
| 36 | + isRunning: false |
| 37 | + }; |
| 38 | + |
| 39 | + nav.enable = function (withStickyNav) { |
| 40 | + var self = this; |
| 41 | + |
| 42 | + // TODO this can likely be removed once the theme javascript is broken |
| 43 | + // out from the RTD assets. This just ensures old projects that are |
| 44 | + // calling `enable()` get the sticky menu on by default. All other cals |
| 45 | + // to `enable` should include an argument for enabling the sticky menu. |
| 46 | + if (typeof(withStickyNav) == 'undefined') { |
| 47 | + withStickyNav = true; |
| 48 | + } |
| 49 | + |
| 50 | + if (self.isRunning) { |
| 51 | + // Only allow enabling nav logic once |
| 52 | + return; |
| 53 | + } |
| 54 | + |
| 55 | + self.isRunning = true; |
| 56 | + jQuery(function ($) { |
| 57 | + self.init($); |
| 58 | + |
| 59 | + self.reset(); |
| 60 | + self.win.on('hashchange', self.reset); |
| 61 | + |
| 62 | + if (withStickyNav) { |
| 63 | + // Set scroll monitor |
| 64 | + self.win.on('scroll', function () { |
| 65 | + if (!self.linkScroll) { |
| 66 | + if (!self.winScroll) { |
| 67 | + self.winScroll = true; |
| 68 | + requestAnimationFrame(function() { self.onScroll(); }); |
| 69 | + } |
| 70 | + } |
| 71 | + }); |
| 72 | + } |
| 73 | + |
| 74 | + // Set resize monitor |
| 75 | + self.win.on('resize', function () { |
| 76 | + if (!self.winResize) { |
| 77 | + self.winResize = true; |
| 78 | + requestAnimationFrame(function() { self.onResize(); }); |
| 79 | + } |
| 80 | + }); |
| 81 | + |
| 82 | + self.onResize(); |
| 83 | + }); |
| 84 | + |
| 85 | + }; |
| 86 | + |
| 87 | + // TODO remove this with a split in theme and Read the Docs JS logic as |
| 88 | + // well, it's only here to support 0.3.0 installs of our theme. |
| 89 | + nav.enableSticky = function() { |
| 90 | + this.enable(true); |
| 91 | + }; |
| 92 | + |
| 93 | + nav.init = function ($) { |
| 94 | + var doc = $(document), |
| 95 | + self = this; |
| 96 | + |
| 97 | + this.navBar = $('div.wy-side-scroll:first'); |
| 98 | + this.win = $(window); |
| 99 | + |
| 100 | + // Set up javascript UX bits |
| 101 | + $(document) |
| 102 | + // Shift nav in mobile when clicking the menu. |
| 103 | + .on('click', "[data-toggle='wy-nav-top']", function() { |
| 104 | + $("[data-toggle='wy-nav-shift']").toggleClass("shift"); |
| 105 | + $("[data-toggle='rst-versions']").toggleClass("shift"); |
| 106 | + }) |
| 107 | + |
| 108 | + // Nav menu link click operations |
| 109 | + .on('click', ".wy-menu-vertical .current ul li a", function() { |
| 110 | + var target = $(this); |
| 111 | + // Close menu when you click a link. |
| 112 | + $("[data-toggle='wy-nav-shift']").removeClass("shift"); |
| 113 | + $("[data-toggle='rst-versions']").toggleClass("shift"); |
| 114 | + // Handle dynamic display of l3 and l4 nav lists |
| 115 | + self.toggleCurrent(target); |
| 116 | + self.hashChange(); |
| 117 | + }) |
| 118 | + .on('click', "[data-toggle='rst-current-version']", function() { |
| 119 | + $("[data-toggle='rst-versions']").toggleClass("shift-up"); |
| 120 | + }) |
| 121 | + |
| 122 | + // Make tables responsive |
| 123 | + $("table.docutils:not(.field-list,.footnote,.citation)") |
| 124 | + .wrap("<div class='wy-table-responsive'></div>"); |
| 125 | + |
| 126 | + // Add extra class to responsive tables that contain |
| 127 | + // footnotes or citations so that we can target them for styling |
| 128 | + $("table.docutils.footnote") |
| 129 | + .wrap("<div class='wy-table-responsive footnote'></div>"); |
| 130 | + $("table.docutils.citation") |
| 131 | + .wrap("<div class='wy-table-responsive citation'></div>"); |
| 132 | + |
| 133 | + // Add expand links to all parents of nested ul |
| 134 | + $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () { |
| 135 | + var link = $(this); |
| 136 | + expand = $('<span class="toctree-expand"></span>'); |
| 137 | + expand.on('click', function (ev) { |
| 138 | + self.toggleCurrent(link); |
| 139 | + ev.stopPropagation(); |
| 140 | + return false; |
| 141 | + }); |
| 142 | + link.prepend(expand); |
| 143 | + }); |
| 144 | + }; |
| 145 | + |
| 146 | + nav.reset = function () { |
| 147 | + // Get anchor from URL and open up nested nav |
| 148 | + var anchor = encodeURI(window.location.hash) || '#'; |
| 149 | + |
| 150 | + try { |
| 151 | + var vmenu = $('.wy-menu-vertical'); |
| 152 | + var link = vmenu.find('[href="' + anchor + '"]'); |
| 153 | + if (link.length === 0) { |
| 154 | + // this link was not found in the sidebar. |
| 155 | + // Find associated id element, then its closest section |
| 156 | + // in the document and try with that one. |
| 157 | + var id_elt = $('.document [id="' + anchor.substring(1) + '"]'); |
| 158 | + var closest_section = id_elt.closest('div.section'); |
| 159 | + link = vmenu.find('[href="#' + closest_section.attr("id") + '"]'); |
| 160 | + if (link.length === 0) { |
| 161 | + // still not found in the sidebar. fall back to main section |
| 162 | + link = vmenu.find('[href="#"]'); |
| 163 | + } |
| 164 | + } |
| 165 | + // If we found a matching link then reset current and re-apply |
| 166 | + // otherwise retain the existing match |
| 167 | + if (link.length > 0) { |
| 168 | + $('.wy-menu-vertical .current').removeClass('current'); |
| 169 | + link.addClass('current'); |
| 170 | + link.closest('li.toctree-l1').addClass('current'); |
| 171 | + link.closest('li.toctree-l1').parent().addClass('current'); |
| 172 | + link.closest('li.toctree-l1').addClass('current'); |
| 173 | + link.closest('li.toctree-l2').addClass('current'); |
| 174 | + link.closest('li.toctree-l3').addClass('current'); |
| 175 | + link.closest('li.toctree-l4').addClass('current'); |
| 176 | + link[0].scrollIntoView(); |
| 177 | + } |
| 178 | + } |
| 179 | + catch (err) { |
| 180 | + console.log("Error expanding nav for anchor", err); |
| 181 | + } |
| 182 | + |
| 183 | + }; |
| 184 | + |
| 185 | + nav.onScroll = function () { |
| 186 | + this.winScroll = false; |
| 187 | + var newWinPosition = this.win.scrollTop(), |
| 188 | + winBottom = newWinPosition + this.winHeight, |
| 189 | + navPosition = this.navBar.scrollTop(), |
| 190 | + newNavPosition = navPosition + (newWinPosition - this.winPosition); |
| 191 | + if (newWinPosition < 0 || winBottom > this.docHeight) { |
| 192 | + return; |
| 193 | + } |
| 194 | + this.navBar.scrollTop(newNavPosition); |
| 195 | + this.winPosition = newWinPosition; |
| 196 | + }; |
| 197 | + |
| 198 | + nav.onResize = function () { |
| 199 | + this.winResize = false; |
| 200 | + this.winHeight = this.win.height(); |
| 201 | + this.docHeight = $(document).height(); |
| 202 | + }; |
| 203 | + |
| 204 | + nav.hashChange = function () { |
| 205 | + this.linkScroll = true; |
| 206 | + this.win.one('hashchange', function () { |
| 207 | + this.linkScroll = false; |
| 208 | + }); |
| 209 | + }; |
| 210 | + |
| 211 | + nav.toggleCurrent = function (elem) { |
| 212 | + var parent_li = elem.closest('li'); |
| 213 | + parent_li.siblings('li.current').removeClass('current'); |
| 214 | + parent_li.siblings().find('li.current').removeClass('current'); |
| 215 | + parent_li.find('> ul li.current').removeClass('current'); |
| 216 | + parent_li.toggleClass('current'); |
| 217 | + } |
| 218 | + |
| 219 | + return nav; |
| 220 | +}; |
| 221 | + |
| 222 | +module.exports.ThemeNav = ThemeNav(); |
| 223 | + |
| 224 | +if (typeof(window) != 'undefined') { |
| 225 | + window.SphinxRtdTheme = { |
| 226 | + Navigation: module.exports.ThemeNav, |
| 227 | + // TODO remove this once static assets are split up between the theme |
| 228 | + // and Read the Docs. For now, this patches 0.3.0 to be backwards |
| 229 | + // compatible with a pre-0.3.0 layout.html |
| 230 | + StickyNav: module.exports.ThemeNav, |
| 231 | + }; |
| 232 | +} |
| 233 | + |
| 234 | + |
| 235 | +// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel |
| 236 | +// https://gist.github.com/paulirish/1579671 |
| 237 | +// MIT license |
| 238 | + |
| 239 | +(function() { |
| 240 | + var lastTime = 0; |
| 241 | + var vendors = ['ms', 'moz', 'webkit', 'o']; |
| 242 | + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { |
| 243 | + window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; |
| 244 | + window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] |
| 245 | + || window[vendors[x]+'CancelRequestAnimationFrame']; |
| 246 | + } |
| 247 | + |
| 248 | + if (!window.requestAnimationFrame) |
| 249 | + window.requestAnimationFrame = function(callback, element) { |
| 250 | + var currTime = new Date().getTime(); |
| 251 | + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); |
| 252 | + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, |
| 253 | + timeToCall); |
| 254 | + lastTime = currTime + timeToCall; |
| 255 | + return id; |
| 256 | + }; |
| 257 | + |
| 258 | + if (!window.cancelAnimationFrame) |
| 259 | + window.cancelAnimationFrame = function(id) { |
| 260 | + clearTimeout(id); |
| 261 | + }; |
| 262 | +}()); |
0 commit comments