PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / admin / resources / js / system.js

system.js in VikBooking Hotel Booking Engine & PMS trunk, at admin/resources/js/system.js

780 lines 16.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 (task && form.task) {
56 form.task.value = task;
57 }
58
59 jQuery(form).submit();
60 }
61
62 JoomlaCore.prototype.submitbutton = function(task) {
63 this.submitform(task, document.adminForm);
64 }
65
66 JoomlaCore.prototype.tableOrdering = function(column, direction, task, form) {
67 if (form === undefined) {
68 form = document.adminForm;
69 }
70
71 if (form.filter_order === undefined) {
72 var orderInput = document.createElement('input');
73 orderInput.type = 'hidden';
74 orderInput.name = 'filter_order';
75
76 form.appendChild(orderInput);
77 }
78
79 form.filter_order.value = column;
80
81 if (form.filter_order_Dir === undefined) {
82 var directionInput = document.createElement('input');
83 directionInput.type = 'hidden';
84 directionInput.name = 'filter_order_Dir';
85
86 form.appendChild(directionInput);
87 }
88
89 form.filter_order_Dir.value = direction;
90
91 this.submitform(task, form);
92 }
93
94 JoomlaCore.getOptions = function(key, def) {
95 // load options if they not exists
96 if (!JoomlaCore.optionsStorage) {
97 JoomlaCore.loadOptions();
98 }
99
100 return JoomlaCore.optionsStorage[key] !== undefined ? JoomlaCore.optionsStorage[key] : def;
101 };
102
103 JoomlaCore.loadOptions = function(options) {
104 if (!options) {
105 var elements = jQuery('script.joomla-options.new');
106 var counter = 0;
107
108 for (var i = 0, l = elements.length; i < l; i++) {
109 var element = elements[i];
110 var str = element.text || element.textContent;
111 var option = {};
112
113 try {
114 option = JSON.parse(str);
115 } catch (err) {
116 console.log(err);
117 }
118
119 if (option) {
120 JoomlaCore.loadOptions(option);
121 counter++;
122 }
123
124 // mark element as loaded
125 jQuery(element).removeClass('new').addClass('loaded');
126 }
127
128 if (counter) {
129 return;
130 }
131 }
132
133 // initial loading
134 if (!JoomlaCore.optionsStorage) {
135 JoomlaCore.optionsStorage = options || {};
136 }
137 // Merge with existing
138 else if (options ) {
139 for (var p in options) {
140 if (options.hasOwnProperty(p)) {
141 JoomlaCore.optionsStorage[p] = options[p];
142 }
143 }
144 }
145 };
146
147 JoomlaCore.isAdmin = function() {
148 return document.location.href.match(/\/wp-admin\//i) ? true : false;
149 }
150
151 /**
152 * Pagination
153 */
154
155 function JPagination(total, limit, start, listener) {
156
157 if (total === undefined) {
158 total = 0;
159 }
160
161 if (limit === undefined) {
162 limit = 0;
163 }
164
165 if (start === undefined) {
166 start = 0;
167 }
168
169 if (listener === undefined) {
170 listener = null;
171 }
172
173 this.total = total;
174 this.limit = limit;
175 this.start = start;
176 this.prefix = '';
177
178 this.listener = listener;
179
180 return this;
181 }
182
183 JPagination.prototype.setTotal = function(total) {
184 this.total = total;
185
186 return this;
187 }
188
189 JPagination.prototype.setLimit = function(limit) {
190 this.limit = limit;
191
192 return this;
193 }
194
195 JPagination.prototype.setStart = function(start) {
196 this.start = start;
197
198 return this;
199 }
200
201 JPagination.prototype.setListener = function(listener) {
202 this.listener = listener;
203
204 return this;
205 }
206
207 JPagination.prototype.setPrefix = function(prefix) {
208 this.prefix = prefix || '';
209
210 return this;
211 }
212
213 JPagination.prototype.submit = function() {
214
215 if (this.listener[this.prefix + 'limitstart'] === undefined) {
216 var limitstart = document.createElement('input');
217 limitstart.type = 'hidden';
218 limitstart.name = this.prefix + 'limitstart';
219
220 this.listener.appendChild(limitstart);
221 }
222
223 if (this.listener[this.prefix + 'limit'] === undefined) {
224 var limit = document.createElement('input');
225 limit.type = 'hidden';
226 limit.name = this.prefix + 'limit';
227
228 this.listener.appendChild(limit);
229 }
230
231 this.listener[this.prefix + 'limitstart'].value = this.start;
232 this.listener[this.prefix + 'limit'].value = this.limit;
233
234 // submit through jQuery in order to
235 // properly emit the "submit" event
236 jQuery(this.listener).submit();
237 }
238
239 JPagination.prototype.first = function() {
240 this.start = 0;
241 this.submit();
242 }
243
244 JPagination.prototype.prev = function() {
245 this.start -= this.limit;
246 this.submit();
247 }
248
249 JPagination.prototype.next = function() {
250 this.start += this.limit;
251 this.submit();
252 }
253
254 JPagination.prototype.last = function() {
255 this.start = (Math.ceil(this.total / this.limit) - 1) * this.limit;
256 this.submit();
257 }
258
259 /**
260 * Text
261 */
262
263 function JText() {
264 this.strings = {};
265
266 return this;
267 }
268
269 JText.prototype._ = function(key, def) {
270 // check for new strings in the optionsStorage, and load them
271 var newStrings = JoomlaCore.getOptions('joomla.jtext');
272
273 if (newStrings) {
274 this.load(newStrings);
275
276 // Clean up the optionsStorage from useless data
277 JoomlaCore.loadOptions({'joomla.jtext': null});
278 }
279
280 def = def === undefined ? '' : def;
281 key = key.toUpperCase();
282
283 return this.strings[key] !== undefined ? this.strings[key] : def;
284 }
285
286 JText.prototype.load = function(object) {
287 for (var key in object) {
288 if (object.hasOwnProperty(key)) {
289 this.strings[key.toUpperCase()] = object[key];
290 }
291 }
292
293 return this;
294 }
295
296 /*
297 * FORM VALIDATION
298 */
299
300 function JFormValidator(form, clazz) {
301 this.form = form;
302
303 if (typeof clazz === 'undefined') {
304 clazz = 'invalid';
305 }
306
307 this.clazz = clazz;
308 this.labels = {};
309
310 // prevent the form submission on enter keydown
311
312 jQuery(this.form).on('keyup', function(e) {
313 var keyCode = e.keyCode || e.which;
314
315 if (keyCode === 13) {
316 e.preventDefault();
317 return false;
318 }
319 });
320
321 this.registerFields('.required');
322 }
323
324 JFormValidator.prototype.isValid = function(input) {
325 var val = jQuery(input).val();
326
327 return val !== null && val.length > 0;
328 }
329
330 JFormValidator.prototype.registerFields = function(selector) {
331
332 var _this = this;
333
334 jQuery(this.form).find(selector).on('blur', function() {
335 if (_this.isValid(this)) {
336 _this.unsetInvalid(this);
337 } else {
338 _this.setInvalid(this);
339 }
340 });
341
342 return this;
343 }
344
345 JFormValidator.prototype.unregisterFields = function(selector) {
346
347 jQuery(this.form).find(selector).off('blur')
348
349 return this;
350 }
351
352 JFormValidator.prototype.validate = function(callback) {
353 var ok = true;
354
355 var _this = this;
356
357 this.clearInvalidTabPane();
358
359 jQuery(this.form).find('.required:input').each(function() {
360 if (_this.isValid(this)) {
361 _this.unsetInvalid(this);
362 } else {
363 _this.setInvalid(this);
364 ok = false;
365
366 if (!jQuery(this).is(':visible')) {
367 // the input is probably hidden behind
368 // an unactive tab pane
369 _this.setInvalidTabPane(this);
370 }
371 }
372 });
373
374 if (typeof callback !== 'undefined') {
375 ok = callback() && ok;
376 }
377
378 return ok;
379 }
380
381 JFormValidator.prototype.setLabel = function(input, label) {
382 this.labels[jQuery(input).attr('name')] = label;
383
384 return this;
385 }
386
387 JFormValidator.prototype.getLabel = function(input) {
388 var name = jQuery(input).attr('name');
389
390 if (this.labels.hasOwnProperty(name)) {
391 return jQuery(this.labels[name]);
392 }
393
394 return jQuery(input).closest('.control').children().filter('b,label');
395 }
396
397 JFormValidator.prototype.setInvalid = function(input) {
398 jQuery(input).addClass(this.clazz);
399 this.getLabel(input).addClass(this.clazz);
400
401 return this;
402 }
403
404 JFormValidator.prototype.unsetInvalid = function(input) {
405 jQuery(input).removeClass(this.clazz);
406 this.getLabel(input).removeClass(this.clazz);
407
408 return this;
409 }
410
411 JFormValidator.prototype.isInvalid = function(input) {
412 return jQuery(input).hasClass(this.clazz);
413 }
414
415 JFormValidator.prototype.clearInvalidTabPane = function() {
416 jQuery('ul.nav-tabs li a').removeClass(this.clazz);
417
418 return this;
419 }
420
421 JFormValidator.prototype.setInvalidTabPane = function(input) {
422 var pane = jQuery(input).closest('.tab-pane');
423
424 if (pane.length) {
425 var id = jQuery(pane).attr('id');
426 var link = jQuery('ul.nav-tabs li a[href="#' + id + '"]');
427
428 if (link.length) {
429 link.addClass(this.clazz);
430 }
431 }
432
433 return this;
434 }
435
436 /**
437 * TRIGGER JMODAL
438 */
439
440 function wpOpenJModal(id, href, onShow, onHide) {
441
442 if (onShow !== undefined)
443 {
444 jQuery('#jmodal-' + id).on('show', onShow);
445 }
446
447 if (onHide !== undefined)
448 {
449 jQuery('#jmodal-' + id).on('hide', onHide);
450 }
451
452 if (!href) {
453 // try to extract url from modal URL input
454 href = jQuery('#jmodal-' + id + ' > input[name="url"]').val();
455 }
456
457 var hideOnEsc = null;
458
459 // check if the modal can be closed using the ESC button
460 if (jQuery('#jmodal-' + id).data('esc') == 1) {
461 hideOnEsc = function(event) {
462 if (event.keyCode == 27) {
463 // close modal when ESC is pressed
464 wpCloseJModal(id);
465 }
466 };
467
468 jQuery(window).on('keydown', hideOnEsc);
469 }
470
471 jQuery('#jmodal-' + id).on('hide.bs.modal', function() {
472 // we should remove the body only whether it has been loaded asynchronously
473 if (href) {
474 jQuery(this).find('.modal-body').remove();
475 }
476
477 jQuery('#jmodal-' + id).off('show.bs.modal');
478 jQuery('#jmodal-' + id).off('hide.bs.modal');
479
480 if (hideOnEsc) {
481 // turn off esc handler too after disposing the modal
482 jQuery(window).off('keydown', hideOnEsc);
483 }
484 });
485
486 // trigger "show" event to support external listeners
487 jQuery('#jmodal-' + id).modal('show').trigger('show');
488
489 var closeBtn = jQuery('#jmodal-' + id).find('button[data-dismiss]');
490
491 // add workaround to trigger hide|hidden events also when
492 // clicking the dismiss button of the modal
493 closeBtn.on('click', function() {
494 jQuery('#jmodal-' + id).trigger('hide').trigger('hidden').trigger('hide.bs.modal');
495 });
496
497 // hide on backdrop click only in case the modal is dismissable
498 if (closeBtn.length || hideOnEsc) {
499 jQuery('.modal-backdrop').on('click', function() {
500 wpCloseJModal(id);
501 });
502 }
503
504 if (href)
505 {
506 wpAppendModalContent('jmodal-box-' + id, href);
507 }
508 }
509
510 function wpCloseJModal(id) {
511 if (id.match(/^jmodal-/)) {
512 // full ID without "#"
513 id = "#" + id;
514 } else if (!id.match(/^#jmodal-/)) {
515 // modal ID only
516 id = "#jmodal-" + id;
517 }
518
519 // close modal and trigger hide|hidden events
520 jQuery(id).modal('hide').trigger('hide').trigger('hidden').trigger('hide.bs.modal');
521 }
522
523 function wpAppendModalContent(id, href) {
524
525 var data = {};
526
527 if (typeof href === 'object') {
528 data = href.serialize();
529 href = 'admin-ajax.php';
530 } else if (typeof href === 'string') {
531 href = href.replace('index.php', 'admin-ajax.php');
532 href = href.replace('admin.php', 'admin-ajax.php');
533 }
534
535 setTimeout(function() {
536
537 doAjax(
538 href,
539 data,
540 function(resp) {
541
542 try {
543 resp = JSON.parse(resp);
544
545 if (Array.isArray(resp)) {
546 resp = resp.shift();
547 }
548 } catch (err) {
549 // the response is already plain HTML
550 }
551
552 // tries to fix any ID conflict
553 resp = makeResponseUnique(resp);
554
555 jQuery('#' + id).html('<div class="modal-body">' + resp + '</div>');
556
557 // route targets for back-end only
558 if (JoomlaCore.isAdmin()) {
559 // replaces any index.php with admin.php
560 routePageTargets('#' + id);
561 }
562
563 ajaxPreventFormSubmit(id);
564 },
565 function(resp) {
566 alert(Joomla.JText._('CONNECTION_LOST'));
567 }
568 );
569
570 }, 128 + Math.random() * 512);
571
572 }
573
574 function makeResponseUnique(resp) {
575 resp = resp.replace(/adminForm/g, 'innerAdminForm');
576
577 return resp;
578 }
579
580 function ajaxPreventFormSubmit(id) {
581 jQuery('#' + id).find('form').on('submit', function(e) {
582 e.preventDefault();
583
584 wpAppendModalContent(id, jQuery(this));
585
586 return false;
587 });
588
589 jQuery('#' + id).find('a[target!="_blank"]').filter('a:not([href^="javascript:"],[href^="#"])').on('click', function(e) {
590 e.preventDefault();
591
592 wpAppendModalContent(id, jQuery(this).attr('href'));
593
594 return false;
595 });
596 }
597
598 function routePageTargets(container) {
599 jQuery(container).find('a[href^="index.php"], form[action^="index.php"]').each(function() {
600 var attr;
601
602 if (jQuery(this).is('a')) {
603 attr = 'href';
604 } else {
605 attr = 'action';
606 }
607
608 var value = jQuery(this).attr(attr);
609
610 jQuery(this).attr(attr, value.replace(/^index\.php/, 'admin.php'));
611 });
612
613 jQuery(container).find('button[onclick^="document.location.href"]').each(function() {
614 // get current event string
615 var onclick = jQuery(this).attr('onclick');
616 // replace index.php into admin.php
617 onclick = onclick.replace(/index\.php/, 'admin.php');
618 // update element attribute
619 jQuery(this).attr('onclick', onclick);
620 });
621 }
622
623 /**
624 * Returns a promise that resolves when the specified instance
625 * gets defined.
626 *
627 * @param function check The callback to invoke to check whether the instance is ready.
628 * @param mixed threshold An optional threshold to estabilish the max number of attempts.
629 *
630 * @return Promise
631 */
632 function __isReady(check, threshold) {
633 return new Promise((resolve, reject) => {
634 // prepare safe counter
635 var count = 0;
636
637 var callback = function() {
638 // increase counter
639 count++;
640
641 // check whether the instance is ready
642 var instance = check();
643
644 if (instance) {
645 // object is now ready
646 resolve(instance);
647 } else {
648 if (!threshold || count < Math.abs(threshold)) {
649 // check again
650 setTimeout(callback, 32 + Math.floor(Math.random() * 128));
651 } else {
652 // instance not ready
653 reject();
654 }
655 }
656 };
657
658 // check
659 callback();
660 });
661 }
662
663 /**
664 * AJAX UTILS
665 */
666
667 function normalizePostData(data) {
668
669 if (data === undefined) {
670 data = {};
671 } else if (Array.isArray(data)) {
672 // the form data is serialized @see jQuery.serializeArray()
673 var form = data;
674
675 data = {};
676
677 for (var i = 0; i < form.length; i++) {
678 // if the field ends with [] it should be an array
679 if (form[i].name.endsWith("[]")) {
680 // if the field doesn't exist yet, create a new list
681 if (!data.hasOwnProperty(form[i].name)) {
682 data[form[i].name] = new Array();
683 }
684
685 // append the value to the array
686 data[form[i].name].push(form[i].value);
687 } else {
688 // otherwise overwrite the value (if any)
689 data[form[i].name] = form[i].value;
690 }
691 }
692 }
693
694 return data;
695 }
696
697 function doAjax(url, data, success, failure, attempt) {
698
699 var AJAX_MAX_ATTEMPTS = 3;
700
701 if (attempt === undefined) {
702 attempt = 1;
703 }
704
705 // return same object if data has been already normalized
706 data = normalizePostData(data);
707
708 return jQuery.ajax({
709 type: 'post',
710 url: url,
711 data: data
712 }).done(function(resp) {
713
714 if (success !== undefined) {
715 success(resp);
716 }
717
718 }).fail(function(err) {
719 // If the error has been raised by a connection failure,
720 // retry automatically the same request. Do not retry if the
721 // number of attempts is higher than the maximum number allowed.
722 if (attempt < AJAX_MAX_ATTEMPTS && isConnectionLostError(err)) {
723
724 // wait 128 milliseconds before launching the request
725 setTimeout(function() {
726 // relaunch same action and increase number of attempts by 1
727 doAjax(url, data, success, failure, attempt + 1);
728 }, 128);
729
730 } else {
731
732 // otherwise raise the failure method
733 if (failure !== undefined) {
734 failure(err);
735 }
736
737 }
738
739 console.log('failure', err);
740
741 if (err.status == 500) {
742 console.log(err.responseText);
743 }
744
745 });
746 }
747
748 function isConnectionLostError(err) {
749 return (
750 err.statusText == 'error'
751 && err.status == 0
752 && (err.readyState == 0 || err.readyState == 4)
753 && (!err.hasOwnProperty('responseText') || err.responseText == '')
754 );
755 }
756
757 /**
758 * BROWSER BACKWARD COMPATIBILITY
759 */
760
761 if (!Array.isArray) {
762 Array.isArray = function(arg) {
763 return Object.prototype.toString.call(arg) === '[object Array]';
764 }
765 }
766
767 /**
768 * Joomla instance is now available on both admin and site sections.
769 * In order to avoid delays with the loading of this class, maybe because of lazy-loading
770 * techniques of the Theme with "deferred" scripts, we no longer use inline JS code.
771 *
772 * @since 1.4.0
773 */
774 if (typeof Joomla === 'undefined') {
775 var Joomla = new JoomlaCore();
776 } else {
777 // reload options
778 JoomlaCore.loadOptions();
779 }
780