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

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