PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 1.10.0
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v1.10.0
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / assets / js / admin / admin.js

admin.js in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 1.10.0, at assets/js/admin/admin.js

1,430 lines 58.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 "use strict";
2
3 ;
4 (function ($, window, document, undefined) {
5 'use strict';
6
7 var merchant = merchant || {};
8 var params = new URLSearchParams(window.location.search);
9 var currentModule = params.get('module');
10 $(document).ready(function () {
11 // AjaxSave
12 var $ajaxForm = $('.merchant-module-page-ajax-form');
13 var $ajaxHeader = $('.merchant-module-page-ajax-header');
14 var $ajaxSaveBtn = $('.merchant-module-save-button');
15 $('.merchant-module-page-content').on('change keypress change.merchant', function () {
16 if (!$(this).is('.merchant-module-question-answer-textarea, .merchant-license-code-input')) {
17 if (!merchant.show_save) {
18 $ajaxHeader.addClass('merchant-show');
19 $ajaxHeader.removeClass('merchant-saving');
20 merchant.show_save = true;
21 }
22 }
23 GroubField.initFlag();
24 });
25 $ajaxForm.ajaxForm({
26 beforeSubmit: function beforeSubmit() {
27 $ajaxHeader.addClass('merchant-saving');
28 },
29 success: function success() {
30 $ajaxHeader.removeClass('merchant-show');
31 merchant.show_save = false;
32
33 // Module Alert after Ajax Save
34 if (!$('.merchant-module-action').hasClass('merchant-enabled')) {
35 var $moduleAlert = $('.merchant-module-alert');
36 $moduleAlert.addClass('merchant-show');
37 $(document).off('click.merchant-alert-close');
38 $(document).on('click.merchant-alert-close', function (e) {
39 if (!$(e.target).closest('.merchant-module-alert-wrapper').length) {
40 $moduleAlert.removeClass('merchant-show');
41 $(document).off('click.merchant-alert-close');
42 }
43 });
44 }
45 $(document).trigger('save.merchant', [currentModule]);
46 }
47 });
48 var $disableModuleSubmitBtn = $('.merchant-module-question-answer-button');
49 var $disableModuleTextField = $('.merchant-module-question-answer-textarea');
50 $disableModuleTextField.on('input', function () {
51 $disableModuleSubmitBtn.prop('disabled', $(this).val().trim() === '');
52 });
53 $disableModuleSubmitBtn.on('click', function (e) {
54 e.preventDefault();
55 var message = $disableModuleTextField.val();
56 if (!message.trim()) {
57 alert('Please provide the required information.');
58 return;
59 }
60 var $button = $(this);
61 $('.merchant-module-question-answer-dropdown').removeClass('merchant-show');
62 $('.merchant-module-question-thank-you-dropdown').addClass('merchant-show');
63 window.wp.ajax.post('merchant_module_feedback', {
64 subject: $disableModuleTextField.attr('data-subject'),
65 message: message,
66 module: $button.closest('.merchant-module-action').find('.merchant-module-page-button-action-activate').data('module'),
67 nonce: window.merchant.nonce
68 });
69 });
70 $('.merchant-module-page-button-action-activate').on('click', function (e) {
71 e.preventDefault();
72 if ($(this).hasClass('merchant-module-deactivated-by-bp')) {
73 return false;
74 }
75 $('.merchant-module-question-list-dropdown').removeClass('merchant-show');
76 $('.merchant-module-question-answer-dropdown').removeClass('merchant-show');
77 $('.merchant-module-question-answer-form').removeClass('merchant-show');
78 $('.merchant-module-question-answer-title').removeClass('merchant-show');
79 $('.merchant-module-question-thank-you-dropdown').removeClass('merchant-show');
80 $('.merchant-module-question-answer-textarea').val('');
81 window.wp.ajax.post('merchant_module_activate', {
82 module: $(this).data('module'),
83 nonce: window.merchant.nonce
84 }).done(function () {
85 $('body').removeClass('merchant-module-disabled').addClass('merchant-module-enabled');
86 $('.merchant-module-action').addClass('merchant-enabled');
87 });
88 });
89 $('.merchant-module-page-button-action-deactivate').on('click', function (e) {
90 e.preventDefault();
91 window.wp.ajax.post('merchant_module_deactivate', {
92 module: $(this).data('module'),
93 nonce: window.merchant.nonce
94 }).done(function () {
95 $('body').removeClass('merchant-module-enabled').addClass('merchant-module-disabled');
96 $('.merchant-module-action').removeClass('merchant-enabled');
97 $('.merchant-module-question-list-dropdown').addClass('merchant-show');
98 });
99 });
100 $('.merchant-module-question-list-dropdown li').on('click', function (e) {
101 $disableModuleSubmitBtn.prop('disabled', $disableModuleTextField.val().trim() === '');
102 var $question = $(this);
103 var target = $question.data('answer-target');
104 var $answer = $('[data-answer-title="' + target + '"]');
105 if ($answer.length) {
106 $answer.addClass('merchant-show').siblings().removeClass('merchant-show');
107 $('.merchant-module-question-answer-dropdown').addClass('merchant-show');
108 $('.merchant-module-question-answer-textarea').attr('data-subject', $question.text().trim());
109 } else {
110 $('.merchant-module-question-thank-you-dropdown').addClass('merchant-show');
111 $('.merchant-module-question-answer-dropdown').removeClass('merchant-show');
112 }
113 $('.merchant-module-question-answer-textarea').val('');
114 $('.merchant-module-question-list-dropdown').removeClass('merchant-show');
115 });
116 $('.merchant-module-dropdown-close').on('click', function (e) {
117 e.preventDefault();
118 $(this).closest('.merchant-module-dropdown').removeClass('merchant-show');
119 });
120 $('.merchant-module-page-button-deactivate').on('click', function (e) {
121 e.preventDefault();
122 var $button = $(this);
123 var $dropdown = $('.merchant-module-deactivate-dropdown');
124 $dropdown.toggleClass('merchant-show');
125 $(document).off('click.merchant-close');
126 $(document).on('click.merchant-close', function (e) {
127 if (!$(e.target).closest('.merchant-module-deactivate').length) {
128 $dropdown.removeClass('merchant-show');
129 $(document).off('click.merchant-close');
130 }
131 });
132 });
133 $('.merchant-range').each(function () {
134 var $range = $(this);
135 var $rangeInput = $range.find('.merchant-range-input');
136 var $numberInput = $range.find('.merchant-range-number-input');
137 $rangeInput.on('change input merchant.range merchant-init.range', function (e) {
138 var $range = $(this);
139 var value = (e.type === 'merchant' ? $numberInput.val() : $range.val()) || 0;
140 var min = $range.attr('min') || 0;
141 var max = $range.attr('max') || 1;
142 var percentage = (value - min) / (max - min) * 100;
143 if ($('body').hasClass('rtl')) {
144 $range.css({
145 'background': 'linear-gradient(to left, #3858E9 0%, #3858E9 ' + percentage + '%, #ddd ' + percentage + '%, #ddd 100%)'
146 });
147 } else {
148 $range.css({
149 'background': 'linear-gradient(to right, #3858E9 0%, #3858E9 ' + percentage + '%, #ddd ' + percentage + '%, #ddd 100%)'
150 });
151 }
152 $rangeInput.val(value);
153 $numberInput.val(value);
154 }).trigger('merchant-init.range');
155 $numberInput.on('change input blur', function () {
156 if ($rangeInput.hasClass('merchant-range-input')) {
157 $rangeInput.val($(this).val()).trigger('merchant.range');
158 }
159 });
160 });
161 $(document).on('click', '.merchant-module-page-setting-field-hidden-desc-trigger', function () {
162 var $trigger = $(this);
163 $trigger.toggleClass('expanded');
164 var showText = $trigger.attr('data-show-text');
165 var hiddenText = $trigger.attr('data-hidden-text');
166 $(this).find('span:first').text($trigger.text() === showText ? hiddenText : showText);
167 $(this).closest('.merchant-module-page-setting-field').find('.merchant-module-page-setting-field-hidden-desc').stop(true, true).slideToggle('fast');
168 });
169
170 // Add support for toggle field inside flexible content.
171 var flexibleToggleField = {
172 init: function init(field) {
173 this.events();
174 },
175 events: function events() {
176 $(document).on('click', '.merchant-flexible-content .merchant-toggle-switch .toggle-switch-label span', function () {
177 var checkBox = $(this).closest('.merchant-toggle-switch').find('.toggle-switch-checkbox');
178 checkBox.prop('checked', !checkBox.prop('checked'));
179 }).trigger('merchant.change');
180 }
181 };
182 var dateTimePickerField = {
183 init: function init() {
184 this.initiate_datepicker();
185 this.events();
186 },
187 initiate_datepicker: function initiate_datepicker() {
188 var elements = $('.merchant-module-page-setting-field .merchant-datetime-field');
189 if (elements.length === 0) {
190 return;
191 }
192 elements.each(function () {
193 var input = $(this).find('input'),
194 options = {
195 locale: JSON.parse(merchant_datepicker_locale),
196 selectedDates: [input.val() ? new Date(input.val()) : ''],
197 onSelect: function onSelect(_ref) {
198 var date = _ref.date,
199 formattedDate = _ref.formattedDate,
200 datepicker = _ref.datepicker;
201 if (typeof formattedDate === "undefined") {
202 // allow removing date
203 input.val('');
204 }
205 input.trigger('change.merchant');
206 input.trigger('change.merchant-datepicker', [formattedDate, input]);
207 }
208 },
209 fieldOptions = $(this).data('options');
210 // add buttons to fieldOptions
211 fieldOptions.buttons = ['clear'];
212 if (fieldOptions) {
213 if (fieldOptions.minDate !== undefined && fieldOptions.minDate === 'today') {
214 fieldOptions.minDate = new Date();
215 if (fieldOptions.timeZone !== undefined && fieldOptions.timeZone !== '') {
216 fieldOptions.minDate = new Date(fieldOptions.minDate.toLocaleString('en-US', {
217 timeZone: fieldOptions.timeZone
218 }));
219 }
220 }
221 console.log(fieldOptions.timeZone);
222 options = Object.assign(options, fieldOptions);
223 }
224 new AirDatepicker(input.getPath(), options);
225 input.attr('readonly', true);
226 });
227 },
228 events: function events() {
229 var self = this;
230 $(document).on('merchant-flexible-content-added', function () {
231 self.initiate_datepicker();
232 });
233 }
234 };
235 dateTimePickerField.init();
236
237 // Sortable.
238 var SortableField = {
239 init: function init(field) {
240 this.events();
241 },
242 events: function events() {
243 var self = this;
244 $('.merchant-sortable').each(function () {
245 var field = $(this),
246 input = field.find('.merchant-sortable-input');
247
248 // Init sortable.
249 $(field.find('ul.merchant-sortable-list').first()).sortable({
250 // Update value when we stop sorting.
251 update: function update() {
252 input.val(self.sortableGetNewVal(field)).trigger('change.merchant');
253 }
254 }).disableSelection().find('li').each(function () {
255 // Enable/disable options when we click on the eye of Thundera.
256 $(this).find('i.visibility').click(function () {
257 $(this).toggleClass('dashicons-visibility-faint').parents('li:eq(0)').toggleClass('invisible');
258 });
259 }).click(function () {
260 // Update value when click in the eye.
261 if ($(event.target).hasClass('dashicons-visibility')) {
262 input.val(self.sortableGetNewVal(field)).trigger('change.merchant');
263 }
264 });
265 });
266 },
267 sortableGetNewVal: function sortableGetNewVal(field) {
268 var items = $(field.find('li'));
269 var newVal = [];
270 _.each(items, function (item) {
271 if (!$(item).hasClass('invisible')) {
272 newVal.push($(item).data('value'));
273 }
274 });
275 return JSON.stringify(newVal);
276 }
277 };
278
279 // Intialize Sortable.
280 SortableField.init();
281 flexibleToggleField.init();
282
283 // Sortable Repeater.
284 var SortableRepeaterField = {
285 init: function init(field) {
286 var self = this;
287
288 // Update the values for all our input fields and initialise the sortable repeater.
289 $('.merchant-sortable-repeater-control').each(function () {
290 // If there is an existing customizer value, populate our rows
291 var defaultValuesArray = JSON.parse($(this).find('.merchant-sortable-repeater-input').val());
292 var numRepeaterItems = defaultValuesArray.length;
293 if (numRepeaterItems > 0) {
294 // Add the first item to our existing input field
295 $(this).find('.repeater-input').val(defaultValuesArray[0]);
296
297 // Create a new row for each new value
298 if (numRepeaterItems > 1) {
299 var i;
300 for (i = 1; i < numRepeaterItems; ++i) {
301 self.appendRow($(this), defaultValuesArray[i]);
302 }
303 }
304 }
305
306 // Make our Repeater fields sortable.
307 if (!$(this).hasClass('disable-sorting')) {
308 $(this).find('.merchant-sortable-repeater.sortable').sortable({
309 update: function update(event, ui) {
310 self.getAllInputs($(this).parent());
311 }
312 });
313 }
314 });
315
316 // Events.
317 this.events();
318 },
319 events: function events() {
320 var self = this;
321
322 // Remove item starting from its parent element
323 $('.merchant-sortable-repeater.sortable').on('click', '.customize-control-sortable-repeater-delete', function (event) {
324 event.preventDefault();
325 $(this).parent().slideUp('fast', function () {
326 var parentContainer = $(this).parent().parent();
327 $(this).remove();
328 self.getAllInputs(parentContainer);
329 });
330 });
331
332 // Add new item
333 $('.customize-control-sortable-repeater-add').click(function (event) {
334 event.preventDefault();
335 self.appendRow($(this).parent());
336 self.getAllInputs($(this).parent());
337 });
338
339 // Refresh our hidden field if any fields change
340 $('.merchant-sortable-repeater.sortable').change(function () {
341 self.getAllInputs($(this).parent());
342 });
343 $('.merchant-sortable-repeater.sortable').on('focusout', '.repeater-input', function () {
344 self.getAllInputs($(this).parent());
345 });
346 },
347 /**
348 * Append a new row to our list of elements.
349 *
350 */
351 appendRow: function appendRow($element) {
352 var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
353 var newRow = '<div class="repeater" style="display:none"><input type="text" value="' + defaultValue + '" class="repeater-input" /><span class="dashicons dashicons-menu"></span><a class="customize-control-sortable-repeater-delete" href="#"><span class="dashicons dashicons-no-alt"></span></a></div>';
354 $element.find('.sortable').append(newRow);
355 $element.find('.sortable').find('.repeater:last').slideDown('slow', function () {
356 $(this).find('input').focus();
357 });
358 },
359 /**
360 * Get the values from the repeater input fields and add to our hidden field.
361 *
362 */
363 getAllInputs: function getAllInputs($element) {
364 var inputValues = $element.find('.repeater-input').map(function () {
365 return $(this).val();
366 }).toArray();
367
368 // Keep one empty item if all deleted.
369 if (!inputValues.length) {
370 inputValues.push('');
371 }
372
373 // Add all the values from our repeater fields to the hidden field (which is the one that actually gets saved)
374 $element.find('.merchant-sortable-repeater-input').val(JSON.stringify(inputValues));
375 // Important! Make sure to trigger change event so Customizer knows it has to save the field
376 $element.find('.merchant-sortable-repeater-input').trigger('change');
377 }
378 };
379
380 // Initialize Sortable Repeater.
381 SortableRepeaterField.init();
382 var GroubField = {
383 init: function init() {
384 var self = this;
385 self.initAccordion();
386 self.initFlag();
387 },
388 initAccordion: function initAccordion() {
389 var self = this;
390 $('.merchant-group-field.has-accordion').each(function () {
391 var element = $(this);
392 element.accordion({
393 collapsible: true,
394 header: "> .title-area",
395 heightStyle: "content",
396 active: element.hasClass('open') ? 0 : false
397 });
398 });
399 },
400 initFlag: function initFlag() {
401 $('.merchant-group-field.has-flag').each(function () {
402 var element = $(this);
403 var field_id = element.data('id');
404 var status_field = element.find(".merchant-field-".concat(field_id, "_status select"));
405 var selected_value = status_field.val();
406 var selected_label = status_field.find('option:selected').text();
407 var status_element = element.find('.field-status');
408 status_element.removeClass('hidden active inactive').text(selected_label).addClass(selected_value);
409 });
410 }
411 };
412
413 // Flexible Content.
414 var FlexibleContentField = {
415 init: function init(field) {
416 var self = this;
417
418 // Update the values for all our input fields and initialise the sortable repeater.
419 $('.merchant-flexible-content-control').each(function () {
420 var hasAccordion = $(this).hasClass('has-accordion'),
421 $content = $(this).find('.merchant-flexible-content');
422 if (hasAccordion) {
423 $content.accordion({
424 collapsible: true,
425 //header: "> div > .layout-header",
426 header: function header(elem) {
427 return elem.find('.layout__inner > .layout-header');
428 },
429 heightStyle: "content"
430 }).sortable({
431 axis: 'y',
432 cursor: 'move',
433 helper: 'original',
434 handle: '.customize-control-flexible-content-move',
435 stop: function stop(event, ui) {
436 $content.trigger('merchant.sorted');
437 self.refreshNumbers($content);
438 $content.accordion("refresh");
439 }
440 });
441 } else {
442 $content.sortable({
443 axis: 'y',
444 cursor: 'move',
445 helper: 'original',
446 handle: '.customize-control-flexible-content-move',
447 stop: function stop(event, ui) {
448 $content.trigger('merchant.sorted');
449 self.refreshNumbers($content);
450 $content.accordion("refresh");
451 }
452 });
453 }
454 });
455 this.updateLayoutTitle();
456 this.updateDiscountPercentMaxVal();
457 // Events.
458 this.events();
459 },
460 updateLayoutTitle: function updateLayoutTitle() {
461 // Update the title for all layout header.
462 $('.merchant-flexible-content .layout').each(function () {
463 var title = $(this).find('.layout-title[data-title-field]');
464 if (title.length) {
465 var input = $(this).find('.layout-body .merchant-field-' + title.data('title-field') + ' input');
466 input.on('change keyup', function () {
467 title.text($(this).val());
468 });
469 title.text(input.val());
470 }
471 });
472 },
473 updateDiscountPercentMaxVal: function updateDiscountPercentMaxVal() {
474 $('.merchant-flexible-content .layout').each(function () {
475 var $layout = $(this);
476 var $discountType = $layout.find('.merchant-module-page-setting-field[data-id="discount_type"]');
477 var $discountVal = $layout.find('.merchant-module-page-setting-field[data-id="discount_value"]');
478 $discountVal = $discountVal.length ? $discountVal : $layout.find('.merchant-module-page-setting-field[data-id="discount"]');
479 $discountVal = $discountVal.length ? $discountVal : $layout.find('.merchant-module-page-setting-field[data-id="discount_amount"]');
480 var checkedValue = $discountType.find('input:checked').val();
481
482 // Set/Remove max value based on the discount type.
483 checkedValue === 'percentage_discount' || checkedValue === 'percentage' ? $discountVal.find('input').attr('max', 100) : $discountVal.find('input').removeAttr('max');
484 });
485 $('.merchant-module-page-setting-fields');
486 },
487 events: function events() {
488 var self = this;
489 $(document).on('change', '.merchant-module-page-setting-field[data-id="discount_type"] input', function () {
490 self.updateDiscountPercentMaxVal();
491 });
492
493 // Update "selected" attribute on select. It's Required for duplicating layouts.
494 $(document).on('change', 'select', function () {
495 var selectedValue = $(this).val();
496 var isMultiple = $(this).prop('multiple');
497 $(this).find('option').each(function () {
498 var currentValue = $(this).val();
499 var isSelected = isMultiple ? selectedValue.includes(currentValue) : currentValue === selectedValue;
500 $(this).attr('selected', isSelected);
501 });
502 });
503 $('.customize-control-flexible-content-add-button').click(function (event) {
504 event.preventDefault();
505 event.stopImmediatePropagation();
506 if ($(this).parent().find('.customize-control-flexible-content-add-list a').length === 1) {
507 // If there is only one layout, trigger click on it.
508 $(this).parent().find('.customize-control-flexible-content-add-list a').trigger('click');
509 return;
510 }
511 $(this).parent().find('.customize-control-flexible-content-add-list').toggleClass('active');
512 });
513
514 // Add new item
515 $(document).on('click', '.customize-control-flexible-content-add', function (event) {
516 event.preventDefault();
517 event.stopImmediatePropagation();
518 var $field = $('.merchant-flexible-content-control[data-id=' + $(this).data('id') + ']');
519 var $layouts = $field.find('.layouts');
520 var $selected = $(this).data('layout');
521 var $layout = $layouts.find('.layout[data-type=' + $selected + ']').clone(true);
522 var $content = $field.find('.merchant-flexible-content');
523 var $items = $content.find('.layout');
524 $layout.find('input, select, textarea').each(function () {
525 if ($(this).data('name')) {
526 $(this).attr('name', $(this).data('name').replace('0', $items.length));
527 }
528 if ($(this).is(':checkbox, :radio') && $(this).attr('checked')) {
529 $(this).prop('checked', true);
530 }
531 });
532 $layout.find('.layout-count').text($items.length + 1);
533 $content.append($layout);
534 $content.removeClass('empty');
535 $(this).parent().removeClass('active');
536 if ($layout.find('.merchant-module-page-setting-field-upload').length) {
537 initUploadField($layout.find('.merchant-module-page-setting-field-upload'));
538 }
539 if ($layout.find('.merchant-module-page-setting-field-select_ajax').length) {
540 initSelectAjax($layout.find('.merchant-module-page-setting-field-select_ajax'));
541 }
542 var parentDiv = $(this).closest('.merchant-flexible-content-control'),
543 hasAccordion = parentDiv.hasClass('has-accordion');
544 if (hasAccordion) {
545 parentDiv.find('.merchant-flexible-content').accordion("refresh");
546 // Expand the accordion last added
547 parentDiv.find('.merchant-flexible-content').accordion("option", "active", -1);
548 }
549 GroubField.init();
550 $(document).trigger('merchant-flexible-content-added', [$layout]);
551 self.updateLayoutTitle();
552 self.updateDiscountPercentMaxVal();
553 });
554
555 // Duplicate item
556 $(document).on('click', '.customize-control-flexible-content-duplicate', function (event) {
557 event.preventDefault();
558 event.stopImmediatePropagation();
559 var $duplicateBtn = $(this);
560 var $flexibleContentWrapper = $duplicateBtn.closest('.merchant-flexible-content-control[data-id=' + $duplicateBtn.data('id') + ']');
561 var $flexibleContent = $flexibleContentWrapper === null || $flexibleContentWrapper === void 0 ? void 0 : $flexibleContentWrapper.find('.merchant-flexible-content');
562 if (!$flexibleContentWrapper.length || !$flexibleContent.length) {
563 return;
564 }
565 var $sourceLayout = $duplicateBtn.closest('.layout');
566 if (!$sourceLayout.length) {
567 return;
568 }
569 $sourceLayout.find('.layout-actions__inner').hide();
570
571 // Clone the layout without data & events.
572 var $clonedLayout = $sourceLayout.clone();
573 var $items = $flexibleContent.find('.layout');
574 var index = $sourceLayout.find('.layout-count').text();
575 $clonedLayout.find('input, select, textarea').each(function () {
576 var $input = $(this);
577 var inputName = $input.attr('name');
578 if (inputName) {
579 var prefix = inputName.split('[')[0];
580 var indexPart = inputName.match(/\[(.*?)\]/g);
581 if (indexPart && indexPart.length > 1) {
582 indexPart[1] = '[' + index + ']';
583 var newName = "".concat(prefix).concat(indexPart.join(''));
584 $input.attr('name', newName);
585 }
586 }
587 });
588
589 // Find select2, Remove and Re-init again. select.select2('destroy') doesn't work.
590 $clonedLayout.find('select').each(function () {
591 if ($(this).hasClass('select2-hidden-accessible')) {
592 $(this).removeClass('select2-hidden-accessible').removeAttr('data-live-search').removeAttr('data-select2-id').removeAttr('aria-hidden').removeAttr('tabindex');
593
594 // Remove the existing dropdown
595 $(this).nextAll('.select2-container').remove();
596
597 // Re-init
598 $(this).select2();
599 }
600 });
601
602 // Removing copied style to make the accordion work properly.
603 $clonedLayout.find('.layout-body').removeAttr('style');
604
605 // Append the cloned layout right after the source one with fadeIn effect.
606 $clonedLayout.hide();
607 $clonedLayout.insertAfter($sourceLayout);
608 $clonedLayout.fadeIn();
609 if ($clonedLayout.find('.merchant-module-page-setting-field-upload').length) {
610 initUploadField($clonedLayout.find('.merchant-module-page-setting-field-upload'));
611 }
612 if ($clonedLayout.find('.merchant-module-page-setting-field-select_ajax').length) {
613 initSelectAjax($clonedLayout.find('.merchant-module-page-setting-field-select_ajax'));
614 }
615 self.refreshNumbers($flexibleContent);
616 $(document).trigger('merchant-flexible-content-added', [$clonedLayout]);
617 if ($flexibleContentWrapper.hasClass('has-accordion')) {
618 $flexibleContent.accordion('refresh');
619 }
620 self.updateLayoutTitle();
621 GroubField.init();
622 });
623
624 // Delete item
625 $(document).on('click', '.customize-control-flexible-content-delete', function (event) {
626 event.preventDefault();
627 var $item = $(this).closest('.layout');
628 var $content = $item.parent();
629 $item.remove();
630 if ($content.find('.layout').length === 0) {
631 $content.addClass('empty');
632 }
633 self.refreshNumbers($content);
634 $(document).trigger('merchant-flexible-content-deleted', [$item]);
635 var parentDiv = $(this).closest('.merchant-flexible-content-control'),
636 hasAccordion = parentDiv.hasClass('has-accordion');
637 if (hasAccordion) {
638 parentDiv.find('.merchant-flexible-content').accordion("refresh");
639 }
640 $(document).trigger('change.merchant');
641 });
642
643 // Toggle Actions(delete/duplicate)
644 $(document).on('click', '.layout-actions__toggle', function (e) {
645 e.preventDefault();
646
647 // Hide other opened elements
648 hideOtherActions($(this).closest('.layout'));
649
650 // Toggle the current element
651 $(this).closest('.layout-actions').find('.layout-actions__inner').stop().slideToggle(300);
652 });
653
654 // Hide Actions when collapse/open
655 $(document).on('click', '.layout-header', function () {
656 hideOtherActions($(this).closest('.layout'));
657 });
658 $(document).on('merchant-flexible-content-added', function (e, $layout) {
659 hideOtherActions($layout);
660 });
661 function hideOtherActions($layout) {
662 if ($layout && $layout.length) {
663 $layout.siblings().find('.layout-actions__inner').slideUp(300);
664 }
665 }
666 },
667 refreshNumbers: function refreshNumbers($content) {
668 $content.find('.layout').each(function (index) {
669 var $count = $(this).find('.layout-count').text();
670 var $inputIndex = parseInt($count) - 1;
671 $(this).find('.layout-count').text(index + 1);
672 $(this).find('input, select, textarea').each(function () {
673 if ($(this).attr('name')) {
674 $(this).attr('name', $(this).attr('name').replace('[' + $inputIndex + ']', '[*refreshed*' + index + ']'));
675 }
676 });
677 });
678 $content.find('.layout').each(function (index) {
679 $(this).find('input, select, textarea').each(function () {
680 // We've added *refreshed* to the attribute name in the prior loop as refreshing the numbers in the attribute can cause
681 // checked boxes to be unchecked due to similar attribute names during the change while sorting, within this loop we remove them
682 var nameAttr = $(this).attr('name');
683 if (nameAttr) {
684 // Check if name attribute exists
685 $(this).attr('name', nameAttr.replace('*refreshed*', ''));
686 }
687 });
688 });
689 $content.parent().find('input').trigger('change.merchant');
690 }
691 };
692
693 // Initialize Flexible Content.
694 FlexibleContentField.init();
695 GroubField.init();
696
697 // Products selector.
698 // Handle keyup event for the search input
699 var debounceTimer;
700 $(document).on('keyup', '.merchant-module-page-setting-field-products_selector .merchant-search-field', function () {
701 clearTimeout(debounceTimer);
702 var categories = [];
703 var $excluded = $(this).closest('[data-id="excluded_products"]');
704 if ($excluded.length) {
705 var $layout = $(this).closest('.layout');
706 var rules = $layout.find('.merchant-field-rules_to_apply select').val() || $layout.find('.merchant-field-rules_to_display select').val() || $layout.find('.merchant-field-display_rules select').val();
707 if (rules === 'categories' || rules === 'by_category') {
708 categories = $layout.find('.merchant-field-category_slugs select').val() || $layout.find('.merchant-field-product_cats select').val();
709 }
710 }
711 var parent = $(this).closest('.merchant-products-search-container');
712 if ($(this).val() !== '') {
713 parent.find('.merchant-searching').addClass('active');
714 var data = {
715 action: 'merchant_admin_products_search',
716 nonce: merchant_admin_options.ajaxnonce,
717 keyword: $(this).val(),
718 product_types: $(this).data('allowed-types'),
719 ids: parent.find('.merchant-selected-products').val(),
720 categories: categories
721 };
722 debounceTimer = setTimeout(function () {
723 $.post(merchant_admin_options.ajaxurl, data, function (response) {
724 var results = parent.find('.merchant-selections-products-preview');
725 results.show();
726 results.html(response);
727 parent.find('.merchant-searching').removeClass('active');
728 });
729 }, 250);
730 } else {
731 parent.find('.merchant-selections-products-preview').html('').hide();
732 }
733 });
734
735 // Products selector.
736 // Handle click/touch event for the search results
737 $(document).on('click touch', '.merchant-module-page-setting-field-products_selector .merchant-selections-products-preview li', function () {
738 var parent = $(this).closest('.merchant-products-search-container'),
739 valueField = parent.find('.merchant-selected-products'),
740 oldValue = valueField.val(),
741 multiple = parent.data('multiple') === 'multiple';
742 if (parent.find('.merchant-selected-products-preview ul li').length > 0 && !multiple) {
743 // replace the first item
744 parent.find('.merchant-selected-products-preview ul li').remove();
745 valueField.val('').change();
746 }
747 $(this).children('.remove').attr('aria-label', 'Remove').html('×');
748 parent.find('.merchant-selected-products-preview ul').append($(this));
749 parent.find('.merchant-selections-products-preview').html('').hide();
750 parent.find('.merchant-search-field').val('').change();
751 if (oldValue === '') {
752 valueField.val($(this).data('id'));
753 } else {
754 if (!multiple) {
755 valueField.val($(this).data('id')).change();
756 } else {
757 var newValue = oldValue.split(',');
758 newValue.push($(this).data('id'));
759 valueField.val(newValue.join(',')).change();
760 }
761 }
762 });
763
764 // Products selector.
765 // Handle click/touch event for the remove button.
766 $(document).on('click touch', '.merchant-selected-products-preview .remove', function () {
767 // Store a reference to the remove button
768 var removeButton = $(this);
769 // Ask for confirmation before removing the product
770 if (confirm(merchant_admin_options.product_delete_confirmation_message)) {
771 var parent = removeButton.closest('.merchant-products-search-container'),
772 valueField = parent.find('.merchant-selected-products'),
773 id = removeButton.parent().data('id');
774 removeButton.parent().remove();
775 var currentValue = valueField.val().split(',');
776 if (currentValue.length > 0) {
777 for (var key in currentValue) {
778 if (parseInt(currentValue[key]) === parseInt(id)) {
779 currentValue.splice(key, 1);
780 }
781 }
782 }
783 valueField.val(currentValue.join(',')).change();
784 valueField.trigger('change.merchant');
785 }
786 });
787 $(document).on('merchant-admin-check-fields merchant-flexible-content-added', function () {
788 $('.merchant-module-page-setting-field').each(function () {
789 var $field = $(this);
790 if ($field.data('condition') && $field.data('condition').length) {
791 var condition = $field.data('condition');
792 var $target = $(this).closest('.layout-body').find('input[name*="' + condition[0] + '"],select[name*="' + condition[0] + '"]');
793 if (!$target.length) {
794 $target = $('input[name="merchant[' + condition[0] + ']"],select[name="merchant[' + condition[0] + ']"]');
795 }
796 if ($target.length) {
797 var passed = false;
798 switch (condition[1]) {
799 case '==':
800 if ($target.attr('type') === 'radio' || $target.attr('type') === 'checkbox') {
801 var checked = $target.parent().find('input:checked');
802 if (checked.length && checked.val() === condition[2]) {
803 passed = true;
804 }
805 }
806 if ($target.is('select') && $target.val() == condition[2]) {
807 passed = true;
808 }
809 break;
810 case 'any':
811 if ($target.attr('type') === 'radio' || $target.attr('type') === 'checkbox') {
812 var _checked = $target.parent().find('input:checked');
813 if (_checked.length && condition[2].split('|').includes(_checked.val())) {
814 passed = true;
815 }
816 }
817 if ($target.is('select') && condition[2].split('|').includes($target.val())) {
818 passed = true;
819 }
820 break;
821 }
822 if (passed) {
823 $field.removeClass('merchant-hide').addClass('merchant-show');
824 } else {
825 $field.removeClass('merchant-show').addClass('merchant-hide');
826 }
827 }
828 }
829 });
830 }).trigger('merchant.change');
831 $(document).on('merchant-admin-check-fields merchant-flexible-content-added keyup', function () {
832 $('.merchant-module-page-setting-field').each(function () {
833 var $field = $(this);
834 if ($field.data('conditions')) {
835 var conditions = $field.data('conditions'),
836 passed = evaluateConditions(conditions, $field);
837 if (passed) {
838 $field.removeClass('merchant-hide').addClass('merchant-show');
839 } else {
840 $field.removeClass('merchant-show').addClass('merchant-hide');
841 }
842 }
843 });
844 }).trigger('merchant.change');
845 $(document).on('change', '.merchant-module-page-setting-field', function () {
846 $(document).trigger('merchant-admin-check-fields');
847 }).trigger('merchant.change');
848 $(document).trigger('merchant-admin-check-fields');
849 $(document).on('merchant-admin-check-color-fields merchant-flexible-content-added', function () {
850 $('.merchant-color').each(function () {
851 var $color = $(this);
852 var $picker = $color.find('.merchant-color-picker');
853 var $input = $color.find('.merchant-color-input');
854 var inited = false;
855 var pickr;
856 $picker.off('click').on('click', function (e) {
857 e.preventDefault();
858 e.stopPropagation();
859 var $bodyHTML = $('body,html');
860 $bodyHTML.addClass('merchant-height-auto');
861 if (!inited) {
862 pickr = new Pickr({
863 el: $picker.get(0),
864 container: 'body',
865 theme: 'merchant',
866 appClass: 'merchant-pcr-app',
867 default: $input.val() || $picker.data('default-color') || '#212121',
868 swatches: ['#000000', '#F44336', '#E91E63', '#673AB7', '#03A9F4', '#8BC34A', '#FFEB3B', '#FFC107', '#FFFFFF'],
869 sliders: 'h',
870 useAsButton: true,
871 components: {
872 hue: true,
873 preview: true,
874 opacity: true,
875 interaction: {
876 input: true,
877 clear: true
878 }
879 },
880 i18n: {
881 'btn:clear': 'Default'
882 }
883 });
884 pickr.on('change', function (color) {
885 var colorCode;
886 if (color.a === 1) {
887 pickr.setColorRepresentation('HEX');
888 colorCode = color.toHEXA().toString(0);
889 } else {
890 pickr.setColorRepresentation('RGBA');
891 colorCode = color.toRGBA().toString(0);
892 }
893 $picker.css({
894 'background-color': colorCode
895 });
896 if ($input.val() !== colorCode) {
897 $input.val(colorCode).trigger('change.merchant');
898 }
899 $(document).trigger('merchant-color-picker-updated', [colorCode, $input]);
900 });
901 pickr.on('clear', function () {
902 var defaultColor = $picker.data('default-color');
903 if (defaultColor) {
904 pickr.setColor(defaultColor);
905 } else {
906 $picker.css({
907 'background-color': 'white'
908 });
909 $input.val('');
910 }
911 });
912 pickr.on('hide', function () {
913 $bodyHTML.removeClass('merchant-height-auto');
914 });
915 $picker.data('pickr', pickr);
916 setTimeout(function () {
917 pickr.show();
918 }, 200);
919 inited = true;
920 } else {
921 pickr.setColor($input.val());
922 }
923 });
924 $input.on('change keyup', function () {
925 var colorCode = $(this).val();
926 $picker.css({
927 'background-color': colorCode
928 });
929 });
930 });
931 });
932 $(document).trigger('merchant-admin-check-color-fields');
933
934 // Create Page Control.
935 var CreatePageControl = {
936 init: function init() {
937 this.events();
938 },
939 events: function events() {
940 var self = this;
941 $(document).on('click', '.merchant-create-page-control-button', function (e) {
942 e.preventDefault();
943 var $this = $(this),
944 $create_message = $this.parent().find('.merchant-create-page-control-create-message'),
945 $success_message = $this.parent().find('.merchant-create-page-control-success-message'),
946 initial_text = $this.text(),
947 creating_text = $this.data('creating-text'),
948 created_text = $this.data('created-text'),
949 page_title = $this.data('page-title'),
950 page_meta_key = $this.data('page-meta-key'),
951 page_meta_value = $this.data('page-meta-value'),
952 option_name = $this.data('option-name'),
953 nonce = $this.data('nonce');
954 if (!page_title) {
955 return false;
956 }
957 $(this).text(creating_text);
958 $(this).attr('disabled', true);
959 $.ajax({
960 type: 'post',
961 url: ajaxurl,
962 data: {
963 action: 'merchant_create_page_control',
964 page_title: page_title,
965 page_meta_key: page_meta_key,
966 page_meta_value: page_meta_value,
967 option_name: option_name,
968 nonce: nonce
969 },
970 success: function success(response) {
971 self.ajaxResponseHandler(response, $this, $success_message, $create_message);
972 }
973 });
974 });
975 },
976 ajaxResponseHandler: function ajaxResponseHandler(response, $this, $success_message, $create_message) {
977 if ('success' === response.status) {
978 var href = $success_message.find('a').attr('href'),
979 newhref = href.replace('?post=&', '?post=' + response.page_id + '&');
980 $success_message.find('a').attr('href', newhref);
981 $success_message.css('display', 'block');
982 $create_message.remove();
983 $this.remove();
984 }
985 }
986 };
987
988 // Initialize Create Page Control.
989 CreatePageControl.init();
990 $('.merchant-module-page-setting-field-gallery').each(function () {
991 var $this = $(this);
992 var $button = $this.find('.merchant-gallery-button');
993 var $input = $this.find('.merchant-gallery-input');
994 var $images = $this.find('.merchant-gallery-images');
995 var $remove = $this.find('.merchant-gallery-remove');
996 var wpMediaFrame;
997 var sortable = $images.sortable({
998 helper: 'original',
999 update: function update(event, ui) {
1000 var selectedIds = [];
1001 $images.find('.merchant-gallery-image').each(function () {
1002 selectedIds.push($(this).data('item-id'));
1003 });
1004 $input.val(selectedIds.join(',')).trigger('change');
1005 }
1006 });
1007 $remove.on('click', function (e) {
1008 e.preventDefault();
1009 $(this).parent().remove();
1010 var selectedIds = [];
1011 $images.find('.merchant-gallery-image').each(function () {
1012 selectedIds.push($(this).data('item-id'));
1013 });
1014 $input.val(selectedIds.join(',')).trigger('change');
1015 });
1016 $button.on('click', function (e) {
1017 var $btn = $(this);
1018 var ids = $input.val();
1019 var mode = ids ? 'edit' : 'add';
1020 e.preventDefault();
1021 if (typeof window.wp === 'undefined' || !window.wp.media || !window.wp.media.gallery) {
1022 return;
1023 }
1024 if (mode === 'add') {
1025 wpMediaFrame = window.wp.media({
1026 library: {
1027 type: 'image'
1028 },
1029 frame: 'post',
1030 state: 'gallery',
1031 multiple: true
1032 });
1033 wpMediaFrame.open();
1034 } else {
1035 wpMediaFrame = window.wp.media.gallery.edit('[gallery ids="' + ids + '"]');
1036 }
1037 wpMediaFrame.on('update', function (selection) {
1038 $images.empty();
1039 var selectedIds = selection.models.map(function (attachment) {
1040 var item = attachment.toJSON();
1041 var thumb = item.sizes && item.sizes.thumbnail && item.sizes.thumbnail.url ? item.sizes.thumbnail.url : item.url;
1042 $images.append('<div class="merchant-gallery-image" data-item-id="' + item.id + '"><i class="merchant-gallery-remove dashicons dashicons-no-alt"></i><img src="' + thumb + '" /></div>');
1043 return item.id;
1044 });
1045 $input.val(selectedIds.join(',')).trigger('change');
1046 $this.find('.merchant-gallery-remove').on('click', function (e) {
1047 e.preventDefault();
1048 $(this).parent().remove();
1049 var selectedIds = [];
1050 $images.find('.merchant-gallery-image').each(function () {
1051 selectedIds.push($(this).data('item-id'));
1052 });
1053 $input.val(selectedIds.join(',')).trigger('change');
1054 });
1055 });
1056 });
1057 });
1058 var initUploadField = function initUploadField(element) {
1059 var $this = element;
1060 var $button = $this.find('.merchant-upload-button');
1061 var $input = $this.find('.merchant-upload-input');
1062 var $wrapper = $this.find('.merchant-upload-wrapper');
1063 var $remove = $this.find('.merchant-upload-remove');
1064 var wpMediaFrame;
1065 $remove.on('click', function (e) {
1066 e.preventDefault();
1067 $(this).parent().remove();
1068 $input.val('').trigger('change');
1069 });
1070 $button.on('click', function (e) {
1071 e.preventDefault();
1072 if (typeof window.wp === 'undefined' || !window.wp.media) {
1073 return;
1074 }
1075 if (!wpMediaFrame) {
1076 wpMediaFrame = window.wp.media({
1077 library: {
1078 type: 'image'
1079 }
1080 });
1081 }
1082 wpMediaFrame.open();
1083 wpMediaFrame.on('select', function () {
1084 $wrapper.empty();
1085 var item = wpMediaFrame.state().get('selection').first().attributes;
1086 var thumb = item.sizes && item.sizes.thumbnail && item.sizes.thumbnail.url ? item.sizes.thumbnail.url : item.url;
1087 $wrapper.append('<div class="merchant-upload-image"><i class="merchant-upload-remove dashicons dashicons-no-alt"></i><img src="' + thumb + '" /></div>');
1088 $input.val(item.id).trigger('change');
1089 $this.find('.merchant-upload-button-drag-drop').hide();
1090 $this.find('.merchant-upload-remove').on('click', function (e) {
1091 e.preventDefault();
1092 $(this).parent().remove();
1093 $input.val('').trigger('change');
1094 $this.find('.merchant-upload-button-drag-drop').show();
1095 });
1096 });
1097 });
1098 };
1099 $('.merchant-module-page-setting-field-upload:not(.template)').each(function () {
1100 initUploadField($(this));
1101 });
1102
1103 // Drag & Drag
1104 var events = ['dragenter', 'dragover', 'dragleave', 'drop'];
1105 jQuery.each(events, function (index, eventName) {
1106 $(document).on(eventName, '.merchant-upload-button-drag-drop', function (e) {
1107 e.preventDefault();
1108 e.stopPropagation();
1109 });
1110 });
1111 $(document).on('dragenter', '.merchant-upload-button-drag-drop', function (e) {
1112 $(this).closest('.merchant-module-page-setting-field-upload').find('.merchant-upload-button').click();
1113 });
1114 var initSelectAjax = function initSelectAjax($selectAjax) {
1115 var $select = $selectAjax.find('select');
1116 var $source = $select.data('source');
1117 var $config = window.merchant_admin_options;
1118 var $object = {
1119 width: '100%',
1120 templateSelection: function templateSelection(category) {
1121 return category.text.replace(/&nbsp;-*\s*/g, '').trim();
1122 }
1123 };
1124 if ($source === 'post' || $source === 'product' || $source === 'user') {
1125 $object.minimumInputLength = 1;
1126 $object.ajax = {
1127 url: $config.ajaxurl,
1128 dataType: 'json',
1129 delay: 250,
1130 cache: true,
1131 data: function data(params) {
1132 return {
1133 action: 'merchant_admin_options_select_ajax',
1134 nonce: $config.ajaxnonce,
1135 term: params.term,
1136 source: $source
1137 };
1138 },
1139 processResults: function processResults(response, params) {
1140 if (response.success) {
1141 return {
1142 results: response.data
1143 };
1144 }
1145 return {};
1146 }
1147 };
1148 }
1149 $select.select2($object);
1150 $selectAjax.find('.select2-selection--multiple').append('<span class="merchant-select2-clear"></span>');
1151 };
1152 $('.merchant-module-page-setting-field-select_ajax:not(.template)').each(function () {
1153 initSelectAjax($(this));
1154 });
1155 $('.merchant-module-page-settings-responsive').each(function () {
1156 var $this = $(this);
1157 var $button = $this.find('.merchant-module-page-settings-devices button');
1158 var $container = $this.find('.merchant-module-page-settings-device-container');
1159 $button.on('click', function (e) {
1160 e.preventDefault();
1161 var $device = $(this).data('device');
1162 $button.removeClass('active');
1163 $container.removeClass('active');
1164 $(this).addClass('active');
1165 $container.each(function () {
1166 if ($(this).data('device') === $device) {
1167 $(this).addClass('active');
1168 }
1169 });
1170 });
1171 });
1172 $('.merchant-animated-buttons').each(function () {
1173 var $button = $(this).find('label');
1174 var $demo = $('.merchant-animation-demo');
1175 var animation;
1176 var animationHover;
1177 $button.on('click', function () {
1178 $demo.removeClass('merchant-animation-' + animation);
1179 $demo.removeClass('merchant-animation-' + animationHover);
1180 animation = $(this).find('input').attr('value');
1181 setTimeout(function () {
1182 $demo.addClass('merchant-animation-' + animation);
1183 }, 100);
1184 setTimeout(function () {
1185 $demo.removeClass('merchant-animation-' + animation);
1186 }, 1000);
1187 });
1188 $button.mouseover(function () {
1189 $demo.removeClass('merchant-animation-' + animation);
1190 animationHover = $(this).find('input').attr('value');
1191 $demo.addClass('merchant-animation-' + animationHover);
1192 }).mouseout(function () {
1193 $demo.removeClass('merchant-animation-' + animationHover);
1194 });
1195 });
1196
1197 // Notifications Sidebar
1198 var $notificationsSidebar = $('.merchant-notifications-sidebar');
1199 if ($notificationsSidebar.length) {
1200 var $notifications = $('.merchant-notifications');
1201 $notifications.on('click', function (e) {
1202 e.preventDefault();
1203 var $notification = $(this);
1204 var latestNotificationDate = $notificationsSidebar.find('.merchant-notification:first-child .merchant-notification-date').data('raw-date');
1205 $notificationsSidebar.toggleClass('opened');
1206 if (!$notification.hasClass('read')) {
1207 $.post(window.merchant.ajax_url, {
1208 action: 'merchant_notifications_read',
1209 nonce: window.merchant.nonce,
1210 latest_notification_date: latestNotificationDate
1211 }, function (response) {
1212 if (response.success) {
1213 setTimeout(function () {
1214 $notification.addClass('read');
1215 }, 2000);
1216 }
1217 });
1218 }
1219 });
1220 $(window).on('scroll', function () {
1221 if (window.pageYOffset > 60) {
1222 $notificationsSidebar.addClass('closing');
1223 setTimeout(function () {
1224 $notificationsSidebar.removeClass('opened');
1225 $notificationsSidebar.removeClass('closing');
1226 }, 300);
1227 }
1228 });
1229
1230 // Close Sidebar
1231 $('.merchant-notifications-sidebar-close').on('click', function (e) {
1232 e.preventDefault();
1233 $notificationsSidebar.addClass('closing');
1234 setTimeout(function () {
1235 $notificationsSidebar.removeClass('opened');
1236 $notificationsSidebar.removeClass('closing');
1237 }, 300);
1238 });
1239 }
1240
1241 // Tabs Navigation.
1242 var tabs = $('.merchant-tabs-nav');
1243 if (tabs.length) {
1244 tabs.each(function () {
1245 var tabWrapperId = $(this).data('tab-wrapper-id');
1246 $(this).find('.merchant-tabs-nav-link').on('click', function (e) {
1247 e.preventDefault();
1248 var tabsNavLink = $(this).closest('.merchant-tabs-nav').find('.merchant-tabs-nav-link'),
1249 to = $(this).data('tab-to');
1250
1251 // Tab Nav Item
1252 tabsNavLink.each(function () {
1253 $(this).closest('.merchant-tabs-nav-item').removeClass('active');
1254 });
1255 $(this).closest('.merchant-tabs-nav-item').addClass('active');
1256
1257 // Tab Content
1258 var tabContentWrapper = $('.merchant-tab-content-wrapper[data-tab-wrapper-id="' + tabWrapperId + '"]');
1259 tabContentWrapper.find('> .merchant-tab-content').removeClass('active');
1260 tabContentWrapper.find('> .merchant-tab-content[data-tab-content-id="' + to + '"]').addClass('active');
1261 });
1262 });
1263 }
1264
1265 // Module Alert
1266 var $moduleAlert = $('.merchant-module-alert');
1267 if ($moduleAlert.length) {
1268 $moduleAlert.find('.merchant-module-alert-close').on('click', function (e) {
1269 e.preventDefault();
1270 $moduleAlert.removeClass('merchant-show');
1271 $(document).off('click.merchant-alert-close');
1272 });
1273 }
1274 });
1275
1276 /**
1277 * Check if a string is numeric.
1278 *
1279 * @param str the string to check
1280 *
1281 * @returns {boolean} true if numeric, false otherwise
1282 */
1283 function isNumeric(str) {
1284 if (typeof str != "string") return false; // we only process strings!
1285 return !isNaN(str) &&
1286 // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
1287 !isNaN(parseFloat(str)); // ...and ensure strings of whitespace fail
1288 }
1289
1290 /**
1291 * Evaluate conditional fields.
1292 *
1293 * @param conditions the array of conditions
1294 * @param field the field that is being evaluated
1295 *
1296 * @returns {boolean}
1297 */
1298 function evaluateConditions(conditions) {
1299 var field = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1300 var passed = false;
1301 if ('relation' in conditions) {
1302 //loop through terms
1303 var relation = conditions.relation.toUpperCase();
1304 // lowercase relation
1305 if (relation === 'OR') {
1306 for (var i = 0; i < conditions.terms.length; i++) {
1307 var term = conditions.terms[i];
1308 passed = evaluateConditions(term, field);
1309 if (passed) {
1310 return true;
1311 }
1312 }
1313 } else if (relation === 'AND') {
1314 var n = 0;
1315 for (var _i = 0; _i < conditions.terms.length; _i++) {
1316 // check if inner terms are passed
1317 var _term = conditions.terms[_i];
1318 if (evaluateConditions(_term, field)) {
1319 n++;
1320 }
1321 }
1322 if (n === conditions.terms.length) {
1323 passed = true;
1324 }
1325 }
1326 } else {
1327 var condition = '';
1328 if ('terms' in conditions) {
1329 condition = conditions.terms[0];
1330 } else {
1331 condition = conditions;
1332 }
1333 var $target = $('input[name="merchant[' + condition.field + ']"],select[name="merchant[' + condition.field + ']"]');
1334 if (!$target.length) {
1335 // check if inside flexible content
1336 var flexibleContentParent = field.closest('.layout-body');
1337 if (flexibleContentParent.length > 0) {
1338 $target = flexibleContentParent.find('.merchant-field-' + condition.field).find('input, select');
1339 }
1340 }
1341 if (!$target.length) {
1342 // Maybe the field is a multiple field
1343 $target = $('input[name="merchant[' + condition.field + '][]"],select[name="merchant[' + condition.field + '][]"]');
1344 }
1345 var value = $target.val();
1346 if ($target.attr('type') === 'checkbox' || $target.attr('type') === 'radio') {
1347 value = $target.is(':checked');
1348 }
1349
1350 // check if the field is multiple checkbox
1351 if ($target.attr('type') === 'checkbox' && $target.length > 1) {
1352 value = [];
1353 $target.each(function () {
1354 if ($(this).is(':checked')) {
1355 value.push($(this).val());
1356 }
1357 });
1358 }
1359
1360 // cast value as string if numeric
1361 if (isNumeric(value)) {
1362 value = Number(value);
1363 }
1364
1365 // check if is array condition.value
1366 if (Array.isArray(condition.value)) {
1367 condition.value = condition.value.map(function (item) {
1368 if (isNumeric(item)) {
1369 return Number(item);
1370 }
1371 return item;
1372 });
1373 }
1374 if (condition.operator === '===' && value === condition.value) {
1375 passed = true;
1376 } else if (condition.operator === '!==' && value !== condition.value) {
1377 passed = true;
1378 } else if (condition.operator === '>' && value > condition.value) {
1379 passed = true;
1380 } else if (condition.operator === '<' && value < condition.value) {
1381 passed = true;
1382 } else if (condition.operator === '>=' && value >= condition.value) {
1383 passed = true;
1384 } else if (condition.operator === '<=' && value <= condition.value) {
1385 passed = true;
1386 } else if (condition.operator === 'in' && condition.value.includes(value)) {
1387 passed = true;
1388 } else if (condition.operator === '!in' && !condition.value.includes(value)) {
1389 passed = true;
1390 } else if (condition.operator === 'contains' && Array.isArray(value) && value.includes(condition.value)) {
1391 passed = true;
1392 } else if (condition.operator === '!contains' && Array.isArray(value) && !value.includes(condition.value)) {
1393 passed = true;
1394 }
1395 }
1396 return passed;
1397 }
1398 })(jQuery, window, document);
1399
1400 // Extend jQuery to add getPath func to get accurate dynamic selector to an element.
1401 jQuery.fn.extend({
1402 getPath: function getPath() {
1403 var pathes = [];
1404 this.each(function (index, element) {
1405 var path,
1406 $node = jQuery(element);
1407 while ($node.length) {
1408 var realNode = $node.get(0),
1409 name = realNode.localName;
1410 if (!name) {
1411 break;
1412 }
1413 name = name.toLowerCase();
1414 var parent = $node.parent();
1415 var sameTagSiblings = parent.children(name);
1416 if (sameTagSiblings.length > 1) {
1417 var allSiblings = parent.children();
1418 var index = allSiblings.index(realNode) + 1;
1419 if (index > 0) {
1420 name += ':nth-child(' + index + ')';
1421 }
1422 }
1423 path = name + (path ? ' > ' + path : '');
1424 $node = parent;
1425 }
1426 pathes.push(path);
1427 });
1428 return pathes.join(',');
1429 }
1430 });