xref: /template/ad-hominem/script.js (revision 17f7220325cfa63d632f384c220c58290644dfbf)
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.cookie_banner.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.getElementsByTagName("main")[0];
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		/* list of 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_ah' 	: {
84				url:'https://ad.hominem.info/de/lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview',
85				type:'ahtpl',
86				base:'https://ad.hominem.info/de/'
87			},
88			'iw_ahen' 	: {
89				url:'https://ad.hominem.info/en/lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview',
90				type:'ahtpl',
91				base:'https://ad.hominem.info/en/'
92			},
93			'iw_dfo' 	: {
94				url:'https://denkfehler.online/lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview',
95				type:'ahtpl',
96				base:'https://denkfehler.online/'
97			}
98		},
99
100		/* callback for the onhover event of links: */
101		_linkHoverCallback: function() {
102
103			var a = jQuery(this);
104			var hi = jQuery.data(this, 'has-info');
105			var href = jQuery(this).attr('href');
106			var wid = null;
107			var url = null;
108			var type = '';
109
110			/* only if the info hasn't been set yet: */
111			if (hi == undefined || hi == '') {
112
113				// remember that we are now working on the link:
114				jQuery.data(this, 'has-info', '0');
115
116				// find the URL to query:
117				for (var cls in $p.linkinfo._restURLs) {
118					if (a.hasClass(cls)) {
119						url = $p.linkinfo._restURLs[cls].url;
120						type = $p.linkinfo._restURLs[cls].type;
121						break;
122					}
123				};
124
125				/* get the ID to request: */
126				switch(type) {
127
128					case 'internal': // internal links
129						url = url.replace('%basedir%', (typeof BASEDIR!=='undefined'?BASEDIR:'/'));
130						wid = jQuery(this).data('wiki-id');
131						break;
132					case 'wikimedia': // wikipedia sites
133						wid = href.substring(href.lastIndexOf('/')+1);
134						break;
135					case 'ahtpl': // Other sites with this template
136						wid = href.substring($p.linkinfo._restURLs[cls].base.length).replaceAll('/', ':');
137						break;
138					default: // unknown -> skip
139						return;
140				}
141
142				// URL found?
143				if (url !== null) {
144
145					/* load the page info */
146					jQuery.ajax({
147						url:		url.replace('%id%', encodeURIComponent(wid)),
148						context:	a,
149						dataType:	'json',
150						crossDomain: true,
151						error:		function(xhr, msg, e) {
152										console.error(msg);
153									},
154						success:	function(data, msg, xhr) {
155										// build the new title for the element:
156										jQuery(this).attr('title', data.title + "\n" + data.extract);
157										jQuery.data(this, 'has-info', '1')
158									},
159						complete:	function() {
160										if (jQuery.data(this, 'has-info') == '0') {
161											jQuery.removeData(this, 'has-info');
162										}
163									}
164					});
165				}
166			}
167		}
168	},
169
170	/* anything related to the search */
171	search: {
172
173		/* initializer */
174		init: function() {
175			$p.search.gui.init();
176		},
177
178		/* the search gui */
179		gui: {
180
181			_container: null,
182			_elements: { field: null, clear: null, search: null },
183
184			/* init the gui */
185			init: function() {
186
187				try {
188
189					/* find all the search elements: */
190					var form = document.getElementById('dw__search');
191
192
193					var div = form.getElementsByClassName('search-field')[0];
194					$p.search.gui._container = div;
195
196					var field = div.getElementsByTagName('input')[0];
197					$p.search.gui._elements.field = field;
198					field.addEventListener('focus', $p.search.gui.__elementFocus);
199					field.addEventListener('blur', $p.search.gui.__elementBlur);
200
201					var buttons = div.getElementsByTagName('button');
202					Array.prototype.forEach.call(buttons, function(b) {
203						var type = b.getAttribute('type');
204						if (type == 'reset') {
205							$p.search.gui._elements.clear = b;
206						} else if (type == 'submit') {
207							$p.search.gui._elements.search = b;
208						}
209						b.addEventListener('focus', $p.search.gui.__elementFocus);
210						b.addEventListener('blur', $p.search.gui.__elementBlur);
211					});
212
213				} catch (e) {
214					console.warn("Can’t initialize search form.");
215					console.error(e);
216				}
217			},
218
219			/* call back for fields */
220			__elementFocus: function() {
221				$p.search.gui._container.classList.add("focus");
222			},
223			__elementBlur: function() {
224				$p.search.gui._container.classList.remove("focus");
225
226			}
227		}
228	},
229
230	/* expaning sections, for menus, etc. */
231	togglers: {
232
233		/* initialize togglers */
234		init:	function() {
235
236			const togglers = document.getElementsByClassName("toggle");
237
238			Array.prototype.forEach.call(togglers, function(t) {
239
240				/* add default state  */
241				if (!(t.classList.contains('show') || (t.classList.contains('hide')))) {
242					t.classList.add('auto');
243				}
244
245				/* add a callback to the toggler buttons */
246				var btn = t.getElementsByClassName('tg_button');
247				Array.prototype.forEach.call(btn, function(b) {
248					b.addEventListener('click', $p.togglers._buttonCallback);
249					b.classList.add('active');
250				});
251
252			});
253		},
254
255		/* callback for the toggler button click */
256		_buttonCallback: function() {
257
258			var t = this.parentNode;
259
260			/* current state of the toggler: */
261			var state = 'auto';
262			if (t.classList.contains('show')) state = 'show';
263			if (t.classList.contains('hide')) state = 'hide';
264			if (t.classList.contains('alt')) state = 'alt';
265
266			/* set new state: */
267			var newState = 'alt';
268			if (state == 'show') { newState = 'hide' }
269			else if (state == 'hide') { newState = 'show' }
270			else if (state == 'alt') { newState = 'auto' }
271
272			t.classList.remove(state);
273			t.classList.add(newState);
274
275		}
276	},
277
278	/* Cookies info banner */
279	cookie_banner: {
280
281		/* initialize Cookies info banner */
282		init: function() {
283
284			// find the cookiebanner button:
285			var btn = jQuery('#cookiebanner button');
286
287			if (btn.length >= 1) { // if found only
288
289				// assign callback:
290				jQuery(btn).click($p.cookie_banner._buttonCallback);
291
292				// set focus:
293				jQuery(btn).first().focus();
294			}
295		},
296
297		/* callback for the "OK" button */
298		_buttonCallback: function() {
299
300			const date = new Date();
301			date.setFullYear(date.getFullYear() + 1);
302
303			var path = ( typeof BASEDIR !== 'undefined' ? BASEDIR : '/');
304
305			document.cookie = 'cookielaw=1; path=' + path + '; expires=' + date.toUTCString() + '; SameSite=Lax';
306			jQuery('#cookiebanner').remove();
307		}
308	}
309};
310
311/* load the script when the DOM is ready */
312
313window.addEventListener("DOMContentLoaded", $p.init);
314