PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.3.2
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.3.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
← All changes | assets/js/admin/admin.js +372 -29 2.2.72.3.2 View file →
@@ -1,6 +1,12 @@
1 1 "use strict";
2 2
3 +function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
4 +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5 +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
6 +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
7 +function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
8 +function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
3 9 function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4 10 ;
5 11 (function ($, window, document, undefined) {
6 12 'use strict';
@@ -16,9 +22,18 @@
16 22 $('.merchant-module-page-content').on('change keypress change.merchant', function (e) {
17 23 if ($(e.target).hasClass('merchant-backup-file') || $(e.target).hasClass('merchant-search-field')) {
18 24 return;
19 25 }
20 - if (!$(this).is('.merchant-module-question-answer-textarea, .merchant-license-code-input')) {
26 +
27 + // Nothing in the preview is a setting. Its controls are there to be played
28 + // with, so a module whose mock-up has working fields cannot dirty the form.
29 + if ($(e.target).closest('.merchant-module-page-preview').length) {
30 + return;
31 + }
32 +
33 + // The licence key and the module feedback textarea save through their
34 + // own handlers, so editing them leaves the save bar alone.
35 + if (!$(e.target).is('.merchant-module-question-answer-textarea, .merchant-license-code-input')) {
21 36 if (!merchant.show_save) {
22 37 $ajaxHeader.addClass('merchant-show');
23 38 $ajaxHeader.removeClass('merchant-saving');
24 39 merchant.show_save = true;
@@ -483,9 +498,25 @@
483 498 init: function init() {
484 499 this.initiate_datepicker();
485 500 this.events();
486 501 },
502 + // Date() cannot parse the bare 'H:i' a time-only picker stores, so pin it to today.
503 + parseInitialDate: function parseInitialDate(value, fieldOptions) {
504 + if (!value) {
505 + return [];
506 + }
507 + if (fieldOptions.onlyTimepicker && /^\d{1,2}:\d{2}$/.test(value)) {
508 + var _value$split = value.split(':'),
509 + _value$split2 = _slicedToArray(_value$split, 2),
510 + hours = _value$split2[0],
511 + minutes = _value$split2[1];
512 + return [new Date(new Date().setHours(Number(hours), Number(minutes), 0, 0))];
513 + }
514 + var date = new Date(value);
515 + return isNaN(date) ? [] : [date];
516 + },
487 517 initiate_datepicker: function initiate_datepicker() {
518 + var self = this;
488 519 var elements = $('.merchant-module-page-setting-field .merchant-datetime-field');
489 520 if (elements.length === 0) {
490 521 return;
491 522 }
@@ -490,11 +521,12 @@
490 521 return;
491 522 }
492 523 elements.each(function (index) {
493 524 var input = $(this).find('input'),
525 + fieldOptions = $(this).data('options') || {},
494 526 options = {
495 527 locale: JSON.parse(merchant_datepicker_locale),
496 - selectedDates: input.val() ? [new Date(input.val())] : [],
528 + selectedDates: self.parseInitialDate(input.val(), fieldOptions),
497 529 onSelect: function onSelect(_ref) {
498 530 var date = _ref.date,
499 531 formattedDate = _ref.formattedDate,
500 532 datepicker = _ref.datepicker;
@@ -505,23 +537,20 @@
505 537 }
506 538 input.trigger('change.merchant');
507 539 input.trigger('change.merchant-datepicker', [formattedDate, input, options, index]);
508 540 }
509 - },
510 - fieldOptions = $(this).data('options');
541 + };
511 542 // add buttons to fieldOptions
512 543 fieldOptions.buttons = ['clear'];
513 - if (fieldOptions) {
514 - if (fieldOptions.minDate !== undefined && fieldOptions.minDate === 'today') {
515 - fieldOptions.minDate = new Date();
516 - if (fieldOptions.timeZone !== undefined && fieldOptions.timeZone !== '') {
517 - fieldOptions.minDate = new Date(fieldOptions.minDate.toLocaleString('en-US', {
518 - timeZone: fieldOptions.timeZone
519 - }));
520 - }
544 + if (fieldOptions.minDate !== undefined && fieldOptions.minDate === 'today') {
545 + fieldOptions.minDate = new Date();
546 + if (fieldOptions.timeZone !== undefined && fieldOptions.timeZone !== '') {
547 + fieldOptions.minDate = new Date(fieldOptions.minDate.toLocaleString('en-US', {
548 + timeZone: fieldOptions.timeZone
549 + }));
521 550 }
522 - options = Object.assign(options, fieldOptions);
523 551 }
552 + options = Object.assign(options, fieldOptions);
524 553 var datepickerObj = new AirDatepicker(input.getPath(), options);
525 554 input.attr('readonly', true);
526 555 $(document).trigger('initiated.merchant-datepicker', [datepickerObj, input, options, index]);
527 556 });
@@ -703,8 +732,230 @@
703 732 };
704 733
705 734 // Initialize Sortable Repeater.
706 735 SortableRepeaterField.init();
736 +
737 + // Sortable Repeater Icons.
738 + var SortableRepeaterIconsField = {
739 + CONTROL: '.merchant-sortable-repeater-icons-control',
740 + init: function init() {
741 + var self = this;
742 + $(self.CONTROL).each(function () {
743 + self.populate($(this));
744 + });
745 + this.events();
746 + },
747 + /**
748 + * Populate rows from the hidden JSON input.
749 + */
750 + populate: function populate($control) {
751 + var self = this;
752 + var items = [];
753 + try {
754 + items = JSON.parse($control.find('.merchant-sortable-repeater-input').val());
755 + } catch (e) {
756 + items = [];
757 + }
758 + if (!Array.isArray(items) || items.length === 0) {
759 + return;
760 + }
761 + var $firstRow = $control.find('.repeater').first();
762 +
763 + // First item populates the existing row.
764 + var firstItem = self.normalizeItem(items[0]);
765 + $firstRow.find('.repeater-input').val(firstItem.text);
766 + self.setRowIcon($firstRow, firstItem.icon);
767 +
768 + // Remaining items get new rows (silent = true to avoid triggering save bar).
769 + for (var i = 1; i < items.length; i++) {
770 + var item = self.normalizeItem(items[i]);
771 + self.appendRow($control, item.text, item.icon, true);
772 + }
773 + },
774 + events: function events() {
775 + var self = this;
776 +
777 + // Toggle icon picker dropdown.
778 + $(document).on('click', self.CONTROL + ' .merchant-icon-picker-toggle', function (e) {
779 + e.preventDefault();
780 + e.stopPropagation();
781 + var $dropdown = $(this).siblings('.merchant-icon-picker-dropdown');
782 +
783 + // Close all other dropdowns first.
784 + $(self.CONTROL + ' .merchant-icon-picker-dropdown').not($dropdown).hide();
785 + $dropdown.toggle();
786 + });
787 +
788 + // Select icon from dropdown.
789 + $(document).on('click', self.CONTROL + ' .merchant-icon-option', function (e) {
790 + e.preventDefault();
791 + e.stopPropagation();
792 + var $repeater = $(this).closest('.repeater');
793 + var iconKey = $(this).data('icon') || '';
794 + self.setRowIcon($repeater, iconKey);
795 + $(this).closest('.merchant-icon-picker-dropdown').hide();
796 + self.syncHiddenInput($(this).closest(self.CONTROL));
797 + });
798 +
799 + // Close dropdown on outside click.
800 + $(document).on('click', function () {
801 + $(SortableRepeaterIconsField.CONTROL + ' .merchant-icon-picker-dropdown').hide();
802 + });
803 +
804 + // Prevent dropdown clicks from closing.
805 + $(document).on('click', self.CONTROL + ' .merchant-icon-picker-dropdown', function (e) {
806 + e.stopPropagation();
807 + });
808 +
809 + // Delete row.
810 + $(document).on('click', self.CONTROL + ' .merchant-sortable-repeater-icons.sortable .customize-control-sortable-repeater-delete', function (e) {
811 + e.preventDefault();
812 + var $control = $(this).closest(self.CONTROL);
813 + $(this).parent().slideUp('fast', function () {
814 + $(this).remove();
815 + self.syncHiddenInput($control);
816 + });
817 + $(document).trigger('merchant-sortable-repeater-item-deleted');
818 + });
819 +
820 + // Add new row.
821 + $(document).on('click', self.CONTROL + ' .customize-control-sortable-repeater-icons-add', function (e) {
822 + e.preventDefault();
823 + var $control = $(this).closest(self.CONTROL);
824 + self.appendRow($control, '', '');
825 + self.syncHiddenInput($control);
826 + });
827 +
828 + // Text change → sync.
829 + $(document).on('focusout', self.CONTROL + ' .merchant-sortable-repeater-icons.sortable .repeater-input', function () {
830 + self.syncHiddenInput($(this).closest(self.CONTROL));
831 + });
832 +
833 + // Sort change → sync.
834 + $(document).on('change', self.CONTROL + ' .merchant-sortable-repeater-icons.sortable', function () {
835 + self.syncHiddenInput($(this).closest(self.CONTROL));
836 + });
837 +
838 + // Re-init on flexible content add.
839 + $(document).on('merchant-flexible-content-added', function (e, $layout) {
840 + var $control = $layout.find(self.CONTROL);
841 + if ($control.length) {
842 + self.populate($control);
843 + self.makeFieldsSortable($control.find('.sortable'));
844 + }
845 + });
846 + },
847 + /**
848 + * Append a new repeater row.
849 + */
850 + appendRow: function appendRow($control, text, icon, silent) {
851 + var self = this;
852 + var iconLibrary = self.getIconLibrary($control);
853 + var dropdownHtml = '<div class="merchant-icon-picker-dropdown" style="display:none;">';
854 + dropdownHtml += '<button type="button" class="merchant-icon-option" data-icon="" title="Use campaign icon"><span class="dashicons dashicons-no-alt"></span></button>';
855 + Object.keys(iconLibrary).forEach(function (key) {
856 + dropdownHtml += '<button type="button" class="merchant-icon-option" data-icon="' + key + '" title="' + key + '">' + iconLibrary[key] + '</button>';
857 + });
858 + dropdownHtml += '</div>';
859 + var escapedText = $('<div>').text(text).html();
860 + var newRow = $('<div class="repeater" style="display:none">' + '<button type="button" class="merchant-icon-picker-toggle" data-icon="" title="Select icon"><span class="dashicons dashicons-plus-alt2"></span></button>' + dropdownHtml + '<input type="text" value="' + escapedText + '" 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>');
861 + $control.find('.sortable').append(newRow);
862 + if (silent) {
863 + newRow.show();
864 + } else {
865 + newRow.slideDown('slow', function () {
866 + $(this).find('input').focus();
867 + });
868 + }
869 + if (icon) {
870 + self.setRowIcon(newRow, icon);
871 + }
872 + self.makeFieldsSortable($control.find('.sortable'));
873 + $(document).trigger('merchant-sortable-repeater-item-added', [newRow, $control.find('.sortable')]);
874 + },
875 + /**
876 + * Set the icon on a repeater row.
877 + */
878 + setRowIcon: function setRowIcon($row, iconKey) {
879 + var $toggle = $row.find('.merchant-icon-picker-toggle');
880 + $toggle.attr('data-icon', iconKey);
881 + if (iconKey) {
882 + var $control = $row.closest(SortableRepeaterIconsField.CONTROL);
883 + var iconLibrary = this.getIconLibrary($control);
884 + var svg = iconLibrary[iconKey] || '';
885 + if (svg) {
886 + $toggle.html(svg).addClass('has-icon');
887 + } else {
888 + $toggle.html('<span class="dashicons dashicons-plus-alt2"></span>').removeClass('has-icon');
889 + }
890 + } else {
891 + $toggle.html('<span class="dashicons dashicons-plus-alt2"></span>').removeClass('has-icon');
892 + }
893 +
894 + // Mark selected option in dropdown.
895 + $row.find('.merchant-icon-option').removeClass('selected');
896 + $row.find('.merchant-icon-option[data-icon="' + iconKey + '"]').addClass('selected');
897 + },
898 + /**
899 + * Sync all rows back to the hidden JSON input.
900 + */
901 + syncHiddenInput: function syncHiddenInput($control) {
902 + var items = [];
903 + $control.find('.merchant-sortable-repeater-icons .repeater').each(function () {
904 + var text = $(this).find('.repeater-input').val();
905 + var icon = $(this).find('.merchant-icon-picker-toggle').attr('data-icon') || '';
906 + items.push({
907 + text: text,
908 + icon: icon
909 + });
910 + });
911 + if (!items.length) {
912 + items.push({
913 + text: '',
914 + icon: ''
915 + });
916 + }
917 + $control.find('.merchant-sortable-repeater-input').val(JSON.stringify(items));
918 + $control.find('.merchant-sortable-repeater-input').trigger('change');
919 + $control.find('.merchant-sortable-repeater-input').trigger('sortable.repeater.change');
920 + },
921 + makeFieldsSortable: function makeFieldsSortable($sortable) {
922 + var self = this;
923 + if (!$sortable.hasClass('disable-sorting')) {
924 + $sortable.sortable({
925 + handle: '.dashicons-menu',
926 + update: function update() {
927 + self.syncHiddenInput($sortable.closest(self.CONTROL));
928 + }
929 + });
930 + }
931 + },
932 + getIconLibrary: function getIconLibrary($control) {
933 + if (!$control.data('_iconLibrary')) {
934 + try {
935 + $control.data('_iconLibrary', JSON.parse($control.attr('data-icons')) || {});
936 + } catch (e) {
937 + $control.data('_iconLibrary', {});
938 + }
939 + }
940 + return $control.data('_iconLibrary');
941 + },
942 + normalizeItem: function normalizeItem(item) {
943 + if (typeof item === 'string') {
944 + return {
945 + text: item,
946 + icon: ''
947 + };
948 + }
949 + return {
950 + text: item.text || '',
951 + icon: item.icon || ''
952 + };
953 + }
954 + };
955 +
956 + // Initialize Sortable Repeater Icons.
957 + SortableRepeaterIconsField.init();
707 958 var GroubField = {
708 959 init: function init() {
709 960 var self = this;
710 961 self.initAccordion();
@@ -1698,17 +1949,16 @@
1698 1949 var val = values[fieldKey];
1699 1950 if (val === undefined || val === null) {
1700 1951 return;
1701 1952 }
1702 - if ($el.is(':checkbox') || $el.is(':radio')) {
1703 - // For checkboxes/radios, check if this input's value matches.
1704 - if ($el.val() === String(val) || val === '1' && $el.is(':checkbox')) {
1705 - $el.prop('checked', true);
1706 - }
1953 + if ($el.is(':checkbox') && !$el.is(':radio')) {
1954 + $el.prop('checked', !!parseInt(val, 10));
1955 + } else if ($el.is(':radio')) {
1956 + $el.prop('checked', $el.val() === String(val));
1707 1957 } else if ($el.is('select')) {
1708 1958 $el.val(val);
1709 1959 } else {
1710 - $el.val(val);
1960 + $el.val(_typeof(val) === 'object' && val !== null ? JSON.stringify(val) : val);
1711 1961 }
1712 1962 });
1713 1963
1714 1964 // Populate select_ajax pre-selected options.
@@ -1798,17 +2048,18 @@
1798 2048 }
1799 2049 });
1800 2050 } else {
1801 2051 var $field = $body.find('[name="' + namePrefix + '[' + key + ']"]');
1802 - if ($field.length) {
1803 - if ($field.is(':checkbox') || $field.is(':radio')) {
1804 - if ($field.val() === String(val) || val === '1' && $field.is(':checkbox')) {
1805 - $field.prop('checked', true);
1806 - }
1807 - } else {
1808 - $field.val(val);
1809 - }
2052 + if (!$field.length) {
2053 + return;
1810 2054 }
2055 + if ($field.is(':checkbox') && !$field.is(':radio')) {
2056 + $field.prop('checked', !!parseInt(val, 10));
2057 + } else if ($field.is(':radio')) {
2058 + $field.prop('checked', $field.val() === String(val));
2059 + } else {
2060 + $field.val(val);
2061 + }
1811 2062 }
1812 2063 });
1813 2064 };
1814 2065 $.each(values, function (key, val) {
@@ -1917,9 +2168,9 @@
1917 2168 parent.find('.merchant-selected-products-preview ul').append($(this));
1918 2169 parent.find('.merchant-selections-products-preview').html('').hide();
1919 2170 parent.find('.merchant-search-field').val('').change();
1920 2171 if (oldValue === '') {
1921 - valueField.val($(this).data('id'));
2172 + valueField.val($(this).data('id')).change();
1922 2173 } else {
1923 2174 if (!multiple) {
1924 2175 valueField.val($(this).data('id')).change();
1925 2176 } else {
@@ -2278,9 +2529,17 @@
2278 2529 });
2279 2530 $(document).on('dragenter', '.merchant-upload-button-drag-drop', function (e) {
2280 2531 $(this).closest('.merchant-module-page-setting-field-upload').find('.merchant-upload-button').click();
2281 2532 });
2282 - var initSelectAjax = function initSelectAjax($selectAjax) {
2533 +
2534 + // Callers pass a collection, and reading the source off a collection would give
2535 + // every select the first field's source, so each field is set up on its own.
2536 + var initSelectAjax = function initSelectAjax($selectAjaxFields) {
2537 + $selectAjaxFields.each(function () {
2538 + initSelectAjaxField($(this));
2539 + });
2540 + };
2541 + var initSelectAjaxField = function initSelectAjaxField($selectAjax) {
2283 2542 var $select = $selectAjax.find('select');
2284 2543 var $source = $select.data('source');
2285 2544 var $config = window.merchant_admin_options;
2286 2545 var $object = {
@@ -2454,8 +2713,92 @@
2454 2713 $moduleAlert.find('.merchant-module-alert-close').on('click', function (e) {
2455 2714 e.preventDefault();
2456 2715 $moduleAlert.removeClass('merchant-show');
2457 2716 $(document).off('click.merchant-alert-close');
2717 + });
2718 + }
2719 +
2720 + // AI Prompt Examples Modal
2721 + var $aiPromptsModal = $('#merchant-ai-prompts-modal');
2722 + if ($aiPromptsModal.length) {
2723 + var $aiPromptsList = $aiPromptsModal.find('.merchant-ai-prompts-modal-list');
2724 + var copyHintText = window.merchant.ai_prompt_copy_hint || 'Click to copy';
2725 + var copiedLabelText = window.merchant.ai_prompt_copied_label || 'Copied!';
2726 + var copyIconSvg = '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="5" y="5" width="8" height="8" rx="1.5" stroke="currentColor" stroke-width="1.3"/><path d="M3 10V3.5C3 2.67157 3.67157 2 4.5 2H10.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>';
2727 + var checkIconSvg = '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.5 4.5L6 12L2.5 8.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>';
2728 + var copyTextToClipboard = function copyTextToClipboard(text, onCopied) {
2729 + if (navigator.clipboard && navigator.clipboard.writeText) {
2730 + navigator.clipboard.writeText(text).then(onCopied);
2731 + return;
2732 + }
2733 + var $temp = $('<textarea readonly></textarea>').val(text).css({
2734 + position: 'fixed',
2735 + top: '-1000px'
2736 + });
2737 + $('body').append($temp);
2738 + $temp[0].select();
2739 + document.execCommand('copy');
2740 + $temp.remove();
2741 + onCopied();
2742 + };
2743 + $(document).on('click', '.merchant-ai-badge', function (e) {
2744 + e.preventDefault();
2745 + e.stopPropagation();
2746 + var prompts = $(this).data('aiPrompts');
2747 + $aiPromptsModal.find('.merchant-ai-prompts-modal-title-text').text($(this).data('aiTitle') || '');
2748 + $aiPromptsModal.find('.merchant-ai-prompts-modal-blurb').text($(this).data('aiBlurb') || '');
2749 + $aiPromptsList.empty();
2750 + if (Array.isArray(prompts)) {
2751 + prompts.forEach(function (prompt) {
2752 + var $row = $('<button type="button" class="merchant-ai-prompt-row"></button>').attr('data-prompt', prompt);
2753 + $row.append($('<span class="merchant-ai-prompt-text"></span>').text(prompt));
2754 + $row.append($('<span class="merchant-ai-prompt-icon"></span>').html(copyIconSvg));
2755 + $row.attr('aria-label', copyHintText);
2756 + $aiPromptsList.append($row);
2757 + });
2758 + }
2759 + $aiPromptsModal.addClass('merchant-show');
2760 + var $badgeIcon = $aiPromptsModal.find('.merchant-ai-prompts-modal-badge svg');
2761 + $badgeIcon.removeClass('merchant-ai-badge-spin');
2762 + void $badgeIcon[0].offsetWidth;
2763 + $badgeIcon.addClass('merchant-ai-badge-spin');
2764 + });
2765 + $(document).on('keydown', '.merchant-ai-badge', function (e) {
2766 + if (e.key === 'Enter' || e.key === ' ') {
2767 + e.preventDefault();
2768 + $(this).trigger('click');
2769 + }
2770 + });
2771 + $aiPromptsList.on('click', '.merchant-ai-prompt-row', function () {
2772 + var $row = $(this);
2773 + if ($row.hasClass('is-copied')) {
2774 + return;
2775 + }
2776 + copyTextToClipboard($row.attr('data-prompt'), function () {
2777 + $row.addClass('is-copied').attr('aria-label', copiedLabelText);
2778 + $row.find('.merchant-ai-prompt-icon').html(checkIconSvg);
2779 + setTimeout(function () {
2780 + $row.removeClass('is-copied').attr('aria-label', copyHintText);
2781 + $row.find('.merchant-ai-prompt-icon').html(copyIconSvg);
2782 + }, 1600);
2783 + });
2784 + });
2785 + var closeAiPromptsModal = function closeAiPromptsModal() {
2786 + $aiPromptsModal.removeClass('merchant-show');
2787 + $aiPromptsModal.find('.merchant-ai-prompts-modal-badge svg').removeClass('merchant-ai-badge-spin');
2788 + };
2789 + $(document).on('click', '.merchant-ai-prompts-modal-close', function () {
2790 + closeAiPromptsModal();
2791 + });
2792 + $aiPromptsModal.on('click', function (e) {
2793 + if ($(e.target).is($aiPromptsModal)) {
2794 + closeAiPromptsModal();
2795 + }
2796 + });
2797 + $(document).on('keydown', function (e) {
2798 + if (e.key === 'Escape' && $aiPromptsModal.hasClass('merchant-show')) {
2799 + closeAiPromptsModal();
2800 + }
2458 2801 });
2459 2802 }
2460 2803 });
2461 2804