1*7f2fe78bSCy Schubert/* 2*7f2fe78bSCy Schubert * doctools.js 3*7f2fe78bSCy Schubert * ~~~~~~~~~~~ 4*7f2fe78bSCy Schubert * 5*7f2fe78bSCy Schubert * Sphinx JavaScript utilities for all documentation. 6*7f2fe78bSCy Schubert * 7*7f2fe78bSCy Schubert * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. 8*7f2fe78bSCy Schubert * :license: BSD, see LICENSE for details. 9*7f2fe78bSCy Schubert * 10*7f2fe78bSCy Schubert */ 11*7f2fe78bSCy Schubert 12*7f2fe78bSCy Schubert/** 13*7f2fe78bSCy Schubert * select a different prefix for underscore 14*7f2fe78bSCy Schubert */ 15*7f2fe78bSCy Schubert$u = _.noConflict(); 16*7f2fe78bSCy Schubert 17*7f2fe78bSCy Schubert/** 18*7f2fe78bSCy Schubert * make the code below compatible with browsers without 19*7f2fe78bSCy Schubert * an installed firebug like debugger 20*7f2fe78bSCy Schubertif (!window.console || !console.firebug) { 21*7f2fe78bSCy Schubert var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22*7f2fe78bSCy Schubert "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23*7f2fe78bSCy Schubert "profile", "profileEnd"]; 24*7f2fe78bSCy Schubert window.console = {}; 25*7f2fe78bSCy Schubert for (var i = 0; i < names.length; ++i) 26*7f2fe78bSCy Schubert window.console[names[i]] = function() {}; 27*7f2fe78bSCy Schubert} 28*7f2fe78bSCy Schubert */ 29*7f2fe78bSCy Schubert 30*7f2fe78bSCy Schubert/** 31*7f2fe78bSCy Schubert * small helper function to urldecode strings 32*7f2fe78bSCy Schubert * 33*7f2fe78bSCy Schubert * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL 34*7f2fe78bSCy Schubert */ 35*7f2fe78bSCy SchubertjQuery.urldecode = function(x) { 36*7f2fe78bSCy Schubert if (!x) { 37*7f2fe78bSCy Schubert return x 38*7f2fe78bSCy Schubert } 39*7f2fe78bSCy Schubert return decodeURIComponent(x.replace(/\+/g, ' ')); 40*7f2fe78bSCy Schubert}; 41*7f2fe78bSCy Schubert 42*7f2fe78bSCy Schubert/** 43*7f2fe78bSCy Schubert * small helper function to urlencode strings 44*7f2fe78bSCy Schubert */ 45*7f2fe78bSCy SchubertjQuery.urlencode = encodeURIComponent; 46*7f2fe78bSCy Schubert 47*7f2fe78bSCy Schubert/** 48*7f2fe78bSCy Schubert * This function returns the parsed url parameters of the 49*7f2fe78bSCy Schubert * current request. Multiple values per key are supported, 50*7f2fe78bSCy Schubert * it will always return arrays of strings for the value parts. 51*7f2fe78bSCy Schubert */ 52*7f2fe78bSCy SchubertjQuery.getQueryParameters = function(s) { 53*7f2fe78bSCy Schubert if (typeof s === 'undefined') 54*7f2fe78bSCy Schubert s = document.location.search; 55*7f2fe78bSCy Schubert var parts = s.substr(s.indexOf('?') + 1).split('&'); 56*7f2fe78bSCy Schubert var result = {}; 57*7f2fe78bSCy Schubert for (var i = 0; i < parts.length; i++) { 58*7f2fe78bSCy Schubert var tmp = parts[i].split('=', 2); 59*7f2fe78bSCy Schubert var key = jQuery.urldecode(tmp[0]); 60*7f2fe78bSCy Schubert var value = jQuery.urldecode(tmp[1]); 61*7f2fe78bSCy Schubert if (key in result) 62*7f2fe78bSCy Schubert result[key].push(value); 63*7f2fe78bSCy Schubert else 64*7f2fe78bSCy Schubert result[key] = [value]; 65*7f2fe78bSCy Schubert } 66*7f2fe78bSCy Schubert return result; 67*7f2fe78bSCy Schubert}; 68*7f2fe78bSCy Schubert 69*7f2fe78bSCy Schubert/** 70*7f2fe78bSCy Schubert * highlight a given string on a jquery object by wrapping it in 71*7f2fe78bSCy Schubert * span elements with the given class name. 72*7f2fe78bSCy Schubert */ 73*7f2fe78bSCy SchubertjQuery.fn.highlightText = function(text, className) { 74*7f2fe78bSCy Schubert function highlight(node, addItems) { 75*7f2fe78bSCy Schubert if (node.nodeType === 3) { 76*7f2fe78bSCy Schubert var val = node.nodeValue; 77*7f2fe78bSCy Schubert var pos = val.toLowerCase().indexOf(text); 78*7f2fe78bSCy Schubert if (pos >= 0 && 79*7f2fe78bSCy Schubert !jQuery(node.parentNode).hasClass(className) && 80*7f2fe78bSCy Schubert !jQuery(node.parentNode).hasClass("nohighlight")) { 81*7f2fe78bSCy Schubert var span; 82*7f2fe78bSCy Schubert var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 83*7f2fe78bSCy Schubert if (isInSVG) { 84*7f2fe78bSCy Schubert span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 85*7f2fe78bSCy Schubert } else { 86*7f2fe78bSCy Schubert span = document.createElement("span"); 87*7f2fe78bSCy Schubert span.className = className; 88*7f2fe78bSCy Schubert } 89*7f2fe78bSCy Schubert span.appendChild(document.createTextNode(val.substr(pos, text.length))); 90*7f2fe78bSCy Schubert node.parentNode.insertBefore(span, node.parentNode.insertBefore( 91*7f2fe78bSCy Schubert document.createTextNode(val.substr(pos + text.length)), 92*7f2fe78bSCy Schubert node.nextSibling)); 93*7f2fe78bSCy Schubert node.nodeValue = val.substr(0, pos); 94*7f2fe78bSCy Schubert if (isInSVG) { 95*7f2fe78bSCy Schubert var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 96*7f2fe78bSCy Schubert var bbox = node.parentElement.getBBox(); 97*7f2fe78bSCy Schubert rect.x.baseVal.value = bbox.x; 98*7f2fe78bSCy Schubert rect.y.baseVal.value = bbox.y; 99*7f2fe78bSCy Schubert rect.width.baseVal.value = bbox.width; 100*7f2fe78bSCy Schubert rect.height.baseVal.value = bbox.height; 101*7f2fe78bSCy Schubert rect.setAttribute('class', className); 102*7f2fe78bSCy Schubert addItems.push({ 103*7f2fe78bSCy Schubert "parent": node.parentNode, 104*7f2fe78bSCy Schubert "target": rect}); 105*7f2fe78bSCy Schubert } 106*7f2fe78bSCy Schubert } 107*7f2fe78bSCy Schubert } 108*7f2fe78bSCy Schubert else if (!jQuery(node).is("button, select, textarea")) { 109*7f2fe78bSCy Schubert jQuery.each(node.childNodes, function() { 110*7f2fe78bSCy Schubert highlight(this, addItems); 111*7f2fe78bSCy Schubert }); 112*7f2fe78bSCy Schubert } 113*7f2fe78bSCy Schubert } 114*7f2fe78bSCy Schubert var addItems = []; 115*7f2fe78bSCy Schubert var result = this.each(function() { 116*7f2fe78bSCy Schubert highlight(this, addItems); 117*7f2fe78bSCy Schubert }); 118*7f2fe78bSCy Schubert for (var i = 0; i < addItems.length; ++i) { 119*7f2fe78bSCy Schubert jQuery(addItems[i].parent).before(addItems[i].target); 120*7f2fe78bSCy Schubert } 121*7f2fe78bSCy Schubert return result; 122*7f2fe78bSCy Schubert}; 123*7f2fe78bSCy Schubert 124*7f2fe78bSCy Schubert/* 125*7f2fe78bSCy Schubert * backward compatibility for jQuery.browser 126*7f2fe78bSCy Schubert * This will be supported until firefox bug is fixed. 127*7f2fe78bSCy Schubert */ 128*7f2fe78bSCy Schubertif (!jQuery.browser) { 129*7f2fe78bSCy Schubert jQuery.uaMatch = function(ua) { 130*7f2fe78bSCy Schubert ua = ua.toLowerCase(); 131*7f2fe78bSCy Schubert 132*7f2fe78bSCy Schubert var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 133*7f2fe78bSCy Schubert /(webkit)[ \/]([\w.]+)/.exec(ua) || 134*7f2fe78bSCy Schubert /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 135*7f2fe78bSCy Schubert /(msie) ([\w.]+)/.exec(ua) || 136*7f2fe78bSCy Schubert ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 137*7f2fe78bSCy Schubert []; 138*7f2fe78bSCy Schubert 139*7f2fe78bSCy Schubert return { 140*7f2fe78bSCy Schubert browser: match[ 1 ] || "", 141*7f2fe78bSCy Schubert version: match[ 2 ] || "0" 142*7f2fe78bSCy Schubert }; 143*7f2fe78bSCy Schubert }; 144*7f2fe78bSCy Schubert jQuery.browser = {}; 145*7f2fe78bSCy Schubert jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 146*7f2fe78bSCy Schubert} 147*7f2fe78bSCy Schubert 148*7f2fe78bSCy Schubert/** 149*7f2fe78bSCy Schubert * Small JavaScript module for the documentation. 150*7f2fe78bSCy Schubert */ 151*7f2fe78bSCy Schubertvar Documentation = { 152*7f2fe78bSCy Schubert 153*7f2fe78bSCy Schubert init : function() { 154*7f2fe78bSCy Schubert this.fixFirefoxAnchorBug(); 155*7f2fe78bSCy Schubert this.highlightSearchWords(); 156*7f2fe78bSCy Schubert this.initIndexTable(); 157*7f2fe78bSCy Schubert if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { 158*7f2fe78bSCy Schubert this.initOnKeyListeners(); 159*7f2fe78bSCy Schubert } 160*7f2fe78bSCy Schubert }, 161*7f2fe78bSCy Schubert 162*7f2fe78bSCy Schubert /** 163*7f2fe78bSCy Schubert * i18n support 164*7f2fe78bSCy Schubert */ 165*7f2fe78bSCy Schubert TRANSLATIONS : {}, 166*7f2fe78bSCy Schubert PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 167*7f2fe78bSCy Schubert LOCALE : 'unknown', 168*7f2fe78bSCy Schubert 169*7f2fe78bSCy Schubert // gettext and ngettext don't access this so that the functions 170*7f2fe78bSCy Schubert // can safely bound to a different name (_ = Documentation.gettext) 171*7f2fe78bSCy Schubert gettext : function(string) { 172*7f2fe78bSCy Schubert var translated = Documentation.TRANSLATIONS[string]; 173*7f2fe78bSCy Schubert if (typeof translated === 'undefined') 174*7f2fe78bSCy Schubert return string; 175*7f2fe78bSCy Schubert return (typeof translated === 'string') ? translated : translated[0]; 176*7f2fe78bSCy Schubert }, 177*7f2fe78bSCy Schubert 178*7f2fe78bSCy Schubert ngettext : function(singular, plural, n) { 179*7f2fe78bSCy Schubert var translated = Documentation.TRANSLATIONS[singular]; 180*7f2fe78bSCy Schubert if (typeof translated === 'undefined') 181*7f2fe78bSCy Schubert return (n == 1) ? singular : plural; 182*7f2fe78bSCy Schubert return translated[Documentation.PLURALEXPR(n)]; 183*7f2fe78bSCy Schubert }, 184*7f2fe78bSCy Schubert 185*7f2fe78bSCy Schubert addTranslations : function(catalog) { 186*7f2fe78bSCy Schubert for (var key in catalog.messages) 187*7f2fe78bSCy Schubert this.TRANSLATIONS[key] = catalog.messages[key]; 188*7f2fe78bSCy Schubert this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 189*7f2fe78bSCy Schubert this.LOCALE = catalog.locale; 190*7f2fe78bSCy Schubert }, 191*7f2fe78bSCy Schubert 192*7f2fe78bSCy Schubert /** 193*7f2fe78bSCy Schubert * add context elements like header anchor links 194*7f2fe78bSCy Schubert */ 195*7f2fe78bSCy Schubert addContextElements : function() { 196*7f2fe78bSCy Schubert $('div[id] > :header:first').each(function() { 197*7f2fe78bSCy Schubert $('<a class="headerlink">\u00B6</a>'). 198*7f2fe78bSCy Schubert attr('href', '#' + this.id). 199*7f2fe78bSCy Schubert attr('title', _('Permalink to this headline')). 200*7f2fe78bSCy Schubert appendTo(this); 201*7f2fe78bSCy Schubert }); 202*7f2fe78bSCy Schubert $('dt[id]').each(function() { 203*7f2fe78bSCy Schubert $('<a class="headerlink">\u00B6</a>'). 204*7f2fe78bSCy Schubert attr('href', '#' + this.id). 205*7f2fe78bSCy Schubert attr('title', _('Permalink to this definition')). 206*7f2fe78bSCy Schubert appendTo(this); 207*7f2fe78bSCy Schubert }); 208*7f2fe78bSCy Schubert }, 209*7f2fe78bSCy Schubert 210*7f2fe78bSCy Schubert /** 211*7f2fe78bSCy Schubert * workaround a firefox stupidity 212*7f2fe78bSCy Schubert * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 213*7f2fe78bSCy Schubert */ 214*7f2fe78bSCy Schubert fixFirefoxAnchorBug : function() { 215*7f2fe78bSCy Schubert if (document.location.hash && $.browser.mozilla) 216*7f2fe78bSCy Schubert window.setTimeout(function() { 217*7f2fe78bSCy Schubert document.location.href += ''; 218*7f2fe78bSCy Schubert }, 10); 219*7f2fe78bSCy Schubert }, 220*7f2fe78bSCy Schubert 221*7f2fe78bSCy Schubert /** 222*7f2fe78bSCy Schubert * highlight the search words provided in the url in the text 223*7f2fe78bSCy Schubert */ 224*7f2fe78bSCy Schubert highlightSearchWords : function() { 225*7f2fe78bSCy Schubert var params = $.getQueryParameters(); 226*7f2fe78bSCy Schubert var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 227*7f2fe78bSCy Schubert if (terms.length) { 228*7f2fe78bSCy Schubert var body = $('div.body'); 229*7f2fe78bSCy Schubert if (!body.length) { 230*7f2fe78bSCy Schubert body = $('body'); 231*7f2fe78bSCy Schubert } 232*7f2fe78bSCy Schubert window.setTimeout(function() { 233*7f2fe78bSCy Schubert $.each(terms, function() { 234*7f2fe78bSCy Schubert body.highlightText(this.toLowerCase(), 'highlighted'); 235*7f2fe78bSCy Schubert }); 236*7f2fe78bSCy Schubert }, 10); 237*7f2fe78bSCy Schubert $('<p class="highlight-link"><a href="javascript:Documentation.' + 238*7f2fe78bSCy Schubert 'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>') 239*7f2fe78bSCy Schubert .appendTo($('#searchbox')); 240*7f2fe78bSCy Schubert } 241*7f2fe78bSCy Schubert }, 242*7f2fe78bSCy Schubert 243*7f2fe78bSCy Schubert /** 244*7f2fe78bSCy Schubert * init the domain index toggle buttons 245*7f2fe78bSCy Schubert */ 246*7f2fe78bSCy Schubert initIndexTable : function() { 247*7f2fe78bSCy Schubert var togglers = $('img.toggler').click(function() { 248*7f2fe78bSCy Schubert var src = $(this).attr('src'); 249*7f2fe78bSCy Schubert var idnum = $(this).attr('id').substr(7); 250*7f2fe78bSCy Schubert $('tr.cg-' + idnum).toggle(); 251*7f2fe78bSCy Schubert if (src.substr(-9) === 'minus.png') 252*7f2fe78bSCy Schubert $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 253*7f2fe78bSCy Schubert else 254*7f2fe78bSCy Schubert $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 255*7f2fe78bSCy Schubert }).css('display', ''); 256*7f2fe78bSCy Schubert if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 257*7f2fe78bSCy Schubert togglers.click(); 258*7f2fe78bSCy Schubert } 259*7f2fe78bSCy Schubert }, 260*7f2fe78bSCy Schubert 261*7f2fe78bSCy Schubert /** 262*7f2fe78bSCy Schubert * helper function to hide the search marks again 263*7f2fe78bSCy Schubert */ 264*7f2fe78bSCy Schubert hideSearchWords : function() { 265*7f2fe78bSCy Schubert $('#searchbox .highlight-link').fadeOut(300); 266*7f2fe78bSCy Schubert $('span.highlighted').removeClass('highlighted'); 267*7f2fe78bSCy Schubert }, 268*7f2fe78bSCy Schubert 269*7f2fe78bSCy Schubert /** 270*7f2fe78bSCy Schubert * make the url absolute 271*7f2fe78bSCy Schubert */ 272*7f2fe78bSCy Schubert makeURL : function(relativeURL) { 273*7f2fe78bSCy Schubert return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 274*7f2fe78bSCy Schubert }, 275*7f2fe78bSCy Schubert 276*7f2fe78bSCy Schubert /** 277*7f2fe78bSCy Schubert * get the current relative url 278*7f2fe78bSCy Schubert */ 279*7f2fe78bSCy Schubert getCurrentURL : function() { 280*7f2fe78bSCy Schubert var path = document.location.pathname; 281*7f2fe78bSCy Schubert var parts = path.split(/\//); 282*7f2fe78bSCy Schubert $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 283*7f2fe78bSCy Schubert if (this === '..') 284*7f2fe78bSCy Schubert parts.pop(); 285*7f2fe78bSCy Schubert }); 286*7f2fe78bSCy Schubert var url = parts.join('/'); 287*7f2fe78bSCy Schubert return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 288*7f2fe78bSCy Schubert }, 289*7f2fe78bSCy Schubert 290*7f2fe78bSCy Schubert initOnKeyListeners: function() { 291*7f2fe78bSCy Schubert $(document).keydown(function(event) { 292*7f2fe78bSCy Schubert var activeElementType = document.activeElement.tagName; 293*7f2fe78bSCy Schubert // don't navigate when in search box, textarea, dropdown or button 294*7f2fe78bSCy Schubert if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' 295*7f2fe78bSCy Schubert && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey 296*7f2fe78bSCy Schubert && !event.shiftKey) { 297*7f2fe78bSCy Schubert switch (event.keyCode) { 298*7f2fe78bSCy Schubert case 37: // left 299*7f2fe78bSCy Schubert var prevHref = $('link[rel="prev"]').prop('href'); 300*7f2fe78bSCy Schubert if (prevHref) { 301*7f2fe78bSCy Schubert window.location.href = prevHref; 302*7f2fe78bSCy Schubert return false; 303*7f2fe78bSCy Schubert } 304*7f2fe78bSCy Schubert break; 305*7f2fe78bSCy Schubert case 39: // right 306*7f2fe78bSCy Schubert var nextHref = $('link[rel="next"]').prop('href'); 307*7f2fe78bSCy Schubert if (nextHref) { 308*7f2fe78bSCy Schubert window.location.href = nextHref; 309*7f2fe78bSCy Schubert return false; 310*7f2fe78bSCy Schubert } 311*7f2fe78bSCy Schubert break; 312*7f2fe78bSCy Schubert } 313*7f2fe78bSCy Schubert } 314*7f2fe78bSCy Schubert }); 315*7f2fe78bSCy Schubert } 316*7f2fe78bSCy Schubert}; 317*7f2fe78bSCy Schubert 318*7f2fe78bSCy Schubert// quick alias for translations 319*7f2fe78bSCy Schubert_ = Documentation.gettext; 320*7f2fe78bSCy Schubert 321*7f2fe78bSCy Schubert$(document).ready(function() { 322*7f2fe78bSCy Schubert Documentation.init(); 323*7f2fe78bSCy Schubert}); 324