PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.20
VikAppointments Services Booking Calendar v1.2.20
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / media / js / system.js
vikappointments / media / js Last commit date
admin.js 1 month ago bootstrap.min.js 1 month ago gutenberg-shortcodes.js 1 month ago gutenberg-tools.js 1 month ago gutenberg-widgets.js 1 month ago system.js 1 month ago tinymce-shortcodes.js 1 month ago
system.js
879 lines
1 /**
2 * Joomla Core
3 */
4
5 function JoomlaCore() {
6 // instantiate only once because iframe pages might invoke this method again
7 if (!JoomlaCore.instance) {
8 // init pagination handler
9 this.paginations = {};
10 // init translations handler
11 this.JText = new JText();
12 // init editors instances
13 this.editors = {instances: {}};
14
15 // register singleton
16 JoomlaCore.instance = this;
17 }
18
19 return JoomlaCore.instance;
20 }
21
22 JoomlaCore.prototype.getPagination = function(prefix) {
23 key = prefix || '__default__';
24
25 if (!this.paginations.hasOwnProperty(key)) {
26 this.paginations[key] = new JPagination();
27 this.paginations[key].setPrefix(prefix)
28 }
29
30 return this.paginations[key];
31 }
32
33 JoomlaCore.prototype.checkAll = function(checkbox) {
34 // Use :visible selector in order to skip hidden checkboxes.
35 // This is helpful to ignore hidden inputs while filtering the list.
36 jQuery('#adminForm input[name="cid[]"]:visible').prop('checked', checkbox.checked);
37 }
38
39 JoomlaCore.prototype.isChecked = function(checked) {
40 // get toggle-all checkbox
41 var allBox = jQuery('#adminForm thead input[type="checkbox"]');
42
43 if (!checked || jQuery('#adminForm input[name="cid[]"]').length != this.hasChecked()) {
44 allBox.prop('checked', false);
45 } else {
46 allBox.prop('checked', true);
47 }
48 }
49
50 JoomlaCore.prototype.hasChecked = function() {
51 return jQuery('#adminForm input[name="cid[]"]:checked').length;
52 }
53
54 JoomlaCore.prototype.submitform = function(task, form) {
55 if (!form) {
56 // use default adminForm if not specified
57 form = document.adminForm;
58 }
59
60 if (task && form.task) {
61 form.task.value = task;
62 }
63
64 // submit through jQuery in order to
65 // properly emit the "submit" event
66 jQuery(form).submit();
67 }
68
69 JoomlaCore.prototype.submitbutton = function(task) {
70 this.submitform(task, document.adminForm);
71 }
72
73 JoomlaCore.prototype.tableOrdering = function(column, direction, task, form) {
74 if (form === undefined) {
75 form = document.adminForm;
76 }
77
78 if (form.filter_order === undefined) {
79 var orderInput = document.createElement('input');
80 orderInput.type = 'hidden';
81 orderInput.name = 'filter_order';
82
83 form.appendChild(orderInput);
84 }
85
86 form.filter_order.value = column;
87
88 if (form.filter_order_Dir === undefined) {
89 var directionInput = document.createElement('input');
90 directionInput.type = 'hidden';
91 directionInput.name = 'filter_order_Dir';
92
93 form.appendChild(directionInput);
94 }
95
96 form.filter_order_Dir.value = direction;
97
98 this.submitform(task, form);
99 }
100
101 JoomlaCore.getOptions = function(key, def) {
102 // load options if they not exists
103 if (!JoomlaCore.optionsStorage) {
104 JoomlaCore.loadOptions();
105 }
106
107 return JoomlaCore.optionsStorage[key] !== undefined ? JoomlaCore.optionsStorage[key] : def;
108 };
109
110 JoomlaCore.loadOptions = function(options) {
111 if (!options) {
112 var elements = jQuery('script.joomla-options.new');
113 var counter = 0;
114
115 for (var i = 0, l = elements.length; i < l; i++) {
116 var element = elements[i];
117 var str = element.text || element.textContent;
118 var option = {};
119
120 try {
121 option = JSON.parse(str);
122 } catch (err) {
123 console.log(err);
124 }
125
126 if (option) {
127 JoomlaCore.loadOptions(option);
128 counter++;
129 }
130
131 // mark element as loaded
132 jQuery(element).removeClass('new').addClass('loaded');
133 }
134
135 if (counter) {
136 return;
137 }
138 }
139
140 // initial loading
141 if (!JoomlaCore.optionsStorage) {
142 JoomlaCore.optionsStorage = options || {};
143 }
144 // Merge with existing
145 else if (options) {
146 for (var p in options) {
147 if (options.hasOwnProperty(p)) {
148 // check whether the options pool already exists
149 if (!JoomlaCore.optionsStorage.hasOwnProperty(p)) {
150 // nope, init pool
151 JoomlaCore.optionsStorage[p] = {};
152 }
153
154 // merge new new options with the existing ones
155 Object.assign(JoomlaCore.optionsStorage[p], options[p]);
156 }
157 }
158 }
159 };
160
161 JoomlaCore.isAdmin = function() {
162 return document.location.href.match(/\/wp-admin\//i) ? true : false;
163 }
164
165 /**
166 * Pagination
167 */
168
169 function JPagination(total, limit, start, listener) {
170
171 if (total === undefined) {
172 total = 0;
173 }
174
175 if (limit === undefined) {
176 limit = 0;
177 }
178
179 if (start === undefined) {
180 start = 0;
181 }
182
183 if (listener === undefined) {
184 listener = null;
185 }
186
187 this.total = total;
188 this.limit = limit;
189 this.start = start;
190 this.prefix = '';
191
192 this.listener = listener;
193
194 return this;
195 }
196
197 JPagination.prototype.setTotal = function(total) {
198 this.total = total;
199
200 return this;
201 }
202
203 JPagination.prototype.setLimit = function(limit) {
204 this.limit = limit;
205
206 return this;
207 }
208
209 JPagination.prototype.setStart = function(start) {
210 this.start = start;
211
212 return this;
213 }
214
215 JPagination.prototype.setListener = function(listener) {
216 this.listener = listener;
217
218 return this;
219 }
220
221 JPagination.prototype.setPrefix = function(prefix) {
222 this.prefix = prefix || '';
223
224 return this;
225 }
226
227 JPagination.prototype.submit = function() {
228
229 if (this.listener[this.prefix + 'limitstart'] === undefined) {
230 var limitstart = document.createElement('input');
231 limitstart.type = 'hidden';
232 limitstart.name = this.prefix + 'limitstart';
233
234 this.listener.appendChild(limitstart);
235 }
236
237 if (this.listener[this.prefix + 'limit'] === undefined) {
238 var limit = document.createElement('input');
239 limit.type = 'hidden';
240 limit.name = this.prefix + 'limit';
241
242 this.listener.appendChild(limit);
243 }
244
245 this.listener[this.prefix + 'limitstart'].value = this.start;
246 this.listener[this.prefix + 'limit'].value = this.limit;
247
248 // submit through jQuery in order to
249 // properly emit the "submit" event
250 jQuery(this.listener).submit();
251 }
252
253 JPagination.prototype.first = function() {
254 this.start = 0;
255 this.submit();
256 }
257
258 JPagination.prototype.prev = function() {
259 this.start -= this.limit;
260 this.submit();
261 }
262
263 JPagination.prototype.next = function() {
264 this.start += this.limit;
265 this.submit();
266 }
267
268 JPagination.prototype.last = function() {
269 this.start = (Math.ceil(this.total / this.limit) - 1) * this.limit;
270 this.submit();
271 }
272
273 /**
274 * Text
275 */
276
277 function JText() {
278 this.strings = {};
279
280 return this;
281 }
282
283 JText.prototype._ = function(key, def) {
284 // check for new strings in the optionsStorage, and load them
285 var newStrings = JoomlaCore.getOptions('joomla.jtext');
286
287 if (newStrings) {
288 this.load(newStrings);
289
290 // Clean up the optionsStorage from useless data
291 JoomlaCore.loadOptions({'joomla.jtext': null});
292 }
293
294 def = def === undefined ? '' : def;
295 key = key.toUpperCase();
296
297 return this.strings[key] !== undefined ? this.strings[key] : def;
298 }
299
300 JText.prototype.load = function(object) {
301 for (var key in object) {
302 if (object.hasOwnProperty(key)) {
303 this.strings[key.toUpperCase()] = object[key];
304 }
305 }
306
307 return this;
308 }
309
310 /*
311 * FORM VALIDATION
312 */
313
314 function JFormValidator(form, clazz) {
315 this.form = form;
316
317 if (typeof clazz === 'undefined') {
318 clazz = 'invalid';
319 }
320
321 this.clazz = clazz;
322 this.labels = {};
323
324 // prevent the form submission on enter keydown
325
326 jQuery(this.form).on('keyup', function(e) {
327 var keyCode = e.keyCode || e.which;
328
329 if (keyCode === 13) {
330 e.preventDefault();
331 return false;
332 }
333 });
334
335 this.registerFields('.required');
336 }
337
338 JFormValidator.prototype.isValid = function(input) {
339 var val = jQuery(input).val();
340
341 return val !== null && val.length > 0;
342 }
343
344 JFormValidator.prototype.registerFields = function(selector) {
345
346 var _this = this;
347
348 jQuery(this.form).find(selector).on('blur', function() {
349 if (_this.isValid(this)) {
350 _this.unsetInvalid(this);
351 } else {
352 _this.setInvalid(this);
353 }
354 });
355
356 return this;
357 }
358
359 JFormValidator.prototype.unregisterFields = function(selector) {
360
361 jQuery(this.form).find(selector).off('blur')
362
363 return this;
364 }
365
366 JFormValidator.prototype.validate = function(callback) {
367 var ok = true;
368
369 var _this = this;
370
371 this.clearInvalidTabPane();
372
373 jQuery(this.form).find('.required:input').each(function() {
374 if (_this.isValid(this)) {
375 _this.unsetInvalid(this);
376 } else {
377 _this.setInvalid(this);
378 ok = false;
379
380 if (!jQuery(this).is(':visible')) {
381 // the input is probably hidden behind
382 // an unactive tab pane
383 _this.setInvalidTabPane(this);
384 }
385 }
386 });
387
388 if (typeof callback !== 'undefined') {
389 ok = callback() && ok;
390 }
391
392 return ok;
393 }
394
395 JFormValidator.prototype.setLabel = function(input, label) {
396 this.labels[jQuery(input).attr('name')] = label;
397
398 return this;
399 }
400
401 JFormValidator.prototype.getLabel = function(input) {
402 var name = jQuery(input).attr('name');
403
404 if (this.labels.hasOwnProperty(name)) {
405 return jQuery(this.labels[name]);
406 }
407
408 return jQuery(input).closest('.control').children().filter('b,label');
409 }
410
411 JFormValidator.prototype.setInvalid = function(input) {
412 jQuery(input).addClass(this.clazz);
413 this.getLabel(input).addClass(this.clazz);
414
415 return this;
416 }
417
418 JFormValidator.prototype.unsetInvalid = function(input) {
419 jQuery(input).removeClass(this.clazz);
420 this.getLabel(input).removeClass(this.clazz);
421
422 return this;
423 }
424
425 JFormValidator.prototype.isInvalid = function(input) {
426 return jQuery(input).hasClass(this.clazz);
427 }
428
429 JFormValidator.prototype.clearInvalidTabPane = function() {
430 jQuery('ul.nav-tabs li a').removeClass(this.clazz);
431
432 return this;
433 }
434
435 JFormValidator.prototype.setInvalidTabPane = function(input) {
436 var pane = jQuery(input).closest('.tab-pane');
437
438 if (pane.length) {
439 var id = jQuery(pane).attr('id');
440 var link = jQuery('ul.nav-tabs li a[href="#' + id + '"]');
441
442 if (link.length) {
443 link.addClass(this.clazz);
444 }
445 }
446
447 return this;
448 }
449
450 /**
451 * TRIGGER JMODAL
452 */
453
454 function wpOpenJModal(id, href, onShow, onHide) {
455
456 if (onShow !== undefined)
457 {
458 jQuery('#jmodal-' + id).on('show', onShow);
459 }
460
461 if (onHide !== undefined)
462 {
463 jQuery('#jmodal-' + id).on('hide', onHide);
464 }
465
466 if (!href) {
467 // try to extract url from modal URL input
468 href = jQuery('#jmodal-' + id + ' > input[name="url"]').val();
469 }
470
471 var hideOnEsc = null;
472
473 // check if the modal can be closed using the ESC button
474 if (jQuery('#jmodal-' + id).data('esc') == 1) {
475 hideOnEsc = function(event) {
476 if (event.keyCode == 27) {
477 // close modal when ESC is pressed
478 wpCloseJModal(id);
479 }
480 };
481
482 jQuery(window).on('keydown', hideOnEsc);
483 }
484
485 jQuery('#jmodal-' + id).on('hide.bs.modal', function() {
486 // we should remove the body only whether it has been loaded asynchronously
487 if (href) {
488 jQuery(this).find('.modal-body').remove();
489 }
490
491 jQuery('#jmodal-' + id).off('show.bs.modal');
492 jQuery('#jmodal-' + id).off('hide.bs.modal');
493
494 if (hideOnEsc) {
495 // turn off esc handler too after disposing the modal
496 jQuery(window).off('keydown', hideOnEsc);
497 }
498 });
499
500 // trigger "show" event to support external listeners
501 jQuery('#jmodal-' + id).modal('show').trigger('show');
502
503 var closeBtn = jQuery('#jmodal-' + id).find('button[data-dismiss]');
504
505 // add workaround to trigger hide|hidden events also when
506 // clicking the dismiss button of the modal
507 closeBtn.on('click', function() {
508 jQuery('#jmodal-' + id).trigger('hide').trigger('hidden').trigger('hide.bs.modal');
509 });
510
511 // hide on backdrop click only in case the modal is dismissable
512 if (closeBtn.length || hideOnEsc) {
513 jQuery('.modal-backdrop').on('click', () => {
514 wpCloseJModal(id);
515 });
516 }
517
518 if (href)
519 {
520 wpAppendModalContent('jmodal-box-' + id, href);
521 }
522 }
523
524 function wpCloseJModal(id) {
525 if (id.match(/^jmodal-/)) {
526 // full ID without "#"
527 id = "#" + id;
528 } else if (!id.match(/^#jmodal-/)) {
529 // modal ID only
530 id = "#jmodal-" + id;
531 }
532
533 // close modal and trigger hide|hidden events
534 jQuery(id).modal('hide').trigger('hide').trigger('hidden').trigger('hide.bs.modal');
535 }
536
537 function wpAppendModalContent(id, href) {
538
539 const modalBody = jQuery('#' + id);
540
541 // check if we have an image URL (? indicates a query string and should not be set)
542 if (typeof href == 'string' && href.match(/\.(png|jpe?g|gif|bmp)$/i) && !href.match(/\?/)) {
543 // we received an image, display it directly within the body
544 modalBody.html(
545 '<div class="modal-body">\n' +
546 '<div class="media-preview"><img src="' + href + '" /></div>' +
547 '</div>\n'
548 );
549
550 return;
551 }
552
553 if (modalBody.html().trim().length > 0) {
554 modalBody.addClass('loading');
555 }
556
557 var data = {};
558
559 if (typeof href === 'object') {
560 var form = href;
561
562 // extract query string from form action
563 var query = jQuery(form).attr('action').match(/(?:admin|index)\.php\?(.*?)$/);
564
565 data = href.serialize();
566 href = 'admin-ajax.php';
567
568 if (query) {
569 // append query string to HREF
570 href += '?' + query.pop();
571 } else {
572 // find the hidden input containing the option
573 var option = jQuery(form).find('input[type="hidden"][name="option"]').val();
574
575 if (option.length) {
576 href += '?action=' + option.replace(/^com_/, '');
577 }
578 }
579 } else if (typeof href === 'string') {
580 href = href.replace('index.php', 'admin-ajax.php');
581 href = href.replace('admin.php', 'admin-ajax.php');
582 }
583
584 setTimeout(() => {
585
586 doAjax(
587 href,
588 data,
589 (resp) => {
590
591 try {
592 resp = JSON.parse(resp);
593
594 if (Array.isArray(resp)) {
595 resp = resp.shift();
596 }
597 } catch (err) {
598 // the response is already plain HTML
599 }
600
601 // tries to fix any ID conflict
602 resp = makeResponseUnique(resp);
603
604 modalBody.removeClass('loading').html('<div class="modal-body">' + resp + '</div>');
605
606 // route targets for back-end only
607 if (JoomlaCore.isAdmin()) {
608 // replaces any index.php with admin.php
609 routePageTargets('#' + id);
610 }
611
612 ajaxPreventFormSubmit(id);
613 },
614 (resp) => {
615 modalBody.removeClass('loading');
616
617 alert(Joomla.JText._('CONNECTION_LOST'));
618 }
619 );
620
621 }, 128 + Math.random() * 512);
622
623 }
624
625 function makeResponseUnique(resp) {
626 resp = resp.replace(/adminForm/g, 'innerAdminForm');
627
628 return resp;
629 }
630
631 function ajaxPreventFormSubmit(id) {
632 jQuery('#' + id).find('form').on('submit', function(e) {
633 e.preventDefault();
634
635 /**
636 * Wait some milliseconds before submitting the form in order to
637 * allow the callbacks attached to the "submit" event to perform
638 * their tasks.
639 */
640 setTimeout(() => {
641 wpAppendModalContent(id, jQuery(this));
642 }, 64);
643
644 return false;
645 });
646
647 jQuery('#' + id).find('a[target!="_blank"]').filter('a:not([href^="javascript:"],[href^="mailto:"],[href^="tel:"],[href^="#"])').on('click', function(e) {
648 var href = jQuery(this).attr('href');
649
650 if (href) {
651 e.preventDefault();
652
653 wpAppendModalContent(id, href);
654 }
655
656 return false;
657 });
658
659 jQuery('#' + id).find('select[onchange^="document.innerAdminForm.submit"]').each(function() {
660 // turn off on change event
661 this.onchange = null;
662
663 jQuery(this).on('change', function(e) {
664 e.preventDefault();
665
666 // register new event to submit form via AJAX
667 wpAppendModalContent(id, jQuery(this).closest('form'));
668 });
669 });
670
671 // hide any buttons that clear the filters because there is no way
672 // to prevent them for being submitted
673 jQuery('#' + id).find('button[onclick^="clearFilters()"]').each(function(e) {
674 // turn off on click event
675 this.onclick = null;
676
677 jQuery(this).on('click', function(e) {
678 e.preventDefault();
679
680 // find all the search filters (input and select)
681 jQuery(this).closest('form').find('.btn-toolbar').find('input, select').each(function() {
682 if (jQuery(this).is('select')) {
683 // in case of a select, extract the value from the first option
684 var firstOptionValue = jQuery(this).find('option').first().val();
685 // update select value
686 jQuery(this).val(firstOptionValue);
687 } else {
688 // empty input text
689 jQuery(this).val('');
690 }
691 });
692
693 // submit form via AJAX
694 wpAppendModalContent(id, jQuery(this).closest('form'));
695 });
696 });
697 }
698
699 function routePageTargets(container) {
700 jQuery(container).find('a[href^="index.php"], form[action^="index.php"]').each(function() {
701 var attr;
702
703 if (jQuery(this).is('a')) {
704 attr = 'href';
705 } else {
706 attr = 'action';
707 }
708
709 var value = jQuery(this).attr(attr);
710
711 jQuery(this).attr(attr, value.replace(/^index\.php/, 'admin.php'));
712 });
713
714 jQuery(container).find('button[onclick^="document.location.href"]').each(function() {
715 // get current event string
716 var onclick = jQuery(this).attr('onclick');
717 // replace index.php into admin.php
718 onclick = onclick.replace(/index\.php/, 'admin.php');
719 // update element attribute
720 jQuery(this).attr('onclick', onclick);
721 });
722 }
723
724 /**
725 * Returns a promise that resolves when the specified instance
726 * gets defined.
727 *
728 * @param function check The callback to invoke to check whether the instance is ready.
729 * @param mixed threshold An optional threshold to establish the max number of attempts.
730 *
731 * @return Promise
732 */
733 function __isReady(check, threshold) {
734 return new Promise((resolve, reject) => {
735 // prepare safe counter
736 var count = 0;
737
738 var callback = function() {
739 // increase counter
740 count++;
741
742 // check whether the instance is ready
743 var instance = check();
744
745 if (instance) {
746 // object is now ready
747 resolve(instance);
748 } else {
749 if (!threshold || count < Math.abs(threshold)) {
750 // check again
751 setTimeout(callback, 32 + Math.floor(Math.random() * 128));
752 } else {
753 // instance not ready
754 reject();
755 }
756 }
757 };
758
759 // check
760 callback();
761 });
762 }
763
764 /**
765 * AJAX UTILS
766 */
767
768 function normalizePostData(data) {
769
770 if (data === undefined) {
771 data = {};
772 } else if (Array.isArray(data)) {
773 // the form data is serialized @see jQuery.serializeArray()
774 var form = data;
775
776 data = {};
777
778 for (var i = 0; i < form.length; i++) {
779 // if the field ends with [] it should be an array
780 if (form[i].name.endsWith("[]")) {
781 // if the field doesn't exist yet, create a new list
782 if (!data.hasOwnProperty(form[i].name)) {
783 data[form[i].name] = new Array();
784 }
785
786 // append the value to the array
787 data[form[i].name].push(form[i].value);
788 } else {
789 // otherwise overwrite the value (if any)
790 data[form[i].name] = form[i].value;
791 }
792 }
793 }
794
795 return data;
796 }
797
798 function doAjax(url, data, success, failure, attempt) {
799
800 var AJAX_MAX_ATTEMPTS = 3;
801
802 if (attempt === undefined) {
803 attempt = 1;
804 }
805
806 // return same object if data has been already normalized
807 data = normalizePostData(data);
808
809 return jQuery.ajax({
810 type: 'post',
811 url: url,
812 data: data
813 }).done(function(resp) {
814
815 if (success !== undefined) {
816 success(resp);
817 }
818
819 }).fail(function(err) {
820 // If the error has been raised by a connection failure,
821 // retry automatically the same request. Do not retry if the
822 // number of attempts is higher than the maximum number allowed.
823 if (attempt < AJAX_MAX_ATTEMPTS && isConnectionLostError(err)) {
824
825 // wait 128 milliseconds before launching the request
826 setTimeout(function() {
827 // relaunch same action and increase number of attempts by 1
828 doAjax(url, data, success, failure, attempt + 1);
829 }, 128);
830
831 } else {
832
833 // otherwise raise the failure method
834 if (failure !== undefined) {
835 failure(err);
836 }
837
838 }
839
840 console.log('failure', err);
841
842 if (err.status == 500) {
843 console.log(err.responseText);
844 }
845
846 });
847 }
848
849 function isConnectionLostError(err) {
850 return (
851 err.statusText == 'error'
852 && err.status == 0
853 && err.readyState == 0
854 && err.responseText == ''
855 );
856 }
857
858 /**
859 * BROWSER BACKWARD COMPATIBILITY
860 */
861
862 if (!Array.isArray) {
863 Array.isArray = function(arg) {
864 return Object.prototype.toString.call(arg) === '[object Array]';
865 }
866 }
867
868 /**
869 * Make Joomla object global or refresh its settings.
870 *
871 * @since 1.0
872 */
873 if (typeof Joomla === 'undefined') {
874 var Joomla = new JoomlaCore();
875 } else {
876 // reload options
877 JoomlaCore.loadOptions();
878 }
879