1 /// XXX: make it cross browser 2 3 /** 4 * make the code below compatible with browsers without 5 * an installed firebug like debugger 6 */ 7 if (!window.console || !console.firebug) { 8 var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", 9 "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; 10 window.console = {}; 11 for (var i = 0; i < names.length; ++i) 12 window.console[names[i]] = function() {} 13 } 14 15 /** 16 * small helper function to urldecode strings 17 */ 18 jQuery.urldecode = function(x) { 19 return decodeURIComponent(x).replace(/\+/g, ' '); 20 } 21 22 /** 23 * small helper function to urlencode strings 24 */ 25 jQuery.urlencode = encodeURIComponent; 26 27 /** 28 * This function returns the parsed url parameters of the 29 * current request. Multiple values per key are supported, 30 * it will always return arrays of strings for the value parts. 31 */ 32 jQuery.getQueryParameters = function(s) { 33 if (typeof s == 'undefined') 34 s = document.location.search; 35 var parts = s.substr(s.indexOf('?') + 1).split('&'); 36 var result = {}; 37 for (var i = 0; i < parts.length; i++) { 38 var tmp = parts[i].split('=', 2); 39 var key = jQuery.urldecode(tmp[0]); 40 var value = jQuery.urldecode(tmp[1]); 41 if (key in result) 42 result[key].push(value); 43 else 44 result[key] = [value]; 45 } 46 return result; 47 } 48 49 /** 50 * small function to check if an array contains 51 * a given item. 52 */ 53 jQuery.contains = function(arr, item) { 54 for (var i = 0; i < arr.length; i++) { 55 if (arr[i] == item) 56 return true; 57 } 58 return false; 59 } 60 61 /** 62 * highlight a given string on a jquery object by wrapping it in 63 * span elements with the given class name. 64 */ 65 jQuery.fn.highlightText = function(text, className) { 66 function highlight(node) { 67 if (node.nodeType == 3) { 68 var val = node.nodeValue; 69 var pos = val.toLowerCase().indexOf(text); 70 if (pos >= 0 && !jQuery.className.has(node.parentNode, className)) { 71 var span = document.createElement("span"); 72 span.className = className; 73 span.appendChild(document.createTextNode(val.substr(pos, text.length))); 74 node.parentNode.insertBefore(span, node.parentNode.insertBefore( 75 document.createTextNode(val.substr(pos + text.length)), 76 node.nextSibling)); 77 node.nodeValue = val.substr(0, pos); 78 } 79 } 80 else if (!jQuery(node).is("button, select, textarea")) { 81 jQuery.each(node.childNodes, function() { 82 highlight(this) 83 }); 84 } 85 } 86 return this.each(function() { 87 highlight(this); 88 }); 89 } 90 91 /** 92 * Small JavaScript module for the documentation. 93 */ 94 var Documentation = { 95 96 init : function() { 97 this.fixFirefoxAnchorBug(); 98 this.highlightSearchWords(); 99 this.initModIndex(); 100 }, 101 102 /** 103 * i18n support 104 */ 105 TRANSLATIONS : {}, 106 PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, 107 LOCALE : 'unknown', 108 109 // gettext and ngettext don't access this so that the functions 110 // can savely bound to a different name (_ = Documentation.gettext) 111 gettext : function(string) { 112 var translated = Documentation.TRANSLATIONS[string]; 113 if (typeof translated == 'undefined') 114 return string; 115 return (typeof translated == 'string') ? translated : translated[0]; 116 }, 117 118 ngettext : function(singular, plural, n) { 119 var translated = Documentation.TRANSLATIONS[singular]; 120 if (typeof translated == 'undefined') 121 return (n == 1) ? singular : plural; 122 return translated[Documentation.PLURALEXPR(n)]; 123 }, 124 125 addTranslations : function(catalog) { 126 for (var key in catalog.messages) 127 this.TRANSLATIONS[key] = catalog.messages[key]; 128 this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 129 this.LOCALE = catalog.locale; 130 }, 131 132 /** 133 * add context elements like header anchor links 134 */ 135 addContextElements : function() { 136 $('div[id] > :header:first').each(function() { 137 $('<a class="headerlink">\u00B6</a>'). 138 attr('href', '#' + this.id). 139 attr('title', _('Permalink to this headline')). 140 appendTo(this); 141 }); 142 $('dt[id]').each(function() { 143 $('<a class="headerlink">\u00B6</a>'). 144 attr('href', '#' + this.id). 145 attr('title', _('Permalink to this definition')). 146 appendTo(this); 147 }); 148 }, 149 150 /** 151 * workaround a firefox stupidity 152 */ 153 fixFirefoxAnchorBug : function() { 154 if (document.location.hash && $.browser.mozilla) 155 window.setTimeout(function() { 156 document.location.href += ''; 157 }, 10); 158 }, 159 160 /** 161 * highlight the search words provided in the url in the text 162 */ 163 highlightSearchWords : function() { 164 var params = $.getQueryParameters(); 165 var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 166 if (terms.length) { 167 var body = $('div.body'); 168 window.setTimeout(function() { 169 $.each(terms, function() { 170 body.highlightText(this.toLowerCase(), 'highlight'); 171 }); 172 }, 10); 173 $('<li class="highlight-link"><a href="javascript:Documentation.' + 174 'hideSearchWords()">' + _('Hide Search Matches') + '</a></li>') 175 .appendTo($('.sidebar .this-page-menu')); 176 } 177 }, 178 179 /** 180 * init the modindex toggle buttons 181 */ 182 initModIndex : function() { 183 var togglers = $('img.toggler').click(function() { 184 var src = $(this).attr('src'); 185 var idnum = $(this).attr('id').substr(7); 186 console.log($('tr.cg-' + idnum).toggle()); 187 if (src.substr(-9) == 'minus.png') 188 $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 189 else 190 $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 191 }).css('display', ''); 192 if (DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX) { 193 togglers.click(); 194 } 195 }, 196 197 /** 198 * helper function to hide the search marks again 199 */ 200 hideSearchWords : function() { 201 $('.sidebar .this-page-menu li.highlight-link').fadeOut(300); 202 $('span.highlight').removeClass('highlight'); 203 }, 204 205 /** 206 * make the url absolute 207 */ 208 makeURL : function(relativeURL) { 209 return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 210 }, 211 212 /** 213 * get the current relative url 214 */ 215 getCurrentURL : function() { 216 var path = document.location.pathname; 217 var parts = path.split(/\//); 218 $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 219 if (this == '..') 220 parts.pop(); 221 }); 222 var url = parts.join('/'); 223 return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 224 } 225 }; 226 227 // quick alias for translations 228 _ = Documentation.gettext; 229 230 $(document).ready(function() { 231 Documentation.init(); 232 }); 233