PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 1.10.4
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v1.10.4
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.4, at assets/js/admin/admin.js

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