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

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