1/** 2 * Page scripts for Ad Hominem Info Template 3 * 4 * @author Sascha Leib <sascha@leib.be> 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 */ 7 8/* everything is contained in the $p namespace: */ 9$p = { 10 11 /* called to initialize the entire script */ 12 init: function() { 13 14 $p.cookie_banner.init(); 15 $p.linkinfo.init(); 16 $p.search.init(); 17 $p.togglers.init(); 18 19 }, 20 21 /* link information */ 22 linkinfo: { 23 init: function() { 24 25 /* find all links in the main section */ 26 var main = document.getElementById("main-layout"); 27 var al = main.getElementsByTagName("a"); 28 Array.prototype.forEach.call(al, function (a) { 29 30 Object.entries($p.linkinfo._restURLs).forEach((c) => { 31 var cls = c[0]; 32 if (a.classList.contains(cls)) { 33 a.addEventListener('mouseover', $p.linkinfo._linkHoverCallback); 34 } 35 }); 36 }); 37 }, 38 39 /* pre-defined REST API URLs for different sites. */ 40 /* variables are enclosed in %, allowed vars are: */ 41 /* - basedir = this site's basedir (e.g. "/"), */ 42 /* - id = the data id of the link (internal only) */ 43 /* - ln = the link name (e.g. for Wikipedia links) */ 44 /* types can be 'internal', 'wikimedia', or 'ahtpl' */ 45 /* for other sites using this template. */ 46 _restURLs : { 47 'wikilink1' : { 48 url: '%basedir%lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview', 49 type:'internal' 50 }, 51 'iw_wp' : { 52 url:'https://en.wikipedia.org/api/rest_v1/page/summary/%id%', 53 type:'wikimedia' 54 }, 55 'iw_wpfr' : { 56 url:'https://fr.wikipedia.org/api/rest_v1/page/summary/%id%', 57 type:'wikimedia' 58 }, 59 'iw_wpde' : { 60 url:'https://de.wikipedia.org/api/rest_v1/page/summary/%id%', 61 type:'wikimedia' 62 }, 63 'iw_wpes' : { 64 url:'https://es.wikipedia.org/api/rest_v1/page/summary/%id%', 65 type:'wikimedia' 66 }, 67 'iw_wppl' : { 68 url:'https://pl.wikipedia.org/api/rest_v1/page/summary/%id%', 69 type:'wikimedia' 70 }, 71 'iw_wpja' : { 72 url:'https://it.wikipedia.org/api/rest_v1/page/summary/%id%', 73 type:'wikimedia' 74 }, 75 'iw_wpru' : { 76 url:'https://ru.wikipedia.org/api/rest_v1/page/summary/%id%', 77 type:'wikimedia' 78 }, 79 'iw_meta' : { 80 url:'https://meta.wikipedia.org/api/rest_v1/page/summary/%id%', 81 type:'wikimedia' 82 }, 83 'iw_fo' : { 84 url:'https://fallacies.online/wiki/lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview', 85 base:'https://fallacies.online/wiki/', 86 type:'ahtpl' 87 }, 88 'iw_dfo' : { 89 url:'https://denkfehler.online/wiki/lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview', 90 base:'https://denkfehler.online/wiki/', 91 type:'ahtpl' 92 } 93 }, 94 /* note: this covers the internal links and the most common 95 wikipedia lang versions. If you know about any other 96 relevant sites to be added here, let the author of this 97 template know (ad@hominem.info) */ 98 99 /* TODO: mechanism to dynamically add sites by site admin */ 100 101 /* callback for the onhover event of links: */ 102 _linkHoverCallback: function() { 103 104 var a = jQuery(this); 105 var hi = jQuery.data(this, 'has-info'); 106 var href = jQuery(this).attr('href'); 107 var wid = null; 108 var url = null; 109 var type = ''; 110 111 /* only if the info hasn't been set yet: */ 112 if (hi == undefined || hi == '') { 113 114 // remember that we are now working on the link: 115 jQuery.data(this, 'has-info', '0'); 116 117 // find the URL to query: 118 try { 119 for (var cls in $p.linkinfo._restURLs) { 120 if (a.hasClass(cls)) { 121 url = $p.linkinfo._restURLs[cls].url; 122 type = $p.linkinfo._restURLs[cls].type; 123 break; 124 } 125 }; 126 } catch (e) {} 127 128 /* get the ID to request: */ 129 switch(type) { 130 131 case 'internal': // internal links 132 url = url.replace('%basedir%', (typeof BASEDIR!=='undefined'?BASEDIR:'/')); 133 wid = jQuery(this).data('wiki-id'); 134 break; 135 case 'wikimedia': // wikipedia sites 136 wid = href.substring(href.lastIndexOf('/')+1); 137 break; 138 case 'ahtpl': // Other sites with this template 139 wid = href.substring($p.linkinfo._restURLs[cls].base.length).replaceAll('/', ':'); 140 break; 141 default: // unknown -> skip 142 return; 143 } 144 145 // URL & ID found? 146 if (url !== null && typeof wid !== 'undefined') { 147 148 /* load the page info */ 149 jQuery.ajax({ 150 url: url.replace('%id%', encodeURIComponent(wid)), 151 context: a, 152 dataType: 'json', 153 crossDomain: true, 154 error: function(xhr, msg, e) { 155 console.error(msg); 156 }, 157 success: function(data, msg, xhr) { 158 // build the new title for the element: 159 if (typeof data.title !== 'undefined') { 160 jQuery(this).attr('title', data.title + "\n" + data.extract); 161 jQuery.data(this, 'has-info', '1'); 162 } 163 }, 164 complete: function() { 165 if (jQuery.data(this, 'has-info') == '0') { 166 jQuery.removeData(this, 'has-info'); 167 } 168 } 169 }); 170 } 171 } 172 } 173 }, 174 175 /* anything related to the search */ 176 search: { 177 178 /* initializer */ 179 init: function() { 180 $p.search.gui.init(); 181 }, 182 183 /* the search gui */ 184 gui: { 185 186 _container: null, 187 _elements: { field: null, clear: null, search: null }, 188 189 /* init the gui */ 190 init: function() { 191 192 try { 193 194 /* find all the search elements: */ 195 var form = document.getElementById('dw__search'); 196 197 var div = form.getElementsByClassName('search-field')[0]; 198 $p.search.gui._container = div; 199 200 var field = div.getElementsByTagName('input')[0]; 201 $p.search.gui._elements.field = field; 202 field.addEventListener('focus', $p.search.gui.__elementFocus); 203 field.addEventListener('blur', $p.search.gui.__elementBlur); 204 205 var buttons = div.getElementsByTagName('button'); 206 Array.prototype.forEach.call(buttons, function(b) { 207 var type = b.getAttribute('type'); 208 if (type == 'reset') { 209 $p.search.gui._elements.clear = b; 210 } else if (type == 'submit') { 211 $p.search.gui._elements.search = b; 212 } 213 b.addEventListener('focus', $p.search.gui.__elementFocus); 214 b.addEventListener('blur', $p.search.gui.__elementBlur); 215 }); 216 217 } catch (e) { 218 console.warn("Can’t initialize search form."); 219 console.error(e); 220 } 221 }, 222 223 /* call back for fields */ 224 __elementFocus: function() { 225 $p.search.gui._container.classList.add("focus"); 226 }, 227 __elementBlur: function() { 228 $p.search.gui._container.classList.remove("focus"); 229 230 } 231 } 232 }, 233 234 /* expaning sections, for menus, etc. */ 235 togglers: { 236 237 /* initialize togglers */ 238 init: function() { 239 240 const togglers = document.getElementsByClassName("toggle"); 241 242 Array.prototype.forEach.call(togglers, function(t) { 243 244 /* add default state */ 245 if (!(t.classList.contains('show') || (t.classList.contains('hide')))) { 246 t.classList.add('auto'); 247 } 248 249 /* add a callback to the toggler buttons */ 250 var btn = t.getElementsByClassName('tg_button'); 251 Array.prototype.forEach.call(btn, function(b) { 252 b.addEventListener('click', $p.togglers._buttonCallback); 253 b.classList.add('active'); 254 }); 255 256 }); 257 }, 258 259 /* callback for the toggler button click */ 260 _buttonCallback: function() { 261 262 var t = this.parentNode; 263 264 /* current state of the toggler: */ 265 var state = 'auto'; 266 if (t.classList.contains('show')) state = 'show'; 267 if (t.classList.contains('hide')) state = 'hide'; 268 if (t.classList.contains('alt')) state = 'alt'; 269 270 /* set new state: */ 271 var newState = 'alt'; 272 if (state == 'show') { newState = 'hide' } 273 else if (state == 'hide') { newState = 'show' } 274 else if (state == 'alt') { newState = 'auto' } 275 276 t.classList.remove(state); 277 t.classList.add(newState); 278 279 } 280 }, 281 282 /* Cookies info banner */ 283 cookie_banner: { 284 285 /* initialize Cookies info banner */ 286 init: function() { 287 288 // find the cookiebanner elements: 289 var btn = jQuery('#cookiebanner button'); 290 291 var cookie = jQuery.cookie('cookielaw'); 292 293 if ( (cookie !== '1') && (btn.length >= 1) ) { // if found only 294 295 // assign callback: 296 jQuery(btn).click($p.cookie_banner._buttonCallback); 297 298 // show the banner 299 jQuery('#cookiebanner').show(); 300 301 // set focus: 302 jQuery(btn).first().focus(); 303 } 304 }, 305 306 /* callback for the "OK" button */ 307 _buttonCallback: function() { 308 309 const date = new Date(); 310 date.setFullYear(date.getFullYear() + 1); 311 312 var path = ( typeof BASEDIR !== 'undefined' ? BASEDIR : '/'); 313 314 document.cookie = 'cookielaw=1; path=' + path + '; expires=' + date.toUTCString() + '; SameSite=Lax'; 315 jQuery('#cookiebanner').remove(); 316 } 317 } 318}; 319 320/* load the script when the DOM is ready */ 321 322window.addEventListener("DOMContentLoaded", $p.init); 323