xref: /template/ad-hominem/script.js (revision 77c863f350a560c134ebf531c15422e9351919d7)
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		_restURLs : {
45				'wikilink1'	: '%basedir%lib/tpl/ad-hominem/rest/pageinfo.php?id=%id%&v=preview',
46				'iw_wp'		: 'https://en.wikipedia.org/api/rest_v1/page/summary/%ln%',
47				'iw_wpfr' 	: 'https://fr.wikipedia.org/api/rest_v1/page/summary/%ln%',
48				'iw_wpde' 	: 'https://de.wikipedia.org/api/rest_v1/page/summary/%ln%',
49				'iw_wpes' 	: 'https://es.wikipedia.org/api/rest_v1/page/summary/%ln%',
50				'iw_wppl' 	: 'https://pl.wikipedia.org/api/rest_v1/page/summary/%ln%',
51				'iw_wpja' 	: 'https://it.wikipedia.org/api/rest_v1/page/summary/%ln%',
52				'iw_wpru' 	: 'https://ru.wikipedia.org/api/rest_v1/page/summary/%ln%',
53				'iw_meta' 	: 'https://meta.wikipedia.org/api/rest_v1/page/summary/%ln%'
54		},
55
56		/* callback for the onhover event of links: */
57		_linkHoverCallback: function() {
58
59			/* TODO: remove jQuery dependency! */
60
61			var a = jQuery(this);
62			var hi = jQuery.data(this, 'has-info');
63			var wid = jQuery(this).data('wiki-id');
64			var url = null;
65
66			/* only if the info hasn't been set yet: */
67			if ((hi == undefined || hi == '') && wid !== undefined) {
68
69				// remember that we are now working on it:
70				jQuery.data(this, 'has-info', '0');
71
72				for (var cls in $p.linkinfo._restURLs) {
73					if (a.hasClass(cls)) {
74						url = $p.linkinfo._restURLs[cls];
75						break;
76					}
77				};
78
79				if (url !== null) {
80
81					/* modify the URLs: */
82					var href = jQuery(this).attr('href');
83
84					var rp = {
85						'basedir': BASEDIR,
86						'id': wid,
87						'ln': href.substring(href.lastIndexOf('/')+1)
88					};
89
90					for (var p in rp) {
91						url = url.replace('%'+p+'%', rp[p]);
92					}
93
94					/* load the page info */
95					jQuery.ajax({
96						url:		url,
97						context:	a,
98						dataType:	'json',
99						error:		function(xhr, msg, e) {
100										console.error(msg);
101									},
102						success:	function(data, msg, xhr) {
103										// build the new title for the element:
104										jQuery(this).attr('title', data.title + "\n" + data.extract);
105										jQuery.data(this, 'has-info', '1')
106									},
107						complete:	function() {
108										if (jQuery.data(this, 'has-info') == '0') {
109											jQuery.removeData(this, 'has-info');
110										}
111									}
112					});
113				}
114			}
115		}
116	},
117
118	/* anything related to the search */
119	search: {
120
121		/* initializer */
122		init: function() {
123			$p.search.gui.init();
124		},
125
126		/* the search gui */
127		gui: {
128
129			_container: null,
130			_elements: { field: null, clear: null, search: null },
131
132			/* init the gui */
133			init: function() {
134
135				try {
136
137					/* find all the search elements: */
138					var form = document.getElementById('dw__search');
139
140
141					var div = form.getElementsByClassName('search-field')[0];
142					$p.search.gui._container = div;
143
144					var field = div.getElementsByTagName('input')[0];
145					$p.search.gui._elements.field = field;
146					field.addEventListener('focus', $p.search.gui.__elementFocus);
147					field.addEventListener('blur', $p.search.gui.__elementBlur);
148
149					var buttons = div.getElementsByTagName('button');
150					Array.prototype.forEach.call(buttons, function(b) {
151						var type = b.getAttribute('type');
152						if (type == 'reset') {
153							$p.search.gui._elements.clear = b;
154						} else if (type == 'submit') {
155							$p.search.gui._elements.search = b;
156						}
157						b.addEventListener('focus', $p.search.gui.__elementFocus);
158						b.addEventListener('blur', $p.search.gui.__elementBlur);
159					});
160
161				} catch (e) {
162					console.warn("Can’t initialize search form.");
163					console.error(e);
164				}
165			},
166
167			/* call back for fields */
168			__elementFocus: function() {
169				$p.search.gui._container.classList.add("focus");
170			},
171			__elementBlur: function() {
172				$p.search.gui._container.classList.remove("focus");
173
174			}
175		}
176	},
177
178	/* expaning sections, for menus, etc. */
179	togglers: {
180
181		/* initialize togglers */
182		init:	function() {
183
184			const togglers = document.getElementsByClassName("toggle");
185
186			Array.prototype.forEach.call(togglers, function(t) {
187
188				/* add default state  */
189				if (!(t.classList.contains('show') || (t.classList.contains('hide')))) {
190					t.classList.add('auto');
191				}
192
193				/* add a callback to the toggler buttons */
194				var btn = t.getElementsByClassName('tg_button');
195				Array.prototype.forEach.call(btn, function(b) {
196					b.addEventListener('click', $p.togglers._buttonCallback);
197					b.classList.add('active');
198				});
199
200			});
201		},
202
203		/* callback for the toggler button click */
204		_buttonCallback: function() {
205
206			var t = this.parentNode;
207
208			/* current state of the toggler: */
209			var state = 'auto';
210			if (t.classList.contains('show')) state = 'show';
211			if (t.classList.contains('hide')) state = 'hide';
212			if (t.classList.contains('alt')) state = 'alt';
213
214			/* set new state: */
215			var newState = 'alt';
216			if (state == 'show') { newState = 'hide' }
217			else if (state == 'hide') { newState = 'show' }
218			else if (state == 'alt') { newState = 'auto' }
219
220			t.classList.remove(state);
221			t.classList.add(newState);
222
223		}
224	},
225
226	/* Cookies info banner */
227	cookie_banner: {
228
229		/* initialize Cookies info banner */
230		init: function() {
231
232			// find the cookiebanner button:
233			var btn = jQuery('#cookiebanner button');
234
235			if (btn.length >= 1) { // if found only
236
237				// assign callback:
238				jQuery(btn).click($p.cookie_banner._buttonCallback);
239
240				// set focus:
241				jQuery(btn).first().focus();
242			}
243		},
244
245		/* callback for the "OK" button */
246		_buttonCallback: function() {
247
248			const date = new Date();
249			date.setFullYear(date.getFullYear() + 1);
250			document.cookie = 'cookielaw=1; path=' + BASEDIR + '; expires=' + date.toUTCString() + '; SameSite=Lax';
251			jQuery('#cookiebanner').remove();
252		}
253	}
254};
255
256/* load the script when the DOM is ready */
257
258window.addEventListener("DOMContentLoaded", $p.init);
259