]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tpl/default/js/shaarli.js
Apply the new timezone template variables to the default theme
[github/shaarli/Shaarli.git] / tpl / default / js / shaarli.js
CommitLineData
b9b41d25
A
1/** @licstart The following is the entire license notice for the
2 * JavaScript code in this page.
3 *
4 * Copyright: (c) 2011-2015 Sébastien SAUVAGE <sebsauvage@sebsauvage.net>
5 * (c) 2011-2017 The Shaarli Community, see AUTHORS
6 *
7 * This software is provided 'as-is', without any express or implied warranty.
8 * In no event will the authors be held liable for any damages arising from
9 * the use of this software.
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software. If you use this software
17 * in a product, an acknowledgment in the product documentation would
18 * be appreciated but is not required.
19 *
20 * 2. Altered source versions must be plainly marked as such, and must
21 * not be misrepresented as being the original software.
22 *
23 * 3. This notice may not be removed or altered from any source distribution.
24 *
25 * @licend The above is the entire license notice
26 * for the JavaScript code in this page.
27 */
28
402b0346
A
29window.onload = function () {
30
31 /**
32 * Retrieve an element up in the tree from its class name.
33 */
34 function getParentByClass(el, className) {
35 var p = el.parentNode;
36 if (p == null || p.classList.contains(className)) {
37 return p;
38 }
39 return getParentByClass(p, className);
40 }
41
42
43 /**
44 * Handle responsive menu.
45 * Source: http://purecss.io/layouts/tucked-menu-vertical/
46 */
47 (function (window, document) {
48 var menu = document.getElementById('shaarli-menu'),
49 WINDOW_CHANGE_EVENT = ('onorientationchange' in window) ? 'orientationchange':'resize';
50
51 function toggleHorizontal() {
52 [].forEach.call(
53 document.getElementById('shaarli-menu').querySelectorAll('.menu-transform'),
54 function(el){
55 el.classList.toggle('pure-menu-horizontal');
56 }
57 );
58 };
59
60 function toggleMenu() {
61 // set timeout so that the panel has a chance to roll up
62 // before the menu switches states
63 if (menu.classList.contains('open')) {
64 setTimeout(toggleHorizontal, 500);
65 }
66 else {
67 toggleHorizontal();
68 }
69 menu.classList.toggle('open');
70 document.getElementById('menu-toggle').classList.toggle('x');
71 };
72
73 function closeMenu() {
74 if (menu.classList.contains('open')) {
75 toggleMenu();
76 }
77 }
78
a0737313
A
79 var menuToggle = document.getElementById('menu-toggle');
80 if (menuToggle != null) {
81 menuToggle.addEventListener('click', function (e) {
82 toggleMenu();
83 });
84 }
402b0346
A
85
86 window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu);
87 })(this, this.document);
88
89 /**
90 * Fold/Expand shaares description and thumbnail.
91 */
92 var foldAllButtons = document.getElementsByClassName('fold-all');
93 var foldButtons = document.getElementsByClassName('fold-button');
94
95 [].forEach.call(foldButtons, function (foldButton) {
96 // Retrieve description
97 var description = null;
98 var thumbnail = null;
99 var linklistItem = getParentByClass(foldButton, 'linklist-item');
100 if (linklistItem != null) {
101 description = linklistItem.querySelector('.linklist-item-description');
102 thumbnail = linklistItem.querySelector('.linklist-item-thumbnail');
103 if (description != null || thumbnail != null) {
104 foldButton.style.display = 'inline';
105 }
106 }
107
108 foldButton.addEventListener('click', function (event) {
109 event.preventDefault();
110 toggleFold(event.target, description, thumbnail);
111 });
112 });
113
114 if (foldAllButtons != null) {
115 [].forEach.call(foldAllButtons, function (foldAllButton) {
116 foldAllButton.addEventListener('click', function (event) {
117 event.preventDefault();
70401690 118 var state = foldAllButton.firstElementChild.getAttribute('class').indexOf('down') != -1 ? 'down' : 'up';
402b0346 119 [].forEach.call(foldButtons, function (foldButton) {
70401690
A
120 if (foldButton.firstElementChild.classList.contains('fa-chevron-up') && state == 'down'
121 || foldButton.firstElementChild.classList.contains('fa-chevron-down') && state == 'up'
122 ) {
123 return;
124 }
402b0346
A
125 // Retrieve description
126 var description = null;
127 var thumbnail = null;
128 var linklistItem = getParentByClass(foldButton, 'linklist-item');
129 if (linklistItem != null) {
130 description = linklistItem.querySelector('.linklist-item-description');
131 thumbnail = linklistItem.querySelector('.linklist-item-thumbnail');
132 if (description != null || thumbnail != null) {
133 foldButton.style.display = 'inline';
134 }
135 }
136
137 toggleFold(foldButton.firstElementChild, description, thumbnail);
138 });
139 foldAllButton.firstElementChild.classList.toggle('fa-chevron-down');
140 foldAllButton.firstElementChild.classList.toggle('fa-chevron-up');
141 });
142 });
143 }
144
145 function toggleFold(button, description, thumb)
146 {
147 // Switch fold/expand - up = fold
148 if (button.classList.contains('fa-chevron-up')) {
149 button.title = 'Expand';
150 if (description != null) {
151 description.style.display = 'none';
152 }
153 if (thumb != null) {
154 thumb.style.display = 'none';
155 }
156 }
157 else {
158 button.title = 'Fold';
159 if (description != null) {
160 description.style.display = 'block';
161 }
162 if (thumb != null) {
163 thumb.style.display = 'block';
164 }
165 }
166 button.classList.toggle('fa-chevron-down');
167 button.classList.toggle('fa-chevron-up');
168 }
169
170 /**
171 * Confirmation message before deletion.
172 */
173 var deleteLinks = document.querySelectorAll('.confirm-delete');
174 [].forEach.call(deleteLinks, function(deleteLink) {
175 deleteLink.addEventListener('click', function(event) {
176 if(! confirm('Are you sure you want to delete this link ?')) {
177 event.preventDefault();
178 }
179 });
180 });
181
182 /**
183 * Close alerts
184 */
185 var closeLinks = document.querySelectorAll('.pure-alert-close');
186 [].forEach.call(closeLinks, function(closeLink) {
187 closeLink.addEventListener('click', function(event) {
188 var alert = getParentByClass(event.target, 'pure-alert-closable');
189 alert.style.display = 'none';
190 });
191 });
192
193 /**
194 * New version dismiss.
195 * Hide the message for one week using localStorage.
196 */
197 var newVersionDismiss = document.getElementById('new-version-dismiss');
198 var newVersionMessage = document.querySelector('.new-version-message');
199 if (newVersionMessage != null
200 && localStorage.getItem('newVersionDismiss') != null
201 && parseInt(localStorage.getItem('newVersionDismiss')) + 7*24*60*60*1000 > (new Date()).getTime()
202 ) {
203 newVersionMessage.style.display = 'none';
204 }
205 if (newVersionDismiss != null) {
206 newVersionDismiss.addEventListener('click', function () {
207 localStorage.setItem('newVersionDismiss', (new Date()).getTime());
208 });
209 }
210
211 var hiddenReturnurl = document.getElementsByName('returnurl');
212 if (hiddenReturnurl != null) {
213 hiddenReturnurl.value = window.location.href;
214 }
215
216 /**
217 * Autofocus text fields
218 */
b9b41d25
A
219 // ES6 syntax
220 let autofocusElements = document.querySelectorAll('.autofocus');
221 for (let autofocusElement of autofocusElements) {
222 if (autofocusElement.value == '') {
223 autofocusElement.focus();
224 break;
225 }
402b0346
A
226 }
227
228 /**
229 * Handle sub menus/forms
230 */
231 var openers = document.getElementsByClassName('subheader-opener');
232 if (openers != null) {
233 [].forEach.call(openers, function(opener) {
234 opener.addEventListener('click', function(event) {
235 event.preventDefault();
236
237 var id = opener.getAttribute('data-open-id');
238 var sub = document.getElementById(id);
239
240 if (sub != null) {
241 [].forEach.call(document.getElementsByClassName('subheader-form'), function (element) {
242 if (element != sub) {
243 removeClass(element, 'open')
244 }
245 });
246
247 sub.classList.toggle('open');
248 }
249 });
250 });
251 }
252
253 function removeClass(element, classname) {
254 element.className = element.className.replace(new RegExp('(?:^|\\s)'+ classname + '(?:\\s|$)'), ' ');
255 }
256
257 /**
258 * Remove CSS target padding (for fixed bar)
259 */
260 if (location.hash != '') {
261 var anchor = document.querySelector(location.hash);
262 if (anchor != null) {
263 var padsize = anchor.clientHeight;
264 console.log(document.querySelector(location.hash).clientHeight);
265 this.window.scroll(0, this.window.scrollY - padsize);
266 anchor.style.paddingTop = 0;
267 }
268 }
70401690
A
269
270 /**
271 * Text area resizer
272 */
273 var description = document.getElementById('lf_description');
274 var observe = function (element, event, handler) {
275 element.addEventListener(event, handler, false);
276 };
277 function init () {
278 function resize () {
279 description.style.height = 'auto';
280 description.style.height = description.scrollHeight+10+'px';
281 }
282 /* 0-timeout to get the already changed text */
283 function delayedResize () {
284 window.setTimeout(resize, 0);
285 }
286 observe(description, 'change', resize);
287 observe(description, 'cut', delayedResize);
288 observe(description, 'paste', delayedResize);
289 observe(description, 'drop', delayedResize);
290 observe(description, 'keydown', delayedResize);
291
292 resize();
293 }
2dd698fd 294
70401690
A
295 if (description != null) {
296 init();
2dd698fd
A
297 // Submit editlink form with CTRL + Enter in the text area.
298 description.addEventListener('keydown', function (event) {
299 if (event.ctrlKey && event.keyCode === 13) {
300 document.getElementById('button-save-edit').click();
301 }
302 });
70401690 303 }
b9b41d25 304
b9b41d25
A
305 /**
306 * Awesomplete trigger.
307 */
308 var tags = document.getElementById('lf_tags');
309 if (tags != null) {
310 awesompleteUniqueTag('#lf_tags');
311 }
312
313 /**
314 * bLazy trigger
315 */
316 var picwall = document.getElementById('picwall_container');
317 if (picwall != null) {
318 var bLazy = new Blazy();
319 }
320
321 /**
322 * Bookmarklet alert
323 */
324 var bookmarkletLinks = document.querySelectorAll('.bookmarklet-link');
325 var bkmMessage = document.getElementById('bookmarklet-alert');
326 [].forEach.call(bookmarkletLinks, function(link) {
327 link.addEventListener('click', function(event) {
328 event.preventDefault();
329 alert(bkmMessage.value);
330 });
331 });
332
333 /**
334 * Firefox Social
335 */
336 var ffButton = document.getElementById('ff-social-button');
337 if (ffButton != null) {
338 ffButton.addEventListener('click', function(event) {
339 activateFirefoxSocial(event.target);
340 });
341 }
342
343 /**
344 * Plugin admin order
345 */
346 var orderPA = document.querySelectorAll('.order');
347 [].forEach.call(orderPA, function(link) {
348 link.addEventListener('click', function(event) {
349 event.preventDefault();
350 if (event.target.classList.contains('order-up')) {
351 return orderUp(event.target.parentNode.parentNode.getAttribute('data-order'));
352 } else if (event.target.classList.contains('order-down')) {
353 return orderDown(event.target.parentNode.parentNode.getAttribute('data-order'));
354 }
355 });
356 });
a0737313
A
357
358 var continent = document.getElementById('continent');
359 var city = document.getElementById('city');
360 if (continent != null && city != null) {
361 continent.addEventListener('change', function(event) {
362 hideTimezoneCities(city, continent.options[continent.selectedIndex].value, true);
363 });
364 hideTimezoneCities(city, continent.options[continent.selectedIndex].value, false);
365 }
402b0346 366};
b9b41d25
A
367
368function activateFirefoxSocial(node) {
369 var loc = location.href;
370 var baseURL = loc.substring(0, loc.lastIndexOf("/"));
371
372 // Keeping the data separated (ie. not in the DOM) so that it's maintainable and diffable.
373 var data = {
374 name: "{$shaarlititle}",
375 description: "The personal, minimalist, super-fast, database free, bookmarking service by the Shaarli community.",
376 author: "Shaarli",
377 version: "1.0.0",
378
379 iconURL: baseURL + "/images/favicon.ico",
380 icon32URL: baseURL + "/images/favicon.ico",
381 icon64URL: baseURL + "/images/favicon.ico",
382
383 shareURL: baseURL + "{noparse}?post=%{url}&title=%{title}&description=%{text}&source=firefoxsocialapi{/noparse}",
384 homepageURL: baseURL
385 };
386 node.setAttribute("data-service", JSON.stringify(data));
387
388 var activate = new CustomEvent("ActivateSocialFeature");
389 node.dispatchEvent(activate);
390}
a0737313
A
391
392/**
393 * Add the class 'hidden' to city options not attached to the current selected continent.
394 *
395 * @param cities List of <option> elements
396 * @param currentContinent Current selected continent
397 * @param reset Set to true to reset the selected value
398 */
399function hideTimezoneCities(cities, currentContinent, reset = false) {
400 var first = true;
401 [].forEach.call(cities, function(option) {
402 if (option.getAttribute('data-continent') != currentContinent) {
403 option.className = 'hidden';
404 } else {
405 option.className = '';
406 if (reset === true && first === true) {
407 option.setAttribute('selected', 'selected');
408 first = false;
409 }
410 }
411 });
412}