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.linkinfo.init(); 15 $p.search.init(); 16 $p.togglers.init(); 17 18 }, 19 20 /* link information */ 21 linkinfo: { 22 init: function() { 23 24 /* find all links in the main section */ 25 var main = document.getElementsByTagName("main")[0]; 26 var al = main.getElementsByTagName("a"); 27 Array.prototype.forEach.call(al, function (a) { 28 29 Object.entries($p.linkinfo._restURLs).forEach((c) => { 30 var cls = c[0]; 31 if (a.classList.contains(cls)) { 32 a.addEventListener('mouseover', $p.linkinfo._linkHoverCallback); 33 } 34 }); 35 }); 36 }, 37 38 /* list of REST API URLs for different sites. */ 39 /* variables are enclosed in %, allowed vars are: */ 40 /* - basedir = this site's basedir (e.g. "/"), */ 41 /* - id = the data id of the link (internal only) */ 42 /* - ln = the link name (e.g. for Wikipedia links) */ 43 _restURLs : { 44 'wikilink1' : '%basedir%lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview', 45 'iw_wp' : 'https://en.wikipedia.org/api/rest_v1/page/summary/%ln%', 46 'iw_wpfr' : 'https://fr.wikipedia.org/api/rest_v1/page/summary/%ln%', 47 'iw_wpde' : 'https://de.wikipedia.org/api/rest_v1/page/summary/%ln%', 48 'iw_wpes' : 'https://es.wikipedia.org/api/rest_v1/page/summary/%ln%', 49 'iw_wppl' : 'https://pl.wikipedia.org/api/rest_v1/page/summary/%ln%', 50 'iw_wpja' : 'https://it.wikipedia.org/api/rest_v1/page/summary/%ln%', 51 'iw_wpru' : 'https://ru.wikipedia.org/api/rest_v1/page/summary/%ln%', 52 'iw_meta' : 'https://meta.wikipedia.org/api/rest_v1/page/summary/%ln%' 53 }, 54 55 /* callback for the onhover event of links: */ 56 _linkHoverCallback: function() { 57 58 /* TODO: remove jQuery dependency! */ 59 60 var a = jQuery(this); 61 var hi = jQuery.data(this, 'has-info'); 62 var url = null; 63 64 /* only if the info hasn't been set yet: */ 65 if (hi == undefined || hi == '') { 66 67 // remember that we are now working on it: 68 jQuery.data(this, 'has-info', '0'); 69 70 for (var cls in $p.linkinfo._restURLs) { 71 if (a.hasClass(cls)) { 72 url = $p.linkinfo._restURLs[cls]; 73 break; 74 } 75 }; 76 77 if (url !== null) { 78 79 /* modify the URLs: */ 80 var href = jQuery(this).attr('href'); 81 82 var rp = { 83 'basedir': BASEDIR, 84 'id': jQuery(this).data('wiki-id'), 85 'ln': href.substring(href.lastIndexOf('/')+1) 86 }; 87 88 for (var p in rp) { 89 url = url.replace('%'+p+'%', rp[p]); 90 } 91 92 /* load the page info */ 93 jQuery.ajax({ 94 url: url, 95 context: a, 96 dataType: 'json', 97 error: function(xhr, msg, e) { 98 console.error(msg); 99 }, 100 success: function(data, msg, xhr) { 101 // build the new title for the element: 102 jQuery(this).attr('title', data.title + "\n" + data.extract); 103 jQuery.data(this, 'has-info', '1') 104 }, 105 complete: function() { 106 if (jQuery.data(this, 'has-info') == '0') { 107 jQuery.removeData(this, 'has-info'); 108 } 109 } 110 }); 111 } 112 } 113 } 114 }, 115 116 /* anything related to the search */ 117 search: { 118 119 /* initializer */ 120 init: function() { 121 $p.search.gui.init(); 122 }, 123 124 /* the search gui */ 125 gui: { 126 127 _container: null, 128 _elements: { field: null, clear: null, search: null }, 129 130 /* init the gui */ 131 init: function() { 132 133 /* find all the search elements: */ 134 var form = document.getElementById('dw__search'); 135 136 var div = form.getElementsByClassName('search-field')[0]; 137 $p.search.gui._container = div; 138 139 var field = div.getElementsByTagName('input')[0]; 140 $p.search.gui._elements.field = field; 141 field.addEventListener('focus', $p.search.gui.__elementFocus); 142 field.addEventListener('blur', $p.search.gui.__elementBlur); 143 144 var buttons = div.getElementsByTagName('button'); 145 Array.prototype.forEach.call(buttons, function(b) { 146 var type = b.getAttribute('type'); 147 if (type == 'reset') { 148 $p.search.gui._elements.clear = b; 149 } else if (type == 'submit') { 150 $p.search.gui._elements.search = b; 151 } 152 b.addEventListener('focus', $p.search.gui.__elementFocus); 153 b.addEventListener('blur', $p.search.gui.__elementBlur); 154 }); 155 156 }, 157 158 /* call back for fields */ 159 __elementFocus: function() { 160 $p.search.gui._container.classList.add("focus"); 161 }, 162 __elementBlur: function() { 163 $p.search.gui._container.classList.remove("focus"); 164 165 } 166 } 167 }, 168 169 /* expaning sections, for menus, etc. */ 170 togglers: { 171 172 /* initialize togglers */ 173 init: function() { 174 175 const togglers = document.getElementsByClassName("toggle"); 176 177 Array.prototype.forEach.call(togglers, function(t) { 178 179 /* add default state */ 180 if (!(t.classList.contains('show') || (t.classList.contains('hide')))) { 181 t.classList.add('auto'); 182 } 183 184 /* add a callback to the toggler buttons */ 185 var btn = t.getElementsByClassName('tg_button'); 186 Array.prototype.forEach.call(btn, function(b) { 187 b.addEventListener('click', $p.togglers._buttonCallback); 188 b.classList.add('active'); 189 }); 190 191 }); 192 }, 193 194 /* callback for the toggler button click */ 195 _buttonCallback: function() { 196 197 var t = this.parentNode; 198 199 /* current state of the toggler: */ 200 var state = 'auto'; 201 if (t.classList.contains('show')) state = 'show'; 202 if (t.classList.contains('hide')) state = 'hide'; 203 if (t.classList.contains('alt')) state = 'alt'; 204 205 /* set new state: */ 206 var newState = 'alt'; 207 if (state == 'show') { newState = 'hide' } 208 else if (state == 'hide') { newState = 'show' } 209 else if (state == 'alt') { newState = 'auto' } 210 211 t.classList.remove(state); 212 t.classList.add(newState); 213 214 } 215 } 216}; 217 218/* load the script when the DOM is ready */ 219 220window.addEventListener("DOMContentLoaded", $p.init); 221