PluginProbe
Floating Button – Easily Create Sticky, Fixed & Floating Buttons / trunk
Floating Button – Easily Create Sticky, Fixed & Floating Buttons vtrunk
trunk 2.0.2 3.0 4.0 4.1.2 4.3 5.0 5.0.1 5.1 5.1.1 5.2 5.3 5.3.1 6.0 6.0.1 6.0.10 6.0.11 6.0.12 6.0.13 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 All 31 releases
floating-button / assets / js / script.js

script.js in Floating Button – Easily Create Sticky, Fixed & Floating Buttons trunk, at assets/js/script.js

554 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * FloatingButton
3 * A JavaScript class for creating customizable floating button.
4 *
5 * @version 1.0.0
6 * @license MIT License
7 * @author Dmytro Lobov
8 */
9
10 'use strict';
11
12 class FloatingButton {
13
14 constructor(options) {
15
16 const defaultOptions = {
17 showAfterTimer: false,
18 hideAfterTimer: false,
19 showAfterPosition: false,
20 hideAfterPosition: false,
21 uncheckedBtn: false,
22 uncheckedSubBtn: false,
23 hideBtns: false,
24
25 };
26
27 this.settings = {...defaultOptions, ...options};
28 this.element = document.getElementById(this.settings.element);
29 }
30
31 activeLikeBtn() {
32 const likeBtn = this.element.querySelector('[data-btn-type="like"]');
33
34 if (!likeBtn) {
35 return false;
36 }
37
38 if (!this.settings.pageId) {
39 const parent = likeBtn.closest('li');
40 if(parent) {
41 parent.remove();
42 } else {
43 this.element.remove();
44 }
45 return false;
46 }
47
48 if (parseInt(localStorage.getItem('likePost')) === this.settings.pageId) {
49 likeBtn.classList.add('_active');
50 }
51
52 }
53
54 displayMenu() {
55
56 if(this.settings.showAfterTimer || this.settings.hideAfterTimer || this.settings.hideAfterPosition || this.settings.showAfterPosition) {
57
58 this.settings.showAfterTimer && this.showAfterTimer(this.settings.showAfterTimer);
59 this.settings.hideAfterTimer && this.hideAfterTimer(this.settings.hideAfterTimer);
60 this.settings.hideAfterPosition && this.hideAfterPosition(this.settings.hideAfterPosition);
61 this.settings.showAfterPosition && this.showAfterPosition(this.settings.showAfterPosition);
62 } else {
63 this.showMenu();
64 }
65
66 }
67
68 showMenu() {
69 this.element.classList.remove('is-hidden');
70
71 }
72
73 hideMenu() {
74 this.element.classList.add('is-hidden');
75
76 }
77
78 showAfterTimer() {
79 setTimeout(() => this.showMenu(), this.settings.showAfterTimer * 1000);
80
81 }
82
83 hideAfterTimer() {
84
85 setTimeout(() => this.element.classList.add('is-hidden'), this.settings.hideAfterTimer * 1000);
86 }
87
88 hideAfterPosition() {
89
90 window.addEventListener('scroll', () => {
91 const shouldHide = window.scrollY > this.settings.hideAfterPosition;
92 if (!shouldHide) {
93 this.showMenu();
94 } else {
95 this.hideMenu();
96 }
97 });
98 }
99
100 showAfterPosition() {
101
102 window.addEventListener('scroll', () => {
103 const shouldHide = window.scrollY <= this.settings.showAfterPosition;
104 if (!shouldHide) {
105 this.showMenu();
106 } else {
107 this.hideMenu();
108 }
109 });
110 }
111
112 actionServices() {
113 this.element.addEventListener('click', (event) => {
114 const target = event.target.closest('[data-btn-type]');
115 if (!target) return;
116
117 event.preventDefault();
118 const action = target.getAttribute('data-btn-type');
119 this.handleAction(action, target);
120 });
121 }
122
123 handleAction(action, link) {
124 const actionMap = {
125 print: () => window.print(),
126 back: () => window.history.back(),
127 forward: () => window.history.forward(),
128 scroll: () => {
129 const anchor = link.getAttribute('href');
130 const element = document.querySelector(anchor);
131 element.scrollIntoView({behavior: 'smooth', block: 'start', inline: 'nearest'});
132 },
133 toTop: () => window.scrollTo({top: 0, behavior: 'smooth'}),
134 tobottom: () => window.scrollTo({top: document.body.scrollHeight, behavior: 'smooth'}),
135 like: () => this.setLikes(link),
136
137 };
138
139 const actionFunction = actionMap[action];
140 if (actionFunction) {
141 actionFunction();
142 }
143 }
144
145 setLikes(link) {
146 const counter = link.getAttribute('data-counter');
147 const item = localStorage.getItem('likePost');
148 if (this.settings.pageId && this.settings.pageId !== parseInt(item)) {
149 const nexCounter = parseInt(counter) + 1;
150 let data = {
151 'action': 'wowp_likes',
152 'post_id': this.settings.pageId, // Enter the id of the post
153 '_ajax_nonce': wowp_flBtn.nonce // replace with how you have localized your nonce
154 };
155
156 let body = new URLSearchParams();
157 for (let key in data) {
158 body.append(key, data[key]);
159 }
160
161 fetch(wowp_flBtn.ajax_url, { // replace with how you have localized your ajaxurl
162 method: 'POST',
163 headers: {
164 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
165 },
166 body: body.toString()
167 })
168 .then(data => {
169 localStorage.setItem('likePost', this.settings.pageId);
170 link.setAttribute('data-counter', nexCounter);
171 link.classList.add('_active');
172 })
173 .catch(error => console.error('Error:', error));
174
175
176 }
177 }
178
179 shareServices() {
180 const links = this.element.querySelectorAll('[data-share]');
181 links.forEach(link => {
182 link.addEventListener('click', () => {
183 this.shareThis(link);
184 });
185 });
186 }
187
188 shareThis(link) {
189 const service = link.getAttribute('data-share');
190 const shareData = this.defaultShareServices();
191 const shareService = shareData[service];
192
193 const winWidth = 550;
194 const winHeight = 450;
195 const topPosition = (screen.height - winHeight) / 2;
196 const leftPosition = (screen.width - winWidth) / 2;
197
198 const winParams = `
199 menubar=no,
200 toolbar=no,
201 location=no,
202 scrollbars=no,
203 status=no,
204 resizable=yes,
205 width=${winWidth},
206 height=${winHeight},
207 top=${topPosition},
208 left=${leftPosition}
209 `;
210
211 window.open(shareService.url, null, winParams);
212 }
213
214 defaultShareServices() {
215 const PAGE_URL = encodeURIComponent(document.location.href);
216 const PAGE_TITLE = encodeURIComponent(document.title);
217
218 return {
219 'blogger': {
220 url: `https://www.blogger.com/blog-this.g?u=${PAGE_URL}&n=${PAGE_TITLE}`,
221 },
222 'buffer': {
223 url: `https://buffer.com/add?text=${PAGE_TITLE}&url=${PAGE_URL}`,
224 },
225 'diaspora': {
226 url: `https://share.diasporafoundation.org/?title=${PAGE_TITLE}&url=${PAGE_URL}`,
227 },
228 'digg': {
229 url: `http://digg.com/submit?url=${PAGE_URL}`,
230 },
231 'douban': {
232 url: `http://www.douban.com/recommend/?url=${PAGE_URL}&title=${PAGE_TITLE}`,
233 },
234
235 'draugiem': {
236 url: `https://www.draugiem.lv/say/ext/add.php?title=${PAGE_TITLE}&url=${PAGE_URL}`,
237 },
238 'email': {
239 url: `mailto:?subject=${PAGE_TITLE}&body=${PAGE_URL}`,
240 },
241 'evernote': {
242 url: `http://www.evernote.com/clip.action?url=${PAGE_URL}&title=${PAGE_TITLE}`,
243 },
244 'facebook': {
245 url: `https://www.facebook.com/sharer.php?u=${PAGE_URL}`,
246 },
247 'flipboard': {
248 url: `https://share.flipboard.com/bookmarklet/popout?v=2&title=${PAGE_TITLE}&url=${PAGE_URL}`,
249 },
250 'google-bookmarks': {
251 url: `https://www.google.com/bookmarks/mark?op=edit&bkmk=${PAGE_URL}&title=${PAGE_TITLE}`,
252 },
253 'googleplus': {
254 url: `https://plus.google.com/share?url=${PAGE_URL}`,
255 },
256 'hacker-news': {
257 url: `https://news.ycombinator.com/submitlink?u=${PAGE_URL}&t=${PAGE_TITLE}`,
258 },
259 'instapaper': {
260 url: `http://www.instapaper.com/edit?url=${PAGE_URL}&title=${PAGE_TITLE}`,
261 },
262 'line': {
263 url: `https://lineit.line.me/share/ui?url=${PAGE_URL}`,
264 },
265 'linkedin': {
266 url: `https://www.linkedin.com/shareArticle?mini=true&url=${PAGE_URL}&title=${PAGE_TITLE}`,
267 },
268 'livejournal': {
269 url: `http://www.livejournal.com/update.bml?subject=${PAGE_TITLE}&event=${PAGE_URL}`,
270 },
271 'myspace': {
272 url: `https://myspace.com/post?u=${PAGE_URL}&t=${PAGE_TITLE}`,
273 },
274 'odnoklassniki': {
275 url: `https://connect.ok.ru/dk?st.cmd=WidgetSharePreview&st.shareUrl=${PAGE_URL}`,
276 },
277 'pinterest': {
278 url: `http://pinterest.com/pin/create/button/?url=${PAGE_URL}`,
279 },
280 'pocket': {
281 url: `https://getpocket.com/edit?url=${PAGE_URL}`,
282 },
283 'qzone': {
284 url: `http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=${PAGE_URL}`,
285 },
286 'reddit': {
287 url: `http://www.reddit.com/submit?url=${PAGE_URL}&title=${PAGE_TITLE}`,
288 },
289 'renren': {
290 url: `http://widget.renren.com/dialog/share?resourceUrl=${PAGE_URL}&srcUrl=${PAGE_URL}&title=${PAGE_TITLE}`,
291 },
292 'skype': {
293 url: `https://web.skype.com/share?url=${PAGE_URL}`,
294 },
295 'stumbleupon': {
296 url: 'http://www.stumbleupon.com/submit?url=${PAGE_URL}&title=${PAGE_TITLE}',
297 },
298 'telegram': {
299 url: `https://telegram.me/share/url?url=${PAGE_URL}&text=${PAGE_TITLE}`,
300 },
301 'tumblr': {
302 url: `https://www.tumblr.com/widgets/share/tool?canonicalUrl=${PAGE_URL}&title=${PAGE_TITLE}`,
303 },
304 'twitter': {
305 url: `https://twitter.com/intent/tweet?url=${PAGE_URL}&text=${PAGE_TITLE}`,
306 },
307 'vk': {
308 url: `http://vk.com/share.php?url=${PAGE_URL}&title=${PAGE_TITLE}`,
309 },
310 'weibo': {
311 url: `http://service.weibo.com/share/share.php?url=${PAGE_URL}&title=${PAGE_TITLE}`,
312 },
313 'whatsapp': {
314 url: `whatsapp://send?text=${PAGE_TITLE}%20%0A${PAGE_URL}`,
315 },
316 'xing': {
317 url: `https://www.xing.com/spi/shares/new?url=${PAGE_URL}`,
318 },
319 };
320 }
321
322 translate() {
323 const languages = this.element.querySelectorAll('[data-google-lang]');
324 if (languages.length > 0) {
325 this.appendScript();
326 }
327 }
328
329 appendScript() {
330 const head = document.head;
331 const script = document.createElement('script');
332 script.src = 'https://translate.google.com/translate_a/element.js?cb=FLBTNTranslateInit';
333 script.setAttribute('defer', '');
334 head.appendChild(script);
335
336 const styleElement = document.createElement('style');
337 styleElement.textContent = '.skiptranslate {display: none !important;}body {top: 0 !important}';
338 head.appendChild(styleElement);
339 }
340
341 static Translate() {
342 const doc = document;
343 const win = window;
344 const deflang = doc.documentElement.lang.slice(0, 2);
345 const lang = this.getLanguage(deflang);
346
347 if (lang === deflang) {
348 this.clearCookie();
349 }
350
351 const languages = Array.from(doc.querySelectorAll('[data-google-lang]'));
352
353 if (!languages.length) {
354 return false;
355 }
356
357 new google.translate.TranslateElement({
358 pageLanguage: deflang,
359 });
360
361 languages.forEach((language) => {
362 language.addEventListener('click', (e) => {
363 e.preventDefault();
364 let lang = language.getAttribute('data-google-lang');
365 this.setCookie(lang);
366 win.location.reload();
367 });
368 });
369 }
370
371 static getLanguage(lang) {
372 const keyValue = document['cookie'].match('(^|;) ?googtrans=([^;]*)(;|$)');
373 const cookieLang = keyValue ? keyValue[2].split('/')[2] : null;
374 return (cookieLang !== undefined && cookieLang !== 'null') ? cookieLang : lang;
375 }
376
377 static clearCookie() {
378 document.cookie = 'googtrans=null';
379 document.cookie = 'googtrans=null; domain=' + document.domain;
380 }
381
382 static setCookie(lang) {
383 document.cookie = 'googtrans=/auto/' + lang;
384 document.cookie = 'googtrans=/auto/' + lang + '; domain=' + document.domain;
385 }
386
387 uncheckBtn() {
388 if (!this.settings.uncheckedBtn) {
389 return;
390 }
391 const id = this.settings.element;
392 const element = this.element;
393 const self = this;
394 document.addEventListener('click', function (evt) {
395 const parent = evt.target.closest('#' + id);
396 if (parent !== element) {
397 element.querySelector('input[type="checkbox"]').checked = false;
398 self.hideButtons('show');
399 }
400 });
401 }
402
403 uncheckedSubBtn() {
404 if (!this.settings.uncheckedSubBtn) {
405 return;
406 }
407 const subBtns = [...this.element.querySelectorAll('ul a')];
408 const self = this;
409 subBtns.forEach((bnt) => {
410 bnt.addEventListener('click', (e) => {
411 this.element.querySelector('input[type="checkbox"]').checked = false;
412 self.hideButtons('show');
413 });
414 });
415 }
416
417 hideButtons(action) {
418 if (!this.settings.hideBtns) {
419 return;
420 }
421 const allButtons = [...document.querySelectorAll('.flBtn')];
422 const otherButtons = allButtons.filter(btn => btn !== this.element);
423 if (action === 'hide') {
424 otherButtons.forEach(btn => btn.classList.add('is-hidden'));
425 } else {
426 otherButtons.forEach(btn => btn.classList.remove('is-hidden'));
427 }
428
429 }
430
431 check() {
432 const checkBox = this.element.querySelector('input[type="checkbox"]');
433 const element = this.element;
434 const self = this;
435
436 if (!checkBox) {
437 return false;
438 }
439
440 function toggleButtons() {
441 if (checkBox.checked) {
442 element.classList.add('flBtn-stop');
443 self.hideButtons('hide');
444 } else {
445 element.classList.remove('flBtn-stop');
446 self.hideButtons('show');
447 }
448 }
449
450 checkBox.addEventListener('change', toggleButtons);
451 toggleButtons();
452 }
453
454 openMenu() {
455 const flBtnMenu = document.querySelectorAll('[data-btn-type="content-menu"]');
456
457 if (!flBtnMenu) {
458 return false;
459 }
460
461 flBtnMenu.forEach((btn) => {
462 btn.addEventListener('click', () => {
463 const parent = btn.closest('.flBtn');
464 const position = btn.getBoundingClientRect();
465 const menuOrder = btn.getAttribute('data-btn-call-menu');
466 const menu = document.querySelector('[data-btn-menu="' + menuOrder + '"]');
467 const subMenu = btn.closest('ul');
468 let typeFirst = false;
469 if (subMenu && subMenu.querySelector('.flBtn-first')) {
470 typeFirst = subMenu.classList.contains('flBtn-first');
471 }
472 const winWidth = window.innerWidth;
473 const winHeight = window.innerHeight;
474 if (parent.classList.contains('flBtn-position-l')) {
475 menu.style.top = position.top + 'px';
476 menu.style.left = position.left + position.width + 10 + 'px';
477 } else if (parent.classList.contains('flBtn-position-r')) {
478 menu.style.top = position.top + 'px';
479 menu.style.right = position.width + 40 + 'px';
480 } else if (parent.classList.contains('flBtn-position-t')) {
481 menu.style.top = position.top + position.width + 10 + 'px';
482 menu.style.left = position.left + 'px';
483 } else if (parent.classList.contains('flBtn-position-b')) {
484 menu.style.left = position.left + 'px';
485 menu.style.bottom = position.width + 40 + 'px';
486 } else if (parent.classList.contains('flBtn-position-tr')) {
487 menu.style.top = typeFirst ? position.top + 'px' : position.bottom + 20 + 'px';
488 menu.style.right = typeFirst ? position.width + 40 + 'px' : winWidth - position.right + 'px';
489 } else if (parent.classList.contains('flBtn-position-tl')) {
490 menu.style.top = typeFirst ? position.top + 'px' : position.bottom + 20 + 'px';
491 menu.style.left = typeFirst ? position.right + 10 + 'px' : position.left + 'px';
492 } else if (parent.classList.contains('flBtn-position-bl')) {
493 menu.style.bottom = typeFirst ? winHeight - position.bottom + 'px' : winHeight - position.top + 20 + 'px';
494 menu.style.left = typeFirst ? position.right + 20 + 'px' : position.left + 'px';
495 } else if (parent.classList.contains('flBtn-position-br')) {
496 menu.style.bottom = typeFirst ? winHeight - position.bottom + 'px' : winHeight - position.top + 20 + 'px';
497 menu.style.right = typeFirst ? winWidth - position.left + 20 + 'px' : winWidth - position.right + 'px';
498 }
499
500 menu.classList.remove('is-hidden');
501
502 });
503 });
504
505 }
506
507 closeMenu() {
508 const flMenuClose = document.querySelectorAll('.flBtn_close');
509 if (!flMenuClose) {
510 return false;
511 }
512
513 flMenuClose.forEach((btn) => {
514 btn.addEventListener('click', () => {
515 const menu = btn.closest('.flBtn_menu-wrapper');
516 menu.classList.add('is-hidden');
517 });
518 });
519 }
520
521 run() {
522 this.activeLikeBtn();
523 this.displayMenu();
524 this.actionServices();
525 this.shareServices();
526 this.translate();
527 this.uncheckBtn();
528 this.uncheckedSubBtn();
529 this.check();
530 this.openMenu();
531 this.closeMenu();
532 }
533
534 static initialize(options) {
535 const flbtn = new FloatingButton(options);
536 flbtn.run();
537 return flbtn;
538 }
539 }
540
541 document.addEventListener('DOMContentLoaded', function () {
542 for (let key in window) {
543 if (key.indexOf('FloatingButton_') >= 0) {
544 const val = window[key];
545 new FloatingButton(val);
546 FloatingButton.initialize(val);
547 }
548 }
549
550 });
551
552 function FLBTNTranslateInit() {
553 FloatingButton.Translate();
554 }