";var p=s.no_patterns||"No patterns - press Enter to add";l+='',l+='
',l+='
',l+='aa',l+='',l+='',l+='',l+="
",l+='',l+='',l+="",l+="
",l+='';break;case"numeric_range":l+='
',l+='',l+='-',l+='',l+="
",l+='';break;case"multi_numeric_range":l+='
',l+='',l+='
',l+='',l+='-',l+='',l+='',l+="
",l+="
",l+='';break;case"multi_select_tiles":l+='
',l+="
",l+='';break;case"date_range":l+='
',l+='',l+='-',l+='',l+="
",l+='';break;case"select":l+='
',l+='',l+="
",l+='';break;case"boolean":l+='
',l+=''+this.escapeHtml(s.yes||"Yes")+"",l+="
",l+='';break;case"combination_attributes":this.escapeHtml(s.combination_help_title||"Combination Targeting"),this.escapeHtml(s.combination_help_desc||"Select attributes to target specific product combinations."),this.escapeHtml(s.combination_help_logic||"Logic:"),this.escapeHtml(s.combination_help_within||"Within group: OR (Red OR Blue)"),this.escapeHtml(s.combination_help_between||"Between groups: AND (Color AND Size)");var u=this.config.combinationMode||"products",h="toggle"===u,f=h?"products":u;l+='
";var p=s.no_patterns||"No patterns - press Enter to add";l+='',l+='
',l+='
',l+='aa',l+='',l+='',l+='',l+="
",l+='',l+='',l+="",l+="
",l+='';break;case"numeric_range":l+='
',l+='',l+='-',l+='',l+="
",l+='';break;case"multi_numeric_range":l+='
',l+='',l+='
',l+='',l+='-',l+='',l+='',l+="
",l+="
",l+='';break;case"multi_select_tiles":l+='
',l+="
",l+='';break;case"date_range":l+='
',l+='',l+='-',l+='',l+="
",l+='';break;case"select":l+='
',l+='',l+="
",l+='';break;case"boolean":l+='
',l+=''+this.escapeHtml(s.yes||"Yes")+"",l+="
",l+='';break;case"combination_attributes":this.escapeHtml(s.combination_help_title||"Combination Targeting"),this.escapeHtml(s.combination_help_desc||"Select attributes to target specific product combinations."),this.escapeHtml(s.combination_help_logic||"Logic:"),this.escapeHtml(s.combination_help_within||"Within group: OR (Red OR Blue)"),this.escapeHtml(s.combination_help_between||"Between groups: AND (Color AND Size)");var u=this.config.combinationMode||"products",h="toggle"===u,f=h?"products":u;l+='
');\n }\n });\n },\n\n /**\n * Render category tree structure\n */\n renderCategoryTree: function(categories, entityType) {\n var self = this;\n var trans = this.config.trans || {};\n var $container = this.$dropdown.find('.dropdown-results');\n var isCmsCategory = entityType === 'cms_categories';\n var categoryLabel = isCmsCategory ? 'CMS categories' : 'categories';\n\n // Get selected IDs from current picker\n var selectedIds = [];\n if (this.activeGroup) {\n var $block = this.$wrapper.find('.target-block[data-block-type=\"' + this.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + this.activeGroup.groupIndex + '\"]');\n\n if (this.activeGroup.section === 'include') {\n var $picker = $group.find('.include-picker');\n $picker.find('.entity-chip').each(function() {\n selectedIds.push(parseInt($(this).data('id'), 10));\n });\n } else {\n var $currentExcludeRow = $group.find('.exclude-row[data-exclude-index=\"' + this.activeGroup.excludeIndex + '\"]');\n var $currentPicker = $currentExcludeRow.find('.exclude-picker');\n $currentPicker.find('.entity-chip').each(function() {\n selectedIds.push(parseInt($(this).data('id'), 10));\n });\n }\n }\n\n // Build tree HTML\n var html = '
';\n\n html += '
';\n\n // Find minimum level (usually 1 or 2)\n var minLevel = categories.length > 0 ? categories[0].level : 1;\n\n categories.forEach(function(cat) {\n var isSelected = selectedIds.indexOf(cat.id) !== -1;\n var indent = (cat.level - minLevel) * 20;\n var hasChildren = cat.has_children;\n\n html += '
';\n\n // Expand/collapse toggle for parents\n if (hasChildren) {\n html += '';\n } else {\n html += '';\n }\n\n // Select children button for parents (on the left, near toggle)\n // Hide in single mode - selecting multiple items doesn't make sense there\n var isSingleMode = self.config.mode === 'single';\n if (hasChildren && !isSingleMode) {\n html += '';\n html += '';\n html += '';\n } else if (!isSingleMode) {\n html += '';\n }\n\n // Checkbox\n html += '';\n\n // Category icon (file icon for CMS categories)\n var iconClass = isCmsCategory ? 'icon-file-text-o' : ('icon-folder' + (hasChildren ? '' : '-o'));\n html += '';\n\n // Name and subtitle\n html += '
';\n html += '' + self.escapeHtml(cat.name) + '';\n html += '' + self.escapeHtml(cat.subtitle) + '';\n html += '
';\n\n html += '
';\n });\n\n html += '
'; // tree-container\n html += '
'; // category-tree\n\n $container.html(html);\n\n // Update results count with appropriate label\n var selectedCount = $container.find('.tree-item.selected').length;\n this.$dropdown.find('.results-count').text(categories.length + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));\n\n // Update select-children button states based on initial selection\n var $allItems = $container.find('.tree-item');\n this.updateSelectChildrenButtons($allItems);\n\n // Hide load more controls in tree view\n this.$dropdown.find('.load-more-controls').hide();\n },\n\n /**\n * Filter category tree by search query (client-side filtering)\n */\n filterCategoryTree: function(query) {\n var self = this;\n var $container = this.$dropdown.find('.category-tree');\n if (!$container.length) {\n return;\n }\n\n var $items = $container.find('.tree-item');\n query = query.toLowerCase().trim();\n\n if (!query) {\n // Show all items when query is empty\n $items.show().removeClass('collapsed');\n $container.find('.tree-toggle i').removeClass('icon-caret-right').addClass('icon-caret-down');\n return;\n }\n\n // First pass: find matching items and their ancestors\n var matchingIds = [];\n var ancestorIds = [];\n\n $items.each(function() {\n var $item = $(this);\n var name = ($item.data('name') || '').toLowerCase();\n if (name.indexOf(query) !== -1) {\n matchingIds.push($item.data('id'));\n // Also mark all ancestors using helper (works for both nleft/nright and parent_id)\n var ancestors = self.findTreeAncestors($item, $items);\n for (var i = 0; i < ancestors.length; i++) {\n ancestorIds.push($(ancestors[i]).data('id'));\n }\n }\n });\n\n // Second pass: show/hide items\n $items.each(function() {\n var $item = $(this);\n var id = $item.data('id');\n if (matchingIds.indexOf(id) !== -1 || ancestorIds.indexOf(id) !== -1) {\n $item.show().removeClass('collapsed');\n $item.find('.tree-toggle i').removeClass('icon-caret-right').addClass('icon-caret-down');\n } else {\n $item.hide();\n }\n });\n\n // Update count with appropriate label\n var visibleCount = $items.filter(':visible').length;\n var selectedCount = $items.filter('.selected').length;\n var entityType = $container.data('entity-type') || 'categories';\n var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';\n this.$dropdown.find('.results-count').text(visibleCount + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));\n },\n\n /**\n * Find all descendant tree items of a parent.\n * Works with nleft/nright (product categories) or parent_id (CMS categories).\n */\n findTreeDescendants: function($parent, $allItems) {\n var nleft = parseInt($parent.data('nleft'), 10);\n var nright = parseInt($parent.data('nright'), 10);\n var parentId = parseInt($parent.data('id'), 10);\n var descendants = [];\n\n // If nleft/nright are valid (product categories), use nested set\n if (nleft > 0 && nright > 0 && nright > nleft) {\n $allItems.each(function() {\n var $item = $(this);\n var childNleft = parseInt($item.data('nleft'), 10);\n var childNright = parseInt($item.data('nright'), 10);\n if (childNleft > nleft && childNright < nright) {\n descendants.push($item);\n }\n });\n } else {\n // CMS categories: use parent_id recursively\n var idsToCheck = [parentId];\n var processed = {};\n\n while (idsToCheck.length > 0) {\n var checkId = idsToCheck.shift();\n if (processed[checkId]) continue;\n processed[checkId] = true;\n\n $allItems.each(function() {\n var $item = $(this);\n var itemParentId = parseInt($item.data('parent-id'), 10);\n var itemId = parseInt($item.data('id'), 10);\n if (itemParentId === checkId && !processed[itemId]) {\n descendants.push($item);\n idsToCheck.push(itemId);\n }\n });\n }\n }\n\n return descendants;\n },\n\n /**\n * Find all ancestor tree items of an item.\n * Works with nleft/nright (product categories) or parent_id (CMS categories).\n */\n findTreeAncestors: function($item, $allItems) {\n var nleft = parseInt($item.data('nleft'), 10);\n var nright = parseInt($item.data('nright'), 10);\n var ancestors = [];\n\n // If nleft/nright are valid (product categories), use nested set\n if (nleft > 0 && nright > 0) {\n $allItems.each(function() {\n var $ancestor = $(this);\n var ancNleft = parseInt($ancestor.data('nleft'), 10);\n var ancNright = parseInt($ancestor.data('nright'), 10);\n if (ancNleft < nleft && ancNright > nright) {\n ancestors.push($ancestor);\n }\n });\n } else {\n // CMS categories: use parent_id chain\n var parentId = parseInt($item.data('parent-id'), 10);\n var processed = {};\n\n while (parentId > 0 && !processed[parentId]) {\n processed[parentId] = true;\n $allItems.each(function() {\n var $ancestor = $(this);\n var ancestorId = parseInt($ancestor.data('id'), 10);\n if (ancestorId === parentId) {\n ancestors.push($ancestor);\n parentId = parseInt($ancestor.data('parent-id'), 10);\n return false; // break inner loop\n }\n });\n }\n }\n\n return ancestors;\n },\n\n /**\n * Update all select-children buttons to reflect current selection state.\n * Shows minus icon if item and all children are selected, plus icon otherwise.\n */\n updateSelectChildrenButtons: function($allItems) {\n var self = this;\n var trans = this.config.trans || {};\n\n $allItems.filter('.has-children').each(function() {\n var $item = $(this);\n var $btn = $item.find('.btn-select-children');\n if (!$btn.length) return;\n\n var descendants = self.findTreeDescendants($item, $allItems);\n\n // Check if parent and ALL descendants are selected\n var allSelected = $item.hasClass('selected');\n for (var i = 0; i < descendants.length && allSelected; i++) {\n if (!$(descendants[i]).hasClass('selected')) {\n allSelected = false;\n }\n }\n\n // Update button icon and title\n if (allSelected && descendants.length > 0) {\n $btn.find('i').removeClass('icon-plus-square').addClass('icon-minus-square');\n $btn.attr('title', trans.deselect_with_children || 'Deselect with all children');\n } else {\n $btn.find('i').removeClass('icon-minus-square').addClass('icon-plus-square');\n $btn.attr('title', trans.select_with_children || 'Select with all children');\n }\n });\n },\n\n // =========================================================================\n // Search History\n // =========================================================================\n\n loadSearchHistory: function() {\n try {\n var stored = localStorage.getItem(this.searchHistoryKey);\n this.searchHistory = stored ? JSON.parse(stored) : {};\n } catch (e) {\n this.searchHistory = {};\n }\n },\n\n saveSearchHistory: function() {\n try {\n localStorage.setItem(this.searchHistoryKey, JSON.stringify(this.searchHistory));\n } catch (e) {\n // localStorage might be full or unavailable\n }\n },\n\n addToSearchHistory: function(entityType, query) {\n if (!query || query.length < 2) return;\n\n if (!this.searchHistory[entityType]) {\n this.searchHistory[entityType] = [];\n }\n\n var history = this.searchHistory[entityType];\n\n // Remove if already exists (will re-add at top)\n var existingIndex = history.indexOf(query);\n if (existingIndex !== -1) {\n history.splice(existingIndex, 1);\n }\n\n // Add at beginning\n history.unshift(query);\n\n // Trim to max\n if (history.length > this.searchHistoryMax) {\n history = history.slice(0, this.searchHistoryMax);\n }\n\n this.searchHistory[entityType] = history;\n this.saveSearchHistory();\n },\n\n removeFromSearchHistory: function(entityType, query) {\n if (!this.searchHistory[entityType]) return;\n\n var index = this.searchHistory[entityType].indexOf(query);\n if (index !== -1) {\n this.searchHistory[entityType].splice(index, 1);\n this.saveSearchHistory();\n }\n },\n\n getSearchHistory: function(entityType) {\n return this.searchHistory[entityType] || [];\n },\n\n showSearchHistory: function(entityType) {\n var history = this.getSearchHistory(entityType);\n var trans = this.config.trans || {};\n var $container = this.$dropdown.find('.dropdown-results');\n\n // Update header\n this.$dropdown.find('.results-count').text(trans.recent_searches || 'Recent searches');\n\n // Hide filters, actions, and results header for history view\n this.$dropdown.find('.dropdown-actions').hide();\n this.$dropdown.find('.filter-panel').removeClass('show');\n this.$dropdown.find('.btn-toggle-filters').removeClass('active');\n this.$dropdown.find('.results-header').hide();\n\n if (!history.length) {\n // No history - just do a regular search\n this.performSearch();\n return;\n }\n\n // Build history items\n var html = '
';\n for (var i = 0; i < history.length; i++) {\n var query = history[i];\n html += '
';\n html += '';\n html += '' + this.escapeHtml(query) + '';\n html += '';\n html += '';\n html += '';\n html += '
';\n }\n html += '
';\n\n $container.html(html);\n this.$dropdown.addClass('show');\n },\n\n // =========================================================================\n // Filter Methods\n // =========================================================================\n\n refreshSearch: function() {\n // In tree view mode, re-filter the tree instead of doing a flat AJAX search\n if (this.viewMode === 'tree') {\n this.filterCategoryTree(this.searchQuery || '');\n return;\n }\n\n this.searchOffset = 0;\n this.loadMoreCount = 20;\n // Reset load more select to default\n if (this.$dropdown) {\n this.$dropdown.find('.load-more-select').val('20');\n // Remove the dynamic \"All\" option\n this.$dropdown.find('.load-more-select option[data-all=\"true\"]').remove();\n }\n this.performSearch(false);\n },\n\n clearFilters: function() {\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n // Entity-specific filters\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n\n if (this.$dropdown) {\n var trans = this.config.trans || {};\n this.$dropdown.find('.refine-input').val('').attr('placeholder', trans.refine_short || 'Refine...');\n this.$dropdown.find('.btn-clear-refine').hide();\n this.$dropdown.find('.btn-refine-negate').removeClass('active');\n this.$dropdown.find('.filter-in-stock').prop('checked', false);\n this.$dropdown.find('.filter-discounted').prop('checked', false);\n this.$dropdown.find('.filter-price-min').val('');\n this.$dropdown.find('.filter-price-max').val('');\n this.$dropdown.find('.filter-attr-chip').removeClass('active');\n this.$dropdown.find('.filter-feat-chip').removeClass('active');\n this.$dropdown.find('.filter-group-toggle').removeClass('active has-selection');\n this.$dropdown.find('.filter-row-values').hide();\n\n // Clear entity-specific filter inputs\n this.$dropdown.find('.filter-product-count-min, .filter-product-count-max').val('');\n this.$dropdown.find('.filter-sales-min, .filter-sales-max').val('');\n this.$dropdown.find('.filter-turnover-min, .filter-turnover-max').val('');\n this.$dropdown.find('.filter-date-add-from, .filter-date-add-to').val('');\n this.$dropdown.find('.filter-last-product-from, .filter-last-product-to').val('');\n this.$dropdown.find('.filter-depth-select').val('');\n this.$dropdown.find('.filter-has-products').prop('checked', false);\n this.$dropdown.find('.filter-has-description').prop('checked', false);\n this.$dropdown.find('.filter-has-image').prop('checked', false);\n this.$dropdown.find('.filter-active-only').prop('checked', true);\n this.$dropdown.find('.filter-attribute-group-select, .filter-feature-group-select').val('');\n }\n\n this.refreshSearch();\n },\n\n // Reset filters without triggering a search (used when switching entity types)\n resetFiltersWithoutSearch: function() {\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n\n if (this.$dropdown) {\n var trans = this.config.trans || {};\n this.$dropdown.find('.refine-input').val('').attr('placeholder', trans.refine_short || 'Refine...');\n this.$dropdown.find('.btn-clear-refine').hide();\n this.$dropdown.find('.btn-refine-negate').removeClass('active');\n this.$dropdown.find('.filter-in-stock').prop('checked', false);\n this.$dropdown.find('.filter-discounted').prop('checked', false);\n this.$dropdown.find('.filter-price-min').val('');\n this.$dropdown.find('.filter-price-max').val('');\n this.$dropdown.find('.filter-attr-chip').removeClass('active');\n this.$dropdown.find('.filter-feat-chip').removeClass('active');\n this.$dropdown.find('.filter-group-toggle').removeClass('active has-selection');\n this.$dropdown.find('.filter-row-values').hide();\n this.$dropdown.find('.filter-product-count-min, .filter-product-count-max').val('');\n this.$dropdown.find('.filter-sales-min, .filter-sales-max').val('');\n this.$dropdown.find('.filter-turnover-min, .filter-turnover-max').val('');\n this.$dropdown.find('.filter-date-add-from, .filter-date-add-to').val('');\n this.$dropdown.find('.filter-last-product-from, .filter-last-product-to').val('');\n this.$dropdown.find('.filter-depth-select').val('');\n this.$dropdown.find('.filter-has-products').prop('checked', false);\n this.$dropdown.find('.filter-has-description').prop('checked', false);\n this.$dropdown.find('.filter-has-image').prop('checked', false);\n this.$dropdown.find('.filter-active-only').prop('checked', true);\n this.$dropdown.find('.filter-attribute-group-select, .filter-feature-group-select').val('');\n }\n // Note: Does NOT call refreshSearch() - caller handles search/load\n },\n\n updateFilterPanelForEntity: function(entityType) {\n if (!this.$dropdown) {\n return;\n }\n\n var $panel = this.$dropdown.find('.filter-panel');\n\n // Hide all filter rows first\n $panel.find('.filter-row').hide();\n\n // Show/hide tree view option based on entity type\n var $treeOption = this.$dropdown.find('.view-mode-select option.tree-view-option');\n if (entityType === 'categories' || entityType === 'cms_categories') {\n $treeOption.prop('disabled', false).prop('hidden', false);\n // Auto-switch to tree view for categories\n if (this.viewMode !== 'tree') {\n this.viewMode = 'tree';\n this.$dropdown.find('.view-mode-select').val('tree');\n this.$dropdown.removeClass('view-list view-cols-2 view-cols-3 view-cols-4 view-cols-5 view-cols-6 view-cols-7 view-cols-8').addClass('view-tree');\n this.loadCategoryTree();\n } else {\n this.loadCategoryTree();\n }\n } else {\n $treeOption.prop('disabled', true).prop('hidden', true);\n // If currently in tree mode, switch back to list\n if (this.viewMode === 'tree') {\n this.viewMode = 'list';\n this.$dropdown.find('.view-mode-select').val('list');\n this.$dropdown.removeClass('view-tree').addClass('view-list');\n }\n }\n\n // Show entity-specific filter row (prepare visibility, but don't auto-expand panel)\n if (entityType === 'products') {\n // Prepare the correct rows to be visible when panel is shown\n $panel.find('.filter-row-quick').show();\n // Show attribute/feature rows if we have cached data\n if (this.filterableData) {\n if (this.filterableData.attributes && this.filterableData.attributes.length > 0) {\n this.$dropdown.find('.filter-row-attributes').show();\n }\n if (this.filterableData.features && this.filterableData.features.length > 0) {\n this.$dropdown.find('.filter-row-features').show();\n }\n }\n } else if (entityType === 'categories') {\n $panel.find('.filter-row-entity-categories').show();\n } else if (entityType === 'manufacturers') {\n $panel.find('.filter-row-entity-manufacturers').show();\n } else if (entityType === 'suppliers') {\n $panel.find('.filter-row-entity-suppliers').show();\n } else if (entityType === 'attributes') {\n $panel.find('.filter-row-entity-attributes').show();\n this.loadAttributeGroups();\n } else if (entityType === 'features') {\n $panel.find('.filter-row-entity-features').show();\n } else if (entityType === 'cms') {\n $panel.find('.filter-row-entity-cms').show();\n } else if (entityType === 'cms_categories') {\n $panel.find('.filter-row-entity-cms-categories').show();\n }\n },\n\n loadAttributeGroups: function() {\n var self = this;\n var $select = this.$dropdown.find('.filter-attribute-group-select');\n\n // Already loaded?\n if ($select.find('option').length > 1) return;\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getAttributeGroups',\n trait: 'EntitySelector'\n },\n success: function(response) {\n if (response.success && response.groups) {\n $.each(response.groups, function(i, group) {\n $select.append('');\n });\n }\n }\n });\n },\n\n loadFeatureGroups: function() {\n var self = this;\n var $select = this.$dropdown.find('.filter-feature-group-select');\n\n // Already loaded?\n if ($select.find('option').length > 1) return;\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getFeatureGroups',\n trait: 'EntitySelector'\n },\n success: function(response) {\n if (response.success && response.groups) {\n $.each(response.groups, function(i, group) {\n $select.append('');\n });\n }\n }\n });\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Filters Module\n * Filter panel, filter state management\n * @partial _filters.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 6605-6758 (filter methods)\n *\n * Contains:\n * - clearFilters() - Reset all filters\n * - resetFiltersWithoutSearch() - Reset without triggering search\n * - updateFilterPanelForEntity() - Show/hide filters based on entity type\n * - loadFilterableData() - Load attributes/features for filter panel\n * - renderFilterDropdowns() - Render attribute/feature group toggles\n * - showFilterGroupValues() - Show values for a filter group\n * - hideFilterGroupValues() - Hide filter values row\n * - updateFilterToggleStates() - Update toggle states based on selections\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.filters = {\n\n clearFilters: function() {\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n\n if (this.$dropdown) {\n var trans = this.config.trans || {};\n this.$dropdown.find('.refine-input').val('');\n this.$dropdown.find('.btn-refine-negate').removeClass('active');\n this.$dropdown.find('.filter-in-stock').prop('checked', false);\n this.$dropdown.find('.filter-discounted').prop('checked', false);\n this.$dropdown.find('.filter-price-min, .filter-price-max').val('');\n this.$dropdown.find('.filter-attr-chip, .filter-feat-chip').removeClass('active');\n this.$dropdown.find('.filter-product-count-min, .filter-product-count-max').val('');\n this.$dropdown.find('.filter-sales-min, .filter-sales-max').val('');\n this.$dropdown.find('.filter-depth-select').val('');\n this.$dropdown.find('.filter-has-products').prop('checked', false);\n this.$dropdown.find('.filter-active-only').prop('checked', true);\n }\n\n this.refreshSearch();\n },\n\n resetFiltersWithoutSearch: function() {\n // Same as clearFilters but doesn't trigger search\n // Used when switching entity types\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n },\n\n updateFilterPanelForEntity: function(entityType) {\n if (!this.$dropdown) return;\n\n var $panel = this.$dropdown.find('.filter-panel');\n\n // Hide all entity-specific filter rows\n $panel.find('.filter-row').hide();\n\n // Show filters for current entity type\n $panel.find('.filter-row[data-entity=\"' + entityType + '\"]').show();\n $panel.find('.filter-row-entity-' + entityType.replace('_', '-')).show();\n\n // Enable/disable tree view option\n var $treeOption = this.$dropdown.find('.tree-view-option');\n if (entityType === 'categories' || entityType === 'cms_categories') {\n $treeOption.prop('disabled', false).show();\n } else {\n $treeOption.prop('disabled', true).hide();\n }\n },\n\n loadFilterableData: function() {\n var self = this;\n\n if (this.filterableData) {\n this.renderFilterDropdowns();\n return;\n }\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n data: {\n ajax: 1,\n action: 'getTargetFilterableAttributes',\n trait: 'EntitySelector'\n },\n dataType: 'json',\n success: function(response) {\n if (response.success && response.data) {\n self.filterableData = response.data;\n self.renderFilterDropdowns();\n }\n }\n });\n },\n\n renderFilterDropdowns: function() {\n if (!this.$dropdown || !this.filterableData) return;\n\n var self = this;\n\n // Render attribute group toggle buttons\n var $attrContainer = this.$dropdown.find('.filter-attributes-container');\n $attrContainer.empty();\n\n if (this.filterableData.attributes && this.filterableData.attributes.length > 0) {\n this.filterableData.attributes.forEach(function(group) {\n var html = '';\n html += '' + group.name + '';\n if (group.count !== undefined) {\n html += ' ' + group.count + '';\n }\n html += '';\n $attrContainer.append(html);\n });\n this.$dropdown.find('.filter-row-attributes').show();\n }\n\n // Render feature group toggle buttons\n var $featContainer = this.$dropdown.find('.filter-features-container');\n $featContainer.empty();\n\n if (this.filterableData.features && this.filterableData.features.length > 0) {\n this.filterableData.features.forEach(function(group) {\n var html = '';\n html += '' + group.name + '';\n if (group.count !== undefined) {\n html += ' ' + group.count + '';\n }\n html += '';\n $featContainer.append(html);\n });\n this.$dropdown.find('.filter-row-features').show();\n }\n },\n\n showFilterGroupValues: function(groupId, type) {\n if (!this.filterableData) return;\n\n var self = this;\n var groups = type === 'attribute' ? this.filterableData.attributes : this.filterableData.features;\n var group = groups.find(function(g) { return g.id == groupId; });\n\n if (!group) return;\n\n // Hide all values rows first, then show the correct one\n this.$dropdown.find('.filter-row-values').hide();\n\n // Target the correct values row based on type\n var valuesRowClass = type === 'attribute' ? '.filter-row-attr-values' : '.filter-row-feat-values';\n var $filterRowValues = this.$dropdown.find(valuesRowClass);\n var $valuesContainer = $filterRowValues.find('.filter-values-container');\n $valuesContainer.empty();\n\n // Add group label\n var html = '' + group.name + ':';\n\n // Add chips\n group.values.forEach(function(val) {\n var isActive = type === 'attribute'\n ? self.filters.attributes.indexOf(val.id) !== -1\n : self.filters.features.indexOf(val.id) !== -1;\n var activeClass = isActive ? ' active' : '';\n var chipClass = type === 'attribute' ? 'filter-attr-chip' : 'filter-feat-chip';\n var colorStyle = val.color ? ' style=\"--chip-color: ' + val.color + '\"' : '';\n var colorClass = val.color ? ' has-color' : '';\n\n html += '';\n if (val.color) {\n html += '';\n }\n html += '' + val.name + '';\n if (val.count !== undefined) {\n html += '(' + val.count + ')';\n }\n html += '';\n });\n\n $valuesContainer.html(html);\n\n // Add close button as sibling (outside filter-values-container, inside filter-row-values)\n $filterRowValues.find('.btn-close-values').remove();\n $filterRowValues.append('');\n $filterRowValues.show();\n\n // Scroll into view if needed\n var rowValues = $filterRowValues[0];\n if (rowValues) {\n rowValues.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n },\n\n hideFilterGroupValues: function() {\n this.$dropdown.find('.filter-row-values').hide();\n this.$dropdown.find('.filter-group-toggle').removeClass('active');\n },\n\n updateFilterToggleStates: function() {\n if (!this.$dropdown || !this.filterableData) return;\n\n var self = this;\n\n // Update attribute group toggles\n if (this.filterableData.attributes) {\n this.filterableData.attributes.forEach(function(group) {\n var $toggle = self.$dropdown.find('.filter-group-toggle[data-group-id=\"' + group.id + '\"][data-type=\"attribute\"]');\n var hasActiveInGroup = group.values.some(function(val) {\n return self.filters.attributes.indexOf(val.id) !== -1;\n });\n $toggle.toggleClass('has-selection', hasActiveInGroup);\n });\n }\n\n // Update feature group toggles\n if (this.filterableData.features) {\n this.filterableData.features.forEach(function(group) {\n var $toggle = self.$dropdown.find('.filter-group-toggle[data-group-id=\"' + group.id + '\"][data-type=\"feature\"]');\n var hasActiveInGroup = group.values.some(function(val) {\n return self.filters.features.indexOf(val.id) !== -1;\n });\n $toggle.toggleClass('has-selection', hasActiveInGroup);\n });\n }\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Chips Module\n * Entity chip rendering, selection management, and pattern tag handling\n * @partial _chips.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n *\n * Contains:\n * - addSelection() / addSelectionNoUpdate() - Add entity chip to picker\n * - removeSelection() - Remove chip and update state\n * - updateChipsVisibility() - Show/hide based on count\n * - loadExistingSelections() - Load saved values on init\n * - collectPickerEntities() / loadPickerValues() - Entity loading helpers\n * - Pattern tag methods: addPatternTag, getPatternTags, updateDraftTagCount\n * - Single mode: getCurrentSingleSelection, showReplaceConfirmation\n * - Count updates: updateConditionCount, updateGroupCounts, updateGroupTotalCount\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.chips = {\n\n // =========================================================================\n // Selection Methods (Entity Chips)\n // =========================================================================\n\n addSelection: function($picker, id, name, data) {\n this.addSelectionNoUpdate($picker, id, name, data);\n var $chips = $picker.find('.entity-chips');\n this.updateChipsVisibility($chips);\n },\n\n addSelectionNoUpdate: function($picker, id, name, data) {\n var $chips = $picker.find('.entity-chips');\n var $block = $picker.closest('.target-block');\n\n // Check for global single mode (only ONE item across ALL entity types)\n var globalMode = this.config.mode || 'multi';\n\n if (globalMode === 'single') {\n // Clear ALL selections in ALL blocks (across all entity types)\n this.$wrapper.find('.entity-chips .entity-chip').remove();\n // Clear all selected states in dropdown\n if (this.$dropdown) {\n this.$dropdown.find('.dropdown-item.selected, .tree-item.selected').removeClass('selected');\n }\n // Clear tab badges (since we're clearing other blocks)\n this.$wrapper.find('.target-block-tab .tab-badge').remove();\n this.$wrapper.find('.target-block-tab').removeClass('has-data');\n } else {\n // Check if this block is in per-block single mode\n var blockMode = $block.data('mode') || 'multi';\n\n // In per-block single mode, clear chips in THIS block only\n if (blockMode === 'single') {\n $chips.find('.entity-chip').remove();\n // Also deselect all items in dropdown\n if (this.$dropdown) {\n this.$dropdown.find('.dropdown-item.selected, .tree-item.selected').removeClass('selected');\n }\n }\n }\n\n if ($chips.find('.entity-chip[data-id=\"' + id + '\"]').length) {\n return;\n }\n\n var html = '';\n\n if (data && data.image) {\n html += '';\n }\n\n html += '' + this.escapeHtml(name) + '';\n html += '';\n html += '';\n\n $chips.append(html);\n },\n\n removeSelection: function($picker, id) {\n var $chips = $picker.find('.entity-chips');\n $picker.find('.entity-chip[data-id=\"' + id + '\"]').remove();\n this.updateChipsVisibility($chips);\n },\n\n updateChipsVisibility: function($chips) {\n var self = this;\n var $allChips = $chips.find('.entity-chip');\n var totalCount = $allChips.length;\n var $toggle = $chips.find('.chips-show-more-toggle');\n var isExpanded = $chips.hasClass('chips-expanded');\n var trans = this.config.trans || {};\n\n // Remove existing toggle if present\n $toggle.remove();\n\n if (totalCount <= this.maxVisibleChips) {\n // All chips visible, no toggle needed\n $allChips.removeClass('chip-hidden');\n $chips.removeClass('chips-expanded chips-collapsed');\n return;\n }\n\n // We have more than maxVisibleChips\n var hiddenCount = totalCount - this.maxVisibleChips;\n\n if (isExpanded) {\n // Show all chips\n $allChips.removeClass('chip-hidden');\n\n // Add collapse toggle\n var collapseText = trans.show_less || 'Show less';\n $chips.append('' +\n ' ' + collapseText + '');\n } else {\n // Hide chips beyond maxVisibleChips\n $allChips.each(function(index) {\n if (index >= self.maxVisibleChips) {\n $(this).addClass('chip-hidden');\n } else {\n $(this).removeClass('chip-hidden');\n }\n });\n\n // Add expand toggle\n var moreText = (trans.show_more || 'Show {count} more').replace('{count}', hiddenCount);\n $chips.addClass('chips-collapsed').removeClass('chips-expanded');\n $chips.append('' +\n ' ' + moreText + '');\n }\n },\n\n // =========================================================================\n // Loading/Initialization\n // =========================================================================\n\n loadExistingSelections: function() {\n var self = this;\n\n // Collect all entity IDs to load, grouped by entity type\n var entitiesToLoad = {}; // { entity_type: { ids: [], pickers: [] } }\n\n this.$wrapper.find('.selection-group').each(function() {\n var $group = $(this);\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType');\n\n // Load include values\n var $includePicker = $group.find('.include-picker');\n self.collectPickerEntities($includePicker, blockType, entitiesToLoad);\n\n // Enhance the include method select if not already enhanced\n self.enhanceMethodSelect($group.find('.include-method-select'));\n\n // Load exclude values from each exclude row\n $group.find('.exclude-row').each(function() {\n var $excludeRow = $(this);\n self.collectPickerEntities($excludeRow.find('.exclude-picker'), blockType, entitiesToLoad);\n\n // Enhance the exclude method select if not already enhanced\n self.enhanceMethodSelect($excludeRow.find('.exclude-method-select'));\n });\n\n // Lock method selector if excludes exist\n var hasExcludes = $group.find('.group-excludes.has-excludes').length > 0;\n if (hasExcludes) {\n self.updateMethodSelectorLock($group, true);\n }\n });\n\n // Now load all entities in bulk for each entity type\n Object.keys(entitiesToLoad).forEach(function(entityType) {\n var data = entitiesToLoad[entityType];\n if (data.ids.length === 0) return;\n\n // Deduplicate IDs\n var uniqueIds = data.ids.filter(function(id, index, arr) {\n return arr.indexOf(id) === index;\n });\n\n $.ajax({\n url: self.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getTargetEntitiesByIds',\n trait: 'EntitySelector',\n entity_type: entityType,\n ids: JSON.stringify(uniqueIds)\n },\n success: function(response) {\n if (response.success && response.entities) {\n // Build a map of id -> entity for quick lookup\n var entityMap = {};\n response.entities.forEach(function(entity) {\n entityMap[entity.id] = entity;\n });\n\n // Update each picker that requested this entity type\n data.pickers.forEach(function(pickerData) {\n var $picker = pickerData.$picker;\n var $chips = $picker.find('.entity-chips');\n var $dataInput = $picker.find('.include-values-data, .exclude-values-data');\n var validIds = [];\n\n // Replace loading chips with real data\n pickerData.ids.forEach(function(id) {\n var $loadingChip = $chips.find('.entity-chip-loading[data-id=\"' + id + '\"]');\n if (entityMap[id]) {\n var entity = entityMap[id];\n validIds.push(entity.id);\n\n // Create real chip\n var html = '';\n if (entity.image) {\n html += '';\n }\n html += '' + self.escapeHtml(entity.name) + '';\n html += '';\n html += '';\n\n $loadingChip.replaceWith(html);\n } else {\n // Entity not found, remove loading chip\n $loadingChip.remove();\n }\n });\n\n // Update chips visibility\n self.updateChipsVisibility($chips);\n\n // If some entities were not found, update the hidden input\n if (validIds.length !== pickerData.ids.length) {\n $dataInput.val(JSON.stringify(validIds));\n self.serializeAllBlocks();\n }\n\n self.updateBlockStatus($picker.closest('.target-block'));\n });\n }\n }\n });\n });\n },\n\n /**\n * Collect entity IDs from a picker for bulk loading\n * Also shows loading placeholders for entity_search types\n */\n collectPickerEntities: function($picker, blockType, entitiesToLoad) {\n if (!$picker.length) {\n return;\n }\n\n var self = this;\n var $dataInput = $picker.find('.include-values-data, .exclude-values-data');\n if (!$dataInput.length) {\n return;\n }\n\n var valueType = $picker.attr('data-value-type');\n var rawValue = $dataInput.val() || '[]';\n\n var values = [];\n try {\n values = JSON.parse(rawValue);\n } catch (e) {\n return;\n }\n\n // Handle non-entity types synchronously\n if (valueType === 'multi_numeric_range') {\n if (!Array.isArray(values) || values.length === 0) return;\n\n var $chipsContainer = $picker.find('.multi-range-chips');\n values.forEach(function(range) {\n if (!range || (range.min === null && range.max === null)) return;\n\n var chipText = '';\n if (range.min !== null && range.max !== null) {\n chipText = range.min + ' - ' + range.max;\n } else if (range.min !== null) {\n chipText = '≥ ' + range.min;\n } else {\n chipText = '≤ ' + range.max;\n }\n\n var $chip = $('', {\n class: 'range-chip',\n 'data-min': range.min !== null ? range.min : '',\n 'data-max': range.max !== null ? range.max : ''\n });\n $chip.append($('', { class: 'range-chip-text', text: chipText }));\n $chip.append($('', {\n type: 'button',\n class: 'btn-remove-range',\n html: ''\n }));\n\n $chipsContainer.append($chip);\n });\n return;\n }\n\n if (valueType === 'multi_select_tiles') {\n if (!Array.isArray(values) || values.length === 0) return;\n\n values.forEach(function(key) {\n $picker.find('.tile-option[data-value=\"' + key + '\"]').addClass('selected');\n });\n return;\n }\n\n if (valueType === 'combination_attributes') {\n if (typeof values !== 'object' || values === null || Object.keys(values).length === 0) {\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n $dataInput.val(JSON.stringify(values));\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n if (!values.length) {\n return;\n }\n\n if (valueType === 'pattern') {\n values.forEach(function(item) {\n if (typeof item === 'string' && item) {\n self.addPatternTag($picker, item, false);\n } else if (item && item.pattern) {\n self.addPatternTag($picker, item.pattern, item.caseSensitive === true);\n }\n });\n return;\n }\n\n // For entity_search type - show loading placeholders and collect for bulk load\n var searchEntity = $picker.attr('data-search-entity') || blockType;\n var $chips = $picker.find('.entity-chips');\n\n // Get icon for entity type\n var entityIcon = this.getEntityTypeIcon(searchEntity);\n\n // Show loading placeholders with entity-specific icons\n values.forEach(function(id) {\n var html = '';\n html += '';\n html += 'Loading...';\n html += '';\n $chips.append(html);\n });\n\n // Collect for bulk load\n if (!entitiesToLoad[searchEntity]) {\n entitiesToLoad[searchEntity] = { ids: [], pickers: [] };\n }\n entitiesToLoad[searchEntity].ids = entitiesToLoad[searchEntity].ids.concat(values);\n entitiesToLoad[searchEntity].pickers.push({\n $picker: $picker,\n ids: values\n });\n },\n\n loadPickerValues: function($picker, blockType) {\n // This function is now only used for dynamic loading (not initial load)\n // Initial load uses collectPickerEntities + bulk AJAX\n if (!$picker.length) return;\n\n var self = this;\n var $dataInput = $picker.find('.include-values-data, .exclude-values-data');\n if (!$dataInput.length) return;\n\n var valueType = $picker.attr('data-value-type');\n var values = [];\n try {\n values = JSON.parse($dataInput.val() || '[]');\n } catch (e) {\n return;\n }\n\n // Handle empty/missing values based on type\n if (valueType === 'multi_numeric_range') {\n // For multi_numeric_range, values is an array of {min, max} objects\n if (!Array.isArray(values) || values.length === 0) return;\n\n var $chipsContainer = $picker.find('.multi-range-chips');\n values.forEach(function(range) {\n if (!range || (range.min === null && range.max === null)) return;\n\n var chipText = '';\n if (range.min !== null && range.max !== null) {\n chipText = range.min + ' - ' + range.max;\n } else if (range.min !== null) {\n chipText = '≥ ' + range.min;\n } else {\n chipText = '≤ ' + range.max;\n }\n\n var $chip = $('', {\n class: 'range-chip',\n 'data-min': range.min !== null ? range.min : '',\n 'data-max': range.max !== null ? range.max : ''\n });\n $chip.append($('', { class: 'range-chip-text', text: chipText }));\n $chip.append($('', {\n type: 'button',\n class: 'btn-remove-range',\n html: ''\n }));\n\n $chipsContainer.append($chip);\n });\n return;\n }\n\n if (valueType === 'multi_select_tiles') {\n // For multi_select_tiles, values is an array of selected keys\n if (!Array.isArray(values) || values.length === 0) return;\n\n values.forEach(function(key) {\n $picker.find('.tile-option[data-value=\"' + key + '\"]').addClass('selected');\n });\n return;\n }\n\n if (valueType === 'combination_attributes') {\n // For combination_attributes, values is an object: { groupId: [valueId1, valueId2], ... }\n if (typeof values !== 'object' || values === null || Object.keys(values).length === 0) {\n // Still need to load the attribute groups UI\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n // Store data in hidden input for later restoration\n $dataInput.val(JSON.stringify(values));\n\n // Load attribute groups and values will be restored after loading\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n if (!values.length) return;\n\n // Handle pattern type - load as tags\n // Supports both old format (array of strings) and new format (array of {pattern, caseSensitive})\n if (valueType === 'pattern') {\n values.forEach(function(item) {\n if (typeof item === 'string' && item) {\n // Old format: just a string (default to case-insensitive)\n self.addPatternTag($picker, item, false);\n } else if (item && item.pattern) {\n // New format: object with pattern and caseSensitive\n self.addPatternTag($picker, item.pattern, item.caseSensitive === true);\n }\n });\n return;\n }\n\n // Handle entity_search type - load via AJAX\n var searchEntity = $picker.attr('data-search-entity') || blockType;\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getTargetEntitiesByIds',\n trait: 'EntitySelector',\n entity_type: searchEntity,\n ids: JSON.stringify(values)\n },\n success: function(response) {\n if (response.success && response.entities) {\n // Track which IDs were actually found (entities may have been deleted)\n var validIds = [];\n response.entities.forEach(function(entity) {\n // Use addSelectionNoUpdate to avoid multiple visibility updates\n self.addSelectionNoUpdate($picker, entity.id, entity.name, entity);\n validIds.push(entity.id);\n });\n\n // Update chips visibility once after all chips are added\n var $chips = $picker.find('.entity-chips');\n self.updateChipsVisibility($chips);\n\n // If some entities were not found, update the hidden input to remove orphaned IDs\n if (validIds.length !== values.length) {\n $dataInput.val(JSON.stringify(validIds));\n // Re-serialize to update the main form data\n self.serializeAllBlocks();\n }\n\n self.updateBlockStatus($picker.closest('.target-block'));\n }\n }\n });\n },\n\n // =========================================================================\n // Pattern Tag Methods\n // =========================================================================\n\n /**\n * Add a pattern tag to the pattern chips container\n */\n addPatternTag: function($wrapper, pattern, caseSensitive) {\n var trans = this.config.trans || {};\n var $chipsContainer = $wrapper.find('.pattern-chips');\n // Default to case-insensitive (false)\n var isCaseSensitive = caseSensitive === true;\n var caseTitle = isCaseSensitive\n ? (trans.case_sensitive || 'Case sensitive - click to toggle')\n : (trans.case_insensitive || 'Case insensitive - click to toggle');\n\n var html = '
';\n html += '';\n html += '' + (isCaseSensitive ? 'Aa' : 'aa') + '';\n html += '';\n html += '' + this.escapeHtml(pattern) + '';\n html += '';\n html += '
';\n $chipsContainer.append(html);\n },\n\n /**\n * Get all pattern tags from a wrapper\n * Returns array of objects: { pattern: string, caseSensitive: boolean }\n */\n getPatternTags: function($wrapper) {\n var patterns = [];\n // Exclude draft-tag which is the input field, not a saved pattern\n $wrapper.find('.pattern-tag:not(.draft-tag)').each(function() {\n var pattern = $(this).data('pattern');\n var caseSensitive = $(this).data('caseSensitive') === 1 || $(this).data('caseSensitive') === '1';\n if (pattern) {\n patterns.push({\n pattern: pattern,\n caseSensitive: caseSensitive\n });\n }\n });\n return patterns;\n },\n\n /**\n * Update the match count displayed in the draft tag while typing\n * Shows live preview with current case sensitivity setting\n */\n updateDraftTagCount: function($draftTag, pattern, caseSensitive) {\n var self = this;\n var $matchCount = $draftTag.find('.pattern-match-count');\n var $countValue = $matchCount.find('.count-value');\n\n // Get entity type from block\n var $block = $draftTag.closest('.target-block');\n var entityType = $block.data('blockType') || 'products';\n\n // Show loading - keep eye icon, update count value\n $countValue.html('');\n $matchCount.show();\n\n // Store pattern for click handler\n $matchCount.data('pattern', pattern);\n $matchCount.data('caseSensitive', caseSensitive);\n $matchCount.data('entityType', entityType);\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countPatternMatches',\n trait: 'EntitySelector',\n pattern: pattern,\n field: 'name',\n entity_type: entityType,\n case_sensitive: caseSensitive ? 1 : 0\n },\n success: function(response) {\n if (response.success) {\n var count = parseInt(response.count, 10) || 0;\n $countValue.text(count);\n $matchCount.show();\n // Add visual feedback based on count\n $matchCount.removeClass('count-zero count-found');\n $matchCount.addClass(count === 0 ? 'count-zero' : 'count-found');\n // Store count for preview\n $matchCount.data('count', count);\n // Update group total count to reflect draft pattern in calculation\n var $group = $draftTag.closest('.selection-group');\n if ($group.length) {\n self.updateGroupTotalCount($group);\n }\n } else {\n $countValue.text('?');\n $matchCount.show();\n }\n },\n error: function() {\n $countValue.text('?');\n $matchCount.show();\n }\n });\n },\n\n /**\n * Update condition count with a pending pattern (typed but not yet added as tag)\n * This shows a live preview of what the count would be if the user pressed Enter\n */\n updateConditionCountWithPendingPattern: function($row, pendingPattern) {\n var self = this;\n var trans = this.config.trans || {};\n\n // Find the count element - in method-selector-wrapper for include, in exclude-header-row for exclude\n var $countEl = $row.find('.method-selector-wrapper > .condition-match-count, > .exclude-header-row > .condition-match-count').first();\n if (!$countEl.length) return;\n\n var isExclude = $row.hasClass('exclude-row');\n var $methodSelect = isExclude\n ? $row.find('.exclude-method-select')\n : $row.find('.include-method-select');\n\n var method = $methodSelect.val();\n if (!method) {\n $countEl.hide();\n return;\n }\n\n var $picker = isExclude\n ? $row.find('.exclude-picker')\n : $row.find('.include-picker');\n\n var valueType = $picker.data('valueType') || 'none';\n\n // Only process for pattern value types\n if (valueType !== 'pattern') {\n return;\n }\n\n // Get existing pattern tags\n var values = this.getPatternTags($picker);\n\n // Add the pending pattern as a temporary tag (case-insensitive by default)\n if (pendingPattern) {\n values.push({ pattern: pendingPattern, caseSensitive: false });\n }\n\n if (values.length === 0) {\n $countEl.hide();\n return;\n }\n\n var $block = $row.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Show loading\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n // Store condition data on badge for popover\n $countEl.data('conditionData', {\n method: method,\n values: values,\n blockType: blockType,\n isExclude: isExclude\n });\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countConditionMatches',\n trait: 'EntitySelector',\n method: method,\n values: JSON.stringify(values),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.removeClass('no-matches clickable');\n if (count === 0) {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('no-matches').show();\n } else {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('clickable').show();\n }\n } else {\n $countEl.hide().removeClass('clickable');\n }\n },\n error: function() {\n $countEl.hide().removeClass('clickable');\n }\n });\n },\n\n /**\n * Fetch pattern match count via AJAX\n */\n fetchPatternMatchCount: function($picker, pattern, $countEl) {\n // Determine field type from method select\n // Check if we're in an exclude row first, then fall back to include\n var $excludeRow = $picker.closest('.exclude-row');\n var $methodSelect;\n if ($excludeRow.length) {\n $methodSelect = $excludeRow.find('.exclude-method-select');\n } else {\n var $group = $picker.closest('.selection-group');\n $methodSelect = $group.find('.include-method-select');\n }\n var method = $methodSelect.val() || '';\n var field = method.indexOf('reference') !== -1 ? 'reference' : 'name';\n\n // Get entity type from block\n var $block = $picker.closest('.target-block');\n var entityType = $block.data('blockType') || 'products';\n\n // Show loading state\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countPatternMatches',\n trait: 'EntitySelector',\n pattern: pattern,\n field: field,\n entity_type: entityType,\n case_sensitive: 0\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.find('.preview-count').text(count);\n $countEl.removeClass('no-matches clickable').show();\n if (count === 0) {\n $countEl.addClass('no-matches');\n } else {\n $countEl.addClass('clickable');\n }\n } else {\n $countEl.hide();\n }\n },\n error: function() {\n $countEl.hide();\n }\n });\n },\n\n // =========================================================================\n // Picker Value Extraction\n // =========================================================================\n\n /**\n * Get values from a picker based on its type\n */\n getPickerValues: function($picker, valueType) {\n switch (valueType) {\n case 'entity_search':\n var ids = [];\n $picker.find('.entity-chip').each(function() {\n var id = $(this).data('id');\n if (id) ids.push(id);\n });\n return ids;\n\n case 'pattern':\n var patternValues = this.getPatternTags($picker);\n // Also include draft pattern if it has content (not yet added as tag)\n var $draftPatternInput = $picker.find('.draft-tag .pattern-input');\n var draftPatternVal = $.trim($draftPatternInput.val());\n if (draftPatternVal) {\n var draftCaseSens = $draftPatternInput.closest('.draft-tag').attr('data-case-sensitive') === '1';\n patternValues.push({\n pattern: draftPatternVal,\n caseSensitive: draftCaseSens\n });\n }\n return patternValues;\n\n case 'numeric_range':\n var min = $picker.find('.range-min-input').val();\n var max = $picker.find('.range-max-input').val();\n return { min: min || null, max: max || null };\n\n case 'date_range':\n var from = $picker.find('.date-from-input').val();\n var to = $picker.find('.date-to-input').val();\n return { from: from || null, to: to || null };\n\n case 'select':\n return [$picker.find('.select-value-input').val()];\n\n case 'boolean':\n return [true];\n\n default:\n return [];\n }\n },\n\n // =========================================================================\n // Count/Status Updates\n // =========================================================================\n\n /**\n * Fetch and update condition match count for a row (include or exclude)\n */\n updateConditionCount: function($row) {\n var self = this;\n var trans = this.config.trans || {};\n\n // Find the count element - in method-selector-wrapper for include, in exclude-header-row for exclude\n var $countEl = $row.find('.method-selector-wrapper > .condition-match-count, > .exclude-header-row > .condition-match-count').first();\n if (!$countEl.length) return;\n\n // Determine if this is an include or exclude row\n var isExclude = $row.hasClass('exclude-row');\n var $methodSelect = isExclude\n ? $row.find('.exclude-method-select')\n : $row.find('.include-method-select');\n\n var method = $methodSelect.val();\n if (!method) {\n $countEl.hide();\n return;\n }\n\n // Get the picker and extract values\n var $picker = isExclude\n ? $row.find('.exclude-picker')\n : $row.find('.include-picker');\n\n var valueType = $picker.data('valueType') || 'none';\n var values = this.getPickerValues($picker, valueType);\n\n // Don't count if no values (except for boolean/all methods)\n var hasNoValues = !values ||\n (Array.isArray(values) && values.length === 0) ||\n (typeof values === 'object' && !Array.isArray(values) && (\n // For combination_attributes, check if attributes object is empty\n (valueType === 'combination_attributes' && values.attributes !== undefined && Object.keys(values.attributes).length === 0) ||\n // For other objects, check if completely empty\n (valueType !== 'combination_attributes' && Object.keys(values).length === 0)\n ));\n if (valueType !== 'none' && valueType !== 'boolean' && hasNoValues) {\n $countEl.hide();\n return;\n }\n\n // Get block type\n var $block = $row.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Show loading\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n // Store condition data on badge for popover\n $countEl.data('conditionData', {\n method: method,\n values: values,\n blockType: blockType,\n isExclude: isExclude\n });\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countConditionMatches',\n trait: 'EntitySelector',\n method: method,\n values: JSON.stringify(values),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.removeClass('no-matches clickable');\n if (count === 0) {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('no-matches').show();\n } else {\n // Show count, make clickable for preview popover\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('clickable').show();\n }\n } else {\n $countEl.hide().removeClass('clickable');\n }\n },\n error: function() {\n $countEl.hide().removeClass('clickable');\n }\n });\n },\n\n /**\n * Update all condition counts in a group\n */\n updateGroupCounts: function($group) {\n var self = this;\n\n // Update include count\n var $include = $group.find('.group-include');\n if ($include.length) {\n this.updateConditionCount($include);\n }\n\n // Update each exclude row count\n $group.find('.exclude-row').each(function() {\n self.updateConditionCount($(this));\n });\n\n // Update group total count (include - excludes)\n this.updateGroupTotalCount($group);\n },\n\n /**\n * Update the group total count badge (include - excludes)\n * Also updates the limit input placeholder\n */\n updateGroupTotalCount: function($group) {\n var self = this;\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n var $badge = $group.find('.group-header .group-count-badge');\n var $limitInput = $group.find('.group-modifier-limit');\n\n // Build group data for AJAX\n var groupData = this.serializeGroup($group, blockType);\n\n // Check if include has valid data\n if (!groupData.include || !groupData.include.method) {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n return;\n }\n\n // Show loading\n $badge.html('').show();\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countGroupItems',\n trait: 'EntitySelector',\n group_data: JSON.stringify(groupData),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var finalCount = response.final_count || 0;\n var excludeCount = response.exclude_count || 0;\n\n // Update badge with eye icon and count\n var badgeHtml = ' ' + finalCount;\n if (excludeCount > 0) {\n badgeHtml += ' (-' + excludeCount + ')';\n }\n $badge.html(badgeHtml);\n $badge.addClass('clickable').show();\n\n // Store group data on badge for preview popover\n $badge.data('groupData', groupData);\n $badge.data('blockType', blockType);\n $badge.data('finalCount', finalCount);\n\n // Update limit placeholder with the count\n $limitInput.attr('placeholder', finalCount);\n\n // Also update the group-preview-badge count (apply limit if set)\n var $previewBadge = $group.find('.group-preview-badge .preview-count');\n if ($previewBadge.length) {\n var limit = parseInt($limitInput.val(), 10);\n var displayCount = (limit > 0 && limit < finalCount) ? limit : finalCount;\n $previewBadge.text(displayCount);\n }\n } else {\n $badge.hide().removeClass('clickable');\n $limitInput.attr('placeholder', '–');\n }\n },\n error: function() {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n }\n });\n },\n\n /**\n * Update all condition counts for all visible groups\n */\n updateAllConditionCounts: function() {\n var self = this;\n this.$wrapper.find('.target-block.active .selection-group').each(function() {\n self.updateGroupCounts($(this));\n });\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Groups Module\n * Selection group management, serialization, block/tab management\n * @partial _groups.js\n *\n * Contains:\n * - Group management: addGroup, removeGroup, clearAllConditions\n * - Block/Tab: switchToBlock, updateTabBadges, updateBlockStatus\n * - Serialization: serializeGroup, serializeAllBlocks, getBlockGroups\n * - Counts: fetchProductCount, updateHeaderTotalCount, updateAllConditionCounts\n * - Excludes: addFirstExcludeRow, addExcludeRow, removeExcludeRow\n * - Validation: validate, showValidationError, clearValidationError\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.groups = {\n\n addGroup: function($block, blockType) {\n var $container = $block.find('.groups-container');\n var trans = this.config.trans || {};\n var blockDef = this.config.blocks[blockType] || {};\n var methods = blockDef.selection_methods || {};\n\n // Remove empty state\n $container.find('.groups-empty-state').remove();\n\n // Get next group index\n var maxIndex = -1;\n $container.find('.selection-group').each(function() {\n var idx = parseInt($(this).data('groupIndex'), 10);\n if (idx > maxIndex) maxIndex = idx;\n });\n var groupIndex = maxIndex + 1;\n\n // Build method options with optgroups\n var methodOptions = this.buildMethodOptions(methods, false);\n\n // Build exclude method options (no \"all\") with optgroups\n var excludeMethodOptions = this.buildMethodOptions(methods, true);\n\n var defaultGroupName = (trans.group || 'Group') + ' ' + (groupIndex + 1);\n var html = '
';\n\n // Group header\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Group body (collapsible content)\n html += '
';\n\n // Include section\n html += '
';\n html += '
';\n html += '
';\n html += '';\n html += '0';\n html += '';\n html += '
';\n var noItemsText = trans.no_items_selected || 'No items selected - use search below';\n html += '
';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n\n // Excludes section (collapsed by default)\n html += '
';\n html += '';\n html += ' ' + (trans.add_exceptions || 'Add exceptions');\n html += '';\n html += '
';\n\n // Group-level modifiers (limit & sort)\n html += '
';\n html += '';\n html += '' + (trans.limit || 'Limit') + '';\n html += '';\n html += '';\n html += '';\n html += '' + (trans.sort || 'Sort') + '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += ' ';\n html += '';\n html += '
';\n\n html += '
'; // Close group-body\n\n html += '
'; // Close selection-group\n\n $container.append(html);\n\n // Find the new group and set method to \"all\" by default\n var $newGroup = $container.find('.selection-group[data-group-index=\"' + groupIndex + '\"]');\n\n // Enhance the method select with styled dropdown\n this.enhanceMethodSelect($newGroup.find('.include-method-select'));\n\n $newGroup.find('.include-method-select').val('all').trigger('change');\n\n this.updateBlockStatus($block);\n this.serializeAllBlocks();\n },\n\n removeGroup: function($group, $block) {\n $group.remove();\n\n var $container = $block.find('.groups-container');\n var remainingGroups = $container.find('.selection-group').length;\n\n if (remainingGroups === 0) {\n var emptyText = this.getEmptyStateText($block);\n var emptyHtml = '
';\n $container.html(emptyHtml);\n }\n\n this.updateBlockStatus($block);\n this.serializeAllBlocks();\n\n // Update tab badges and header total count\n this.updateTabBadges();\n },\n\n clearAllConditions: function() {\n var self = this;\n\n // Remove all groups from all blocks\n this.$wrapper.find('.target-block').each(function() {\n var $block = $(this);\n var $container = $block.find('.groups-container');\n\n // Remove all groups\n $container.find('.selection-group').remove();\n\n // Show empty state\n var emptyText = self.getEmptyStateText($block);\n var emptyHtml = '
';\n $container.html(emptyHtml);\n\n self.updateBlockStatus($block);\n });\n\n // Update serialized data\n this.serializeAllBlocks();\n\n // Update tab badges and header count\n this.updateTabBadges();\n\n // Also update header total count immediately (since all cleared)\n this.updateHeaderTotalCount();\n },\n\n switchToBlock: function(blockType) {\n // Update tabs\n this.$wrapper.find('.target-block-tab').removeClass('active');\n this.$wrapper.find('.target-block-tab[data-block-type=\"' + blockType + '\"]').addClass('active');\n\n // Update blocks\n this.$wrapper.find('.target-block').removeClass('active').hide();\n this.$wrapper.find('.target-block[data-block-type=\"' + blockType + '\"]').addClass('active').show();\n\n // Close dropdown if open\n this.hideDropdown();\n },\n\n updateTabBadges: function() {\n var self = this;\n\n this.$wrapper.find('.target-block-tab').each(function() {\n var $tab = $(this);\n var blockType = $tab.data('blockType');\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + blockType + '\"]');\n var groupCount = $block.find('.selection-group').length;\n\n // Update or add badge\n var $badge = $tab.find('.tab-badge');\n if (groupCount > 0) {\n // Show loading state first\n if ($badge.length) {\n $badge.addClass('loading').html('');\n } else {\n $tab.append('');\n }\n $tab.addClass('has-data');\n\n // Fetch real product count\n self.fetchProductCount(blockType, $tab);\n } else {\n $badge.remove();\n $tab.removeClass('has-data');\n }\n });\n\n // Update target switch state based on whether any data exists\n this.updateTargetSwitchState();\n },\n\n updateTargetSwitchState: function() {\n var $switch = this.$wrapper.find('.prestashop-switch');\n if (!$switch.length) {\n return;\n }\n\n // Check if any block has data\n var hasData = false;\n this.$wrapper.find('.target-block').each(function() {\n if ($(this).find('.selection-group').length > 0) {\n hasData = true;\n return false; // break\n }\n });\n\n // Update switch: value=\"1\" is \"Everyone/All/None\", value=\"0\" is \"Specific/Selected\"\n if (hasData) {\n $switch.find('input[value=\"0\"]').prop('checked', true);\n } else {\n $switch.find('input[value=\"1\"]').prop('checked', true);\n }\n },\n\n fetchProductCount: function(blockType, $tab) {\n var self = this;\n var data = {};\n\n // Read from hidden input (contains full saved data or freshly serialized data)\n var $hiddenInput = this.$wrapper.find('input[name=\"' + this.config.name + '\"]');\n var savedData = {};\n try {\n savedData = JSON.parse($hiddenInput.val() || '{}');\n } catch (e) {\n savedData = {};\n }\n\n // Get groups for the requested block type\n var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];\n\n if (groups.length === 0) {\n $tab.find('.tab-badge').remove();\n $tab.removeClass('has-data');\n $tab.removeData('previewData');\n return;\n }\n\n // Show loading state\n var $badge = $tab.find('.tab-badge');\n if (!$badge.length) {\n $badge = $('');\n $tab.append($badge);\n } else {\n $badge.addClass('loading').html('');\n }\n $tab.addClass('has-data');\n\n data[blockType] = { groups: groups };\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewEntitySelector',\n trait: 'EntitySelector',\n conditions: JSON.stringify(data),\n block_type: blockType,\n limit: 10\n },\n success: function(response) {\n if (response.success) {\n var $badge = $tab.find('.tab-badge');\n $badge.removeClass('loading').html(' ' + response.count);\n\n // Store preview data for popover\n $tab.data('previewData', response);\n\n // Update header total count\n self.updateHeaderTotalCount();\n } else {\n $tab.find('.tab-badge').remove();\n }\n },\n error: function() {\n $tab.find('.tab-badge').remove();\n self.updateHeaderTotalCount();\n }\n });\n },\n\n updateHeaderTotalCount: function() {\n var self = this;\n var total = 0;\n\n // Sum up all tab badge counts\n this.$wrapper.find('.target-block-tab .tab-badge').each(function() {\n var $badge = $(this);\n if (!$badge.hasClass('loading')) {\n var count = parseInt($badge.text(), 10);\n if (!isNaN(count)) {\n total += count;\n }\n }\n });\n\n var $totalBadge = this.$wrapper.find('.trait-total-count');\n if (total > 0) {\n $totalBadge.text(total).show();\n } else {\n $totalBadge.hide();\n }\n\n // Update show-all toggle state\n this.updateShowAllToggle();\n },\n\n updateShowAllToggle: function() {\n var $toggle = this.$wrapper.find('.trait-show-all-toggle');\n if (!$toggle.length) return;\n\n var $checkbox = $toggle.find('.show-all-checkbox');\n var hasData = this.$wrapper.find('.target-block-tab.has-data').length > 0;\n\n // If there's data, uncheck (not showing to all), otherwise check\n $checkbox.prop('checked', !hasData);\n },\n\n updateBlockStatus: function($block) {\n var $status = $block.find('.block-status');\n var blockType = $block.data('blockType');\n var blockDef = this.config.blocks[blockType] || {};\n var trans = this.config.trans || {};\n\n var groups = this.getBlockGroups($block);\n\n if (groups.length === 0) {\n var emptyMeansAll = this.config.emptyMeansAll !== false;\n if (emptyMeansAll) {\n $status.text((trans.all || 'All') + ' ' + (blockDef.entity_label_plural || 'items'));\n } else {\n $status.text(trans.nothing_selected || 'Nothing selected');\n }\n } else {\n $status.text(groups.length + ' ' + (groups.length === 1 ? (trans.group || 'group') : (trans.groups || 'groups')));\n }\n },\n\n getEmptyStateText: function($block) {\n var blockType = $block.data('blockType');\n var blockMode = $block.data('mode') || 'multi';\n var blockDef = this.config.blocks[blockType] || {};\n var trans = this.config.trans || {};\n var emptyMeansAll = this.config.emptyMeansAll !== false;\n\n if (blockMode === 'single') {\n return trans.no_item_selected || 'No item selected';\n }\n\n if (emptyMeansAll) {\n return (trans.all || 'All') + ' ' + (blockDef.entity_label_plural || 'items') + ' ' + (trans.included || 'included');\n }\n\n return trans.nothing_selected || 'Nothing selected';\n },\n\n serializeGroup: function($group, blockType) {\n var self = this;\n\n // Include\n var includeMethod = $group.find('.include-method-select').val() || 'all';\n var $includePicker = $group.find('.include-picker');\n var includeValues = this.getPickerValues($includePicker);\n\n // Excludes (multiple rows)\n var excludes = [];\n var $excludesSection = $group.find('.group-excludes.has-excludes');\n if ($excludesSection.length) {\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var excludeMethod = $row.find('.exclude-method-select').val() || null;\n var $excludePicker = $row.find('.exclude-picker');\n var excludeValues = self.getPickerValues($excludePicker);\n\n if (excludeMethod && excludeValues && (Array.isArray(excludeValues) ? excludeValues.length > 0 : true)) {\n excludes.push({\n method: excludeMethod,\n values: excludeValues\n });\n }\n });\n }\n\n var groupData = {\n include: {\n method: includeMethod,\n values: includeValues\n }\n };\n\n if (excludes.length > 0) {\n groupData.excludes = excludes;\n }\n\n // Add modifiers if present\n var modifiers = this.getGroupModifiers($group);\n if (modifiers.limit || modifiers.sort_by) {\n groupData.modifiers = modifiers;\n }\n\n return groupData;\n },\n\n serializeAllBlocks: function($changedRow) {\n var self = this;\n var data = {};\n\n this.$wrapper.find('.target-block').each(function() {\n var $block = $(this);\n var blockType = $block.data('blockType');\n var groups = self.getBlockGroups($block);\n\n // Groups now contain their own modifiers, no block-level modifiers\n if (groups.length > 0) {\n data[blockType] = { groups: groups };\n }\n\n self.updateBlockStatus($block);\n });\n\n // Update hidden input first\n var $input = this.$wrapper.find('input[name=\"' + this.config.name + '\"]');\n $input.val(JSON.stringify(data));\n\n // Then update tab badges (reads from hidden input)\n this.updateTabBadges();\n\n // Debounced update of condition count - only for changed row if specified\n if (this.countUpdateTimeout) {\n clearTimeout(this.countUpdateTimeout);\n }\n this.countUpdateTimeout = setTimeout(function() {\n if ($changedRow && $changedRow.length) {\n // Update the specific row that changed\n self.updateConditionCount($changedRow);\n // Also update the group total count (include - excludes)\n var $group = $changedRow.closest('.selection-group');\n if ($group.length) {\n self.updateGroupTotalCount($group);\n }\n } else {\n // Fallback: update all counts (initial load, structure changes)\n self.updateAllConditionCounts();\n }\n }, 500);\n },\n\n getBlockGroups: function($block) {\n var self = this;\n var groups = [];\n\n $block.find('.selection-group').each(function() {\n var $group = $(this);\n\n // Include\n var includeMethod = $group.find('.include-method-select').val() || 'all';\n var $includePicker = $group.find('.include-picker');\n var includeValues = self.getPickerValues($includePicker);\n\n // Skip groups with invalid include conditions (e.g., \"specific products\" with none selected)\n if (!self.isConditionValid(includeMethod, includeValues, $includePicker)) {\n return true; // continue to next group\n }\n\n // Excludes (multiple rows) - only include valid ones\n var excludes = [];\n var $excludesSection = $group.find('.group-excludes.has-excludes');\n if ($excludesSection.length) {\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var excludeMethod = $row.find('.exclude-method-select').val() || null;\n var $excludePicker = $row.find('.exclude-picker');\n var excludeValues = self.getPickerValues($excludePicker);\n\n // Only include valid exclude conditions\n if (excludeMethod && self.isConditionValid(excludeMethod, excludeValues, $excludePicker)) {\n excludes.push({\n method: excludeMethod,\n values: excludeValues\n });\n }\n });\n }\n\n var groupData = {\n include: {\n method: includeMethod,\n values: includeValues\n }\n };\n\n // Group name (optional, for organizational purposes)\n var groupName = $.trim($group.attr('data-group-name') || '');\n if (groupName) {\n groupData.name = groupName;\n }\n\n if (excludes.length > 0) {\n groupData.excludes = excludes;\n }\n\n // Group-level modifiers\n var modifiers = self.getGroupModifiers($group);\n if (modifiers.limit || modifiers.sort_by) {\n groupData.modifiers = modifiers;\n }\n\n groups.push(groupData);\n });\n\n return groups;\n },\n\n getGroupModifiers: function($group) {\n var limit = $group.find('.group-modifier-limit').val();\n var sortBy = $group.find('.group-modifier-sort').val() || 'sales';\n var $sortDirBtn = $group.find('.group-modifiers .btn-sort-dir');\n var sortDir = $sortDirBtn.data('dir') || 'DESC';\n\n return {\n limit: limit ? parseInt(limit, 10) : null,\n sort_by: sortBy || null,\n sort_dir: sortDir || 'DESC'\n };\n },\n\n getPickerValues: function($picker) {\n var valueType = $picker.attr('data-value-type') || 'entity_search';\n var values = [];\n\n switch (valueType) {\n case 'entity_search':\n $picker.find('.entity-chip').each(function() {\n var id = $(this).data('id');\n values.push(isNaN(id) ? id : Number(id));\n });\n break;\n\n case 'pattern':\n values = this.getPatternTags($picker);\n // Also include draft pattern if it has content (not yet added as tag)\n var $draftInput = $picker.find('.draft-tag .pattern-input');\n var draftPattern = $.trim($draftInput.val());\n if (draftPattern) {\n var draftCaseSensitive = $draftInput.closest('.draft-tag').attr('data-case-sensitive') === '1';\n values.push({\n pattern: draftPattern,\n caseSensitive: draftCaseSensitive\n });\n }\n break;\n\n case 'numeric_range':\n var min = $picker.find('.range-min-input').val();\n var max = $picker.find('.range-max-input').val();\n if (min !== '' || max !== '') {\n values = {\n min: min !== '' ? parseFloat(min) : null,\n max: max !== '' ? parseFloat(max) : null\n };\n }\n break;\n\n case 'date_range':\n var from = $picker.find('.date-from-input').val();\n var to = $picker.find('.date-to-input').val();\n if (from || to) {\n values = {\n from: from || null,\n to: to || null\n };\n }\n break;\n\n case 'select':\n var selectVal = $picker.find('.select-value-input').val();\n if (selectVal) {\n values = [selectVal];\n }\n break;\n\n case 'boolean':\n values = [true];\n break;\n\n case 'multi_numeric_range':\n var ranges = [];\n $picker.find('.range-chip').each(function() {\n var $chip = $(this);\n var minVal = $chip.data('min');\n var maxVal = $chip.data('max');\n ranges.push({\n min: minVal !== '' && minVal !== undefined ? parseFloat(minVal) : null,\n max: maxVal !== '' && maxVal !== undefined ? parseFloat(maxVal) : null\n });\n });\n if (ranges.length > 0) {\n values = ranges;\n }\n break;\n\n case 'multi_select_tiles':\n $picker.find('.tile-option.selected').each(function() {\n values.push($(this).data('value'));\n });\n break;\n\n case 'combination_attributes':\n // Returns object: { mode: 'products'|'combinations', attributes: { groupId: [valueId1, valueId2], ... } }\n var combAttrs = {};\n $picker.find('.comb-attr-value.selected').each(function() {\n var groupId = $(this).data('groupId').toString();\n var valueId = $(this).data('valueId');\n if (!combAttrs[groupId]) {\n combAttrs[groupId] = [];\n }\n combAttrs[groupId].push(valueId);\n });\n if (Object.keys(combAttrs).length > 0) {\n // Get mode: from radio if toggle exists, otherwise from config\n var $combPicker = $picker.find('.combination-attributes-picker');\n var configMode = $combPicker.data('combinationMode') || this.config.combinationMode || 'products';\n var combMode;\n if (configMode === 'toggle') {\n combMode = $picker.find('.comb-mode-radio:checked').val() || 'products';\n } else {\n combMode = configMode;\n }\n values = {\n mode: combMode,\n attributes: combAttrs\n };\n }\n break;\n }\n\n return values;\n },\n\n isConditionValid: function(method, values, $picker) {\n // 'all' method never needs values\n if (method === 'all') {\n return true;\n }\n\n // Boolean methods are always valid (the value is implicit true)\n var valueType = $picker.attr('data-value-type') || 'entity_search';\n if (valueType === 'boolean') {\n return true;\n }\n\n // For other methods, check if values are meaningful\n if (Array.isArray(values)) {\n return values.length > 0;\n }\n\n // For object values (ranges, combination_attributes), check if meaningful\n if (typeof values === 'object' && values !== null) {\n // Special handling for combination_attributes: { mode, attributes }\n if (valueType === 'combination_attributes' && values.attributes !== undefined) {\n return Object.keys(values.attributes).length > 0;\n }\n // For ranges and other objects, check if at least one bound is set\n return Object.keys(values).some(function(key) {\n return values[key] !== null && values[key] !== '';\n });\n }\n\n return false;\n },\n\n updateAllConditionCounts: function() {\n var self = this;\n this.$wrapper.find('.target-block.active .selection-group').each(function() {\n self.updateGroupCounts($(this));\n });\n },\n\n updateGroupCounts: function($group) {\n var self = this;\n\n // Update include count\n var $include = $group.find('.group-include');\n if ($include.length) {\n this.updateConditionCount($include);\n }\n\n // Update each exclude row count\n $group.find('.exclude-row').each(function() {\n self.updateConditionCount($(this));\n });\n\n // Update group total count (include - excludes)\n this.updateGroupTotalCount($group);\n },\n\n updateConditionCount: function($row) {\n var self = this;\n var trans = this.config.trans || {};\n\n // Find the count element - in method-selector-wrapper for include, in exclude-header-row for exclude\n var $countEl = $row.find('.method-selector-wrapper > .condition-match-count, > .exclude-header-row .condition-match-count').first();\n if (!$countEl.length) return;\n\n // Determine if this is an include or exclude row\n var isExclude = $row.hasClass('exclude-row');\n var $methodSelect = isExclude\n ? $row.find('.exclude-method-select')\n : $row.find('.include-method-select');\n\n var method = $methodSelect.val();\n if (!method) {\n $countEl.hide();\n return;\n }\n\n // Get the picker and extract values\n var $picker = isExclude\n ? $row.find('.exclude-picker')\n : $row.find('.include-picker');\n\n var valueType = $picker.data('valueType') || 'none';\n var values = this.getPickerValues($picker, valueType);\n\n // Don't count if no values (except for boolean/all methods)\n var hasNoValues = !values ||\n (Array.isArray(values) && values.length === 0) ||\n (typeof values === 'object' && !Array.isArray(values) && (\n // For combination_attributes, check if attributes object is empty\n (valueType === 'combination_attributes' && values.attributes !== undefined && Object.keys(values.attributes).length === 0) ||\n // For other objects, check if completely empty\n (valueType !== 'combination_attributes' && Object.keys(values).length === 0)\n ));\n if (valueType !== 'none' && valueType !== 'boolean' && hasNoValues) {\n $countEl.hide();\n return;\n }\n\n // Get block type\n var $block = $row.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Show loading\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n // Store condition data on badge for popover\n $countEl.data('conditionData', {\n method: method,\n values: values,\n blockType: blockType,\n isExclude: isExclude\n });\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countConditionMatches',\n trait: 'EntitySelector',\n method: method,\n values: JSON.stringify(values),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.removeClass('no-matches clickable');\n if (count === 0) {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('no-matches').show();\n } else {\n // Show count, make clickable for preview popover\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('clickable').show();\n }\n } else {\n $countEl.hide().removeClass('clickable');\n }\n },\n error: function() {\n $countEl.hide().removeClass('clickable');\n }\n });\n },\n\n updateGroupTotalCount: function($group) {\n var self = this;\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n var $badge = $group.find('.group-header .group-count-badge');\n var $limitInput = $group.find('.group-modifier-limit');\n\n // Build group data for AJAX\n var groupData = this.serializeGroup($group, blockType);\n\n // Check if include has valid data\n if (!groupData.include || !groupData.include.method) {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n return;\n }\n\n // Show loading\n $badge.html('').show();\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countGroupItems',\n trait: 'EntitySelector',\n group_data: JSON.stringify(groupData),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var finalCount = response.final_count || 0;\n var excludeCount = response.exclude_count || 0;\n\n // Update badge with eye icon and count\n var badgeHtml = ' ' + finalCount;\n if (excludeCount > 0) {\n badgeHtml += ' (-' + excludeCount + ')';\n }\n $badge.html(badgeHtml);\n $badge.addClass('clickable').show();\n\n // Store group data on badge for preview popover\n $badge.data('groupData', groupData);\n $badge.data('blockType', blockType);\n $badge.data('finalCount', finalCount);\n\n // Update limit placeholder with the count\n $limitInput.attr('placeholder', finalCount);\n\n // Also update the group-preview-badge count (apply limit if set)\n var $previewBadge = $group.find('.group-preview-badge .preview-count');\n if ($previewBadge.length) {\n var limit = parseInt($limitInput.val(), 10);\n var displayCount = (limit > 0 && limit < finalCount) ? limit : finalCount;\n $previewBadge.text(displayCount);\n }\n } else {\n $badge.hide().removeClass('clickable');\n $limitInput.attr('placeholder', '–');\n }\n },\n error: function() {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n }\n });\n },\n\n // Exclude row management\n addFirstExcludeRow: function($group, $block) {\n var $excludesDiv = $group.find('.group-excludes');\n var trans = this.config.trans || {};\n\n // Build the full excludes structure with first row\n var html = '
';\n html += ' ' + (trans.except || 'EXCEPT') + '';\n html += '
';\n\n html += '
';\n html += this.buildExcludeRowHtml($block, 0);\n html += '
';\n\n html += '';\n html += ' ' + (trans.add_another_exception || 'Add another exception');\n html += '';\n\n $excludesDiv.addClass('has-excludes').html(html);\n this.updateMethodSelectorLock($group, true);\n this.serializeAllBlocks();\n },\n\n addExcludeRow: function($group, $block) {\n var $container = $group.find('.exclude-rows-container');\n\n // Get next exclude index\n var maxIndex = -1;\n $container.find('.exclude-row').each(function() {\n var idx = parseInt($(this).data('excludeIndex'), 10);\n if (idx > maxIndex) maxIndex = idx;\n });\n var excludeIndex = maxIndex + 1;\n\n var html = this.buildExcludeRowHtml($block, excludeIndex);\n $container.append(html);\n\n // Enhance the exclude method select with styled dropdown\n var $newRow = $container.find('.exclude-row[data-exclude-index=\"' + excludeIndex + '\"]');\n this.enhanceMethodSelect($newRow.find('.exclude-method-select'));\n\n this.serializeAllBlocks();\n },\n\n buildExcludeRowHtml: function($block, excludeIndex) {\n var blockType = $block.data('blockType');\n var blockDef = this.config.blocks[blockType] || {};\n var methods = blockDef.selection_methods || {};\n var trans = this.config.trans || {};\n\n // Build exclude method options with optgroups (no \"all\")\n var excludeMethodOptions = this.buildMethodOptions(methods, true);\n\n // Find first non-all method for default search entity\n var firstSearchEntity = blockType;\n var firstValueType = 'entity_search';\n $.each(methods, function(methodKey, methodDef) {\n if (methodKey === 'all') return true;\n firstSearchEntity = methodDef.search_entity || blockType;\n firstValueType = methodDef.value_type || 'entity_search';\n return false; // break\n });\n\n var html = '
';\n\n // Header row with method select wrapped in method-selector-wrapper (same as include)\n html += '
';\n html += '
';\n html += '';\n html += '0';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Value picker based on first method's value type\n html += this.buildValuePickerHtml('exclude', firstValueType, firstSearchEntity, methods);\n\n html += '
';\n\n return html;\n },\n\n removeExcludeRow: function($excludeRow, $group, $block) {\n var $container = $group.find('.exclude-rows-container');\n var trans = this.config.trans || {};\n\n $excludeRow.remove();\n\n // Check if there are remaining exclude rows\n var remainingRows = $container.find('.exclude-row').length;\n\n if (remainingRows === 0) {\n // Remove entire excludes section and show \"Add exceptions\" button\n var $excludesDiv = $group.find('.group-excludes');\n $excludesDiv.removeClass('has-excludes').html(\n '' +\n ' ' + (trans.add_exceptions || 'Add exceptions') +\n ''\n );\n // Unlock the method selector since no excludes exist\n this.updateMethodSelectorLock($group, false);\n }\n\n this.serializeAllBlocks();\n },\n\n // Method options building\n buildMethodOptions: function(methods, excludeAll) {\n var self = this;\n var trans = this.config.trans || {};\n var html = '';\n\n // Group labels\n var groupLabels = {\n 'select_by': trans.select_by || 'Select by...',\n 'filter_by': trans.filter_by || 'Filter by...'\n };\n\n // Separate methods by group\n var grouped = {};\n var ungrouped = {};\n\n $.each(methods, function(methodKey, methodDef) {\n if (excludeAll && methodKey === 'all') return true; // skip\n\n var group = methodDef.group || '';\n if (group) {\n if (!grouped[group]) {\n grouped[group] = {};\n }\n grouped[group][methodKey] = methodDef;\n } else {\n ungrouped[methodKey] = methodDef;\n }\n });\n\n // Render ungrouped options first\n $.each(ungrouped, function(methodKey, methodDef) {\n html += self.buildMethodOption(methodKey, methodDef);\n });\n\n // Render grouped options with optgroups\n $.each(grouped, function(groupKey, groupMethods) {\n var groupLabel = groupLabels[groupKey] || groupKey.replace(/_/g, ' ');\n html += '';\n });\n\n return html;\n },\n\n buildMethodOption: function(methodKey, methodDef) {\n var html = '';\n return html;\n },\n\n buildValuePickerHtml: function(section, valueType, searchEntity, methods) {\n var trans = this.config.trans || {};\n var pickerClass = section + '-picker';\n var chipsClass = section + '-chips';\n var dataClass = section + '-values-data';\n var html = '';\n\n if (valueType === 'none') {\n html = '
';\n html += '';\n html += '
';\n return html;\n }\n\n html = '
';\n\n switch (valueType) {\n case 'entity_search':\n var noItemsText = trans.no_items_selected || 'No items selected - use search below';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n html += '';\n break;\n\n case 'pattern':\n // Build tooltip content for data-details attribute\n var tooltipContent = '' + this.escapeHtml(trans.pattern_help_title || 'Pattern Syntax') + '';\n tooltipContent += '
';\n tooltipContent += '
*' + this.escapeHtml(trans.pattern_help_wildcard || 'any text (wildcard)') + '
' + this.escapeHtml(trans.combination_help_within || 'Within group: OR (Red OR Blue)') + '
';\n combTooltip += '
' + this.escapeHtml(trans.combination_help_between || 'Between groups: AND (Color AND Size)') + '
';\n combTooltip += '
';\n combTooltip += '
';\n\n // Combination mode from config: 'products', 'combinations', or 'toggle'\n var combMode = this.config.combinationMode || 'products';\n var showModeToggle = (combMode === 'toggle');\n var defaultMode = showModeToggle ? 'products' : combMode;\n\n html += '
';\n // Mode toggle: only show when config is 'toggle'\n if (showModeToggle) {\n html += '
';\n html += '';\n html += '';\n html += '
';\n }\n html += '
';\n html += ' ' + this.escapeHtml(trans.loading || 'Loading...') + '';\n html += '
';\n html += '
';\n // Store mode along with attributes: { mode: 'products'|'combinations', attributes: { groupId: [valueIds] } }\n html += '';\n break;\n\n default:\n html += '';\n break;\n }\n\n html += '
';\n return html;\n },\n\n // Sort options\n getSortOptionsArray: function(blockType) {\n var trans = this.config.trans || {};\n\n switch (blockType) {\n case 'products':\n return [\n { value: 'sales', label: trans.sort_bestsellers || 'Best sellers' },\n { value: 'date_add', label: trans.sort_newest || 'Newest' },\n { value: 'price', label: trans.sort_price || 'Price' },\n { value: 'name', label: trans.sort_name || 'Name' },\n { value: 'position', label: trans.sort_position || 'Position' },\n { value: 'quantity', label: trans.sort_stock || 'Stock quantity' },\n { value: 'random', label: trans.sort_random || 'Random' }\n ];\n case 'categories':\n return [\n { value: 'name', label: trans.sort_name || 'Name' },\n { value: 'position', label: trans.sort_position || 'Position' },\n { value: 'product_count', label: trans.sort_products || 'Products count' },\n { value: 'date_add', label: trans.sort_newest || 'Newest' }\n ];\n default:\n return [\n { value: 'name', label: trans.sort_name || 'Name' },\n { value: 'date_add', label: trans.sort_newest || 'Newest' }\n ];\n }\n },\n\n getSortIconClass: function(sortBy, sortDir) {\n var isAsc = (sortDir === 'ASC');\n\n switch (sortBy) {\n case 'name':\n return isAsc ? 'icon-sort-alpha-asc' : 'icon-sort-alpha-desc';\n case 'price':\n case 'quantity':\n case 'product_count':\n return isAsc ? 'icon-sort-numeric-asc' : 'icon-sort-numeric-desc';\n case 'date_add':\n case 'newest_products':\n return isAsc ? 'icon-sort-numeric-asc' : 'icon-sort-numeric-desc';\n case 'sales':\n case 'total_sales':\n return isAsc ? 'icon-sort-amount-asc' : 'icon-sort-amount-desc';\n case 'position':\n return isAsc ? 'icon-sort-numeric-asc' : 'icon-sort-numeric-desc';\n case 'random':\n return 'icon-random';\n default:\n return isAsc ? 'icon-sort-amount-asc' : 'icon-sort-amount-desc';\n }\n },\n\n cycleSortOption: function($btn, blockType) {\n var sortOptions = this.getSortOptionsArray(blockType);\n var currentSort = $btn.data('sort') || 'sales';\n var currentDir = $btn.data('dir') || 'DESC';\n\n // Find current index\n var currentIndex = -1;\n for (var i = 0; i < sortOptions.length; i++) {\n if (sortOptions[i].value === currentSort) {\n currentIndex = i;\n break;\n }\n }\n\n // Cycle: first toggle direction, then move to next sort option\n var newSort, newDir, newLabel;\n if (currentDir === 'DESC') {\n // Toggle to ASC, same sort\n newSort = currentSort;\n newDir = 'ASC';\n } else {\n // Move to next sort option, reset to DESC\n var nextIndex = (currentIndex + 1) % sortOptions.length;\n newSort = sortOptions[nextIndex].value;\n newDir = 'DESC';\n }\n\n // Find label for new sort\n for (var j = 0; j < sortOptions.length; j++) {\n if (sortOptions[j].value === newSort) {\n newLabel = sortOptions[j].label;\n break;\n }\n }\n\n // Update button\n $btn.data('sort', newSort);\n $btn.data('dir', newDir);\n $btn.attr('data-sort', newSort);\n $btn.attr('data-dir', newDir);\n $btn.attr('title', newLabel + ' ' + (newDir === 'DESC' ? '↓' : '↑'));\n $btn.find('i').attr('class', this.getSortIconClass(newSort, newDir));\n },\n\n // Validation\n validate: function() {\n var isRequired = this.$wrapper.data('required') === 1 || this.$wrapper.data('required') === '1';\n if (!isRequired) {\n return true;\n }\n\n // Check if any block has data (groups with selections)\n var hasData = false;\n this.$wrapper.find('.target-block').each(function() {\n if ($(this).find('.selection-group').length > 0) {\n hasData = true;\n return false; // break\n }\n });\n\n if (!hasData) {\n // Show validation error\n this.showValidationError();\n return false;\n }\n\n // Valid - remove any previous error\n this.clearValidationError();\n return true;\n },\n\n showValidationError: function() {\n this.$wrapper.addClass('has-validation-error');\n var message = this.$wrapper.data('required-message') || 'Please select at least one item';\n\n // Remove any existing error\n this.$wrapper.find('.trait-validation-error').remove();\n\n // Add error message after header\n var $error = $('
', {\n class: 'trait-validation-error',\n html: ' ' + message\n });\n this.$wrapper.find('.condition-trait-header').after($error);\n\n // Scroll to error\n $('html, body').animate({\n scrollTop: this.$wrapper.offset().top - 100\n }, 300);\n\n // Expand the trait if collapsed\n if (!this.$wrapper.find('.condition-trait-body').is(':visible')) {\n this.$wrapper.find('.condition-trait-body').slideDown(200);\n this.$wrapper.removeClass('collapsed');\n }\n },\n\n clearValidationError: function() {\n this.$wrapper.removeClass('has-validation-error');\n this.$wrapper.find('.trait-validation-error').remove();\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Methods Module\n * Method dropdown rendering, value pickers, combination picker\n * @partial _methods.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 6760-6848 (initMethodDropdowns, enhanceMethodSelect)\n * 6849-7051 (showMethodDropdownMenu, buildMethodDropdownMenuHtml, closeMethodDropdownMenu)\n * 7053-7138 (populateTiles, applyRangeInputConstraints, showRangeInputError)\n * 7139-7380 (combination picker methods)\n * 7382-7550 (updateMethodInfoPlaceholder, getBuiltInMethodHelp)\n * 7748-7888 (buildSortOptions, updateModifierButtonState, updateMethodSelectorLock)\n *\n * Contains:\n * - initMethodDropdowns() - Initialize styled dropdowns\n * - enhanceMethodSelect() - Convert select to styled dropdown\n * - showMethodDropdownMenu() - Show method selection menu\n * - buildMethodDropdownMenuHtml() - Build menu HTML\n * - closeMethodDropdownMenu() - Close dropdown menu\n * - updateMethodTrigger() - Update trigger display\n * - populateTiles() - Build multi-select tiles\n * - applyRangeInputConstraints() - Set numeric input constraints\n * - showRangeInputError() - Display validation error\n * - loadCombinationAttributeGroups() - Load attribute groups for picker\n * - loadCombinationAttributeValues() - Load values for attribute group\n * - restoreCombinationSelections() - Restore saved combination state\n * - updateCombinationData() - Save combination selection\n * - updateCombinationGroupCounts() - Update selection counts\n * - updateMethodInfoPlaceholder() - Show method help\n * - getBuiltInMethodHelp() - Get help text for methods\n * - buildSortOptions() - Build sort dropdown options\n * - updateModifierButtonState() - Update modifier toggle state\n * - updateMethodSelectorLock() - Lock/unlock method selector\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.methods = {\n\n /**\n * Initialize styled method dropdowns for all method selects\n */\n initMethodDropdowns: function() {\n var self = this;\n this.$wrapper.find('.include-method-select').each(function() {\n self.enhanceMethodSelect($(this));\n });\n this.$wrapper.find('.exclude-method-select').each(function() {\n self.enhanceMethodSelect($(this));\n });\n this.initMethodInfoPlaceholders();\n },\n\n /**\n * Initialize info placeholders for all existing method selects\n */\n initMethodInfoPlaceholders: function() {\n var self = this;\n this.$wrapper.find('.selection-group').each(function() {\n var $group = $(this);\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Include method info\n var includeMethod = $group.find('.include-method-select').val() || 'all';\n self.updateMethodInfoPlaceholder($group.find('.method-selector-wrapper'), includeMethod, blockType);\n\n // Exclude methods info\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var excludeMethod = $row.find('.exclude-method-select').val();\n if (excludeMethod) {\n self.updateMethodInfoPlaceholder($row.find('.method-selector-wrapper'), excludeMethod, blockType);\n }\n });\n });\n },\n\n /**\n * Enhance a single method select with styled dropdown\n */\n enhanceMethodSelect: function($select) {\n var self = this;\n\n if (!$select.length || $select.data('methodDropdownInit')) {\n return;\n }\n $select.data('methodDropdownInit', true);\n\n $select.addClass('method-select-hidden');\n\n var $selectedOption = $select.find('option:selected');\n var selectedIcon = $selectedOption.data('icon') || 'icon-caret-down';\n var selectedLabel = $selectedOption.text();\n\n var triggerHtml = '
';\n\n var $trigger = $(triggerHtml);\n $select.after($trigger);\n\n $trigger.on('click', function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var $wrapper = $select.closest('.method-selector-wrapper');\n if ($wrapper.hasClass('selector-locked')) {\n return;\n }\n\n self.showMethodDropdownMenu($select, $trigger);\n });\n\n $select.on('change.methodDropdown', function() {\n self.updateMethodTrigger($select, $trigger);\n });\n },\n\n /**\n * Update the trigger display to match current selection\n */\n updateMethodTrigger: function($select, $trigger) {\n var $selectedOption = $select.find('option:selected');\n var selectedIcon = $selectedOption.data('icon') || 'icon-caret-down';\n var selectedLabel = $selectedOption.text();\n\n $trigger.find('.method-trigger-icon').attr('class', selectedIcon + ' method-trigger-icon');\n $trigger.find('.method-trigger-label').text(selectedLabel);\n },\n\n /**\n * Show the method dropdown menu\n */\n showMethodDropdownMenu: function($select, $trigger) {\n var self = this;\n\n this.closeMethodDropdownMenu();\n\n var menuHtml = this.buildMethodDropdownMenuHtml($select);\n var $menu = $(menuHtml);\n\n var triggerOffset = $trigger.offset();\n var triggerWidth = $trigger.outerWidth();\n var triggerHeight = $trigger.outerHeight();\n\n $menu.css({\n position: 'absolute',\n top: triggerOffset.top + triggerHeight + 2,\n left: triggerOffset.left,\n minWidth: triggerWidth,\n zIndex: 10001\n });\n\n $('body').append($menu);\n this.$methodDropdownMenu = $menu;\n this.$methodDropdownSelect = $select;\n this.$methodDropdownTrigger = $trigger;\n\n $menu.on('click', '.method-dropdown-item', function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var value = $(this).data('value');\n $select.val(value).trigger('change');\n self.closeMethodDropdownMenu();\n });\n\n $(document).on('click.methodDropdown', function(e) {\n if (!$(e.target).closest('.method-dropdown-menu, .method-dropdown-trigger').length) {\n self.closeMethodDropdownMenu();\n }\n });\n\n $(document).on('keydown.methodDropdown', function(e) {\n if (e.keyCode === 27) {\n self.closeMethodDropdownMenu();\n }\n });\n },\n\n /**\n * Build the dropdown menu HTML\n */\n buildMethodDropdownMenuHtml: function($select) {\n var self = this;\n var html = '
';\n\n // Render ungrouped options first\n $select.children('option').each(function() {\n var $el = $(this);\n var icon = $el.data('icon') || 'icon-asterisk';\n var label = $el.text();\n var value = $el.val();\n var isSelected = $el.is(':selected');\n\n html += '
';\n html += '';\n html += '' + self.escapeHtml(label) + '';\n if (isSelected) {\n html += '';\n }\n html += '
';\n });\n\n // Render optgroups\n $select.children('optgroup').each(function() {\n var $optgroup = $(this);\n var groupLabel = $optgroup.attr('label') || '';\n\n html += '
';\n html += '
' + self.escapeHtml(groupLabel) + '
';\n html += '
';\n\n $optgroup.children('option').each(function() {\n var $el = $(this);\n var icon = $el.data('icon') || 'icon-cog';\n var label = $el.text();\n var value = $el.val();\n var isSelected = $el.is(':selected');\n\n html += '
';\n html += '';\n html += '' + self.escapeHtml(label) + '';\n if (isSelected) {\n html += '';\n }\n html += '
';\n });\n\n html += '
'; // close items\n html += '
'; // close optgroup\n });\n\n html += '
';\n return html;\n },\n\n /**\n * Close the method dropdown menu\n */\n closeMethodDropdownMenu: function() {\n if (this.$methodDropdownMenu) {\n this.$methodDropdownMenu.remove();\n this.$methodDropdownMenu = null;\n }\n this.$methodDropdownSelect = null;\n this.$methodDropdownTrigger = null;\n $(document).off('click.methodDropdown keydown.methodDropdown');\n },\n\n /**\n * Populate tiles for multi_select_tiles value picker\n */\n populateTiles: function($picker, options, exclusive) {\n var self = this;\n var $container = $picker.find('.multi-select-tiles');\n $container.empty();\n\n if (exclusive) {\n $container.attr('data-exclusive', 'true');\n } else {\n $container.removeAttr('data-exclusive');\n }\n\n $.each(options, function(key, optData) {\n var label = typeof optData === 'object' ? optData.label : optData;\n var icon = typeof optData === 'object' && optData.icon ? optData.icon : null;\n var color = typeof optData === 'object' && optData.color ? optData.color : null;\n\n var tileClass = 'tile-option';\n if (color) {\n tileClass += ' tile-color-' + color;\n }\n\n var $tile = $('', {\n type: 'button',\n class: tileClass,\n 'data-value': key\n });\n\n if (icon) {\n $tile.append($('', { class: icon }));\n }\n $tile.append($('', { class: 'tile-label', text: label }));\n\n $container.append($tile);\n });\n },\n\n /**\n * Apply step/min constraints to numeric range inputs\n */\n applyRangeInputConstraints: function($picker, step, min) {\n var $inputs = $picker.find('.range-min-input, .range-max-input');\n\n if (typeof step !== 'undefined' && step !== null) {\n $inputs.attr('step', step);\n } else {\n $inputs.attr('step', 'any');\n }\n\n if (typeof min !== 'undefined' && min !== null) {\n $inputs.attr('min', min);\n } else {\n $inputs.removeAttr('min');\n }\n },\n\n /**\n * Show error message on range input\n */\n showRangeInputError: function($input, message) {\n var $container = $input.closest('.multi-range-input-row');\n\n $container.find('.range-input-error').remove();\n $container.find('.range-min-input, .range-max-input').removeClass('has-error');\n\n $input.addClass('has-error');\n var $error = $('', {\n class: 'range-input-error',\n text: message\n });\n $container.append($error);\n\n setTimeout(function() {\n $input.removeClass('has-error');\n $error.fadeOut(200, function() {\n $(this).remove();\n });\n }, 3000);\n },\n\n /**\n * Load attribute groups for combination picker\n */\n loadCombinationAttributeGroups: function($picker) {\n var self = this;\n var trans = this.config.trans || {};\n var $container = $picker.find('.combination-groups-container');\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getAttributeGroups',\n trait: 'TargetConditions'\n },\n success: function(response) {\n $container.empty();\n\n if (!response.success || !response.groups || response.groups.length === 0) {\n $container.html('' +\n self.escapeHtml(trans.no_attribute_groups || 'No attribute groups found') +\n '');\n return;\n }\n\n response.groups.forEach(function(group) {\n var $groupDiv = $('
' + this.escapeHtml(trans.help_combination_within || 'Within group: OR (Red OR Blue)') + '
';\n html += '
' + this.escapeHtml(trans.help_combination_between || 'Between groups: AND (Color AND Size)') + '
';\n html += '
';\n break;\n\n case 'by_carrier':\n html = '' + this.escapeHtml(trans.help_carrier_title || 'By Carrier') + '';\n html += '
' + this.escapeHtml(trans.help_carrier_desc || 'Select items available with specific carriers.') + '
';\n break;\n\n case 'by_condition':\n html = '' + this.escapeHtml(trans.help_condition_title || 'By Condition') + '';\n html += '
' + this.escapeHtml(trans.help_condition_desc || 'Filter by product condition: New, Used, or Refurbished.') + '
';\n break;\n\n case 'by_visibility':\n html = '' + this.escapeHtml(trans.help_visibility_title || 'By Visibility') + '';\n html += '
' + this.escapeHtml(trans.help_visibility_desc || 'Filter by where products are visible in the store.') + '
';\n break;\n\n case 'by_active_status':\n html = '' + this.escapeHtml(trans.help_active_title || 'By Active Status') + '';\n html += '
' + this.escapeHtml(trans.help_active_desc || 'Filter by whether products are enabled or disabled.') + '
';\n break;\n\n case 'by_stock_status':\n html = '' + this.escapeHtml(trans.help_stock_title || 'By Stock Status') + '';\n html += '
' + this.escapeHtml(trans.help_stock_desc || 'Filter by stock availability: In stock, Out of stock, or Low stock.') + '
';\n break;\n\n case 'by_on_sale':\n case 'by_has_specific_price':\n case 'by_is_virtual':\n case 'by_is_pack':\n case 'by_has_combinations':\n case 'by_available_for_order':\n case 'by_online_only':\n case 'by_has_related':\n case 'by_has_customization':\n case 'by_has_attachments':\n case 'by_has_additional_shipping':\n html = '' + this.escapeHtml(trans.help_boolean_title || 'Yes/No Filter') + '';\n html += '
' + this.escapeHtml(trans.help_boolean_desc || 'Filter products by this property.') + '
';\n break;\n\n case 'by_name_pattern':\n case 'by_reference_pattern':\n case 'by_description_pattern':\n case 'by_long_description_pattern':\n case 'by_ean13_pattern':\n case 'by_upc_pattern':\n case 'by_isbn_pattern':\n case 'by_mpn_pattern':\n case 'by_meta_title_pattern':\n case 'by_meta_description_pattern':\n html = '' + this.escapeHtml(trans.help_pattern_title || 'Pattern Matching') + '';\n html += '
' + this.escapeHtml(trans.help_pattern_desc || 'Match text using patterns with wildcards.') + '
{letter} ' + this.escapeHtml(trans.help_pattern_letter || 'single letter A-Z') + '
';\n break;\n\n case 'by_id_range':\n case 'by_price_range':\n case 'by_weight_range':\n case 'by_quantity_range':\n case 'by_position_range':\n html = '' + this.escapeHtml(trans.help_range_title || 'Numeric Range') + '';\n html += '
' + this.escapeHtml(trans.help_range_desc || 'Filter by numeric values within specified ranges.') + '
';\n html += '
' + this.escapeHtml(trans.help_range_tip || 'Leave min or max empty for open-ended ranges.') + '
';\n break;\n\n case 'by_date_added':\n case 'by_date_updated':\n html = '' + this.escapeHtml(trans.help_date_title || 'Date Range') + '';\n html += '
' + this.escapeHtml(trans.help_date_desc || 'Filter by date within a specific period.') + '
';\n break;\n\n default:\n break;\n }\n\n return html;\n },\n\n /**\n * Build sort options HTML for a specific block type\n */\n buildSortOptions: function(blockType) {\n var options = [];\n\n switch (blockType) {\n case 'products':\n options = [\n { value: 'sales', label: 'Best sellers' },\n { value: 'date_add', label: 'Newest' },\n { value: 'price', label: 'Price' },\n { value: 'name', label: 'Name' },\n { value: 'position', label: 'Position' },\n { value: 'quantity', label: 'Stock quantity' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n case 'categories':\n options = [\n { value: 'name', label: 'Name' },\n { value: 'position', label: 'Position' },\n { value: 'product_count', label: 'Product count' },\n { value: 'total_sales', label: 'Best sellers' },\n { value: 'newest_products', label: 'Newest products' },\n { value: 'date_add', label: 'Creation date' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n case 'manufacturers':\n case 'suppliers':\n options = [\n { value: 'name', label: 'Name' },\n { value: 'product_count', label: 'Product count' },\n { value: 'total_sales', label: 'Best sellers' },\n { value: 'newest_products', label: 'Newest products' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n case 'cms':\n case 'cms_categories':\n options = [\n { value: 'name', label: 'Name' },\n { value: 'position', label: 'Position' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n default:\n options = [\n { value: 'name', label: 'Name' },\n { value: 'random', label: 'Random' }\n ];\n }\n\n var html = '';\n for (var i = 0; i < options.length; i++) {\n html += '';\n }\n\n return html;\n },\n\n /**\n * Update the modifier toggle button state\n */\n updateModifierButtonState: function($group) {\n var limit = $group.find('.group-modifier-limit').val();\n var sortBy = $group.find('.group-modifier-sort').val();\n var $modifiers = $group.find('.group-modifiers');\n var $btn = $group.find('.btn-toggle-modifiers');\n var trans = this.config.trans || {};\n\n $btn.find('.modifier-summary').remove();\n\n if (limit || sortBy) {\n $modifiers.addClass('has-values');\n\n var summary = [];\n if (limit) {\n summary.push((trans.top || 'Top') + ' ' + limit);\n }\n if (sortBy) {\n var sortLabel = $group.find('.group-modifier-sort option:selected').text();\n summary.push(sortLabel);\n }\n\n var $arrow = $btn.find('.toggle-arrow');\n $('' + this.escapeHtml(summary.join(', ')) + '').insertBefore($arrow);\n } else {\n $modifiers.removeClass('has-values');\n }\n },\n\n /**\n * Lock/unlock method selector when excludes are present\n */\n updateMethodSelectorLock: function($group, locked) {\n var $select = $group.find('.include-method-select');\n var $wrapper = $select.closest('.method-selector-wrapper');\n var trans = this.config.trans || {};\n\n if (locked) {\n $select.prop('disabled', true);\n\n if (!$wrapper.length) {\n $select.wrap('');\n $wrapper = $select.parent('.method-selector-wrapper');\n }\n\n $wrapper.addClass('selector-locked');\n if (!$wrapper.find('.mpr-info-wrapper').length) {\n var lockHtml = '' +\n '' +\n '' +\n (trans.remove_excludes_first || 'Remove all exceptions to change selection type') +\n '' +\n '';\n var $countEl = $wrapper.find('.condition-match-count');\n if ($countEl.length) {\n $countEl.before(lockHtml);\n } else {\n $wrapper.append(lockHtml);\n }\n }\n } else {\n $select.prop('disabled', false);\n if ($wrapper.length) {\n $wrapper.removeClass('selector-locked');\n $wrapper.find('.mpr-info-wrapper.lock-indicator').remove();\n } else {\n $select.siblings('.mpr-info-wrapper.lock-indicator').remove();\n }\n }\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Preview Module\n * Preview popover and pattern preview modal\n * @partial _preview.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 2906-2942 (updateHeaderTotalCount, updateShowAllToggle)\n * 2943-3051 (showPreviewPopover)\n * 3053-3076 (renderPreviewItems)\n * 3078-3100 (filterPreviewItems)\n * 3102-3183 (loadMorePreviewItems)\n * 3185-3194 (hidePreviewPopover)\n * 3196-3287 (showPatternPreviewModal)\n * 3289-3400 (refreshGroupPreviewIfOpen) - estimated\n * 7592-7700 (showReplaceConfirmation, getCurrentSingleSelection)\n * 7703-7745 (getBlockMode, isBlockSingleMode)\n *\n * Contains:\n * - showPreviewPopover() - Show tab count preview\n * - hidePreviewPopover() - Close preview popover\n * - renderPreviewItems() - Render item list in preview\n * - filterPreviewItems() - Filter preview items by query\n * - loadMorePreviewItems() - Load additional preview items\n * - showPatternPreviewModal() - Pattern match preview modal\n * - refreshGroupPreviewIfOpen() - Refresh preview if open\n * - updateHeaderTotalCount() - Update header total badge\n * - updateShowAllToggle() - Update show-all checkbox state\n * - showReplaceConfirmation() - Single mode replace dialog\n * - getCurrentSingleSelection() - Get current selection in single mode\n * - getBlockMode() - Get block selection mode\n * - isBlockSingleMode() - Check if block is single-select\n * - getEntityTypeLabel() - Get human-readable entity label\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.preview = {\n\n updateHeaderTotalCount: function() {\n var self = this;\n var total = 0;\n\n this.$wrapper.find('.target-block-tab .tab-badge').each(function() {\n var $badge = $(this);\n if (!$badge.hasClass('loading')) {\n var count = parseInt($badge.text(), 10);\n if (!isNaN(count)) {\n total += count;\n }\n }\n });\n\n var $totalBadge = this.$wrapper.find('.trait-total-count');\n if (total > 0) {\n $totalBadge.text(total).show();\n } else {\n $totalBadge.hide();\n }\n\n this.updateShowAllToggle();\n },\n\n updateShowAllToggle: function() {\n var $toggle = this.$wrapper.find('.trait-show-all-toggle');\n if (!$toggle.length) return;\n\n var $checkbox = $toggle.find('.show-all-checkbox');\n var hasData = this.$wrapper.find('.target-block-tab.has-data').length > 0;\n\n $checkbox.prop('checked', !hasData);\n },\n\n showPreviewPopover: function($tab) {\n var previewData = $tab.data('previewData');\n if (!previewData) {\n return;\n }\n\n this.hidePreviewPopover();\n\n var $badge = $tab.find('.tab-badge');\n $badge.addClass('popover-open');\n this.$activeBadge = $badge;\n var items = previewData.items || previewData.products || [];\n this.previewLoadedCount = items.length;\n this.previewBlockType = $tab.data('blockType');\n\n var blockType = this.previewBlockType;\n var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n\n var trans = this.config.trans || {};\n var html = '
';\n\n html += '
';\n html += '' + previewData.count + ' ' + entityLabelPlural + ' ' + (trans.items_matched || 'matched') + '';\n html += '';\n html += '
';\n\n html += '
';\n html += '';\n html += '
';\n\n if (items.length > 0) {\n html += '
';\n html += this.renderPreviewItems(items);\n html += '
';\n\n if (previewData.hasMore) {\n var remaining = previewData.count - items.length;\n html += '';\n }\n } else {\n html += '
' + (trans.no_preview || 'No items to preview') + '
';\n }\n\n html += '
';\n\n var $popover = $(html);\n $('body').append($popover);\n\n this.$previewList = $popover.find('.preview-list');\n this.allPreviewData = previewData;\n\n var self = this;\n $popover.find('.preview-close').on('click', function() {\n self.hidePreviewPopover();\n });\n\n $popover.find('.preview-filter-input').on('input', function() {\n var query = $(this).val().toLowerCase().trim();\n self.filterPreviewItems(query);\n });\n\n $popover.find('.btn-load-more-preview').on('click', function() {\n self.loadMorePreviewItems($tab, $(this));\n });\n\n var badgeOffset = $badge.offset();\n var badgeHeight = $badge.outerHeight();\n var badgeWidth = $badge.outerWidth();\n var popoverWidth = $popover.outerWidth();\n\n var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);\n var minLeft = 10;\n var maxLeft = $(window).width() - popoverWidth - 10;\n leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));\n\n $popover.css({\n position: 'absolute',\n top: badgeOffset.top + badgeHeight + 8,\n left: leftPos,\n zIndex: 10000\n });\n\n // Add show class to trigger visibility\n $popover.addClass('show');\n\n this.$previewPopover = $popover;\n },\n\n renderPreviewItems: function(products) {\n var html = '';\n $.each(products, function(i, product) {\n var itemClass = 'preview-item' + (product.isCombination ? ' is-combination' : '');\n var attrs = (product.attributes || '').toLowerCase();\n html += '
';\n if (product.image) {\n html += '';\n } else {\n html += '';\n }\n html += '
';\n html += '' + product.name + '';\n if (product.attributes) {\n html += '' + product.attributes + '';\n }\n if (product.reference) {\n html += '' + product.reference + '';\n }\n html += '
';\n html += '
';\n });\n return html;\n },\n\n filterPreviewItems: function(query) {\n if (!this.$previewList) return;\n\n var $items = this.$previewList.find('.preview-item');\n\n if (!query) {\n $items.show();\n return;\n }\n\n $items.each(function() {\n var $item = $(this);\n var name = $item.data('name') || '';\n var ref = $item.data('ref') || '';\n var attrs = $item.data('attrs') || '';\n\n if (name.indexOf(query) !== -1 || ref.indexOf(query) !== -1 || attrs.indexOf(query) !== -1) {\n $item.show();\n } else {\n $item.hide();\n }\n });\n },\n\n loadMorePreviewItems: function($tab, $btn) {\n var self = this;\n var blockType = this.previewBlockType;\n\n var $footer = $btn.closest('.preview-footer');\n var $select = $footer.find('.load-more-select');\n var loadCount = parseInt($select.val(), 10) || 20;\n\n var $hiddenInput = this.$wrapper.find('input[name=\"' + this.config.name + '\"]');\n var savedData = {};\n try {\n savedData = JSON.parse($hiddenInput.val() || '{}');\n } catch (e) {\n return;\n }\n\n var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];\n if (groups.length === 0) return;\n\n var data = {};\n data[blockType] = { groups: groups };\n\n $btn.prop('disabled', true).find('i').removeClass('icon-plus').addClass('icon-spinner icon-spin');\n $select.prop('disabled', true);\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewTargetConditions',\n trait: 'TargetConditions',\n conditions: JSON.stringify(data),\n block_type: blockType,\n limit: self.previewLoadedCount + loadCount,\n offset: 0\n },\n success: function(response) {\n var items = response.items || response.products || [];\n if (response.success && items.length > 0) {\n self.$previewList.html(self.renderPreviewItems(items));\n self.previewLoadedCount = items.length;\n\n if (response.hasMore) {\n var remaining = response.count - items.length;\n $footer.find('.remaining-count').text(remaining);\n\n var $allOption = $select.find('option:last');\n if ($allOption.val() !== '10' && $allOption.val() !== '20' && $allOption.val() !== '50' && $allOption.val() !== '100') {\n $allOption.val(remaining).text(self.config.trans.all + ' (' + remaining + ')');\n }\n\n $btn.prop('disabled', false).find('i').removeClass('icon-spinner icon-spin').addClass('icon-plus');\n $select.prop('disabled', false);\n } else {\n $footer.remove();\n }\n\n $tab.data('previewData', response);\n self.allPreviewData = response;\n\n var filterQuery = self.$previewPopover.find('.preview-filter-input').val();\n if (filterQuery) {\n self.filterPreviewItems(filterQuery.toLowerCase().trim());\n }\n }\n },\n error: function() {\n $btn.prop('disabled', false).find('i').removeClass('icon-spinner icon-spin').addClass('icon-plus');\n $select.prop('disabled', false);\n }\n });\n },\n\n hidePreviewPopover: function() {\n if (this.$activeBadge) {\n this.$activeBadge.removeClass('popover-open');\n this.$activeBadge = null;\n }\n if (this.$previewPopover) {\n this.$previewPopover.remove();\n this.$previewPopover = null;\n }\n },\n\n showPatternPreviewModal: function(pattern, entityType, caseSensitive, count) {\n var self = this;\n var trans = this.config.trans || {};\n\n var blockConfig = this.config.blocks && this.config.blocks[entityType] ? this.config.blocks[entityType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n var entityLabelSingular = blockConfig.entity_label || 'item';\n\n var html = '
';\n html += '
';\n html += '
';\n html += '';\n html += ' ' + (trans.preview || 'Preview') + ': ' + this.escapeHtml(pattern) + '';\n html += '';\n html += '' + count + ' ' + (count === 1 ? entityLabelSingular : entityLabelPlural) + '';\n html += '';\n html += '
');\n }\n });\n },\n\n refreshGroupPreviewIfOpen: function($group) {\n var self = this;\n\n if (!this.$activeBadge || !this.$previewPopover) {\n return;\n }\n\n // Check if preview is for this group and refresh if needed\n },\n\n /**\n * Show preview popover for condition match count badge\n */\n showConditionPreviewPopover: function($badge) {\n var self = this;\n var conditionData = $badge.data('conditionData');\n\n if (!conditionData) {\n return;\n }\n\n this.hidePreviewPopover();\n\n $badge.addClass('popover-open loading');\n this.$activeBadge = $badge;\n\n var trans = this.config.trans || {};\n var blockType = conditionData.blockType || 'products';\n var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n\n // Fetch preview items from backend\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewConditionItems',\n trait: 'EntitySelector',\n method: conditionData.method,\n values: JSON.stringify(conditionData.values),\n block_type: blockType,\n limit: 10\n },\n success: function(response) {\n $badge.removeClass('loading');\n\n if (response.success) {\n var items = response.items || [];\n self.showItemsPopover($badge, items, response.count, response.hasMore, entityLabelPlural, blockType, 'condition');\n }\n },\n error: function() {\n $badge.removeClass('loading popover-open');\n self.$activeBadge = null;\n }\n });\n },\n\n /**\n * Show preview popover for group count badge\n */\n showGroupPreviewPopover: function($badge, $group, blockType) {\n var self = this;\n\n // If $group not passed, try to find it\n if (!$group) {\n $group = $badge.closest('.selection-group');\n }\n\n if (!blockType) {\n var $block = $badge.closest('.target-block');\n blockType = $block.data('blockType') || 'products';\n }\n\n var groupData = $badge.data('groupData');\n\n if (!groupData) {\n // Try to serialize from DOM\n groupData = this.serializeGroup($group, blockType);\n }\n\n if (!groupData || !groupData.include) {\n return;\n }\n\n this.hidePreviewPopover();\n\n $badge.addClass('popover-open loading');\n this.$activeBadge = $badge;\n\n var trans = this.config.trans || {};\n var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n\n // Fetch preview items from backend\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewGroupItems',\n trait: 'EntitySelector',\n group_data: JSON.stringify(groupData),\n block_type: blockType,\n limit: 10\n },\n success: function(response) {\n $badge.removeClass('loading');\n\n if (response.success) {\n var items = response.items || [];\n self.showItemsPopover($badge, items, response.count, response.hasMore, entityLabelPlural, blockType, 'group');\n } else {\n $badge.removeClass('popover-open');\n self.$activeBadge = null;\n }\n },\n error: function() {\n $badge.removeClass('loading popover-open');\n self.$activeBadge = null;\n }\n });\n },\n\n /**\n * Common popover display for both condition and group previews\n */\n showItemsPopover: function($badge, items, totalCount, hasMore, entityLabel, blockType, previewType) {\n var self = this;\n var trans = this.config.trans || {};\n\n var html = '
';\n\n html += '
';\n html += '' + totalCount + ' ' + entityLabel + '';\n html += '';\n html += '
';\n\n if (items.length > 0) {\n html += '
';\n html += this.renderPreviewItems(items);\n html += '
';\n\n if (hasMore) {\n var remaining = totalCount - items.length;\n html += '';\n }\n } else {\n html += '
' + (trans.no_preview || 'No items to preview') + '
';\n }\n\n html += '
';\n\n var $popover = $(html);\n $('body').append($popover);\n\n $popover.find('.preview-close').on('click', function() {\n self.hidePreviewPopover();\n });\n\n // Position popover below badge\n var badgeOffset = $badge.offset();\n var badgeHeight = $badge.outerHeight();\n var badgeWidth = $badge.outerWidth();\n var popoverWidth = $popover.outerWidth();\n\n var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);\n var minLeft = 10;\n var maxLeft = $(window).width() - popoverWidth - 10;\n leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));\n\n var topPos = badgeOffset.top + badgeHeight + 8;\n\n $popover.css({\n position: 'absolute',\n top: topPos,\n left: leftPos,\n zIndex: 10000\n });\n\n // Add show class for CSS transition\n $popover.addClass('show');\n\n this.$previewPopover = $popover;\n },\n\n /**\n * Render preview items HTML\n */\n renderPreviewItems: function(items) {\n var html = '';\n\n for (var i = 0; i < items.length; i++) {\n var item = items[i];\n html += '
';\n\n // Image or icon\n if (item.image) {\n html += '';\n } else {\n html += '
inventory_2
';\n }\n\n // Info\n html += '
';\n html += '
' + this.escapeHtml(item.name || 'Unnamed') + '
';\n\n var meta = [];\n if (item.reference) {\n meta.push('Ref: ' + item.reference);\n }\n if (item.manufacturer) {\n meta.push(item.manufacturer);\n }\n if (item.category) {\n meta.push(item.category);\n }\n if (item.attributes) {\n meta.push(item.attributes);\n }\n\n if (meta.length > 0) {\n html += '
' + this.escapeHtml(meta.join(' • ')) + '
';\n }\n\n html += '
';\n\n // Price or status\n if (typeof item.price !== 'undefined') {\n html += '
' + this.formatPrice(item.price) + '
';\n }\n if (typeof item.active !== 'undefined' && !item.active) {\n html += 'Inactive';\n }\n\n html += '
';\n }\n\n return html;\n },\n\n /**\n * Format price for display\n */\n formatPrice: function(price) {\n if (typeof price !== 'number') {\n price = parseFloat(price) || 0;\n }\n return price.toFixed(2) + ' €';\n },\n\n /**\n * Show preview popover for filter group toggle (attribute/feature groups)\n */\n showFilterGroupPreviewPopover: function($badge, groupId, groupType, groupName) {\n var self = this;\n\n this.hidePreviewPopover();\n\n $badge.addClass('popover-open loading');\n this.$activeBadge = $badge;\n\n var trans = this.config.trans || {};\n var entityLabelPlural = 'products';\n\n // Fetch products matching this attribute/feature group\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewFilterGroupProducts',\n trait: 'EntitySelector',\n group_id: groupId,\n group_type: groupType,\n limit: 10\n },\n success: function(response) {\n $badge.removeClass('loading');\n\n if (response.success) {\n var items = response.items || [];\n var totalCount = response.count || 0;\n var hasMore = response.hasMore || false;\n\n self.showFilterGroupItemsPopover($badge, items, totalCount, hasMore, entityLabelPlural, groupName, groupType);\n } else {\n $badge.removeClass('popover-open');\n self.$activeBadge = null;\n }\n },\n error: function() {\n $badge.removeClass('loading popover-open');\n self.$activeBadge = null;\n }\n });\n },\n\n /**\n * Show popover for filter group preview items\n */\n showFilterGroupItemsPopover: function($badge, items, totalCount, hasMore, entityLabel, groupName, groupType) {\n var self = this;\n var trans = this.config.trans || {};\n\n var typeLabel = groupType === 'attribute' ? (trans.attribute || 'Attribute') : (trans.feature || 'Feature');\n var html = '
';\n\n html += '
';\n html += '' + totalCount + ' ' + entityLabel + '';\n html += '';\n html += '
';\n\n if (items.length > 0) {\n html += '
';\n html += this.renderPreviewItems(items);\n html += '
';\n\n if (hasMore) {\n var remaining = totalCount - items.length;\n html += '';\n }\n } else {\n html += '
' + (trans.no_preview || 'No items to preview') + '
';\n }\n\n html += '
';\n\n var $popover = $(html);\n $('body').append($popover);\n\n $popover.find('.preview-close').on('click', function() {\n self.hidePreviewPopover();\n });\n\n // Position popover below badge\n var badgeOffset = $badge.offset();\n var badgeHeight = $badge.outerHeight();\n var badgeWidth = $badge.outerWidth();\n var popoverWidth = $popover.outerWidth();\n\n var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);\n var minLeft = 10;\n var maxLeft = $(window).width() - popoverWidth - 10;\n leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));\n\n var topPos = badgeOffset.top + badgeHeight + 8;\n\n $popover.css({\n position: 'absolute',\n top: topPos,\n left: leftPos,\n zIndex: 10000\n });\n\n $popover.addClass('show');\n\n this.$previewPopover = $popover;\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Core Module\n * Factory, initialization, state management\n * @partial _core.js\n *\n * IMPORTANT: This file must be loaded LAST in the concatenation order\n * as it combines all mixins from other partials.\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 15-55 (createTargetConditionsInstance, state variables)\n * 56-110 (init method)\n * 108-132 (observeNewSelects)\n * 7889-7951 (Factory object, window export, document ready)\n *\n * Contains:\n * - createTargetConditionsInstance() - Factory function\n * - State variable initialization\n * - init() - Main initialization method\n * - observeNewSelects() - MutationObserver for dynamic selects\n * - loadExistingSelections() - Restore saved state\n * - TargetConditions factory object\n * - window.TargetConditions export\n * - Document ready auto-initialization\n */\n\n(function($) {\n 'use strict';\n\n /**\n * Create a new TargetConditions instance\n * Each instance is independent and manages its own wrapper/state\n */\n function createTargetConditionsInstance() {\n // Base instance object with state variables\n var instance = {\n config: {},\n $wrapper: null,\n $dropdown: null,\n activeGroup: null, // { blockType, groupIndex, section: 'include'|'exclude' }\n searchTimeout: null,\n searchResults: [],\n searchTotal: 0,\n searchOffset: 0,\n searchQuery: '',\n isLoading: false,\n loadMoreCount: 20,\n // Sort, filter, view state\n viewMode: 'list',\n currentSort: { field: 'name', dir: 'ASC' },\n refineQuery: '',\n refineNegate: false,\n filters: {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: []\n },\n filterableData: null,\n // Search history\n searchHistory: {},\n searchHistoryMax: 10,\n searchHistoryKey: 'targetConditionsSearchHistory',\n // Chips visibility\n maxVisibleChips: 20,\n // Method dropdown references\n $methodDropdownMenu: null,\n $methodDropdownSelect: null,\n $methodDropdownTrigger: null,\n // Preview state\n $previewPopover: null,\n $activeBadge: null,\n $previewList: null,\n previewLoadedCount: 0,\n previewBlockType: null,\n allPreviewData: null,\n // Count update timeout\n countUpdateTimeout: null,\n\n init: function(options) {\n this.config = $.extend({\n id: 'target-conditions',\n name: 'target_conditions',\n namePrefix: 'target_',\n mode: 'multi', // Global mode: 'multi' or 'single'\n blocks: {},\n ajaxUrl: '',\n trans: {}\n }, options);\n\n this.$wrapper = $('[data-entity-selector-id=\"' + this.config.id + '\"]');\n\n if (!this.$wrapper.length) {\n return;\n }\n\n // Global single mode - hide \"Add Group\" buttons\n if (this.config.mode === 'single') {\n this.$wrapper.find('.btn-add-group').hide();\n this.$wrapper.find('.group-excludes').hide();\n this.$wrapper.find('.group-modifiers').hide();\n }\n\n // Add fullwidth class to parent form-group\n var $formGroup = this.$wrapper.closest('.form-group');\n $formGroup.addClass('condition-trait-fullwidth');\n $formGroup.find('.col-lg-offset-3').removeClass('col-lg-offset-3');\n\n this.createDropdown();\n this.bindEvents();\n this.loadExistingSelections();\n this.loadSearchHistory();\n\n // Initialize styled method dropdowns\n this.initMethodDropdowns();\n\n // Watch for dynamically added selects\n this.observeNewSelects();\n\n // Update counts on page load\n var self = this;\n setTimeout(function() {\n self.updateTabBadges();\n self.updateAllConditionCounts();\n }, 100);\n },\n\n observeNewSelects: function() {\n var self = this;\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.addedNodes.length) {\n $(mutation.addedNodes).find('.include-method-select, .exclude-method-select').each(function() {\n self.enhanceMethodSelect($(this));\n });\n }\n });\n });\n\n observer.observe(this.$wrapper[0], {\n childList: true,\n subtree: true\n });\n },\n\n loadExistingSelections: function() {\n // TODO: Extract full implementation from original\n // Reads JSON from hidden input and populates chips\n }\n };\n\n // Merge all mixins into the instance\n // Each mixin adds its methods to window._EntitySelectorMixins\n var mixins = window._EntitySelectorMixins || {};\n\n // Merge utils mixin\n if (mixins.utils) {\n $.extend(instance, mixins.utils);\n }\n\n // Merge events mixin\n if (mixins.events) {\n $.extend(instance, mixins.events);\n }\n\n // Merge dropdown mixin\n if (mixins.dropdown) {\n $.extend(instance, mixins.dropdown);\n }\n\n // Merge search mixin\n if (mixins.search) {\n $.extend(instance, mixins.search);\n }\n\n // Merge filters mixin\n if (mixins.filters) {\n $.extend(instance, mixins.filters);\n }\n\n // Merge chips mixin\n if (mixins.chips) {\n $.extend(instance, mixins.chips);\n }\n\n // Merge groups mixin\n if (mixins.groups) {\n $.extend(instance, mixins.groups);\n }\n\n // Merge methods mixin\n if (mixins.methods) {\n $.extend(instance, mixins.methods);\n }\n\n // Merge preview mixin\n if (mixins.preview) {\n $.extend(instance, mixins.preview);\n }\n\n return instance;\n }\n\n // Factory object for creating and managing instances\n var TargetConditions = {\n instances: [],\n\n // Create and initialize a new instance\n create: function(options) {\n var instance = createTargetConditionsInstance();\n instance.init(options);\n this.instances.push(instance);\n return instance;\n },\n\n // For backwards compatibility - init creates a new instance\n init: function(options) {\n return this.create(options);\n },\n\n // Validate all instances - returns true if all valid\n validateAll: function() {\n var allValid = true;\n for (var i = 0; i < this.instances.length; i++) {\n if (!this.instances[i].validate()) {\n allValid = false;\n }\n }\n return allValid;\n }\n };\n\n // Export to window\n window.TargetConditions = TargetConditions;\n\n // Auto-initialize on document ready\n $(document).ready(function() {\n // Auto-initialize from data-config attributes on wrapper elements\n $('[data-entity-selector-id]').each(function() {\n var configData = $(this).data('config');\n if (configData) {\n TargetConditions.create(configData);\n }\n });\n\n // Tips box toggle handler\n $(document).on('click', '.target-tips-box .tips-header', function(e) {\n e.preventDefault();\n $(this).closest('.target-tips-box').toggleClass('expanded');\n });\n\n // Form submission validation for required target conditions\n $(document).on('submit', 'form', function(e) {\n var $form = $(this);\n if ($form.find('.target-conditions-trait[data-required]').length > 0) {\n if (!TargetConditions.validateAll()) {\n e.preventDefault();\n return false;\n }\n }\n });\n });\n\n})(jQuery);\n"]}
\ No newline at end of file
+{"version":3,"sources":["_utils.js","_events.js","_dropdown.js","_search.js","_filters.js","_chips.js","_groups.js","_methods.js","_preview.js","_core.js"],"names":["$","window","_EntitySelectorMixins","utils","escapeHtml","str","String","replace","escapeAttr","getEntityTypeIcon","entityType","products","categories","manufacturers","suppliers","attributes","features","cms","cms_categories","getEntityTypeLabel","trans","this","config","product","category","manufacturer","supplier","attribute","feature","cms_page","cms_category","validate","$wrapper","data","hasData","find","each","length","clearValidationError","showValidationError","addClass","message","remove","$error","class","html","after","animate","scrollTop","offset","top","is","slideDown","removeClass","getBlockMode","blockType","blockDef","blocks","mode","isBlockSingleMode","getCurrentSingleSelection","$chip","first","$block","closest","name","text","jQuery","events","bindEvents","self","on","e","preventDefault","switchToBlock","stopPropagation","$tab","hasClass","hidePreviewPopover","showPreviewPopover","$badge","showConditionPreviewPopover","showGroupPreviewPopover","document","groupId","groupType","groupName","showFilterGroupPreviewPopover","target","$body","stop","slideUp","toggleClass","$btn","currentState","attr","collapse_all","expand_all","prop","clearAllConditions","val","addGroup","$group","removeGroup","$input","trim","serializeAllBlocks","addFirstExcludeRow","addExcludeRow","$excludeRow","removeExcludeRow","hideDropdown","$row","methods","selection_methods","$option","valueType","searchEntity","methodOptions","$oldPicker","newPickerHtml","buildValuePickerHtml","replaceWith","$select","$newPicker","empty","key","label","append","isExclusive","populateTiles","step","min","applyRangeInputConstraints","loadCombinationAttributeGroups","selectedMethod","updateMethodInfoPlaceholder","updateBlockStatus","keyCode","click","$draftTag","$picker","pattern","caseSensitive","addPatternTag","focus","hide","clearTimeout","$matchCount","timeout","setTimeout","updateDraftTagCount","updateGroupTotalCount","$tag","isDraftTag","newCaseSensitive","caseTitle","case_sensitive","case_insensitive","count","showPatternPreviewModal","currentPattern","$editInput","$saveBtn","$cancelBtn","$editActions","prepend","select","ev","newPattern","show","content","tooltipClass","$tooltip","triggerWidth","outerWidth","tooltipWidth","tooltipHeight","outerHeight","left","width","css","position","$container","$chipsContainer","$minInput","$maxInput","minVal","maxVal","parseFloat","minAllowed","hasMinConstraint","minNum","maxNum","showRangeInputError","min_value_error","min_greater_than_max","chipText","decimals","split","Math","round","toFixed","type","$tile","$value","updateCombinationData","query","toLowerCase","indexOf","$modifiers","$content","slideToggle","$limitInput","limit","parseInt","finalCount","$previewBadge","displayCount","updateModifierButtonState","refreshGroupPreviewIfOpen","newDir","$icon","groupIndex","section","excludeIndex","activeGroup","searchResults","searchOffset","searchQuery","viewMode","resetFiltersWithoutSearch","$dropdown","updateFilterPanelForEntity","loadFilterableData","positionDropdown","performSearch","searchTimeout","filterCategoryTree","$item","removeFromSearchHistory","fadeOut","id","isSelected","removeSelection","currentSelection","newEntityType","showReplaceConfirmation","addSelection","$chips","updateChipsVisibility","addSelectionNoUpdate","isLoading","loadCount","loadMoreCount","currentSort","field","refreshSearch","dir","value","loadCategoryTree","$allItems","isCollapsed","descendants","findTreeDescendants","i","toggle","updateCount","selectedCount","totalCount","categoryLabel","updateSelectChildrenButtons","allSelected","j","$child","select_with_children","k","$descendant","deselect_with_children","minLevel","Infinity","level","hasChildren","refineQuery","refineTimeout","refineNegate","placeholder","refine_exclude","refine_short","$panel","showSearchHistory","filters","inStock","discounted","priceMin","priceMax","productCountMin","productCountMax","salesMin","salesMax","turnoverMin","turnoverMax","dateAddFrom","dateAddTo","lastProductFrom","lastProductTo","depth","hasProducts","hasDescription","hasImage","activeOnly","attributeGroup","featureGroup","isColor","isCustom","indexable","isActive","hideFilterGroupValues","showFilterGroupValues","filterArray","index","push","splice","updateFilterToggleStates","clearFilters","ctrlKey","metaKey","trigger","dropdown","createDropdown","select_all","all","clear_selection","clear","sort_name","sort_id","sort_position","sort_popularity","sort_selected","view_list","view_tree","cols","exclude_matches","toggle_filters","recent_searches","in_stock","price","max","clear_filters","product_count","total_sales","turnover","active_only","all_levels","root","has_products","has_description","has_image","date_added","from","to","last_product","attribute_group","all_groups","color_only","feature_group","custom_only","sale","stock","sold","load","of","remaining","cancel","done","$searchBox","searchBoxOffset","searchBoxHeight","pickerOffset","pickerWidth","dropdownTop","dropdownLeft","dropdownWidth","viewportWidth","maxHeight","height","zIndex","search","categoryTreeCache","appendMode","requestData","ajax","action","trait","entity_type","q","sort_by","sort_dir","refine","refine_negate","filter_in_stock","filter_discounted","filter_price_min","filter_price_max","filter_attributes","JSON","stringify","filter_features","filter_product_count_min","filter_product_count_max","filter_depth","filter_has_products","filter_has_description","filter_has_image","filter_sales_min","filter_sales_max","filter_turnover_min","filter_turnover_max","filter_active","filter_date_add_from","filter_date_add_to","filter_last_product_from","filter_last_product_to","filter_attribute_group","filter_is_color","filter_feature_group","filter_is_custom","filter_indexable","url","ajaxUrl","dataType","success","response","total","addToSearchHistory","concat","results","searchTotal","renderSearchResults","error","selectedIds","hiddenIds","currentSearchEntity","currentExcludeIndex","isProductSearch","isListView","visibleResults","filter","item","hiddenCount","countText","forEach","itemClass","image","subtitle","iconClass","subtitleLines","line","idx","regular_price_formatted","price_formatted","has_discount","stockClass","stock_status","undefined","stock_qty","sales_qty","no_results","hasMore","$loadMoreControls","$allOption","hasHistory","getSearchHistory","cacheKey","renderCategoryTree","xhr","status","isCmsCategory","cat","indent","has_children","parent_id","nleft","nright","isSingleMode","$items","matchingIds","ancestorIds","ancestors","findTreeAncestors","visibleCount","$parent","parentId","childNleft","childNright","idsToCheck","processed","checkId","shift","itemParentId","itemId","$ancestor","ancNleft","ancNright","loadSearchHistory","stored","localStorage","getItem","searchHistoryKey","searchHistory","parse","saveSearchHistory","setItem","history","existingIndex","unshift","searchHistoryMax","slice","$treeOption","filterableData","loadAttributeGroups","groups","group","loadFeatureGroups","renderFilterDropdowns","$attrContainer","$featContainer","g","valuesRowClass","$filterRowValues","$valuesContainer","values","activeClass","chipClass","colorStyle","color","colorClass","rowValues","scrollIntoView","behavior","block","$toggle","hasActiveInGroup","some","chips","$allChips","isExpanded","maxVisibleChips","collapseText","show_less","moreText","show_more","loadExistingSelections","entitiesToLoad","$includePicker","collectPickerEntities","enhanceMethodSelect","updateMethodSelectorLock","Object","keys","ids","uniqueIds","arr","entities","entityMap","entity","pickers","pickerData","$dataInput","validIds","$loadingChip","rawValue","entityIcon","Array","isArray","range","loadPickerValues","isCaseSensitive","remove_pattern","getPatternTags","patterns","$countValue","updateConditionCountWithPendingPattern","pendingPattern","$countEl","isExclude","method","block_type","fetchPatternMatchCount","getPickerValues","patternValues","$draftPatternInput","draftPatternVal","draftCaseSens","updateConditionCount","hasNoValues","updateGroupCounts","$include","groupData","serializeGroup","include","group_data","final_count","excludeCount","exclude_count","badgeHtml","updateAllConditionCounts","maxIndex","buildMethodOptions","click_to_name","remove_group","no_items_selected","search_placeholder","add_exceptions","limit_tooltip","sort","sort_bestsellers","sort_newest","sort_price","sort_stock","sort_random","sort_direction","preview_results","$newGroup","emptyHtml","getEmptyStateText","updateTabBadges","updateHeaderTotalCount","groupCount","fetchProductCount","updateTargetSwitchState","$switch","$hiddenInput","savedData","removeData","conditions","isNaN","$totalBadge","updateShowAllToggle","$checkbox","$status","getBlockGroups","emptyMeansAll","entity_label_plural","nothing_selected","blockMode","no_item_selected","included","includeMethod","includeValues","excludes","excludeMethod","$excludePicker","excludeValues","modifiers","getGroupModifiers","$changedRow","countUpdateTimeout","isConditionValid","sortBy","sortDir","Number","$draftInput","draftPattern","draftCaseSensitive","selectVal","ranges","combAttrs","toString","valueId","combMode","configMode","combinationMode","$excludesDiv","except","buildExcludeRowHtml","add_another_exception","$newRow","excludeMethodOptions","firstSearchEntity","firstValueType","methodKey","methodDef","search_entity","value_type","remove_this_exception","excludeAll","groupLabels","select_by","filter_by","grouped","ungrouped","buildMethodOption","groupKey","groupMethods","groupLabel","icon","options","exclusive","pickerClass","chipsClass","dataClass","noItemsText","tooltipContent","pattern_help_title","pattern_help_wildcard","pattern_help_number","pattern_help_letter","pattern_help_examples","pattern_example_1","pattern_example_2","pattern_example_3","noPatternText","no_patterns","enter_pattern","click_to_preview","add_pattern","add_range","yes","combination_help_title","combination_help_desc","combination_help_logic","combination_help_within","combination_help_between","showModeToggle","defaultMode","Date","now","comb_mode_products","comb_mode_combinations","loading","getSortOptionsArray","sort_products","getSortIconClass","isAsc","cycleSortOption","newSort","newLabel","sortOptions","currentDir","currentIndex","initMethodDropdowns","initMethodInfoPlaceholders","$selectedOption","selectedIcon","selectedLabel","triggerHtml","$trigger","showMethodDropdownMenu","updateMethodTrigger","closeMethodDropdownMenu","menuHtml","buildMethodDropdownMenuHtml","$menu","triggerOffset","triggerHeight","minWidth","$methodDropdownMenu","$methodDropdownSelect","$methodDropdownTrigger","children","$el","$optgroup","off","removeAttr","optData","tileClass","$inputs","$groupDiv","$groupHeader","$toolbar","title","filter_results","loadCombinationAttributeValues","no_attribute_groups","error_loading","id_attribute_group","productCount","$valueBtn","restoreCombinationSelections","no_values","dataStr","valueIds","updateCombinationGroupCounts","$headerRow","$placeholder","methodHelp","helpContent","getBuiltInMethodHelp","$infoWrapper","help_all_title","help_all_desc","help_specific_title","help_specific_desc","help_category_title","help_category_desc","help_manufacturer_title","help_manufacturer_desc","help_supplier_title","help_supplier_desc","help_tag_title","help_tag_desc","help_attribute_title","help_attribute_desc","help_feature_title","help_feature_desc","help_combination_title","help_combination_desc","help_combination_logic","help_combination_within","help_combination_between","help_carrier_title","help_carrier_desc","help_condition_title","help_condition_desc","help_visibility_title","help_visibility_desc","help_active_title","help_active_desc","help_stock_title","help_stock_desc","help_boolean_title","help_boolean_desc","help_pattern_title","help_pattern_desc","help_pattern_wildcard","help_pattern_number","help_pattern_letter","help_range_title","help_range_desc","help_range_tip","help_date_title","help_date_desc","buildSortOptions","summary","sortLabel","$arrow","join","insertBefore","locked","wrap","parent","lockHtml","remove_excludes_first","before","siblings","preview","previewData","$activeBadge","items","previewLoadedCount","previewBlockType","entityLabelPlural","items_matched","renderPreviewItems","no_preview","$popover","$previewList","allPreviewData","filterPreviewItems","loadMorePreviewItems","badgeOffset","badgeHeight","badgeWidth","popoverWidth","leftPos","maxLeft","$previewPopover","isCombination","attrs","reference","ref","$footer","filterQuery","blockConfig","entityLabelSingular","entity_label","$modal","listHtml","no_matches","and","more","conditionData","showItemsPopover","entityLabel","previewType","topPos","meta","formatPrice","active","group_id","group_type","showFilterGroupItemsPopover","TargetConditions","instances","create","instance","init","extend","namePrefix","$formGroup","observeNewSelects","MutationObserver","mutations","mutation","addedNodes","observe","childList","subtree","mixins","createTargetConditionsInstance","validateAll","allValid","ready","configData"],"mappings":"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","file":"entity-selector.min.js","sourcesContent":["/**\n * Entity Selector - Utilities Module\n * Helper functions: escape, validation, icons, search history\n * @partial _utils.js (must be loaded first)\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 7552-7570 (escapeHtml, escapeAttr)\n * 7577-7590 (getEntityTypeLabel)\n * 6289-6350 (validate, showValidationError, clearValidationError)\n * 7115-7137 (showRangeInputError)\n * 7728-7745 (getBlockMode, isBlockSingleMode)\n * 7707-7723 (getCurrentSingleSelection)\n * 5411-5467 (search history methods)\n */\n\n(function($) {\n 'use strict';\n\n // Create mixin namespace\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n // Utility functions mixin\n window._EntitySelectorMixins.utils = {\n\n escapeHtml: function(str) {\n if (str === null || str === undefined) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n },\n\n escapeAttr: function(str) {\n if (str === null || str === undefined) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n },\n\n getEntityTypeIcon: function(entityType) {\n var icons = {\n 'products': 'icon-shopping-cart',\n 'categories': 'icon-folder-open',\n 'manufacturers': 'icon-building',\n 'suppliers': 'icon-truck',\n 'attributes': 'icon-list-alt',\n 'features': 'icon-tags',\n 'cms': 'icon-file-text',\n 'cms_categories': 'icon-folder'\n };\n return icons[entityType] || 'icon-cube';\n },\n\n getEntityTypeLabel: function(entityType) {\n var trans = this.config.trans || {};\n var labels = {\n 'products': trans.product || 'Product',\n 'categories': trans.category || 'Category',\n 'manufacturers': trans.manufacturer || 'Manufacturer',\n 'suppliers': trans.supplier || 'Supplier',\n 'attributes': trans.attribute || 'Attribute',\n 'features': trans.feature || 'Feature',\n 'cms': trans.cms_page || 'CMS Page',\n 'cms_categories': trans.cms_category || 'CMS Category'\n };\n return labels[entityType] || entityType;\n },\n\n validate: function() {\n var isRequired = this.$wrapper.data('required') === 1 || this.$wrapper.data('required') === '1';\n if (!isRequired) return true;\n\n var hasData = false;\n this.$wrapper.find('.target-block').each(function() {\n if ($(this).find('.selection-group').length > 0) {\n hasData = true;\n return false;\n }\n });\n\n if (!hasData) {\n this.showValidationError();\n return false;\n }\n\n this.clearValidationError();\n return true;\n },\n\n showValidationError: function() {\n this.$wrapper.addClass('has-validation-error');\n var message = this.$wrapper.data('required-message') || 'Please select at least one item';\n this.$wrapper.find('.trait-validation-error').remove();\n var $error = $('
', {\n class: 'trait-validation-error',\n html: ' ' + message\n });\n this.$wrapper.find('.condition-trait-header').after($error);\n $('html, body').animate({ scrollTop: this.$wrapper.offset().top - 100 }, 300);\n if (!this.$wrapper.find('.condition-trait-body').is(':visible')) {\n this.$wrapper.find('.condition-trait-body').slideDown(200);\n this.$wrapper.removeClass('collapsed');\n }\n },\n\n clearValidationError: function() {\n this.$wrapper.removeClass('has-validation-error');\n this.$wrapper.find('.trait-validation-error').remove();\n },\n\n getBlockMode: function(blockType) {\n var blockDef = this.config.blocks[blockType];\n return (blockDef && blockDef.mode) ? blockDef.mode : 'multi';\n },\n\n isBlockSingleMode: function(blockType) {\n return this.getBlockMode(blockType) === 'single';\n },\n\n getCurrentSingleSelection: function() {\n if ((this.config.mode || 'multi') !== 'single') return null;\n var $chip = this.$wrapper.find('.entity-chips .entity-chip').first();\n if ($chip.length) {\n var $block = $chip.closest('.target-block');\n return {\n name: $chip.find('.chip-name').text() || $chip.data('id'),\n entityType: $block.data('block-type') || 'item'\n };\n }\n return null;\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Events Module\n * All event binding and handlers\n * @partial _events.js\n *\n * Contains event handlers for:\n * - Tab switching\n * - Block/group collapse toggle\n * - Dropdown open/close\n * - Search input handling\n * - Item selection/deselection\n * - Group add/remove\n * - Exclude row add/remove\n * - Method select changes\n * - Filter panel toggles\n * - Keyboard shortcuts (Ctrl+A, Ctrl+D, Esc, Enter)\n * - Load more pagination\n * - Sort controls\n * - View mode switching\n * - Tree view events\n * - Preview badge clicks\n * - Pattern tag interactions\n * - Combination picker events\n * - Group modifier events\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.events = {\n\n bindEvents: function() {\n var self = this;\n\n // Tab switching\n this.$wrapper.on('click', '.target-block-tab', function(e) {\n e.preventDefault();\n var blockType = $(this).data('blockType');\n self.switchToBlock(blockType);\n });\n\n // Tab badge click for preview popover (toggle)\n this.$wrapper.on('click', '.target-block-tab .tab-badge', function(e) {\n e.stopPropagation();\n e.preventDefault();\n console.log('[EntitySelector] Tab badge clicked', {\n hasLoading: $(this).hasClass('loading'),\n hasPopoverOpen: $(this).hasClass('popover-open'),\n previewData: $(this).closest('.target-block-tab').data('previewData')\n });\n\n var $tab = $(this).closest('.target-block-tab');\n var $badge = $(this);\n\n if ($badge.hasClass('popover-open')) {\n self.hidePreviewPopover();\n } else {\n self.showPreviewPopover($tab);\n }\n });\n\n // Condition count badge click for preview popover\n this.$wrapper.on('click', '.condition-match-count.clickable', function(e) {\n e.stopPropagation();\n e.preventDefault();\n console.log('[EntitySelector] Condition match count clicked', this);\n\n var $badge = $(this);\n\n if ($badge.hasClass('popover-open')) {\n self.hidePreviewPopover();\n } else {\n self.showConditionPreviewPopover($badge);\n }\n });\n\n // Group count badge click for preview popover\n this.$wrapper.on('click', '.group-count-badge.clickable', function(e) {\n e.stopPropagation();\n e.preventDefault();\n console.log('[EntitySelector] Group count badge clicked', this);\n\n var $badge = $(this);\n\n if ($badge.hasClass('popover-open')) {\n self.hidePreviewPopover();\n } else {\n self.showGroupPreviewPopover($badge);\n }\n });\n\n // Filter group toggle count badge click for preview popover\n $(document).on('click', '.filter-group-toggle .toggle-count.clickable', function(e) {\n e.stopPropagation();\n e.preventDefault();\n\n var $badge = $(this);\n var groupId = $badge.data('groupId');\n var groupType = $badge.data('type');\n var groupName = $badge.data('groupName');\n\n if ($badge.hasClass('popover-open')) {\n self.hidePreviewPopover();\n } else {\n self.showFilterGroupPreviewPopover($badge, groupId, groupType, groupName);\n }\n });\n\n // Close popover when clicking outside\n $(document).on('click', function(e) {\n if (!$(e.target).closest('.target-preview-popover').length &&\n !$(e.target).closest('.tab-badge').length &&\n !$(e.target).closest('.condition-match-count').length &&\n !$(e.target).closest('.group-count-badge').length &&\n !$(e.target).closest('.group-modifiers').length &&\n !$(e.target).closest('.group-preview-badge').length &&\n !$(e.target).closest('.toggle-count.clickable').length) {\n self.hidePreviewPopover();\n }\n });\n\n // Block-level collapse toggle (click on header)\n this.$wrapper.on('click', '.condition-trait-header', function(e) {\n if ($(e.target).closest('.target-block-tabs').length ||\n $(e.target).closest('.trait-header-actions').length ||\n $(e.target).closest('.prestashop-switch').length) {\n return;\n }\n var $body = self.$wrapper.find('.condition-trait-body');\n $body.stop(true, true);\n if ($body.is(':visible')) {\n $body.slideUp(200);\n self.$wrapper.addClass('collapsed');\n } else {\n $body.slideDown(200);\n self.$wrapper.removeClass('collapsed');\n }\n });\n\n // Group-level collapse toggle (click on group header or toggle icon)\n this.$wrapper.on('click', '.group-header', function(e) {\n if ($(e.target).closest('.btn-remove-group, .group-name-input').length) {\n return;\n }\n if (self.$wrapper.data('mode') === 'single') {\n return;\n }\n var $group = $(this).closest('.selection-group');\n $group.toggleClass('collapsed');\n });\n\n // Toggle all groups (single button that switches between expand/collapse)\n this.$wrapper.on('click', '.trait-header-actions .btn-toggle-groups', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $btn = $(this);\n var currentState = $btn.attr('data-state') || 'collapsed';\n var trans = self.config.trans || {};\n\n if (currentState === 'collapsed') {\n self.$wrapper.find('.selection-group').removeClass('collapsed');\n $btn.attr('data-state', 'expanded');\n $btn.attr('title', trans.collapse_all || 'Collapse all groups');\n $btn.find('i').removeClass('icon-expand').addClass('icon-compress');\n } else {\n self.$wrapper.find('.selection-group').addClass('collapsed');\n $btn.attr('data-state', 'collapsed');\n $btn.attr('title', trans.expand_all || 'Expand all groups');\n $btn.find('i').removeClass('icon-compress').addClass('icon-expand');\n }\n });\n\n // Show all toggle change (legacy checkbox)\n this.$wrapper.on('change', '.trait-show-all-toggle .show-all-checkbox', function(e) {\n e.stopPropagation();\n var isChecked = $(this).prop('checked');\n if (isChecked) {\n self.clearAllConditions();\n }\n });\n\n // Target switch change (PrestaShop native switch)\n this.$wrapper.on('change', '.target-switch-toggle', function(e) {\n e.stopPropagation();\n var value = $(this).val();\n if (value === '1') {\n self.clearAllConditions();\n self.$wrapper.find('.condition-trait-body').slideUp(200);\n self.$wrapper.addClass('collapsed');\n } else {\n self.$wrapper.find('.condition-trait-body').slideDown(200);\n self.$wrapper.removeClass('collapsed');\n }\n });\n\n // Add group\n this.$wrapper.on('click', '.btn-add-group', function(e) {\n e.preventDefault();\n var $block = $(this).closest('.target-block');\n var blockType = $block.data('blockType');\n self.addGroup($block, blockType);\n });\n\n // Remove group\n this.$wrapper.on('click', '.btn-remove-group', function(e) {\n e.preventDefault();\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n self.removeGroup($group, $block);\n });\n\n // Group name input - stop propagation to prevent collapse\n this.$wrapper.on('click focus', '.group-name-input', function(e) {\n e.stopPropagation();\n });\n\n // Group name change\n this.$wrapper.on('change blur', '.group-name-input', function() {\n var $input = $(this);\n var $group = $input.closest('.selection-group');\n var name = $.trim($input.val());\n $group.attr('data-group-name', name);\n self.serializeAllBlocks();\n });\n\n // Add exceptions (first exclude row)\n this.$wrapper.on('click', '.btn-add-exclude', function(e) {\n e.preventDefault();\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n self.addFirstExcludeRow($group, $block);\n });\n\n // Add another exclude row\n this.$wrapper.on('click', '.btn-add-another-exclude', function(e) {\n e.preventDefault();\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n self.addExcludeRow($group, $block);\n });\n\n // Remove individual exclude row\n this.$wrapper.on('click', '.btn-remove-exclude-row', function(e) {\n e.preventDefault();\n var $excludeRow = $(this).closest('.exclude-row');\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n self.removeExcludeRow($excludeRow, $group, $block);\n });\n\n // Include method change\n this.$wrapper.on('change', '.include-method-select', function() {\n self.hideDropdown();\n\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n var $row = $group.find('.group-include');\n var blockType = $block.data('blockType');\n var blockDef = self.config.blocks[blockType] || {};\n var methods = blockDef.selection_methods || {};\n\n var $option = $(this).find('option:selected');\n var valueType = $option.data('valueType') || 'none';\n var searchEntity = $option.data('searchEntity') || '';\n var methodOptions = $option.data('options') || null;\n\n var $oldPicker = $group.find('.include-picker');\n var newPickerHtml = self.buildValuePickerHtml('include', valueType, searchEntity, methods);\n $oldPicker.replaceWith(newPickerHtml);\n\n if (valueType === 'select' && methodOptions) {\n var $newPicker = $group.find('.include-picker');\n var $select = $newPicker.find('.select-value-input');\n $select.empty();\n $.each(methodOptions, function(key, label) {\n $select.append('');\n });\n }\n\n if (valueType === 'multi_select_tiles' && methodOptions) {\n var $newPicker = $group.find('.include-picker');\n var isExclusive = $option.data('exclusive') === true;\n self.populateTiles($newPicker, methodOptions, isExclusive);\n }\n\n if (valueType === 'multi_numeric_range') {\n var $newPicker = $group.find('.include-picker');\n var step = $option.data('step');\n var min = $option.data('min');\n self.applyRangeInputConstraints($newPicker, step, min);\n }\n\n if (valueType === 'combination_attributes') {\n var $newPicker = $group.find('.include-picker');\n self.loadCombinationAttributeGroups($newPicker);\n }\n\n var selectedMethod = $(this).val();\n self.updateMethodInfoPlaceholder($group.find('.method-selector-wrapper'), selectedMethod, blockType);\n\n self.updateBlockStatus($block);\n self.serializeAllBlocks($row);\n });\n\n // Exclude method change (within an exclude row)\n this.$wrapper.on('change', '.exclude-method-select', function() {\n self.hideDropdown();\n\n var $excludeRow = $(this).closest('.exclude-row');\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n var blockType = $block.data('blockType');\n var blockDef = self.config.blocks[blockType] || {};\n var methods = blockDef.selection_methods || {};\n\n var $option = $(this).find('option:selected');\n var valueType = $option.data('valueType') || 'entity_search';\n var searchEntity = $option.data('searchEntity') || blockType;\n var methodOptions = $option.data('options') || null;\n\n var $oldPicker = $excludeRow.find('.exclude-picker');\n var newPickerHtml = self.buildValuePickerHtml('exclude', valueType, searchEntity, methods);\n $oldPicker.replaceWith(newPickerHtml);\n\n if (valueType === 'select' && methodOptions) {\n var $newPicker = $excludeRow.find('.exclude-picker');\n var $select = $newPicker.find('.select-value-input');\n $select.empty();\n $.each(methodOptions, function(key, label) {\n $select.append('');\n });\n }\n\n if (valueType === 'multi_select_tiles' && methodOptions) {\n var $newPicker = $excludeRow.find('.exclude-picker');\n var isExclusive = $option.data('exclusive') === true;\n self.populateTiles($newPicker, methodOptions, isExclusive);\n }\n\n if (valueType === 'multi_numeric_range') {\n var $newPicker = $excludeRow.find('.exclude-picker');\n var step = $option.data('step');\n var min = $option.data('min');\n self.applyRangeInputConstraints($newPicker, step, min);\n }\n\n if (valueType === 'combination_attributes') {\n var $newPicker = $excludeRow.find('.exclude-picker');\n self.loadCombinationAttributeGroups($newPicker);\n }\n\n var selectedMethod = $(this).val();\n self.updateMethodInfoPlaceholder($excludeRow.find('.exclude-header-row'), selectedMethod, blockType);\n\n self.serializeAllBlocks($excludeRow);\n });\n\n // Handle pattern input Enter key - adds pattern as tag\n this.$wrapper.on('keydown', '.pattern-input', function(e) {\n if (e.keyCode === 13) {\n e.preventDefault();\n var $btn = $(this).closest('.draft-tag').find('.btn-add-pattern');\n $btn.click();\n }\n });\n\n // Handle add pattern button click (in draft tag)\n this.$wrapper.on('click', '.draft-tag .btn-add-pattern', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $draftTag = $(this).closest('.draft-tag');\n var $picker = $draftTag.closest('.value-picker');\n var $row = $draftTag.closest('.group-include, .exclude-row');\n var $input = $draftTag.find('.pattern-input');\n var pattern = $.trim($input.val());\n\n if (pattern) {\n var caseSensitive = $draftTag.attr('data-case-sensitive') === '1';\n self.addPatternTag($picker, pattern, caseSensitive);\n\n $input.val('').focus();\n $draftTag.find('.pattern-match-count').removeClass('count-found count-zero').hide();\n $draftTag.find('.pattern-match-count .count-value').text('');\n\n self.serializeAllBlocks($row);\n }\n });\n\n // Handle pattern input live typing - update match count in draft tag\n this.$wrapper.on('input', '.pattern-input', function() {\n var $input = $(this);\n var $draftTag = $input.closest('.draft-tag');\n if (!$draftTag.length) return;\n\n var pattern = $.trim($input.val());\n\n if ($input.data('countTimeout')) {\n clearTimeout($input.data('countTimeout'));\n }\n\n var $matchCount = $draftTag.find('.pattern-match-count');\n\n if (!pattern) {\n $matchCount.removeClass('count-found count-zero').hide();\n $matchCount.find('.count-value').text('');\n var $group = $draftTag.closest('.selection-group');\n if ($group.length) {\n self.updateGroupTotalCount($group);\n }\n return;\n }\n\n var timeout = setTimeout(function() {\n var caseSensitive = $draftTag.attr('data-case-sensitive') === '1';\n self.updateDraftTagCount($draftTag, pattern, caseSensitive);\n }, 300);\n $input.data('countTimeout', timeout);\n });\n\n // Handle pattern tag remove\n this.$wrapper.on('click', '.pattern-tag .btn-remove-pattern', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $row = $(this).closest('.group-include, .exclude-row');\n $(this).closest('.pattern-tag').remove();\n self.serializeAllBlocks($row);\n });\n\n // Handle pattern tag case-sensitivity toggle\n this.$wrapper.on('click', '.pattern-tag .btn-toggle-case', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $tag = $(this).closest('.pattern-tag');\n var $btn = $(this);\n var trans = self.config.trans || {};\n var isDraftTag = $tag.hasClass('draft-tag');\n\n var isCaseSensitive = $tag.data('caseSensitive') === 1 || $tag.data('caseSensitive') === '1' || $tag.attr('data-case-sensitive') === '1';\n var newCaseSensitive = !isCaseSensitive;\n\n $tag.data('caseSensitive', newCaseSensitive ? 1 : 0);\n $tag.attr('data-case-sensitive', newCaseSensitive ? '1' : '0');\n $tag.toggleClass('case-sensitive', newCaseSensitive);\n\n $btn.find('.case-icon').text(newCaseSensitive ? 'Aa' : 'aa');\n var caseTitle = newCaseSensitive\n ? (trans.case_sensitive || 'Case sensitive - click to toggle')\n : (trans.case_insensitive || 'Case insensitive - click to toggle');\n $btn.attr('title', caseTitle);\n\n if (isDraftTag) {\n var pattern = $.trim($tag.find('.pattern-input').val());\n if (pattern) {\n self.updateDraftTagCount($tag, pattern, newCaseSensitive);\n }\n } else {\n var $row = $tag.closest('.group-include, .exclude-row');\n self.serializeAllBlocks($row);\n }\n });\n\n // Handle pattern match count click - show preview modal\n this.$wrapper.on('click', '.pattern-match-count', function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var $matchCount = $(this);\n var count = $matchCount.data('count');\n var pattern = $matchCount.data('pattern');\n var entityType = $matchCount.data('entityType');\n var caseSensitive = $matchCount.data('caseSensitive');\n\n if (!count || count <= 0 || !pattern) {\n return;\n }\n\n self.showPatternPreviewModal(pattern, entityType, caseSensitive, count);\n });\n\n // Handle pattern tag edit (click on tag text)\n this.$wrapper.on('click', '.pattern-tag .pattern-tag-text', function(e) {\n e.preventDefault();\n var $tag = $(this).closest('.pattern-tag');\n if ($tag.hasClass('editing')) return;\n\n var currentPattern = $tag.data('pattern');\n\n var $editInput = $('').val(currentPattern);\n var $saveBtn = $('');\n var $cancelBtn = $('');\n var $editActions = $('').append($saveBtn, $cancelBtn);\n\n $tag.addClass('editing').find('.pattern-tag-text').hide();\n $tag.find('.btn-remove-pattern').hide();\n $tag.prepend($editActions).prepend($editInput);\n $editInput.focus().select();\n\n $editInput.on('keydown', function(ev) {\n if (ev.keyCode === 13) {\n ev.preventDefault();\n $saveBtn.click();\n } else if (ev.keyCode === 27) {\n ev.preventDefault();\n $cancelBtn.click();\n }\n });\n });\n\n // Pattern edit - Save button\n this.$wrapper.on('click', '.pattern-tag .btn-pattern-save', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $tag = $(this).closest('.pattern-tag');\n var $editInput = $tag.find('.pattern-tag-edit');\n var currentPattern = $tag.data('pattern');\n var newPattern = $.trim($editInput.val());\n\n if (newPattern && newPattern !== currentPattern) {\n $tag.data('pattern', newPattern);\n $tag.find('.pattern-tag-text').text(newPattern);\n }\n $editInput.remove();\n $tag.find('.pattern-edit-actions').remove();\n $tag.removeClass('editing').find('.pattern-tag-text, .btn-remove-pattern').show();\n var $row = $tag.closest('.group-include, .exclude-row');\n self.serializeAllBlocks($row);\n });\n\n // Pattern edit - Cancel button\n this.$wrapper.on('click', '.pattern-tag .btn-pattern-cancel', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $tag = $(this).closest('.pattern-tag');\n $tag.find('.pattern-tag-edit').remove();\n $tag.find('.pattern-edit-actions').remove();\n $tag.removeClass('editing').find('.pattern-tag-text, .btn-remove-pattern').show();\n });\n\n // Handle mpr-info-wrapper tooltip with fixed positioning\n this.$wrapper.on('mouseenter', '.mpr-info-wrapper[data-details]', function() {\n var $wrapper = $(this);\n if ($wrapper.data('tooltip-active')) return;\n\n var content = $wrapper.attr('data-details');\n var tooltipClass = $wrapper.attr('data-tooltip-class') || '';\n var $tooltip = $('
', { class: 'mpr-tooltip mpr-tooltip-fixed ' + tooltipClass, html: content });\n\n $('body').append($tooltip);\n $wrapper.data('tooltip-active', true);\n\n var offset = $wrapper.offset();\n var triggerWidth = $wrapper.outerWidth();\n var tooltipWidth = $tooltip.outerWidth();\n var tooltipHeight = $tooltip.outerHeight();\n\n var left = offset.left + (triggerWidth / 2) - (tooltipWidth / 2);\n var top = offset.top - tooltipHeight - 10;\n\n if (left < 10) left = 10;\n if (left + tooltipWidth > $(window).width() - 10) {\n left = $(window).width() - tooltipWidth - 10;\n }\n\n $tooltip.css({\n position: 'fixed',\n left: left + 'px',\n top: (top - $(window).scrollTop()) + 'px'\n });\n\n $wrapper.data('tooltip-el', $tooltip);\n });\n\n this.$wrapper.on('mouseleave', '.mpr-info-wrapper[data-details]', function() {\n var $wrapper = $(this);\n var $tooltip = $wrapper.data('tooltip-el');\n if ($tooltip) {\n $tooltip.remove();\n }\n $wrapper.data('tooltip-active', false);\n $wrapper.data('tooltip-el', null);\n });\n\n // Handle numeric range input changes\n this.$wrapper.on('change', '.range-min-input, .range-max-input', function() {\n var $row = $(this).closest('.group-include, .exclude-row');\n self.serializeAllBlocks($row);\n });\n\n // Handle date range input changes\n this.$wrapper.on('change', '.date-from-input, .date-to-input', function() {\n var $row = $(this).closest('.group-include, .exclude-row');\n self.serializeAllBlocks($row);\n });\n\n // Handle select value changes\n this.$wrapper.on('change', '.select-value-input', function() {\n var $row = $(this).closest('.group-include, .exclude-row');\n self.serializeAllBlocks($row);\n });\n\n // Handle multi-range add button click\n this.$wrapper.on('click', '.btn-add-range', function(e) {\n e.preventDefault();\n var $picker = $(this).closest('.value-picker');\n var $row = $(this).closest('.group-include, .exclude-row');\n var $container = $picker.find('.multi-range-container');\n var $chipsContainer = $container.find('.multi-range-chips');\n var $minInput = $container.find('.range-min-input');\n var $maxInput = $container.find('.range-max-input');\n\n var minVal = $minInput.val().trim();\n var maxVal = $maxInput.val().trim();\n\n if (minVal === '' && maxVal === '') {\n return;\n }\n\n var step = parseFloat($minInput.attr('step')) || 0.01;\n var minAllowed = $minInput.attr('min');\n var hasMinConstraint = typeof minAllowed !== 'undefined' && minAllowed !== '';\n minAllowed = hasMinConstraint ? parseFloat(minAllowed) : null;\n\n var minNum = minVal !== '' ? parseFloat(minVal) : null;\n var maxNum = maxVal !== '' ? parseFloat(maxVal) : null;\n\n if (hasMinConstraint) {\n if (minNum !== null && minNum < minAllowed) {\n self.showRangeInputError($minInput, self.config.trans.min_value_error || 'Minimum value is ' + minAllowed);\n return;\n }\n if (maxNum !== null && maxNum < minAllowed) {\n self.showRangeInputError($maxInput, self.config.trans.min_value_error || 'Minimum value is ' + minAllowed);\n return;\n }\n }\n\n if (minNum !== null && maxNum !== null && minNum > maxNum) {\n self.showRangeInputError($minInput, self.config.trans.min_greater_than_max || 'Min cannot be greater than max');\n return;\n }\n\n var decimals = step < 1 ? String(step).split('.')[1].length : 0;\n if (minNum !== null) {\n if (step >= 1) {\n minNum = Math.round(minNum);\n } else {\n minNum = parseFloat(minNum.toFixed(decimals));\n }\n minVal = String(minNum);\n }\n if (maxNum !== null) {\n if (step >= 1) {\n maxNum = Math.round(maxNum);\n } else {\n maxNum = parseFloat(maxNum.toFixed(decimals));\n }\n maxVal = String(maxNum);\n }\n\n var chipText = '';\n if (minVal !== '' && maxVal !== '') {\n chipText = minVal + ' - ' + maxVal;\n } else if (minVal !== '') {\n chipText = '≥ ' + minVal;\n } else {\n chipText = '≤ ' + maxVal;\n }\n\n var $chip = $('', {\n class: 'range-chip',\n 'data-min': minVal,\n 'data-max': maxVal\n });\n $chip.append($('', { class: 'range-chip-text', text: chipText }));\n $chip.append($('', {\n type: 'button',\n class: 'btn-remove-range',\n html: ''\n }));\n\n $chipsContainer.append($chip);\n\n $minInput.val('');\n $maxInput.val('');\n\n self.serializeAllBlocks($row);\n });\n\n // Handle multi-range chip removal\n this.$wrapper.on('click', '.btn-remove-range', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $chip = $(this).closest('.range-chip');\n var $row = $chip.closest('.group-include, .exclude-row');\n $chip.remove();\n self.serializeAllBlocks($row);\n });\n\n // Handle Enter key in multi-range inputs\n this.$wrapper.on('keydown', '.multi-range-container .range-min-input, .multi-range-container .range-max-input', function(e) {\n if (e.keyCode === 13) {\n e.preventDefault();\n $(this).closest('.multi-range-container').find('.btn-add-range').click();\n }\n });\n\n // Handle multi-select tile clicks\n this.$wrapper.on('click', '.tile-option', function(e) {\n e.preventDefault();\n var $tile = $(this);\n var $container = $tile.closest('.multi-select-tiles');\n var $row = $tile.closest('.group-include, .exclude-row');\n var isExclusive = $container.attr('data-exclusive') === 'true';\n\n if (isExclusive) {\n if ($tile.hasClass('selected')) {\n $tile.removeClass('selected');\n } else {\n $container.find('.tile-option').removeClass('selected');\n $tile.addClass('selected');\n }\n } else {\n $tile.toggleClass('selected');\n }\n\n self.serializeAllBlocks($row);\n });\n\n // Handle combination attribute value toggle\n this.$wrapper.on('click', '.comb-attr-value', function(e) {\n e.preventDefault();\n var $value = $(this);\n var $row = $value.closest('.group-include, .exclude-row');\n var $picker = $value.closest('.value-picker');\n\n $value.toggleClass('selected');\n self.updateCombinationData($picker);\n self.serializeAllBlocks($row);\n });\n\n // Handle combination mode toggle\n this.$wrapper.on('change', '.comb-mode-radio', function() {\n var $picker = $(this).closest('.value-picker');\n var $row = $(this).closest('.group-include, .exclude-row');\n self.updateCombinationData($picker);\n self.serializeAllBlocks($row);\n });\n\n // Handle combination select all\n this.$wrapper.on('click', '.comb-select-all', function(e) {\n e.preventDefault();\n var $group = $(this).closest('.comb-attr-group');\n var $picker = $(this).closest('.value-picker');\n var $row = $(this).closest('.group-include, .exclude-row');\n $group.find('.comb-attr-value:visible').addClass('selected');\n self.updateCombinationData($picker);\n self.serializeAllBlocks($row);\n });\n\n // Handle combination select none\n this.$wrapper.on('click', '.comb-select-none', function(e) {\n e.preventDefault();\n var $group = $(this).closest('.comb-attr-group');\n var $picker = $(this).closest('.value-picker');\n var $row = $(this).closest('.group-include, .exclude-row');\n $group.find('.comb-attr-value').removeClass('selected');\n self.updateCombinationData($picker);\n self.serializeAllBlocks($row);\n });\n\n // Handle combination attribute search/filter\n this.$wrapper.on('input', '.comb-attr-search', function() {\n var query = $(this).val().toLowerCase().trim();\n var $group = $(this).closest('.comb-attr-group');\n $group.find('.comb-attr-value').each(function() {\n var name = $(this).data('name') || '';\n if (!query || name.indexOf(query) !== -1) {\n $(this).show();\n } else {\n $(this).hide();\n }\n });\n });\n\n // Handle group-level modifier toggle\n this.$wrapper.on('click', '.btn-toggle-modifiers', function(e) {\n e.preventDefault();\n var $btn = $(this);\n var $modifiers = $btn.closest('.group-modifiers');\n var $content = $modifiers.find('.group-modifiers-content');\n $content.slideToggle(150, function() {\n $modifiers.toggleClass('expanded', $content.is(':visible'));\n });\n });\n\n // Handle group-level modifier changes\n this.$wrapper.on('change input', '.group-modifier-limit', function() {\n var $group = $(this).closest('.selection-group');\n var $limitInput = $(this);\n var limit = parseInt($limitInput.val(), 10);\n var $badge = $group.find('.group-header .group-count-badge');\n var finalCount = $badge.data('finalCount') || 0;\n\n var $previewBadge = $group.find('.group-preview-badge .preview-count');\n if ($previewBadge.length && finalCount > 0) {\n var displayCount = (limit > 0 && limit < finalCount) ? limit : finalCount;\n $previewBadge.text(displayCount);\n }\n\n self.updateModifierButtonState($group);\n self.serializeAllBlocks();\n self.refreshGroupPreviewIfOpen($group);\n });\n\n // Sort dropdown change\n this.$wrapper.on('change', '.group-modifier-sort', function() {\n var $group = $(this).closest('.selection-group');\n self.serializeAllBlocks();\n self.refreshGroupPreviewIfOpen($group);\n });\n\n // Sort direction button click\n this.$wrapper.on('click', '.group-modifiers .btn-sort-dir', function(e) {\n e.preventDefault();\n var $btn = $(this);\n var $group = $btn.closest('.selection-group');\n var currentDir = $btn.data('dir') || 'DESC';\n var newDir = (currentDir === 'DESC') ? 'ASC' : 'DESC';\n\n $btn.data('dir', newDir);\n $btn.attr('data-dir', newDir);\n\n var $icon = $btn.find('i');\n if (newDir === 'ASC') {\n $icon.removeClass('icon-sort-amount-desc').addClass('icon-sort-amount-asc');\n } else {\n $icon.removeClass('icon-sort-amount-asc').addClass('icon-sort-amount-desc');\n }\n\n self.serializeAllBlocks();\n self.refreshGroupPreviewIfOpen($group);\n });\n\n // Group preview badge click\n this.$wrapper.on('click', '.group-preview-badge.clickable', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $badge = $(this);\n var $group = $badge.closest('.selection-group');\n var $block = $badge.closest('.target-block');\n var blockType = $block.data('blockType');\n\n if ($badge.hasClass('popover-open')) {\n self.hidePreviewPopover();\n return;\n }\n\n self.showGroupPreviewPopover($badge, $group, blockType);\n });\n\n // Search input focus\n this.$wrapper.on('focus', '.entity-search-input', function() {\n var $picker = $(this).closest('.value-picker');\n var $group = $(this).closest('.selection-group');\n var $block = $(this).closest('.target-block');\n var blockType = $block.data('blockType');\n var groupIndex = parseInt($group.data('groupIndex'), 10);\n var section = $picker.hasClass('include-picker') ? 'include' : 'exclude';\n var searchEntity = $picker.attr('data-search-entity') || blockType;\n\n var excludeIndex = null;\n if (section === 'exclude') {\n var $excludeRow = $(this).closest('.exclude-row');\n if ($excludeRow.length) {\n excludeIndex = parseInt($excludeRow.data('excludeIndex'), 10);\n }\n }\n\n var entityChanged = self.activeGroup && self.activeGroup.searchEntity !== searchEntity;\n if (entityChanged) {\n self.searchResults = [];\n self.searchOffset = 0;\n self.searchQuery = '';\n self.viewMode = 'list';\n self.resetFiltersWithoutSearch();\n self.$dropdown.find('.dropdown-results').empty();\n self.$dropdown.find('.filter-panel').removeClass('show');\n self.$dropdown.find('.btn-toggle-filters').removeClass('active');\n }\n\n self.activeGroup = {\n blockType: blockType,\n groupIndex: groupIndex,\n section: section,\n excludeIndex: excludeIndex,\n searchEntity: searchEntity\n };\n\n self.searchOffset = 0;\n self.searchQuery = $(this).val().trim();\n\n self.updateFilterPanelForEntity(searchEntity);\n\n if (searchEntity === 'products') {\n self.loadFilterableData();\n }\n\n self.positionDropdown($(this));\n\n if (self.viewMode === 'tree') {\n return;\n }\n\n self.performSearch();\n });\n\n // Search input typing\n this.$wrapper.on('input', '.entity-search-input', function() {\n var query = $(this).val().trim();\n self.searchQuery = query;\n self.searchOffset = 0;\n\n if (self.viewMode === 'tree') {\n self.filterCategoryTree(query);\n return;\n }\n\n clearTimeout(self.searchTimeout);\n self.searchTimeout = setTimeout(function() {\n self.performSearch();\n }, 300);\n });\n\n // History item click\n this.$dropdown.on('click', '.history-item', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var query = $(this).data('query');\n if (query && self.activeGroup) {\n var $input = self.$wrapper.find('.entity-search-input:focus');\n if (!$input.length) {\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + self.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + self.activeGroup.groupIndex + '\"]');\n $input = $group.find('.entity-search-input').first();\n }\n $input.val(query);\n self.searchQuery = query;\n self.searchOffset = 0;\n self.performSearch();\n }\n });\n\n // Delete history item\n this.$dropdown.on('click', '.history-item .btn-delete-history', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var $item = $(this).closest('.history-item');\n var query = $item.data('query');\n if (query && self.activeGroup) {\n self.removeFromSearchHistory(self.activeGroup.searchEntity, query);\n $item.fadeOut(150, function() {\n $(this).remove();\n if (!self.$dropdown.find('.history-item').length) {\n self.performSearch();\n }\n });\n }\n });\n\n // Dropdown item click\n this.$dropdown.on('click', '.dropdown-item', function(e) {\n e.preventDefault();\n var $item = $(this);\n var id = $item.data('id');\n var name = $item.data('name');\n var isSelected = $item.hasClass('selected');\n\n if (!self.activeGroup) return;\n\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + self.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + self.activeGroup.groupIndex + '\"]');\n var $picker;\n var $row;\n\n if (self.activeGroup.section === 'include') {\n $picker = $group.find('.include-picker');\n $row = $group.find('.group-include');\n } else {\n var $excludeRow = $group.find('.exclude-row[data-exclude-index=\"' + self.activeGroup.excludeIndex + '\"]');\n $picker = $excludeRow.find('.exclude-picker');\n $row = $excludeRow;\n }\n\n if (isSelected) {\n self.removeSelection($picker, id);\n $item.toggleClass('selected');\n self.serializeAllBlocks($row);\n } else {\n var currentSelection = self.getCurrentSingleSelection();\n if (currentSelection) {\n var newEntityType = self.activeGroup.blockType;\n self.showReplaceConfirmation(currentSelection, { name: name, entityType: newEntityType }, function() {\n self.addSelection($picker, id, name, $item.data());\n $item.addClass('selected');\n self.serializeAllBlocks($row);\n });\n } else {\n self.addSelection($picker, id, name, $item.data());\n $item.toggleClass('selected');\n self.serializeAllBlocks($row);\n }\n }\n });\n\n // Chip remove\n this.$wrapper.on('click', '.chip-remove', function(e) {\n e.stopPropagation();\n var $chip = $(this).closest('.entity-chip');\n var $picker = $(this).closest('.value-picker');\n var $row = $(this).closest('.group-include, .exclude-row');\n var id = $chip.data('id');\n\n self.removeSelection($picker, id);\n self.serializeAllBlocks($row);\n\n if (self.$dropdown && self.$dropdown.hasClass('show')) {\n self.$dropdown.find('.dropdown-item[data-id=\"' + id + '\"]').removeClass('selected');\n }\n });\n\n // Chips show more/less toggle\n this.$wrapper.on('click', '.chips-show-more-toggle', function(e) {\n e.stopPropagation();\n var $chips = $(this).closest('.entity-chips');\n\n if ($chips.hasClass('chips-expanded')) {\n $chips.removeClass('chips-expanded').addClass('chips-collapsed');\n } else {\n $chips.addClass('chips-expanded').removeClass('chips-collapsed');\n }\n\n self.updateChipsVisibility($chips);\n });\n\n // Select All\n this.$dropdown.on('click', '.btn-select-all', function(e) {\n e.preventDefault();\n if (!self.activeGroup) return;\n\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + self.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + self.activeGroup.groupIndex + '\"]');\n var $picker;\n var $row;\n\n if (self.activeGroup.section === 'include') {\n $picker = $group.find('.include-picker');\n $row = $group.find('.group-include');\n } else {\n var $excludeRow = $group.find('.exclude-row[data-exclude-index=\"' + self.activeGroup.excludeIndex + '\"]');\n $picker = $excludeRow.find('.exclude-picker');\n $row = $excludeRow;\n }\n\n var $visibleItems = self.$dropdown.find('.dropdown-item:visible');\n $visibleItems.each(function() {\n if (!$(this).hasClass('selected')) {\n var id = $(this).data('id');\n var name = $(this).data('name');\n self.addSelectionNoUpdate($picker, id, name, $(this).data());\n $(this).addClass('selected');\n }\n });\n\n var $chips = $picker.find('.entity-chips');\n self.updateChipsVisibility($chips);\n\n self.serializeAllBlocks($row);\n });\n\n // Clear selection\n this.$dropdown.on('click', '.btn-clear-selection', function(e) {\n e.preventDefault();\n if (!self.activeGroup) return;\n\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + self.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + self.activeGroup.groupIndex + '\"]');\n var $picker;\n var $row;\n\n if (self.activeGroup.section === 'include') {\n $picker = $group.find('.include-picker');\n $row = $group.find('.group-include');\n } else {\n var $excludeRow = $group.find('.exclude-row[data-exclude-index=\"' + self.activeGroup.excludeIndex + '\"]');\n $picker = $excludeRow.find('.exclude-picker');\n $row = $excludeRow;\n }\n\n var $chips = $picker.find('.entity-chips');\n $chips.empty().removeClass('chips-expanded chips-collapsed');\n self.$dropdown.find('.dropdown-item').removeClass('selected');\n self.serializeAllBlocks($row);\n });\n\n // Done/confirm\n this.$dropdown.on('click', '.btn-confirm-dropdown', function(e) {\n e.preventDefault();\n self.hideDropdown();\n });\n\n // Cancel\n this.$dropdown.on('click', '.btn-cancel-dropdown', function(e) {\n e.preventDefault();\n self.hideDropdown();\n });\n\n // Load more\n this.$dropdown.on('click', '.btn-load-more', function(e) {\n e.preventDefault();\n if (self.isLoading) return;\n\n var loadCount = parseInt(self.$dropdown.find('.load-more-select').val(), 10) || 20;\n self.searchOffset = self.searchResults.length;\n self.loadMoreCount = loadCount;\n self.performSearch(true);\n });\n\n // Sort field change\n this.$dropdown.on('change', '.sort-field-select', function() {\n self.currentSort.field = $(this).val();\n self.refreshSearch();\n });\n\n // Sort direction toggle\n this.$dropdown.on('click', '.btn-sort-dir', function(e) {\n e.preventDefault();\n var $btn = $(this);\n var currentDir = $btn.data('dir');\n var newDir = currentDir === 'ASC' ? 'DESC' : 'ASC';\n $btn.data('dir', newDir);\n $btn.find('i').attr('class', newDir === 'ASC' ? 'icon-sort-alpha-asc' : 'icon-sort-alpha-desc');\n self.currentSort.dir = newDir;\n self.refreshSearch();\n });\n\n // View mode change\n this.$dropdown.on('change', '.view-mode-select', function() {\n var value = $(this).val();\n self.viewMode = value;\n self.$dropdown.removeClass('view-list view-tree view-cols-2 view-cols-3 view-cols-4 view-cols-5 view-cols-6 view-cols-7 view-cols-8');\n self.$dropdown.addClass('view-' + value);\n\n var searchEntity = self.activeGroup ? self.activeGroup.searchEntity : '';\n if (value === 'tree' && (searchEntity === 'categories' || searchEntity === 'cms_categories')) {\n self.loadCategoryTree();\n } else if (value !== 'tree') {\n self.performSearch();\n }\n });\n\n // Tree view: Toggle expand/collapse\n this.$dropdown.on('click', '.category-tree .tree-toggle', function(e) {\n e.stopPropagation();\n var $item = $(this).closest('.tree-item');\n var $allItems = self.$dropdown.find('.tree-item');\n\n $item.toggleClass('collapsed');\n var isCollapsed = $item.hasClass('collapsed');\n\n $(this).find('i').toggleClass('icon-caret-down', !isCollapsed)\n .toggleClass('icon-caret-right', isCollapsed);\n\n var descendants = self.findTreeDescendants($item, $allItems);\n for (var i = 0; i < descendants.length; i++) {\n $(descendants[i]).toggle(!isCollapsed);\n }\n });\n\n // Tree view: Item click (select/deselect)\n this.$dropdown.on('click', '.category-tree .tree-item', function(e) {\n if ($(e.target).closest('.tree-toggle, .btn-select-children').length) {\n return;\n }\n\n var $item = $(this);\n var id = $item.data('id');\n var name = $item.data('name');\n var isSelected = $item.hasClass('selected');\n\n if (!self.activeGroup) return;\n\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + self.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + self.activeGroup.groupIndex + '\"]');\n var $picker;\n var $row;\n\n if (self.activeGroup.section === 'include') {\n $picker = $group.find('.include-picker');\n $row = $group.find('.group-include');\n } else {\n var $excludeRow = $group.find('.exclude-row[data-exclude-index=\"' + self.activeGroup.excludeIndex + '\"]');\n $picker = $excludeRow.find('.exclude-picker');\n $row = $excludeRow;\n }\n\n var $allItems = self.$dropdown.find('.tree-item');\n\n var updateCount = function() {\n var selectedCount = self.$dropdown.find('.tree-item.selected').length;\n var totalCount = self.$dropdown.find('.tree-item').length;\n var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';\n var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';\n self.$dropdown.find('.results-count').text(totalCount + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));\n self.updateSelectChildrenButtons($allItems);\n };\n\n if (isSelected) {\n self.removeSelection($picker, id);\n $item.toggleClass('selected');\n self.serializeAllBlocks($row);\n updateCount();\n } else {\n var currentSelection = self.getCurrentSingleSelection();\n if (currentSelection) {\n var newEntityType = self.activeGroup.blockType;\n self.showReplaceConfirmation(currentSelection, { name: name, entityType: newEntityType }, function() {\n self.$dropdown.find('.tree-item.selected').removeClass('selected');\n self.addSelection($picker, id, name, $item.data());\n $item.addClass('selected');\n self.serializeAllBlocks($row);\n updateCount();\n });\n } else {\n self.addSelection($picker, id, name, $item.data());\n $item.toggleClass('selected');\n self.serializeAllBlocks($row);\n updateCount();\n }\n }\n });\n\n // Tree view: Select/Deselect with children button (toggle)\n this.$dropdown.on('click', '.category-tree .btn-select-children', function(e) {\n e.stopPropagation();\n var $btn = $(this);\n var $item = $btn.closest('.tree-item');\n var $allItems = self.$dropdown.find('.tree-item');\n\n if (!self.activeGroup) return;\n\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + self.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + self.activeGroup.groupIndex + '\"]');\n var $picker;\n var $row;\n\n if (self.activeGroup.section === 'include') {\n $picker = $group.find('.include-picker');\n $row = $group.find('.group-include');\n } else {\n var $excludeRow = $group.find('.exclude-row[data-exclude-index=\"' + self.activeGroup.excludeIndex + '\"]');\n $picker = $excludeRow.find('.exclude-picker');\n $row = $excludeRow;\n }\n\n var descendants = self.findTreeDescendants($item, $allItems);\n\n var allSelected = $item.hasClass('selected');\n for (var i = 0; i < descendants.length && allSelected; i++) {\n if (!$(descendants[i]).hasClass('selected')) {\n allSelected = false;\n }\n }\n\n var trans = self.config.trans || {};\n\n if (allSelected) {\n self.removeSelection($picker, $item.data('id'));\n $item.removeClass('selected');\n\n for (var j = 0; j < descendants.length; j++) {\n var $child = $(descendants[j]);\n self.removeSelection($picker, $child.data('id'));\n $child.removeClass('selected');\n }\n\n $btn.find('i').removeClass('icon-minus-square').addClass('icon-plus-square');\n $btn.attr('title', trans.select_with_children || 'Select with all children');\n } else {\n if (!$item.hasClass('selected')) {\n self.addSelectionNoUpdate($picker, $item.data('id'), $item.data('name'), $item.data());\n $item.addClass('selected');\n }\n\n for (var k = 0; k < descendants.length; k++) {\n var $descendant = $(descendants[k]);\n if (!$descendant.hasClass('selected')) {\n self.addSelectionNoUpdate($picker, $descendant.data('id'), $descendant.data('name'), $descendant.data());\n $descendant.addClass('selected');\n }\n }\n\n $btn.find('i').removeClass('icon-plus-square').addClass('icon-minus-square');\n $btn.attr('title', trans.deselect_with_children || 'Deselect with all children');\n }\n\n var $chips = $picker.find('.entity-chips');\n self.updateChipsVisibility($chips);\n\n self.serializeAllBlocks($row);\n self.updateSelectChildrenButtons($allItems);\n\n var selectedCount = self.$dropdown.find('.tree-item.selected').length;\n var totalCount = self.$dropdown.find('.tree-item').length;\n var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';\n var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';\n self.$dropdown.find('.results-count').text(totalCount + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));\n });\n\n // Tree view: Expand all\n this.$dropdown.on('click', '.category-tree .btn-expand-all', function(e) {\n e.preventDefault();\n self.$dropdown.find('.tree-item').removeClass('collapsed').show();\n self.$dropdown.find('.tree-toggle i').removeClass('icon-caret-right').addClass('icon-caret-down');\n });\n\n // Tree view: Collapse all\n this.$dropdown.on('click', '.category-tree .btn-collapse-all', function(e) {\n e.preventDefault();\n var minLevel = Infinity;\n self.$dropdown.find('.tree-item').each(function() {\n var level = parseInt($(this).data('level'), 10);\n if (level < minLevel) minLevel = level;\n });\n\n self.$dropdown.find('.tree-item').each(function() {\n var $item = $(this);\n var level = parseInt($item.data('level'), 10);\n var hasChildren = $item.hasClass('has-children');\n\n if (level === minLevel) {\n if (hasChildren) {\n $item.addClass('collapsed');\n $item.find('.tree-toggle i').removeClass('icon-caret-down').addClass('icon-caret-right');\n }\n $item.show();\n } else {\n $item.hide();\n }\n });\n });\n\n // Refine search input\n this.$dropdown.on('keyup', '.refine-input', function() {\n var query = $(this).val().trim();\n self.refineQuery = query;\n self.$dropdown.find('.btn-clear-refine').toggle(query.length > 0);\n\n clearTimeout(self.refineTimeout);\n self.refineTimeout = setTimeout(function() {\n self.refreshSearch();\n }, 300);\n });\n\n // Clear refine search\n this.$dropdown.on('click', '.btn-clear-refine', function(e) {\n e.preventDefault();\n self.refineQuery = '';\n self.$dropdown.find('.refine-input').val('');\n $(this).hide();\n self.refreshSearch();\n });\n\n // Toggle refine negate (NOT contains)\n this.$dropdown.on('click', '.btn-refine-negate', function(e) {\n e.preventDefault();\n self.refineNegate = !self.refineNegate;\n $(this).toggleClass('active', self.refineNegate);\n\n var trans = self.config.trans || {};\n var placeholder = self.refineNegate\n ? (trans.refine_exclude || 'Exclude...')\n : (trans.refine_short || 'Refine...');\n self.$dropdown.find('.refine-input').attr('placeholder', placeholder);\n\n if (self.refineQuery) {\n self.refreshSearch();\n }\n });\n\n // Toggle filter panel\n this.$dropdown.on('click', '.btn-toggle-filters', function(e) {\n e.preventDefault();\n var $panel = self.$dropdown.find('.filter-panel');\n $panel.toggleClass('show');\n $(this).toggleClass('active', $panel.hasClass('show'));\n\n if ($panel.hasClass('show') && self.activeGroup) {\n self.updateFilterPanelForEntity(self.activeGroup.searchEntity);\n }\n });\n\n // Show search history\n this.$dropdown.on('click', '.btn-show-history', function(e) {\n e.preventDefault();\n $(this).toggleClass('active');\n if ($(this).hasClass('active') && self.activeGroup) {\n self.showSearchHistory(self.activeGroup.searchEntity);\n } else {\n self.performSearch();\n }\n });\n\n // Quick filter checkboxes\n this.$dropdown.on('change', '.filter-in-stock', function() {\n self.filters.inStock = $(this).is(':checked');\n self.refreshSearch();\n });\n\n this.$dropdown.on('change', '.filter-discounted', function() {\n self.filters.discounted = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Price range filter\n this.$dropdown.on('change', '.filter-price-min, .filter-price-max', function() {\n var $panel = self.$dropdown.find('.filter-panel');\n self.filters.priceMin = $panel.find('.filter-price-min').val() || null;\n self.filters.priceMax = $panel.find('.filter-price-max').val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Product count range\n this.$dropdown.on('change', '.filter-product-count-min, .filter-product-count-max', function() {\n var $row = $(this).closest('.filter-row');\n self.filters.productCountMin = $row.find('.filter-product-count-min').val() || null;\n self.filters.productCountMax = $row.find('.filter-product-count-max').val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Sales range\n this.$dropdown.on('change', '.filter-sales-min, .filter-sales-max', function() {\n var $row = $(this).closest('.filter-row');\n self.filters.salesMin = $row.find('.filter-sales-min').val() || null;\n self.filters.salesMax = $row.find('.filter-sales-max').val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Turnover/revenue range\n this.$dropdown.on('change', '.filter-turnover-min, .filter-turnover-max', function() {\n var $row = $(this).closest('.filter-row');\n self.filters.turnoverMin = $row.find('.filter-turnover-min').val() || null;\n self.filters.turnoverMax = $row.find('.filter-turnover-max').val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Date added range\n this.$dropdown.on('change', '.filter-date-add-from, .filter-date-add-to', function() {\n var $row = $(this).closest('.filter-row');\n self.filters.dateAddFrom = $row.find('.filter-date-add-from').val() || null;\n self.filters.dateAddTo = $row.find('.filter-date-add-to').val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Last product date range\n this.$dropdown.on('change', '.filter-last-product-from, .filter-last-product-to', function() {\n var $row = $(this).closest('.filter-row');\n self.filters.lastProductFrom = $row.find('.filter-last-product-from').val() || null;\n self.filters.lastProductTo = $row.find('.filter-last-product-to').val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Depth (categories)\n this.$dropdown.on('change', '.filter-depth-select', function() {\n self.filters.depth = $(this).val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Has products (categories)\n this.$dropdown.on('change', '.filter-has-products', function() {\n self.filters.hasProducts = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Entity-specific filters: Has description (categories)\n this.$dropdown.on('change', '.filter-has-description', function() {\n self.filters.hasDescription = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Entity-specific filters: Has image (categories)\n this.$dropdown.on('change', '.filter-has-image', function() {\n self.filters.hasImage = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Entity-specific filters: Active only\n this.$dropdown.on('change', '.filter-active-only', function() {\n self.filters.activeOnly = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Entity-specific filters: Attribute group select\n this.$dropdown.on('change', '.filter-attribute-group-select', function() {\n self.filters.attributeGroup = $(this).val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Feature group select\n this.$dropdown.on('change', '.filter-feature-group-select', function() {\n self.filters.featureGroup = $(this).val() || null;\n self.refreshSearch();\n });\n\n // Entity-specific filters: Color attributes only\n this.$dropdown.on('change', '.filter-is-color', function() {\n self.filters.isColor = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Entity-specific filters: Custom feature values only\n this.$dropdown.on('change', '.filter-is-custom', function() {\n self.filters.isCustom = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Entity-specific filters: CMS indexable\n this.$dropdown.on('change', '.filter-indexable', function() {\n self.filters.indexable = $(this).is(':checked');\n self.refreshSearch();\n });\n\n // Clear entity-specific filters\n this.$dropdown.on('click', '.filter-row-entity-categories .btn-clear-filters, .filter-row-entity-manufacturers .btn-clear-filters, .filter-row-entity-suppliers .btn-clear-filters, .filter-row-entity-attributes .btn-clear-filters, .filter-row-entity-features .btn-clear-filters, .filter-row-entity-cms .btn-clear-filters, .filter-row-entity-cms-categories .btn-clear-filters', function(e) {\n e.preventDefault();\n var $row = $(this).closest('.filter-row');\n $row.find('input[type=\"number\"]').val('');\n $row.find('input[type=\"date\"]').val('');\n $row.find('select').val('');\n $row.find('input[type=\"checkbox\"]').prop('checked', false);\n $row.find('.filter-active-only').prop('checked', true);\n\n self.filters.productCountMin = null;\n self.filters.productCountMax = null;\n self.filters.salesMin = null;\n self.filters.salesMax = null;\n self.filters.turnoverMin = null;\n self.filters.turnoverMax = null;\n self.filters.depth = null;\n self.filters.hasProducts = false;\n self.filters.hasDescription = false;\n self.filters.hasImage = false;\n self.filters.activeOnly = true;\n self.filters.attributeGroup = null;\n self.filters.featureGroup = null;\n self.filters.isColor = false;\n self.filters.isCustom = false;\n self.filters.indexable = false;\n self.filters.dateAddFrom = null;\n self.filters.dateAddTo = null;\n self.filters.lastProductFrom = null;\n self.filters.lastProductTo = null;\n self.refreshSearch();\n });\n\n // Toggle filter group - show values\n this.$dropdown.on('click', '.filter-group-toggle', function(e) {\n // Ignore clicks on the preview badge\n if ($(e.target).closest('.toggle-count.clickable').length) {\n return;\n }\n e.preventDefault();\n var $btn = $(this);\n var groupId = $btn.data('group-id');\n var type = $btn.data('type');\n var isActive = $btn.hasClass('active');\n\n self.$dropdown.find('.filter-group-toggle').removeClass('active');\n\n if (isActive) {\n self.hideFilterGroupValues();\n } else {\n $btn.addClass('active');\n self.showFilterGroupValues(groupId, type);\n }\n });\n\n // Close values row\n this.$dropdown.on('click', '.btn-close-values', function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.hideFilterGroupValues();\n });\n\n // Toggle filter chip (attribute/feature value)\n this.$dropdown.on('click', '.filter-chip', function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var $chip = $(this);\n var id = parseInt($chip.data('id'), 10);\n var isAttribute = $chip.hasClass('filter-attr-chip');\n var filterArray = isAttribute ? self.filters.attributes : self.filters.features;\n\n var index = filterArray.indexOf(id);\n if (index === -1) {\n filterArray.push(id);\n $chip.addClass('active');\n } else {\n filterArray.splice(index, 1);\n $chip.removeClass('active');\n }\n\n self.updateFilterToggleStates();\n self.refreshSearch();\n });\n\n // Clear all filters\n this.$dropdown.on('click', '.filter-row-quick .btn-clear-filters', function(e) {\n e.preventDefault();\n self.clearFilters();\n });\n\n // Click outside to close\n $(document).on('click', function(e) {\n if (!$(e.target).closest('.value-picker').length &&\n !$(e.target).closest('.target-search-dropdown').length) {\n self.hideDropdown();\n }\n });\n\n // Keyboard shortcuts\n $(document).on('keydown', function(e) {\n if (!self.$dropdown || !self.$dropdown.hasClass('show')) return;\n\n // Ctrl+A / Cmd+A - Select All\n if ((e.ctrlKey || e.metaKey) && e.keyCode === 65) {\n e.preventDefault();\n e.stopPropagation();\n self.$dropdown.find('.btn-select-all').trigger('click');\n return false;\n }\n\n // Ctrl+D / Cmd+D - Clear/Deselect all\n if ((e.ctrlKey || e.metaKey) && e.keyCode === 68) {\n e.preventDefault();\n e.stopPropagation();\n self.$dropdown.find('.btn-clear-selection').trigger('click');\n return false;\n }\n\n if (e.key === 'Escape') {\n e.preventDefault();\n self.hideDropdown();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n self.hideDropdown();\n }\n });\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Dropdown Module\n * Search dropdown UI creation and positioning\n * @partial _dropdown.js\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.dropdown = {\n\n createDropdown: function() {\n this.$wrapper.find('.target-search-dropdown').remove();\n\n var trans = this.config.trans || {};\n\n var html = '
';\n\n // Header with results count, actions, sort controls, view mode\n html += '
';\n html += '0 results';\n\n html += '
';\n\n // Select all / Clear buttons with keyboard shortcuts\n html += '';\n html += ' ' + (trans.all || 'All') + ' Ctrl+A';\n html += '';\n html += '';\n html += ' ' + (trans.clear || 'Clear') + ' Ctrl+D';\n html += '';\n\n // Sort controls\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '';\n\n // View mode selector\n html += '';\n html += '
'; // End sort-controls\n\n // Refine search\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Filter toggle button\n html += '';\n html += '';\n html += '';\n\n // History button\n html += '';\n html += '';\n html += '';\n\n html += '
'; // End dropdown-actions\n html += '
'; // End dropdown-header\n\n // Filter panel\n html += '
';\n\n // Quick filters row (for products)\n html += '
';\n html += '';\n html += '';\n\n // Price range\n html += '
';\n html += '' + (trans.price || 'Price') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Attribute/Feature filter toggles for products\n html += '
';\n html += ' ' + (trans.attributes || 'Attributes') + ':';\n html += '';\n html += '
';\n html += '
';\n html += '';\n html += '
';\n\n html += '
';\n html += ' ' + (trans.features || 'Features') + ':';\n html += '';\n html += '
';\n html += '
';\n html += '';\n html += '
';\n\n // Entity-specific filters: Categories\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.product_count || 'Products') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.total_sales || 'Sales') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.turnover || 'Revenue') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.depth || 'Depth') + ':';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '
';\n html += '
';\n\n // Entity-specific filters: Manufacturers\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.product_count || 'Products') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.total_sales || 'Sales') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.turnover || 'Revenue') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.date_added || 'Added') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.last_product || 'Last product') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n\n // Entity-specific filters: Suppliers\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.product_count || 'Products') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.total_sales || 'Sales') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.turnover || 'Revenue') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.date_added || 'Added') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.last_product || 'Last product') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n\n // Entity-specific filters: Attributes\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.product_count || 'Products') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.total_sales || 'Sales') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.turnover || 'Revenue') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.attribute_group || 'Group') + ':';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '
';\n html += '
';\n\n // Entity-specific filters: Features\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.product_count || 'Products') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.total_sales || 'Sales') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += ' ' + (trans.turnover || 'Revenue') + ':';\n html += '';\n html += '-';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n html += '
';\n html += ' ' + (trans.feature_group || 'Group') + ':';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '
';\n html += '
';\n\n // Entity-specific filters: CMS Pages\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Entity-specific filters: CMS Categories\n html += '
';\n html += '';\n html += '';\n html += '
';\n\n html += '
'; // End filter-panel\n\n // Results header for list view (product columns)\n html += '
';\n html += '';\n html += '' + (trans.product || 'Product') + '';\n html += '' + (trans.price || 'Price') + '';\n html += '' + (trans.sale || 'Sale') + '';\n html += '' + (trans.stock || 'Stock') + '';\n html += '' + (trans.sold || 'Sold') + '';\n html += '
';\n\n // Results\n html += '';\n\n // Footer\n html += '';\n\n html += '
';\n\n this.$dropdown = $(html);\n $('body').append(this.$dropdown);\n },\n\n hideDropdown: function() {\n if (this.$dropdown) {\n this.$dropdown.removeClass('show');\n }\n this.activeGroup = null;\n },\n\n positionDropdown: function($input) {\n if (!this.$dropdown) return;\n\n var $picker = $input.closest('.value-picker');\n var $searchBox = $input.closest('.entity-search-box');\n\n // Get absolute positions (dropdown is appended to body)\n var searchBoxOffset = $searchBox.offset();\n var searchBoxHeight = $searchBox.outerHeight();\n var pickerOffset = $picker.offset();\n var pickerWidth = $picker.outerWidth();\n\n // Calculate position relative to document\n var dropdownTop = searchBoxOffset.top + searchBoxHeight + 4;\n var dropdownLeft = pickerOffset.left;\n var dropdownWidth = Math.max(pickerWidth, 400);\n\n // Ensure dropdown doesn't overflow the viewport horizontally\n var viewportWidth = $(window).width();\n if (dropdownLeft + dropdownWidth > viewportWidth - 10) {\n dropdownWidth = viewportWidth - dropdownLeft - 10;\n }\n\n // Ensure dropdown doesn't overflow viewport vertically\n var viewportHeight = $(window).height();\n var scrollTop = $(window).scrollTop();\n var maxHeight = viewportHeight - (dropdownTop - scrollTop) - 20;\n maxHeight = Math.max(maxHeight, 400);\n\n this.$dropdown.css({\n position: 'absolute',\n top: dropdownTop,\n left: dropdownLeft,\n width: dropdownWidth,\n maxHeight: maxHeight,\n zIndex: 10000\n });\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Search Module\n * AJAX search, results rendering, category tree, filters, search history\n * @partial _search.js\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.search = {\n\n // Category tree cache\n categoryTreeCache: null,\n\n /**\n * Perform AJAX search for entities\n */\n performSearch: function(appendMode) {\n var self = this;\n\n if (!this.activeGroup) return;\n\n this.isLoading = true;\n\n var searchEntity = this.activeGroup.searchEntity;\n\n // Build request data with sort and filter params\n var limit = appendMode && this.loadMoreCount ? this.loadMoreCount : 20;\n var requestData = {\n ajax: 1,\n action: 'searchTargetEntities',\n trait: 'EntitySelector',\n entity_type: searchEntity,\n q: this.searchQuery,\n limit: limit,\n offset: appendMode ? this.searchOffset : 0,\n sort_by: this.currentSort ? this.currentSort.field : 'name',\n sort_dir: this.currentSort ? this.currentSort.dir : 'ASC'\n };\n\n // Add refine query if present\n if (this.refineQuery) {\n requestData.refine = this.refineQuery;\n if (this.refineNegate) {\n requestData.refine_negate = 1;\n }\n }\n\n // Add product-specific filters\n if (searchEntity === 'products' && this.filters) {\n if (this.filters.inStock) {\n requestData.filter_in_stock = 1;\n }\n if (this.filters.discounted) {\n requestData.filter_discounted = 1;\n }\n if (this.filters.priceMin !== null && this.filters.priceMin !== '') {\n requestData.filter_price_min = this.filters.priceMin;\n }\n if (this.filters.priceMax !== null && this.filters.priceMax !== '') {\n requestData.filter_price_max = this.filters.priceMax;\n }\n if (this.filters.attributes && this.filters.attributes.length > 0) {\n requestData.filter_attributes = JSON.stringify(this.filters.attributes);\n }\n if (this.filters.features && this.filters.features.length > 0) {\n requestData.filter_features = JSON.stringify(this.filters.features);\n }\n }\n\n // Add entity-specific filters for non-product entities\n if (searchEntity !== 'products' && this.filters) {\n // Product count range (categories, manufacturers, suppliers, attributes, features)\n if (this.filters.productCountMin !== null && this.filters.productCountMin !== '') {\n requestData.filter_product_count_min = this.filters.productCountMin;\n }\n if (this.filters.productCountMax !== null && this.filters.productCountMax !== '') {\n requestData.filter_product_count_max = this.filters.productCountMax;\n }\n\n // Category-specific\n if (searchEntity === 'categories') {\n if (this.filters.depth) {\n requestData.filter_depth = this.filters.depth;\n }\n if (this.filters.hasProducts) {\n requestData.filter_has_products = 1;\n }\n if (this.filters.hasDescription) {\n requestData.filter_has_description = 1;\n }\n if (this.filters.hasImage) {\n requestData.filter_has_image = 1;\n }\n if (this.filters.salesMin !== null && this.filters.salesMin !== '') {\n requestData.filter_sales_min = this.filters.salesMin;\n }\n if (this.filters.salesMax !== null && this.filters.salesMax !== '') {\n requestData.filter_sales_max = this.filters.salesMax;\n }\n if (this.filters.turnoverMin !== null && this.filters.turnoverMin !== '') {\n requestData.filter_turnover_min = this.filters.turnoverMin;\n }\n if (this.filters.turnoverMax !== null && this.filters.turnoverMax !== '') {\n requestData.filter_turnover_max = this.filters.turnoverMax;\n }\n if (this.filters.activeOnly) {\n requestData.filter_active = 1;\n }\n }\n\n // Manufacturer-specific\n if (searchEntity === 'manufacturers') {\n if (this.filters.salesMin !== null && this.filters.salesMin !== '') {\n requestData.filter_sales_min = this.filters.salesMin;\n }\n if (this.filters.salesMax !== null && this.filters.salesMax !== '') {\n requestData.filter_sales_max = this.filters.salesMax;\n }\n if (this.filters.turnoverMin !== null && this.filters.turnoverMin !== '') {\n requestData.filter_turnover_min = this.filters.turnoverMin;\n }\n if (this.filters.turnoverMax !== null && this.filters.turnoverMax !== '') {\n requestData.filter_turnover_max = this.filters.turnoverMax;\n }\n if (this.filters.dateAddFrom) {\n requestData.filter_date_add_from = this.filters.dateAddFrom;\n }\n if (this.filters.dateAddTo) {\n requestData.filter_date_add_to = this.filters.dateAddTo;\n }\n if (this.filters.lastProductFrom) {\n requestData.filter_last_product_from = this.filters.lastProductFrom;\n }\n if (this.filters.lastProductTo) {\n requestData.filter_last_product_to = this.filters.lastProductTo;\n }\n if (this.filters.activeOnly) {\n requestData.filter_active = 1;\n }\n }\n\n // Supplier-specific\n if (searchEntity === 'suppliers') {\n if (this.filters.salesMin !== null && this.filters.salesMin !== '') {\n requestData.filter_sales_min = this.filters.salesMin;\n }\n if (this.filters.salesMax !== null && this.filters.salesMax !== '') {\n requestData.filter_sales_max = this.filters.salesMax;\n }\n if (this.filters.turnoverMin !== null && this.filters.turnoverMin !== '') {\n requestData.filter_turnover_min = this.filters.turnoverMin;\n }\n if (this.filters.turnoverMax !== null && this.filters.turnoverMax !== '') {\n requestData.filter_turnover_max = this.filters.turnoverMax;\n }\n if (this.filters.dateAddFrom) {\n requestData.filter_date_add_from = this.filters.dateAddFrom;\n }\n if (this.filters.dateAddTo) {\n requestData.filter_date_add_to = this.filters.dateAddTo;\n }\n if (this.filters.lastProductFrom) {\n requestData.filter_last_product_from = this.filters.lastProductFrom;\n }\n if (this.filters.lastProductTo) {\n requestData.filter_last_product_to = this.filters.lastProductTo;\n }\n if (this.filters.activeOnly) {\n requestData.filter_active = 1;\n }\n }\n\n // Attribute-specific\n if (searchEntity === 'attributes') {\n if (this.filters.salesMin !== null && this.filters.salesMin !== '') {\n requestData.filter_sales_min = this.filters.salesMin;\n }\n if (this.filters.salesMax !== null && this.filters.salesMax !== '') {\n requestData.filter_sales_max = this.filters.salesMax;\n }\n if (this.filters.turnoverMin !== null && this.filters.turnoverMin !== '') {\n requestData.filter_turnover_min = this.filters.turnoverMin;\n }\n if (this.filters.turnoverMax !== null && this.filters.turnoverMax !== '') {\n requestData.filter_turnover_max = this.filters.turnoverMax;\n }\n if (this.filters.attributeGroup) {\n requestData.filter_attribute_group = this.filters.attributeGroup;\n }\n if (this.filters.isColor) {\n requestData.filter_is_color = 1;\n }\n }\n\n // Feature-specific\n if (searchEntity === 'features') {\n if (this.filters.salesMin !== null && this.filters.salesMin !== '') {\n requestData.filter_sales_min = this.filters.salesMin;\n }\n if (this.filters.salesMax !== null && this.filters.salesMax !== '') {\n requestData.filter_sales_max = this.filters.salesMax;\n }\n if (this.filters.turnoverMin !== null && this.filters.turnoverMin !== '') {\n requestData.filter_turnover_min = this.filters.turnoverMin;\n }\n if (this.filters.turnoverMax !== null && this.filters.turnoverMax !== '') {\n requestData.filter_turnover_max = this.filters.turnoverMax;\n }\n if (this.filters.featureGroup) {\n requestData.filter_feature_group = this.filters.featureGroup;\n }\n if (this.filters.isCustom) {\n requestData.filter_is_custom = 1;\n }\n }\n\n // CMS-specific\n if (searchEntity === 'cms') {\n if (this.filters.activeOnly) {\n requestData.filter_active = 1;\n }\n if (this.filters.indexable) {\n requestData.filter_indexable = 1;\n }\n }\n\n // CMS Categories-specific\n if (searchEntity === 'cms_categories') {\n if (this.filters.activeOnly) {\n requestData.filter_active = 1;\n }\n }\n }\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: requestData,\n success: function(response) {\n self.isLoading = false;\n\n if (!response.success) return;\n\n // Save to search history if query is not empty and has results\n if (self.searchQuery && self.searchQuery.length >= 2 && response.total > 0) {\n self.addToSearchHistory(searchEntity, self.searchQuery);\n }\n\n if (appendMode) {\n self.searchResults = self.searchResults.concat(response.results || []);\n } else {\n self.searchResults = response.results || [];\n }\n self.searchTotal = response.total || 0;\n self.searchOffset = appendMode ? self.searchOffset + (response.results || []).length : (response.results || []).length;\n\n self.renderSearchResults(appendMode);\n self.$dropdown.addClass('show');\n },\n error: function() {\n self.isLoading = false;\n }\n });\n },\n\n /**\n * Render search results in the dropdown\n */\n renderSearchResults: function(appendMode) {\n var self = this;\n var trans = this.config.trans || {};\n var $container = this.$dropdown.find('.dropdown-results');\n\n // Get selected IDs from current picker (to mark as selected)\n // and hidden IDs from sibling exclude pickers with same entity type (to hide completely)\n var selectedIds = [];\n var hiddenIds = [];\n if (this.activeGroup) {\n var $block = this.$wrapper.find('.target-block[data-block-type=\"' + this.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + this.activeGroup.groupIndex + '\"]');\n var currentSearchEntity = this.activeGroup.searchEntity;\n var currentExcludeIndex = this.activeGroup.excludeIndex;\n\n if (this.activeGroup.section === 'include') {\n // For include section, just get current picker's selections\n var $picker = $group.find('.include-picker');\n $picker.find('.entity-chip').each(function() {\n selectedIds.push(String($(this).data('id')));\n });\n } else {\n // For exclude section, get current picker's selections AND\n // collect IDs from sibling exclude rows with same entity type to hide\n var $currentExcludeRow = $group.find('.exclude-row[data-exclude-index=\"' + currentExcludeIndex + '\"]');\n var $currentPicker = $currentExcludeRow.find('.exclude-picker');\n\n // Get selected IDs from current exclude row\n $currentPicker.find('.entity-chip').each(function() {\n selectedIds.push(String($(this).data('id')));\n });\n\n // Get hidden IDs from OTHER exclude rows with the same entity type\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var rowIndex = parseInt($row.data('excludeIndex'), 10);\n\n // Skip current exclude row\n if (rowIndex === currentExcludeIndex) return;\n\n var $picker = $row.find('.exclude-picker');\n var rowEntityType = $picker.attr('data-search-entity') || self.activeGroup.blockType;\n\n // Only collect if same entity type\n if (rowEntityType === currentSearchEntity) {\n $picker.find('.entity-chip').each(function() {\n hiddenIds.push(String($(this).data('id')));\n });\n }\n });\n }\n }\n\n // Check if this is a product search\n var isProductSearch = this.activeGroup && this.activeGroup.searchEntity === 'products';\n var isListView = this.viewMode === 'list';\n\n // Show/hide results header for products in list view\n this.$dropdown.find('.results-header').toggle(isProductSearch && isListView);\n\n // Build HTML - filter out items that are hidden (selected in sibling exclude rows)\n var visibleResults = this.searchResults.filter(function(item) {\n return hiddenIds.indexOf(String(item.id)) === -1;\n });\n\n // Update count (show visible count and total, noting hidden items if any)\n var hiddenCount = this.searchResults.length - visibleResults.length;\n var countText = visibleResults.length + ' / ' + this.searchTotal + ' results';\n if (hiddenCount > 0) {\n countText += ' (' + hiddenCount + ' hidden)';\n }\n this.$dropdown.find('.results-count').text(countText);\n\n var html = '';\n if (visibleResults.length === 0 && !appendMode) {\n html = '
' + (trans.no_results || 'No results found') + '
';\n } else {\n visibleResults.forEach(function(item) {\n var isSelected = selectedIds.indexOf(String(item.id)) !== -1;\n var itemClass = 'dropdown-item' + (isSelected ? ' selected' : '');\n if (item.type === 'product') itemClass += ' result-item-product';\n\n html += '
';\n\n html += '';\n\n if (item.image) {\n html += '
';\n } else {\n // Entity-specific icons\n var iconClass = 'icon-cube'; // default\n var searchEntity = self.activeGroup ? self.activeGroup.searchEntity : null;\n if (searchEntity === 'categories') iconClass = 'icon-folder';\n else if (searchEntity === 'manufacturers') iconClass = 'icon-building';\n else if (searchEntity === 'suppliers') iconClass = 'icon-truck';\n else if (searchEntity === 'attributes') iconClass = 'icon-paint-brush';\n else if (searchEntity === 'features') iconClass = 'icon-list-ul';\n else if (searchEntity === 'cms') iconClass = 'icon-file-text-o';\n else if (searchEntity === 'cms_categories') iconClass = 'icon-folder-o';\n html += '
';\n }\n\n html += '
';\n html += '
' + self.escapeHtml(item.name) + '
';\n if (item.subtitle) {\n // Split multi-line subtitles into separate divs for styling\n var subtitleLines = item.subtitle.split('\\n');\n html += '
';\n subtitleLines.forEach(function(line, idx) {\n var lineClass = idx === 0 ? 'subtitle-line subtitle-line-primary' : 'subtitle-line subtitle-line-secondary';\n html += '
' + self.escapeHtml(line) + '
';\n });\n html += '
';\n }\n html += '
';\n\n // Add product-specific columns (price, sale price, stock, sold)\n if (item.type === 'product' && isListView) {\n // Regular price\n html += '
';\n html += '' + (item.regular_price_formatted || item.price_formatted || '') + '';\n html += '
';\n\n // Sale price (only if discounted)\n if (item.has_discount) {\n html += '
';\n html += '' + (item.price_formatted || '') + '';\n html += '
';\n } else {\n html += '';\n }\n\n // Stock column\n var stockClass = item.stock_status === 'out_of_stock' ? 'stock-out' :\n (item.stock_status === 'low_stock' ? 'stock-low' : 'stock-ok');\n html += '
';\n html += '' + (item.stock_qty !== undefined ? item.stock_qty : '') + '';\n html += '
';\n\n // Sales column\n html += '
';\n html += '' + (item.sales_qty !== undefined ? item.sales_qty : '0') + '';\n html += '
';\n }\n\n html += '
';\n });\n }\n\n if (appendMode) {\n $container.append(html);\n } else {\n $container.html(html);\n }\n\n // Show/hide load more controls and update remaining count\n var hasMore = this.searchResults.length < this.searchTotal;\n var $loadMoreControls = this.$dropdown.find('.load-more-controls');\n $loadMoreControls.toggle(hasMore);\n\n if (hasMore) {\n var remaining = this.searchTotal - this.searchResults.length;\n $loadMoreControls.find('.remaining-count').text(remaining);\n\n // Update \"All\" option in dropdown\n var $select = $loadMoreControls.find('.load-more-select');\n var $allOption = $select.find('option[data-all=\"true\"]');\n if ($allOption.length) {\n $allOption.val(remaining).text((trans.all || 'All') + ' (' + remaining + ')');\n } else {\n $select.find('option:last').after('');\n }\n }\n\n // Ensure dropdown-actions are visible and history button is deactivated\n this.$dropdown.find('.dropdown-actions').show();\n this.$dropdown.find('.btn-show-history').removeClass('active');\n\n // Disable history button if no search history for current entity type\n var entityType = this.activeGroup ? this.activeGroup.searchEntity : null;\n var hasHistory = entityType && this.getSearchHistory(entityType).length > 0;\n this.$dropdown.find('.btn-show-history').prop('disabled', !hasHistory);\n },\n\n /**\n * Load and display category tree view\n */\n loadCategoryTree: function() {\n var self = this;\n var $container = this.$dropdown.find('.dropdown-results');\n var entityType = this.activeGroup ? this.activeGroup.searchEntity : 'categories';\n\n // Show the dropdown\n this.$dropdown.addClass('show');\n\n // Show loading state\n $container.html('
Loading category tree...
');\n\n // Use separate cache for each entity type\n var cacheKey = entityType + 'TreeCache';\n if (this[cacheKey]) {\n this.renderCategoryTree(this[cacheKey], entityType);\n return;\n }\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getCategoryTree',\n trait: 'EntitySelector',\n entity_type: entityType\n },\n success: function(response) {\n if (response.success && response.categories) {\n self[cacheKey] = response.categories;\n self.renderCategoryTree(response.categories, entityType);\n } else {\n $container.html('
');\n }\n });\n },\n\n /**\n * Render category tree structure\n */\n renderCategoryTree: function(categories, entityType) {\n var self = this;\n var trans = this.config.trans || {};\n var $container = this.$dropdown.find('.dropdown-results');\n var isCmsCategory = entityType === 'cms_categories';\n var categoryLabel = isCmsCategory ? 'CMS categories' : 'categories';\n\n // Get selected IDs from current picker\n var selectedIds = [];\n if (this.activeGroup) {\n var $block = this.$wrapper.find('.target-block[data-block-type=\"' + this.activeGroup.blockType + '\"]');\n var $group = $block.find('.selection-group[data-group-index=\"' + this.activeGroup.groupIndex + '\"]');\n\n if (this.activeGroup.section === 'include') {\n var $picker = $group.find('.include-picker');\n $picker.find('.entity-chip').each(function() {\n selectedIds.push(parseInt($(this).data('id'), 10));\n });\n } else {\n var $currentExcludeRow = $group.find('.exclude-row[data-exclude-index=\"' + this.activeGroup.excludeIndex + '\"]');\n var $currentPicker = $currentExcludeRow.find('.exclude-picker');\n $currentPicker.find('.entity-chip').each(function() {\n selectedIds.push(parseInt($(this).data('id'), 10));\n });\n }\n }\n\n // Build tree HTML\n var html = '
';\n\n html += '
';\n\n // Find minimum level (usually 1 or 2)\n var minLevel = categories.length > 0 ? categories[0].level : 1;\n\n categories.forEach(function(cat) {\n var isSelected = selectedIds.indexOf(cat.id) !== -1;\n var indent = (cat.level - minLevel) * 20;\n var hasChildren = cat.has_children;\n\n html += '
';\n\n // Expand/collapse toggle for parents\n if (hasChildren) {\n html += '';\n } else {\n html += '';\n }\n\n // Select children button for parents (on the left, near toggle)\n // Hide in single mode - selecting multiple items doesn't make sense there\n var isSingleMode = self.config.mode === 'single';\n if (hasChildren && !isSingleMode) {\n html += '';\n html += '';\n html += '';\n } else if (!isSingleMode) {\n html += '';\n }\n\n // Checkbox\n html += '';\n\n // Category icon (file icon for CMS categories)\n var iconClass = isCmsCategory ? 'icon-file-text-o' : ('icon-folder' + (hasChildren ? '' : '-o'));\n html += '';\n\n // Name and subtitle\n html += '
';\n html += '' + self.escapeHtml(cat.name) + '';\n html += '' + self.escapeHtml(cat.subtitle) + '';\n html += '
';\n\n html += '
';\n });\n\n html += '
'; // tree-container\n html += '
'; // category-tree\n\n $container.html(html);\n\n // Update results count with appropriate label\n var selectedCount = $container.find('.tree-item.selected').length;\n this.$dropdown.find('.results-count').text(categories.length + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));\n\n // Update select-children button states based on initial selection\n var $allItems = $container.find('.tree-item');\n this.updateSelectChildrenButtons($allItems);\n\n // Hide load more controls in tree view\n this.$dropdown.find('.load-more-controls').hide();\n },\n\n /**\n * Filter category tree by search query (client-side filtering)\n */\n filterCategoryTree: function(query) {\n var self = this;\n var $container = this.$dropdown.find('.category-tree');\n if (!$container.length) {\n return;\n }\n\n var $items = $container.find('.tree-item');\n query = query.toLowerCase().trim();\n\n if (!query) {\n // Show all items when query is empty\n $items.show().removeClass('collapsed');\n $container.find('.tree-toggle i').removeClass('icon-caret-right').addClass('icon-caret-down');\n return;\n }\n\n // First pass: find matching items and their ancestors\n var matchingIds = [];\n var ancestorIds = [];\n\n $items.each(function() {\n var $item = $(this);\n var name = ($item.data('name') || '').toLowerCase();\n if (name.indexOf(query) !== -1) {\n matchingIds.push($item.data('id'));\n // Also mark all ancestors using helper (works for both nleft/nright and parent_id)\n var ancestors = self.findTreeAncestors($item, $items);\n for (var i = 0; i < ancestors.length; i++) {\n ancestorIds.push($(ancestors[i]).data('id'));\n }\n }\n });\n\n // Second pass: show/hide items\n $items.each(function() {\n var $item = $(this);\n var id = $item.data('id');\n if (matchingIds.indexOf(id) !== -1 || ancestorIds.indexOf(id) !== -1) {\n $item.show().removeClass('collapsed');\n $item.find('.tree-toggle i').removeClass('icon-caret-right').addClass('icon-caret-down');\n } else {\n $item.hide();\n }\n });\n\n // Update count with appropriate label\n var visibleCount = $items.filter(':visible').length;\n var selectedCount = $items.filter('.selected').length;\n var entityType = $container.data('entity-type') || 'categories';\n var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';\n this.$dropdown.find('.results-count').text(visibleCount + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));\n },\n\n /**\n * Find all descendant tree items of a parent.\n * Works with nleft/nright (product categories) or parent_id (CMS categories).\n */\n findTreeDescendants: function($parent, $allItems) {\n var nleft = parseInt($parent.data('nleft'), 10);\n var nright = parseInt($parent.data('nright'), 10);\n var parentId = parseInt($parent.data('id'), 10);\n var descendants = [];\n\n // If nleft/nright are valid (product categories), use nested set\n if (nleft > 0 && nright > 0 && nright > nleft) {\n $allItems.each(function() {\n var $item = $(this);\n var childNleft = parseInt($item.data('nleft'), 10);\n var childNright = parseInt($item.data('nright'), 10);\n if (childNleft > nleft && childNright < nright) {\n descendants.push($item);\n }\n });\n } else {\n // CMS categories: use parent_id recursively\n var idsToCheck = [parentId];\n var processed = {};\n\n while (idsToCheck.length > 0) {\n var checkId = idsToCheck.shift();\n if (processed[checkId]) continue;\n processed[checkId] = true;\n\n $allItems.each(function() {\n var $item = $(this);\n var itemParentId = parseInt($item.data('parent-id'), 10);\n var itemId = parseInt($item.data('id'), 10);\n if (itemParentId === checkId && !processed[itemId]) {\n descendants.push($item);\n idsToCheck.push(itemId);\n }\n });\n }\n }\n\n return descendants;\n },\n\n /**\n * Find all ancestor tree items of an item.\n * Works with nleft/nright (product categories) or parent_id (CMS categories).\n */\n findTreeAncestors: function($item, $allItems) {\n var nleft = parseInt($item.data('nleft'), 10);\n var nright = parseInt($item.data('nright'), 10);\n var ancestors = [];\n\n // If nleft/nright are valid (product categories), use nested set\n if (nleft > 0 && nright > 0) {\n $allItems.each(function() {\n var $ancestor = $(this);\n var ancNleft = parseInt($ancestor.data('nleft'), 10);\n var ancNright = parseInt($ancestor.data('nright'), 10);\n if (ancNleft < nleft && ancNright > nright) {\n ancestors.push($ancestor);\n }\n });\n } else {\n // CMS categories: use parent_id chain\n var parentId = parseInt($item.data('parent-id'), 10);\n var processed = {};\n\n while (parentId > 0 && !processed[parentId]) {\n processed[parentId] = true;\n $allItems.each(function() {\n var $ancestor = $(this);\n var ancestorId = parseInt($ancestor.data('id'), 10);\n if (ancestorId === parentId) {\n ancestors.push($ancestor);\n parentId = parseInt($ancestor.data('parent-id'), 10);\n return false; // break inner loop\n }\n });\n }\n }\n\n return ancestors;\n },\n\n /**\n * Update all select-children buttons to reflect current selection state.\n * Shows minus icon if item and all children are selected, plus icon otherwise.\n */\n updateSelectChildrenButtons: function($allItems) {\n var self = this;\n var trans = this.config.trans || {};\n\n $allItems.filter('.has-children').each(function() {\n var $item = $(this);\n var $btn = $item.find('.btn-select-children');\n if (!$btn.length) return;\n\n var descendants = self.findTreeDescendants($item, $allItems);\n\n // Check if parent and ALL descendants are selected\n var allSelected = $item.hasClass('selected');\n for (var i = 0; i < descendants.length && allSelected; i++) {\n if (!$(descendants[i]).hasClass('selected')) {\n allSelected = false;\n }\n }\n\n // Update button icon and title\n if (allSelected && descendants.length > 0) {\n $btn.find('i').removeClass('icon-plus-square').addClass('icon-minus-square');\n $btn.attr('title', trans.deselect_with_children || 'Deselect with all children');\n } else {\n $btn.find('i').removeClass('icon-minus-square').addClass('icon-plus-square');\n $btn.attr('title', trans.select_with_children || 'Select with all children');\n }\n });\n },\n\n // =========================================================================\n // Search History\n // =========================================================================\n\n loadSearchHistory: function() {\n try {\n var stored = localStorage.getItem(this.searchHistoryKey);\n this.searchHistory = stored ? JSON.parse(stored) : {};\n } catch (e) {\n this.searchHistory = {};\n }\n },\n\n saveSearchHistory: function() {\n try {\n localStorage.setItem(this.searchHistoryKey, JSON.stringify(this.searchHistory));\n } catch (e) {\n // localStorage might be full or unavailable\n }\n },\n\n addToSearchHistory: function(entityType, query) {\n if (!query || query.length < 2) return;\n\n if (!this.searchHistory[entityType]) {\n this.searchHistory[entityType] = [];\n }\n\n var history = this.searchHistory[entityType];\n\n // Remove if already exists (will re-add at top)\n var existingIndex = history.indexOf(query);\n if (existingIndex !== -1) {\n history.splice(existingIndex, 1);\n }\n\n // Add at beginning\n history.unshift(query);\n\n // Trim to max\n if (history.length > this.searchHistoryMax) {\n history = history.slice(0, this.searchHistoryMax);\n }\n\n this.searchHistory[entityType] = history;\n this.saveSearchHistory();\n },\n\n removeFromSearchHistory: function(entityType, query) {\n if (!this.searchHistory[entityType]) return;\n\n var index = this.searchHistory[entityType].indexOf(query);\n if (index !== -1) {\n this.searchHistory[entityType].splice(index, 1);\n this.saveSearchHistory();\n }\n },\n\n getSearchHistory: function(entityType) {\n return this.searchHistory[entityType] || [];\n },\n\n showSearchHistory: function(entityType) {\n var history = this.getSearchHistory(entityType);\n var trans = this.config.trans || {};\n var $container = this.$dropdown.find('.dropdown-results');\n\n // Update header\n this.$dropdown.find('.results-count').text(trans.recent_searches || 'Recent searches');\n\n // Hide filters, actions, and results header for history view\n this.$dropdown.find('.dropdown-actions').hide();\n this.$dropdown.find('.filter-panel').removeClass('show');\n this.$dropdown.find('.btn-toggle-filters').removeClass('active');\n this.$dropdown.find('.results-header').hide();\n\n if (!history.length) {\n // No history - just do a regular search\n this.performSearch();\n return;\n }\n\n // Build history items\n var html = '
';\n for (var i = 0; i < history.length; i++) {\n var query = history[i];\n html += '
';\n html += '';\n html += '' + this.escapeHtml(query) + '';\n html += '';\n html += '';\n html += '';\n html += '
';\n }\n html += '
';\n\n $container.html(html);\n this.$dropdown.addClass('show');\n },\n\n // =========================================================================\n // Filter Methods\n // =========================================================================\n\n refreshSearch: function() {\n // In tree view mode, re-filter the tree instead of doing a flat AJAX search\n if (this.viewMode === 'tree') {\n this.filterCategoryTree(this.searchQuery || '');\n return;\n }\n\n this.searchOffset = 0;\n this.loadMoreCount = 20;\n // Reset load more select to default\n if (this.$dropdown) {\n this.$dropdown.find('.load-more-select').val('20');\n // Remove the dynamic \"All\" option\n this.$dropdown.find('.load-more-select option[data-all=\"true\"]').remove();\n }\n this.performSearch(false);\n },\n\n clearFilters: function() {\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n // Entity-specific filters\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n\n if (this.$dropdown) {\n var trans = this.config.trans || {};\n this.$dropdown.find('.refine-input').val('').attr('placeholder', trans.refine_short || 'Refine...');\n this.$dropdown.find('.btn-clear-refine').hide();\n this.$dropdown.find('.btn-refine-negate').removeClass('active');\n this.$dropdown.find('.filter-in-stock').prop('checked', false);\n this.$dropdown.find('.filter-discounted').prop('checked', false);\n this.$dropdown.find('.filter-price-min').val('');\n this.$dropdown.find('.filter-price-max').val('');\n this.$dropdown.find('.filter-attr-chip').removeClass('active');\n this.$dropdown.find('.filter-feat-chip').removeClass('active');\n this.$dropdown.find('.filter-group-toggle').removeClass('active has-selection');\n this.$dropdown.find('.filter-row-values').hide();\n\n // Clear entity-specific filter inputs\n this.$dropdown.find('.filter-product-count-min, .filter-product-count-max').val('');\n this.$dropdown.find('.filter-sales-min, .filter-sales-max').val('');\n this.$dropdown.find('.filter-turnover-min, .filter-turnover-max').val('');\n this.$dropdown.find('.filter-date-add-from, .filter-date-add-to').val('');\n this.$dropdown.find('.filter-last-product-from, .filter-last-product-to').val('');\n this.$dropdown.find('.filter-depth-select').val('');\n this.$dropdown.find('.filter-has-products').prop('checked', false);\n this.$dropdown.find('.filter-has-description').prop('checked', false);\n this.$dropdown.find('.filter-has-image').prop('checked', false);\n this.$dropdown.find('.filter-active-only').prop('checked', true);\n this.$dropdown.find('.filter-attribute-group-select, .filter-feature-group-select').val('');\n }\n\n this.refreshSearch();\n },\n\n // Reset filters without triggering a search (used when switching entity types)\n resetFiltersWithoutSearch: function() {\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n\n if (this.$dropdown) {\n var trans = this.config.trans || {};\n this.$dropdown.find('.refine-input').val('').attr('placeholder', trans.refine_short || 'Refine...');\n this.$dropdown.find('.btn-clear-refine').hide();\n this.$dropdown.find('.btn-refine-negate').removeClass('active');\n this.$dropdown.find('.filter-in-stock').prop('checked', false);\n this.$dropdown.find('.filter-discounted').prop('checked', false);\n this.$dropdown.find('.filter-price-min').val('');\n this.$dropdown.find('.filter-price-max').val('');\n this.$dropdown.find('.filter-attr-chip').removeClass('active');\n this.$dropdown.find('.filter-feat-chip').removeClass('active');\n this.$dropdown.find('.filter-group-toggle').removeClass('active has-selection');\n this.$dropdown.find('.filter-row-values').hide();\n this.$dropdown.find('.filter-product-count-min, .filter-product-count-max').val('');\n this.$dropdown.find('.filter-sales-min, .filter-sales-max').val('');\n this.$dropdown.find('.filter-turnover-min, .filter-turnover-max').val('');\n this.$dropdown.find('.filter-date-add-from, .filter-date-add-to').val('');\n this.$dropdown.find('.filter-last-product-from, .filter-last-product-to').val('');\n this.$dropdown.find('.filter-depth-select').val('');\n this.$dropdown.find('.filter-has-products').prop('checked', false);\n this.$dropdown.find('.filter-has-description').prop('checked', false);\n this.$dropdown.find('.filter-has-image').prop('checked', false);\n this.$dropdown.find('.filter-active-only').prop('checked', true);\n this.$dropdown.find('.filter-attribute-group-select, .filter-feature-group-select').val('');\n }\n // Note: Does NOT call refreshSearch() - caller handles search/load\n },\n\n updateFilterPanelForEntity: function(entityType) {\n if (!this.$dropdown) {\n return;\n }\n\n var $panel = this.$dropdown.find('.filter-panel');\n\n // Hide all filter rows first\n $panel.find('.filter-row').hide();\n\n // Show/hide tree view option based on entity type\n var $treeOption = this.$dropdown.find('.view-mode-select option.tree-view-option');\n if (entityType === 'categories' || entityType === 'cms_categories') {\n $treeOption.prop('disabled', false).prop('hidden', false);\n // Auto-switch to tree view for categories\n if (this.viewMode !== 'tree') {\n this.viewMode = 'tree';\n this.$dropdown.find('.view-mode-select').val('tree');\n this.$dropdown.removeClass('view-list view-cols-2 view-cols-3 view-cols-4 view-cols-5 view-cols-6 view-cols-7 view-cols-8').addClass('view-tree');\n this.loadCategoryTree();\n } else {\n this.loadCategoryTree();\n }\n } else {\n $treeOption.prop('disabled', true).prop('hidden', true);\n // If currently in tree mode, switch back to list\n if (this.viewMode === 'tree') {\n this.viewMode = 'list';\n this.$dropdown.find('.view-mode-select').val('list');\n this.$dropdown.removeClass('view-tree').addClass('view-list');\n }\n }\n\n // Show entity-specific filter row (prepare visibility, but don't auto-expand panel)\n if (entityType === 'products') {\n // Prepare the correct rows to be visible when panel is shown\n $panel.find('.filter-row-quick').show();\n // Show attribute/feature rows if we have cached data\n if (this.filterableData) {\n if (this.filterableData.attributes && this.filterableData.attributes.length > 0) {\n this.$dropdown.find('.filter-row-attributes').show();\n }\n if (this.filterableData.features && this.filterableData.features.length > 0) {\n this.$dropdown.find('.filter-row-features').show();\n }\n }\n } else if (entityType === 'categories') {\n $panel.find('.filter-row-entity-categories').show();\n } else if (entityType === 'manufacturers') {\n $panel.find('.filter-row-entity-manufacturers').show();\n } else if (entityType === 'suppliers') {\n $panel.find('.filter-row-entity-suppliers').show();\n } else if (entityType === 'attributes') {\n $panel.find('.filter-row-entity-attributes').show();\n this.loadAttributeGroups();\n } else if (entityType === 'features') {\n $panel.find('.filter-row-entity-features').show();\n } else if (entityType === 'cms') {\n $panel.find('.filter-row-entity-cms').show();\n } else if (entityType === 'cms_categories') {\n $panel.find('.filter-row-entity-cms-categories').show();\n }\n },\n\n loadAttributeGroups: function() {\n var self = this;\n var $select = this.$dropdown.find('.filter-attribute-group-select');\n\n // Already loaded?\n if ($select.find('option').length > 1) return;\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getAttributeGroups',\n trait: 'EntitySelector'\n },\n success: function(response) {\n if (response.success && response.groups) {\n $.each(response.groups, function(i, group) {\n $select.append('');\n });\n }\n }\n });\n },\n\n loadFeatureGroups: function() {\n var self = this;\n var $select = this.$dropdown.find('.filter-feature-group-select');\n\n // Already loaded?\n if ($select.find('option').length > 1) return;\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getFeatureGroups',\n trait: 'EntitySelector'\n },\n success: function(response) {\n if (response.success && response.groups) {\n $.each(response.groups, function(i, group) {\n $select.append('');\n });\n }\n }\n });\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Filters Module\n * Filter panel, filter state management\n * @partial _filters.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 6605-6758 (filter methods)\n *\n * Contains:\n * - clearFilters() - Reset all filters\n * - resetFiltersWithoutSearch() - Reset without triggering search\n * - updateFilterPanelForEntity() - Show/hide filters based on entity type\n * - loadFilterableData() - Load attributes/features for filter panel\n * - renderFilterDropdowns() - Render attribute/feature group toggles\n * - showFilterGroupValues() - Show values for a filter group\n * - hideFilterGroupValues() - Hide filter values row\n * - updateFilterToggleStates() - Update toggle states based on selections\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.filters = {\n\n clearFilters: function() {\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n\n if (this.$dropdown) {\n var trans = this.config.trans || {};\n this.$dropdown.find('.refine-input').val('');\n this.$dropdown.find('.btn-refine-negate').removeClass('active');\n this.$dropdown.find('.filter-in-stock').prop('checked', false);\n this.$dropdown.find('.filter-discounted').prop('checked', false);\n this.$dropdown.find('.filter-price-min, .filter-price-max').val('');\n this.$dropdown.find('.filter-attr-chip, .filter-feat-chip').removeClass('active');\n this.$dropdown.find('.filter-product-count-min, .filter-product-count-max').val('');\n this.$dropdown.find('.filter-sales-min, .filter-sales-max').val('');\n this.$dropdown.find('.filter-depth-select').val('');\n this.$dropdown.find('.filter-has-products').prop('checked', false);\n this.$dropdown.find('.filter-active-only').prop('checked', true);\n }\n\n this.refreshSearch();\n },\n\n resetFiltersWithoutSearch: function() {\n // Same as clearFilters but doesn't trigger search\n // Used when switching entity types\n this.refineQuery = '';\n this.refineNegate = false;\n this.filters = {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: [],\n productCountMin: null,\n productCountMax: null,\n salesMin: null,\n salesMax: null,\n turnoverMin: null,\n turnoverMax: null,\n depth: null,\n hasProducts: false,\n hasDescription: false,\n hasImage: false,\n activeOnly: true,\n attributeGroup: null,\n featureGroup: null,\n dateAddFrom: null,\n dateAddTo: null,\n lastProductFrom: null,\n lastProductTo: null\n };\n },\n\n updateFilterPanelForEntity: function(entityType) {\n if (!this.$dropdown) return;\n\n var $panel = this.$dropdown.find('.filter-panel');\n\n // Hide all entity-specific filter rows\n $panel.find('.filter-row').hide();\n\n // Show filters for current entity type\n $panel.find('.filter-row[data-entity=\"' + entityType + '\"]').show();\n $panel.find('.filter-row-entity-' + entityType.replace('_', '-')).show();\n\n // Enable/disable tree view option\n var $treeOption = this.$dropdown.find('.tree-view-option');\n if (entityType === 'categories' || entityType === 'cms_categories') {\n $treeOption.prop('disabled', false).show();\n } else {\n $treeOption.prop('disabled', true).hide();\n }\n },\n\n loadFilterableData: function() {\n var self = this;\n\n if (this.filterableData) {\n this.renderFilterDropdowns();\n return;\n }\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n data: {\n ajax: 1,\n action: 'getTargetFilterableAttributes',\n trait: 'EntitySelector'\n },\n dataType: 'json',\n success: function(response) {\n if (response.success && response.data) {\n self.filterableData = response.data;\n self.renderFilterDropdowns();\n }\n }\n });\n },\n\n renderFilterDropdowns: function() {\n if (!this.$dropdown || !this.filterableData) return;\n\n var self = this;\n\n // Render attribute group toggle buttons\n var $attrContainer = this.$dropdown.find('.filter-attributes-container');\n $attrContainer.empty();\n\n if (this.filterableData.attributes && this.filterableData.attributes.length > 0) {\n this.filterableData.attributes.forEach(function(group) {\n var html = '';\n html += '' + group.name + '';\n if (group.count !== undefined) {\n html += ' ' + group.count + '';\n }\n html += '';\n $attrContainer.append(html);\n });\n this.$dropdown.find('.filter-row-attributes').show();\n }\n\n // Render feature group toggle buttons\n var $featContainer = this.$dropdown.find('.filter-features-container');\n $featContainer.empty();\n\n if (this.filterableData.features && this.filterableData.features.length > 0) {\n this.filterableData.features.forEach(function(group) {\n var html = '';\n html += '' + group.name + '';\n if (group.count !== undefined) {\n html += ' ' + group.count + '';\n }\n html += '';\n $featContainer.append(html);\n });\n this.$dropdown.find('.filter-row-features').show();\n }\n },\n\n showFilterGroupValues: function(groupId, type) {\n if (!this.filterableData) return;\n\n var self = this;\n var groups = type === 'attribute' ? this.filterableData.attributes : this.filterableData.features;\n var group = groups.find(function(g) { return g.id == groupId; });\n\n if (!group) return;\n\n // Hide all values rows first, then show the correct one\n this.$dropdown.find('.filter-row-values').hide();\n\n // Target the correct values row based on type\n var valuesRowClass = type === 'attribute' ? '.filter-row-attr-values' : '.filter-row-feat-values';\n var $filterRowValues = this.$dropdown.find(valuesRowClass);\n var $valuesContainer = $filterRowValues.find('.filter-values-container');\n $valuesContainer.empty();\n\n // Add group label\n var html = '' + group.name + ':';\n\n // Add chips\n group.values.forEach(function(val) {\n var isActive = type === 'attribute'\n ? self.filters.attributes.indexOf(val.id) !== -1\n : self.filters.features.indexOf(val.id) !== -1;\n var activeClass = isActive ? ' active' : '';\n var chipClass = type === 'attribute' ? 'filter-attr-chip' : 'filter-feat-chip';\n var colorStyle = val.color ? ' style=\"--chip-color: ' + val.color + '\"' : '';\n var colorClass = val.color ? ' has-color' : '';\n\n html += '';\n if (val.color) {\n html += '';\n }\n html += '' + val.name + '';\n if (val.count !== undefined) {\n html += '(' + val.count + ')';\n }\n html += '';\n });\n\n $valuesContainer.html(html);\n\n // Add close button as sibling (outside filter-values-container, inside filter-row-values)\n $filterRowValues.find('.btn-close-values').remove();\n $filterRowValues.append('');\n $filterRowValues.show();\n\n // Scroll into view if needed\n var rowValues = $filterRowValues[0];\n if (rowValues) {\n rowValues.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n },\n\n hideFilterGroupValues: function() {\n this.$dropdown.find('.filter-row-values').hide();\n this.$dropdown.find('.filter-group-toggle').removeClass('active');\n },\n\n updateFilterToggleStates: function() {\n if (!this.$dropdown || !this.filterableData) return;\n\n var self = this;\n\n // Update attribute group toggles\n if (this.filterableData.attributes) {\n this.filterableData.attributes.forEach(function(group) {\n var $toggle = self.$dropdown.find('.filter-group-toggle[data-group-id=\"' + group.id + '\"][data-type=\"attribute\"]');\n var hasActiveInGroup = group.values.some(function(val) {\n return self.filters.attributes.indexOf(val.id) !== -1;\n });\n $toggle.toggleClass('has-selection', hasActiveInGroup);\n });\n }\n\n // Update feature group toggles\n if (this.filterableData.features) {\n this.filterableData.features.forEach(function(group) {\n var $toggle = self.$dropdown.find('.filter-group-toggle[data-group-id=\"' + group.id + '\"][data-type=\"feature\"]');\n var hasActiveInGroup = group.values.some(function(val) {\n return self.filters.features.indexOf(val.id) !== -1;\n });\n $toggle.toggleClass('has-selection', hasActiveInGroup);\n });\n }\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Chips Module\n * Entity chip rendering, selection management, and pattern tag handling\n * @partial _chips.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n *\n * Contains:\n * - addSelection() / addSelectionNoUpdate() - Add entity chip to picker\n * - removeSelection() - Remove chip and update state\n * - updateChipsVisibility() - Show/hide based on count\n * - loadExistingSelections() - Load saved values on init\n * - collectPickerEntities() / loadPickerValues() - Entity loading helpers\n * - Pattern tag methods: addPatternTag, getPatternTags, updateDraftTagCount\n * - Single mode: getCurrentSingleSelection, showReplaceConfirmation\n * - Count updates: updateConditionCount, updateGroupCounts, updateGroupTotalCount\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.chips = {\n\n // =========================================================================\n // Selection Methods (Entity Chips)\n // =========================================================================\n\n addSelection: function($picker, id, name, data) {\n this.addSelectionNoUpdate($picker, id, name, data);\n var $chips = $picker.find('.entity-chips');\n this.updateChipsVisibility($chips);\n },\n\n addSelectionNoUpdate: function($picker, id, name, data) {\n var $chips = $picker.find('.entity-chips');\n var $block = $picker.closest('.target-block');\n\n // Check for global single mode (only ONE item across ALL entity types)\n var globalMode = this.config.mode || 'multi';\n\n if (globalMode === 'single') {\n // Clear ALL selections in ALL blocks (across all entity types)\n this.$wrapper.find('.entity-chips .entity-chip').remove();\n // Clear all selected states in dropdown\n if (this.$dropdown) {\n this.$dropdown.find('.dropdown-item.selected, .tree-item.selected').removeClass('selected');\n }\n // Clear tab badges (since we're clearing other blocks)\n this.$wrapper.find('.target-block-tab .tab-badge').remove();\n this.$wrapper.find('.target-block-tab').removeClass('has-data');\n } else {\n // Check if this block is in per-block single mode\n var blockMode = $block.data('mode') || 'multi';\n\n // In per-block single mode, clear chips in THIS block only\n if (blockMode === 'single') {\n $chips.find('.entity-chip').remove();\n // Also deselect all items in dropdown\n if (this.$dropdown) {\n this.$dropdown.find('.dropdown-item.selected, .tree-item.selected').removeClass('selected');\n }\n }\n }\n\n if ($chips.find('.entity-chip[data-id=\"' + id + '\"]').length) {\n return;\n }\n\n var html = '';\n\n if (data && data.image) {\n html += '';\n }\n\n html += '' + this.escapeHtml(name) + '';\n html += '';\n html += '';\n\n $chips.append(html);\n },\n\n removeSelection: function($picker, id) {\n var $chips = $picker.find('.entity-chips');\n $picker.find('.entity-chip[data-id=\"' + id + '\"]').remove();\n this.updateChipsVisibility($chips);\n },\n\n updateChipsVisibility: function($chips) {\n var self = this;\n var $allChips = $chips.find('.entity-chip');\n var totalCount = $allChips.length;\n var $toggle = $chips.find('.chips-show-more-toggle');\n var isExpanded = $chips.hasClass('chips-expanded');\n var trans = this.config.trans || {};\n\n // Remove existing toggle if present\n $toggle.remove();\n\n if (totalCount <= this.maxVisibleChips) {\n // All chips visible, no toggle needed\n $allChips.removeClass('chip-hidden');\n $chips.removeClass('chips-expanded chips-collapsed');\n return;\n }\n\n // We have more than maxVisibleChips\n var hiddenCount = totalCount - this.maxVisibleChips;\n\n if (isExpanded) {\n // Show all chips\n $allChips.removeClass('chip-hidden');\n\n // Add collapse toggle\n var collapseText = trans.show_less || 'Show less';\n $chips.append('' +\n ' ' + collapseText + '');\n } else {\n // Hide chips beyond maxVisibleChips\n $allChips.each(function(index) {\n if (index >= self.maxVisibleChips) {\n $(this).addClass('chip-hidden');\n } else {\n $(this).removeClass('chip-hidden');\n }\n });\n\n // Add expand toggle\n var moreText = (trans.show_more || 'Show {count} more').replace('{count}', hiddenCount);\n $chips.addClass('chips-collapsed').removeClass('chips-expanded');\n $chips.append('' +\n ' ' + moreText + '');\n }\n },\n\n // =========================================================================\n // Loading/Initialization\n // =========================================================================\n\n loadExistingSelections: function() {\n var self = this;\n\n // Collect all entity IDs to load, grouped by entity type\n var entitiesToLoad = {}; // { entity_type: { ids: [], pickers: [] } }\n\n this.$wrapper.find('.selection-group').each(function() {\n var $group = $(this);\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType');\n\n // Load include values\n var $includePicker = $group.find('.include-picker');\n self.collectPickerEntities($includePicker, blockType, entitiesToLoad);\n\n // Enhance the include method select if not already enhanced\n self.enhanceMethodSelect($group.find('.include-method-select'));\n\n // Load exclude values from each exclude row\n $group.find('.exclude-row').each(function() {\n var $excludeRow = $(this);\n self.collectPickerEntities($excludeRow.find('.exclude-picker'), blockType, entitiesToLoad);\n\n // Enhance the exclude method select if not already enhanced\n self.enhanceMethodSelect($excludeRow.find('.exclude-method-select'));\n });\n\n // Lock method selector if excludes exist\n var hasExcludes = $group.find('.group-excludes.has-excludes').length > 0;\n if (hasExcludes) {\n self.updateMethodSelectorLock($group, true);\n }\n });\n\n // Now load all entities in bulk for each entity type\n Object.keys(entitiesToLoad).forEach(function(entityType) {\n var data = entitiesToLoad[entityType];\n if (data.ids.length === 0) return;\n\n // Deduplicate IDs\n var uniqueIds = data.ids.filter(function(id, index, arr) {\n return arr.indexOf(id) === index;\n });\n\n $.ajax({\n url: self.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getTargetEntitiesByIds',\n trait: 'EntitySelector',\n entity_type: entityType,\n ids: JSON.stringify(uniqueIds)\n },\n success: function(response) {\n if (response.success && response.entities) {\n // Build a map of id -> entity for quick lookup\n var entityMap = {};\n response.entities.forEach(function(entity) {\n entityMap[entity.id] = entity;\n });\n\n // Update each picker that requested this entity type\n data.pickers.forEach(function(pickerData) {\n var $picker = pickerData.$picker;\n var $chips = $picker.find('.entity-chips');\n var $dataInput = $picker.find('.include-values-data, .exclude-values-data');\n var validIds = [];\n\n // Replace loading chips with real data\n pickerData.ids.forEach(function(id) {\n var $loadingChip = $chips.find('.entity-chip-loading[data-id=\"' + id + '\"]');\n if (entityMap[id]) {\n var entity = entityMap[id];\n validIds.push(entity.id);\n\n // Create real chip\n var html = '';\n if (entity.image) {\n html += '';\n }\n html += '' + self.escapeHtml(entity.name) + '';\n html += '';\n html += '';\n\n $loadingChip.replaceWith(html);\n } else {\n // Entity not found, remove loading chip\n $loadingChip.remove();\n }\n });\n\n // Update chips visibility\n self.updateChipsVisibility($chips);\n\n // If some entities were not found, update the hidden input\n if (validIds.length !== pickerData.ids.length) {\n $dataInput.val(JSON.stringify(validIds));\n self.serializeAllBlocks();\n }\n\n self.updateBlockStatus($picker.closest('.target-block'));\n });\n }\n }\n });\n });\n },\n\n /**\n * Collect entity IDs from a picker for bulk loading\n * Also shows loading placeholders for entity_search types\n */\n collectPickerEntities: function($picker, blockType, entitiesToLoad) {\n if (!$picker.length) {\n return;\n }\n\n var self = this;\n var $dataInput = $picker.find('.include-values-data, .exclude-values-data');\n if (!$dataInput.length) {\n return;\n }\n\n var valueType = $picker.attr('data-value-type');\n var rawValue = $dataInput.val() || '[]';\n\n var values = [];\n try {\n values = JSON.parse(rawValue);\n } catch (e) {\n return;\n }\n\n // Handle non-entity types synchronously\n if (valueType === 'multi_numeric_range') {\n if (!Array.isArray(values) || values.length === 0) return;\n\n var $chipsContainer = $picker.find('.multi-range-chips');\n values.forEach(function(range) {\n if (!range || (range.min === null && range.max === null)) return;\n\n var chipText = '';\n if (range.min !== null && range.max !== null) {\n chipText = range.min + ' - ' + range.max;\n } else if (range.min !== null) {\n chipText = '≥ ' + range.min;\n } else {\n chipText = '≤ ' + range.max;\n }\n\n var $chip = $('', {\n class: 'range-chip',\n 'data-min': range.min !== null ? range.min : '',\n 'data-max': range.max !== null ? range.max : ''\n });\n $chip.append($('', { class: 'range-chip-text', text: chipText }));\n $chip.append($('', {\n type: 'button',\n class: 'btn-remove-range',\n html: ''\n }));\n\n $chipsContainer.append($chip);\n });\n return;\n }\n\n if (valueType === 'multi_select_tiles') {\n if (!Array.isArray(values) || values.length === 0) return;\n\n values.forEach(function(key) {\n $picker.find('.tile-option[data-value=\"' + key + '\"]').addClass('selected');\n });\n return;\n }\n\n if (valueType === 'combination_attributes') {\n if (typeof values !== 'object' || values === null || Object.keys(values).length === 0) {\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n $dataInput.val(JSON.stringify(values));\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n if (!values.length) {\n return;\n }\n\n if (valueType === 'pattern') {\n values.forEach(function(item) {\n if (typeof item === 'string' && item) {\n self.addPatternTag($picker, item, false);\n } else if (item && item.pattern) {\n self.addPatternTag($picker, item.pattern, item.caseSensitive === true);\n }\n });\n return;\n }\n\n // For entity_search type - show loading placeholders and collect for bulk load\n var searchEntity = $picker.attr('data-search-entity') || blockType;\n var $chips = $picker.find('.entity-chips');\n\n // Get icon for entity type\n var entityIcon = this.getEntityTypeIcon(searchEntity);\n\n // Show loading placeholders with entity-specific icons\n values.forEach(function(id) {\n var html = '';\n html += '';\n html += 'Loading...';\n html += '';\n $chips.append(html);\n });\n\n // Collect for bulk load\n if (!entitiesToLoad[searchEntity]) {\n entitiesToLoad[searchEntity] = { ids: [], pickers: [] };\n }\n entitiesToLoad[searchEntity].ids = entitiesToLoad[searchEntity].ids.concat(values);\n entitiesToLoad[searchEntity].pickers.push({\n $picker: $picker,\n ids: values\n });\n },\n\n loadPickerValues: function($picker, blockType) {\n // This function is now only used for dynamic loading (not initial load)\n // Initial load uses collectPickerEntities + bulk AJAX\n if (!$picker.length) return;\n\n var self = this;\n var $dataInput = $picker.find('.include-values-data, .exclude-values-data');\n if (!$dataInput.length) return;\n\n var valueType = $picker.attr('data-value-type');\n var values = [];\n try {\n values = JSON.parse($dataInput.val() || '[]');\n } catch (e) {\n return;\n }\n\n // Handle empty/missing values based on type\n if (valueType === 'multi_numeric_range') {\n // For multi_numeric_range, values is an array of {min, max} objects\n if (!Array.isArray(values) || values.length === 0) return;\n\n var $chipsContainer = $picker.find('.multi-range-chips');\n values.forEach(function(range) {\n if (!range || (range.min === null && range.max === null)) return;\n\n var chipText = '';\n if (range.min !== null && range.max !== null) {\n chipText = range.min + ' - ' + range.max;\n } else if (range.min !== null) {\n chipText = '≥ ' + range.min;\n } else {\n chipText = '≤ ' + range.max;\n }\n\n var $chip = $('', {\n class: 'range-chip',\n 'data-min': range.min !== null ? range.min : '',\n 'data-max': range.max !== null ? range.max : ''\n });\n $chip.append($('', { class: 'range-chip-text', text: chipText }));\n $chip.append($('', {\n type: 'button',\n class: 'btn-remove-range',\n html: ''\n }));\n\n $chipsContainer.append($chip);\n });\n return;\n }\n\n if (valueType === 'multi_select_tiles') {\n // For multi_select_tiles, values is an array of selected keys\n if (!Array.isArray(values) || values.length === 0) return;\n\n values.forEach(function(key) {\n $picker.find('.tile-option[data-value=\"' + key + '\"]').addClass('selected');\n });\n return;\n }\n\n if (valueType === 'combination_attributes') {\n // For combination_attributes, values is an object: { groupId: [valueId1, valueId2], ... }\n if (typeof values !== 'object' || values === null || Object.keys(values).length === 0) {\n // Still need to load the attribute groups UI\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n // Store data in hidden input for later restoration\n $dataInput.val(JSON.stringify(values));\n\n // Load attribute groups and values will be restored after loading\n self.loadCombinationAttributeGroups($picker);\n return;\n }\n\n if (!values.length) return;\n\n // Handle pattern type - load as tags\n // Supports both old format (array of strings) and new format (array of {pattern, caseSensitive})\n if (valueType === 'pattern') {\n values.forEach(function(item) {\n if (typeof item === 'string' && item) {\n // Old format: just a string (default to case-insensitive)\n self.addPatternTag($picker, item, false);\n } else if (item && item.pattern) {\n // New format: object with pattern and caseSensitive\n self.addPatternTag($picker, item.pattern, item.caseSensitive === true);\n }\n });\n return;\n }\n\n // Handle entity_search type - load via AJAX\n var searchEntity = $picker.attr('data-search-entity') || blockType;\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getTargetEntitiesByIds',\n trait: 'EntitySelector',\n entity_type: searchEntity,\n ids: JSON.stringify(values)\n },\n success: function(response) {\n if (response.success && response.entities) {\n // Track which IDs were actually found (entities may have been deleted)\n var validIds = [];\n response.entities.forEach(function(entity) {\n // Use addSelectionNoUpdate to avoid multiple visibility updates\n self.addSelectionNoUpdate($picker, entity.id, entity.name, entity);\n validIds.push(entity.id);\n });\n\n // Update chips visibility once after all chips are added\n var $chips = $picker.find('.entity-chips');\n self.updateChipsVisibility($chips);\n\n // If some entities were not found, update the hidden input to remove orphaned IDs\n if (validIds.length !== values.length) {\n $dataInput.val(JSON.stringify(validIds));\n // Re-serialize to update the main form data\n self.serializeAllBlocks();\n }\n\n self.updateBlockStatus($picker.closest('.target-block'));\n }\n }\n });\n },\n\n // =========================================================================\n // Pattern Tag Methods\n // =========================================================================\n\n /**\n * Add a pattern tag to the pattern chips container\n */\n addPatternTag: function($wrapper, pattern, caseSensitive) {\n var trans = this.config.trans || {};\n var $chipsContainer = $wrapper.find('.pattern-chips');\n // Default to case-insensitive (false)\n var isCaseSensitive = caseSensitive === true;\n var caseTitle = isCaseSensitive\n ? (trans.case_sensitive || 'Case sensitive - click to toggle')\n : (trans.case_insensitive || 'Case insensitive - click to toggle');\n\n var html = '
';\n html += '';\n html += '' + (isCaseSensitive ? 'Aa' : 'aa') + '';\n html += '';\n html += '' + this.escapeHtml(pattern) + '';\n html += '';\n html += '
';\n $chipsContainer.append(html);\n },\n\n /**\n * Get all pattern tags from a wrapper\n * Returns array of objects: { pattern: string, caseSensitive: boolean }\n */\n getPatternTags: function($wrapper) {\n var patterns = [];\n // Exclude draft-tag which is the input field, not a saved pattern\n $wrapper.find('.pattern-tag:not(.draft-tag)').each(function() {\n var pattern = $(this).data('pattern');\n var caseSensitive = $(this).data('caseSensitive') === 1 || $(this).data('caseSensitive') === '1';\n if (pattern) {\n patterns.push({\n pattern: pattern,\n caseSensitive: caseSensitive\n });\n }\n });\n return patterns;\n },\n\n /**\n * Update the match count displayed in the draft tag while typing\n * Shows live preview with current case sensitivity setting\n */\n updateDraftTagCount: function($draftTag, pattern, caseSensitive) {\n var self = this;\n var $matchCount = $draftTag.find('.pattern-match-count');\n var $countValue = $matchCount.find('.count-value');\n\n // Get entity type from block\n var $block = $draftTag.closest('.target-block');\n var entityType = $block.data('blockType') || 'products';\n\n // Show loading - keep eye icon, update count value\n $countValue.html('');\n $matchCount.show();\n\n // Store pattern for click handler\n $matchCount.data('pattern', pattern);\n $matchCount.data('caseSensitive', caseSensitive);\n $matchCount.data('entityType', entityType);\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countPatternMatches',\n trait: 'EntitySelector',\n pattern: pattern,\n field: 'name',\n entity_type: entityType,\n case_sensitive: caseSensitive ? 1 : 0\n },\n success: function(response) {\n if (response.success) {\n var count = parseInt(response.count, 10) || 0;\n $countValue.text(count);\n $matchCount.show();\n // Add visual feedback based on count\n $matchCount.removeClass('count-zero count-found');\n $matchCount.addClass(count === 0 ? 'count-zero' : 'count-found');\n // Store count for preview\n $matchCount.data('count', count);\n // Update group total count to reflect draft pattern in calculation\n var $group = $draftTag.closest('.selection-group');\n if ($group.length) {\n self.updateGroupTotalCount($group);\n }\n } else {\n $countValue.text('?');\n $matchCount.show();\n }\n },\n error: function() {\n $countValue.text('?');\n $matchCount.show();\n }\n });\n },\n\n /**\n * Update condition count with a pending pattern (typed but not yet added as tag)\n * This shows a live preview of what the count would be if the user pressed Enter\n */\n updateConditionCountWithPendingPattern: function($row, pendingPattern) {\n var self = this;\n var trans = this.config.trans || {};\n\n // Find the count element - in method-selector-wrapper for include, in exclude-header-row for exclude\n var $countEl = $row.find('.method-selector-wrapper > .condition-match-count, > .exclude-header-row > .condition-match-count').first();\n if (!$countEl.length) return;\n\n var isExclude = $row.hasClass('exclude-row');\n var $methodSelect = isExclude\n ? $row.find('.exclude-method-select')\n : $row.find('.include-method-select');\n\n var method = $methodSelect.val();\n if (!method) {\n $countEl.hide();\n return;\n }\n\n var $picker = isExclude\n ? $row.find('.exclude-picker')\n : $row.find('.include-picker');\n\n var valueType = $picker.data('valueType') || 'none';\n\n // Only process for pattern value types\n if (valueType !== 'pattern') {\n return;\n }\n\n // Get existing pattern tags\n var values = this.getPatternTags($picker);\n\n // Add the pending pattern as a temporary tag (case-insensitive by default)\n if (pendingPattern) {\n values.push({ pattern: pendingPattern, caseSensitive: false });\n }\n\n if (values.length === 0) {\n $countEl.hide();\n return;\n }\n\n var $block = $row.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Show loading\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n // Store condition data on badge for popover\n $countEl.data('conditionData', {\n method: method,\n values: values,\n blockType: blockType,\n isExclude: isExclude\n });\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countConditionMatches',\n trait: 'EntitySelector',\n method: method,\n values: JSON.stringify(values),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.removeClass('no-matches clickable');\n if (count === 0) {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('no-matches').show();\n } else {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('clickable').show();\n }\n } else {\n $countEl.hide().removeClass('clickable');\n }\n },\n error: function() {\n $countEl.hide().removeClass('clickable');\n }\n });\n },\n\n /**\n * Fetch pattern match count via AJAX\n */\n fetchPatternMatchCount: function($picker, pattern, $countEl) {\n // Determine field type from method select\n // Check if we're in an exclude row first, then fall back to include\n var $excludeRow = $picker.closest('.exclude-row');\n var $methodSelect;\n if ($excludeRow.length) {\n $methodSelect = $excludeRow.find('.exclude-method-select');\n } else {\n var $group = $picker.closest('.selection-group');\n $methodSelect = $group.find('.include-method-select');\n }\n var method = $methodSelect.val() || '';\n var field = method.indexOf('reference') !== -1 ? 'reference' : 'name';\n\n // Get entity type from block\n var $block = $picker.closest('.target-block');\n var entityType = $block.data('blockType') || 'products';\n\n // Show loading state\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countPatternMatches',\n trait: 'EntitySelector',\n pattern: pattern,\n field: field,\n entity_type: entityType,\n case_sensitive: 0\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.find('.preview-count').text(count);\n $countEl.removeClass('no-matches clickable').show();\n if (count === 0) {\n $countEl.addClass('no-matches');\n } else {\n $countEl.addClass('clickable');\n }\n } else {\n $countEl.hide();\n }\n },\n error: function() {\n $countEl.hide();\n }\n });\n },\n\n // =========================================================================\n // Picker Value Extraction\n // =========================================================================\n\n /**\n * Get values from a picker based on its type\n */\n getPickerValues: function($picker, valueType) {\n switch (valueType) {\n case 'entity_search':\n var ids = [];\n $picker.find('.entity-chip').each(function() {\n var id = $(this).data('id');\n if (id) ids.push(id);\n });\n return ids;\n\n case 'pattern':\n var patternValues = this.getPatternTags($picker);\n // Also include draft pattern if it has content (not yet added as tag)\n var $draftPatternInput = $picker.find('.draft-tag .pattern-input');\n var draftPatternVal = $.trim($draftPatternInput.val());\n if (draftPatternVal) {\n var draftCaseSens = $draftPatternInput.closest('.draft-tag').attr('data-case-sensitive') === '1';\n patternValues.push({\n pattern: draftPatternVal,\n caseSensitive: draftCaseSens\n });\n }\n return patternValues;\n\n case 'numeric_range':\n var min = $picker.find('.range-min-input').val();\n var max = $picker.find('.range-max-input').val();\n return { min: min || null, max: max || null };\n\n case 'date_range':\n var from = $picker.find('.date-from-input').val();\n var to = $picker.find('.date-to-input').val();\n return { from: from || null, to: to || null };\n\n case 'select':\n return [$picker.find('.select-value-input').val()];\n\n case 'boolean':\n return [true];\n\n default:\n return [];\n }\n },\n\n // =========================================================================\n // Count/Status Updates\n // =========================================================================\n\n /**\n * Fetch and update condition match count for a row (include or exclude)\n */\n updateConditionCount: function($row) {\n var self = this;\n var trans = this.config.trans || {};\n\n // Find the count element - in method-selector-wrapper for include, in exclude-header-row for exclude\n var $countEl = $row.find('.method-selector-wrapper > .condition-match-count, > .exclude-header-row > .condition-match-count').first();\n if (!$countEl.length) return;\n\n // Determine if this is an include or exclude row\n var isExclude = $row.hasClass('exclude-row');\n var $methodSelect = isExclude\n ? $row.find('.exclude-method-select')\n : $row.find('.include-method-select');\n\n var method = $methodSelect.val();\n if (!method) {\n $countEl.hide();\n return;\n }\n\n // Get the picker and extract values\n var $picker = isExclude\n ? $row.find('.exclude-picker')\n : $row.find('.include-picker');\n\n var valueType = $picker.data('valueType') || 'none';\n var values = this.getPickerValues($picker, valueType);\n\n // Don't count if no values (except for boolean/all methods)\n var hasNoValues = !values ||\n (Array.isArray(values) && values.length === 0) ||\n (typeof values === 'object' && !Array.isArray(values) && (\n // For combination_attributes, check if attributes object is empty\n (valueType === 'combination_attributes' && values.attributes !== undefined && Object.keys(values.attributes).length === 0) ||\n // For other objects, check if completely empty\n (valueType !== 'combination_attributes' && Object.keys(values).length === 0)\n ));\n if (valueType !== 'none' && valueType !== 'boolean' && hasNoValues) {\n $countEl.hide();\n return;\n }\n\n // Get block type\n var $block = $row.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Show loading\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n // Store condition data on badge for popover\n $countEl.data('conditionData', {\n method: method,\n values: values,\n blockType: blockType,\n isExclude: isExclude\n });\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countConditionMatches',\n trait: 'EntitySelector',\n method: method,\n values: JSON.stringify(values),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.removeClass('no-matches clickable');\n if (count === 0) {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('no-matches').show();\n } else {\n // Show count, make clickable for preview popover\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('clickable').show();\n }\n } else {\n $countEl.hide().removeClass('clickable');\n }\n },\n error: function() {\n $countEl.hide().removeClass('clickable');\n }\n });\n },\n\n /**\n * Update all condition counts in a group\n */\n updateGroupCounts: function($group) {\n var self = this;\n\n // Update include count\n var $include = $group.find('.group-include');\n if ($include.length) {\n this.updateConditionCount($include);\n }\n\n // Update each exclude row count\n $group.find('.exclude-row').each(function() {\n self.updateConditionCount($(this));\n });\n\n // Update group total count (include - excludes)\n this.updateGroupTotalCount($group);\n },\n\n /**\n * Update the group total count badge (include - excludes)\n * Also updates the limit input placeholder\n */\n updateGroupTotalCount: function($group) {\n var self = this;\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n var $badge = $group.find('.group-header .group-count-badge');\n var $limitInput = $group.find('.group-modifier-limit');\n\n // Build group data for AJAX\n var groupData = this.serializeGroup($group, blockType);\n\n // Check if include has valid data\n if (!groupData.include || !groupData.include.method) {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n return;\n }\n\n // Show loading\n $badge.html('').show();\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countGroupItems',\n trait: 'EntitySelector',\n group_data: JSON.stringify(groupData),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var finalCount = response.final_count || 0;\n var excludeCount = response.exclude_count || 0;\n\n // Update badge with eye icon and count\n var badgeHtml = ' ' + finalCount;\n if (excludeCount > 0) {\n badgeHtml += ' (-' + excludeCount + ')';\n }\n $badge.html(badgeHtml);\n $badge.addClass('clickable').show();\n\n // Store group data on badge for preview popover\n $badge.data('groupData', groupData);\n $badge.data('blockType', blockType);\n $badge.data('finalCount', finalCount);\n\n // Update limit placeholder with the count\n $limitInput.attr('placeholder', finalCount);\n\n // Also update the group-preview-badge count (apply limit if set)\n var $previewBadge = $group.find('.group-preview-badge .preview-count');\n if ($previewBadge.length) {\n var limit = parseInt($limitInput.val(), 10);\n var displayCount = (limit > 0 && limit < finalCount) ? limit : finalCount;\n $previewBadge.text(displayCount);\n }\n } else {\n $badge.hide().removeClass('clickable');\n $limitInput.attr('placeholder', '–');\n }\n },\n error: function() {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n }\n });\n },\n\n /**\n * Update all condition counts for all visible groups\n */\n updateAllConditionCounts: function() {\n var self = this;\n this.$wrapper.find('.target-block.active .selection-group').each(function() {\n self.updateGroupCounts($(this));\n });\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Groups Module\n * Selection group management, serialization, block/tab management\n * @partial _groups.js\n *\n * Contains:\n * - Group management: addGroup, removeGroup, clearAllConditions\n * - Block/Tab: switchToBlock, updateTabBadges, updateBlockStatus\n * - Serialization: serializeGroup, serializeAllBlocks, getBlockGroups\n * - Counts: fetchProductCount, updateHeaderTotalCount, updateAllConditionCounts\n * - Excludes: addFirstExcludeRow, addExcludeRow, removeExcludeRow\n * - Validation: validate, showValidationError, clearValidationError\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.groups = {\n\n addGroup: function($block, blockType) {\n var $container = $block.find('.groups-container');\n var trans = this.config.trans || {};\n var blockDef = this.config.blocks[blockType] || {};\n var methods = blockDef.selection_methods || {};\n\n // Remove empty state\n $container.find('.groups-empty-state').remove();\n\n // Get next group index\n var maxIndex = -1;\n $container.find('.selection-group').each(function() {\n var idx = parseInt($(this).data('groupIndex'), 10);\n if (idx > maxIndex) maxIndex = idx;\n });\n var groupIndex = maxIndex + 1;\n\n // Build method options with optgroups\n var methodOptions = this.buildMethodOptions(methods, false);\n\n // Build exclude method options (no \"all\") with optgroups\n var excludeMethodOptions = this.buildMethodOptions(methods, true);\n\n var defaultGroupName = (trans.group || 'Group') + ' ' + (groupIndex + 1);\n var html = '
';\n\n // Group header\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Group body (collapsible content)\n html += '
';\n\n // Include section\n html += '
';\n html += '
';\n html += '
';\n html += '';\n html += '0';\n html += '';\n html += '
';\n var noItemsText = trans.no_items_selected || 'No items selected - use search below';\n html += '
';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n html += '';\n html += '
';\n html += '
';\n html += '
';\n\n // Excludes section (collapsed by default)\n html += '
';\n html += '';\n html += ' ' + (trans.add_exceptions || 'Add exceptions');\n html += '';\n html += '
';\n\n // Group-level modifiers (limit & sort)\n html += '
';\n html += '';\n html += '' + (trans.limit || 'Limit') + '';\n html += '';\n html += '';\n html += '';\n html += '' + (trans.sort || 'Sort') + '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += '';\n html += ' ';\n html += '';\n html += '
';\n\n html += '
'; // Close group-body\n\n html += '
'; // Close selection-group\n\n $container.append(html);\n\n // Find the new group and set method to \"all\" by default\n var $newGroup = $container.find('.selection-group[data-group-index=\"' + groupIndex + '\"]');\n\n // Enhance the method select with styled dropdown\n this.enhanceMethodSelect($newGroup.find('.include-method-select'));\n\n $newGroup.find('.include-method-select').val('all').trigger('change');\n\n this.updateBlockStatus($block);\n this.serializeAllBlocks();\n },\n\n removeGroup: function($group, $block) {\n $group.remove();\n\n var $container = $block.find('.groups-container');\n var remainingGroups = $container.find('.selection-group').length;\n\n if (remainingGroups === 0) {\n var emptyText = this.getEmptyStateText($block);\n var emptyHtml = '
';\n $container.html(emptyHtml);\n }\n\n this.updateBlockStatus($block);\n this.serializeAllBlocks();\n\n // Update tab badges and header total count\n this.updateTabBadges();\n },\n\n clearAllConditions: function() {\n var self = this;\n\n // Remove all groups from all blocks\n this.$wrapper.find('.target-block').each(function() {\n var $block = $(this);\n var $container = $block.find('.groups-container');\n\n // Remove all groups\n $container.find('.selection-group').remove();\n\n // Show empty state\n var emptyText = self.getEmptyStateText($block);\n var emptyHtml = '
';\n $container.html(emptyHtml);\n\n self.updateBlockStatus($block);\n });\n\n // Update serialized data\n this.serializeAllBlocks();\n\n // Update tab badges and header count\n this.updateTabBadges();\n\n // Also update header total count immediately (since all cleared)\n this.updateHeaderTotalCount();\n },\n\n switchToBlock: function(blockType) {\n // Update tabs\n this.$wrapper.find('.target-block-tab').removeClass('active');\n this.$wrapper.find('.target-block-tab[data-block-type=\"' + blockType + '\"]').addClass('active');\n\n // Update blocks\n this.$wrapper.find('.target-block').removeClass('active').hide();\n this.$wrapper.find('.target-block[data-block-type=\"' + blockType + '\"]').addClass('active').show();\n\n // Close dropdown if open\n this.hideDropdown();\n },\n\n updateTabBadges: function() {\n var self = this;\n\n this.$wrapper.find('.target-block-tab').each(function() {\n var $tab = $(this);\n var blockType = $tab.data('blockType');\n var $block = self.$wrapper.find('.target-block[data-block-type=\"' + blockType + '\"]');\n var groupCount = $block.find('.selection-group').length;\n\n // Update or add badge\n var $badge = $tab.find('.tab-badge');\n if (groupCount > 0) {\n // Show loading state first\n if ($badge.length) {\n $badge.addClass('loading').html('');\n } else {\n $tab.append('');\n }\n $tab.addClass('has-data');\n\n // Fetch real product count\n self.fetchProductCount(blockType, $tab);\n } else {\n $badge.remove();\n $tab.removeClass('has-data');\n }\n });\n\n // Update target switch state based on whether any data exists\n this.updateTargetSwitchState();\n },\n\n updateTargetSwitchState: function() {\n var $switch = this.$wrapper.find('.prestashop-switch');\n if (!$switch.length) {\n return;\n }\n\n // Check if any block has data\n var hasData = false;\n this.$wrapper.find('.target-block').each(function() {\n if ($(this).find('.selection-group').length > 0) {\n hasData = true;\n return false; // break\n }\n });\n\n // Update switch: value=\"1\" is \"Everyone/All/None\", value=\"0\" is \"Specific/Selected\"\n if (hasData) {\n $switch.find('input[value=\"0\"]').prop('checked', true);\n } else {\n $switch.find('input[value=\"1\"]').prop('checked', true);\n }\n },\n\n fetchProductCount: function(blockType, $tab) {\n var self = this;\n var data = {};\n\n // Read from hidden input (contains full saved data or freshly serialized data)\n var $hiddenInput = this.$wrapper.find('input[name=\"' + this.config.name + '\"]');\n var savedData = {};\n try {\n savedData = JSON.parse($hiddenInput.val() || '{}');\n } catch (e) {\n savedData = {};\n }\n\n // Get groups for the requested block type\n var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];\n\n if (groups.length === 0) {\n $tab.find('.tab-badge').remove();\n $tab.removeClass('has-data');\n $tab.removeData('previewData');\n return;\n }\n\n // Show loading state\n var $badge = $tab.find('.tab-badge');\n if (!$badge.length) {\n $badge = $('');\n $tab.append($badge);\n } else {\n $badge.addClass('loading').html('');\n }\n $tab.addClass('has-data');\n\n data[blockType] = { groups: groups };\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewEntitySelector',\n trait: 'EntitySelector',\n conditions: JSON.stringify(data),\n block_type: blockType,\n limit: 10\n },\n success: function(response) {\n if (response.success) {\n var $badge = $tab.find('.tab-badge');\n $badge.removeClass('loading').html(' ' + response.count);\n\n // Store preview data for popover\n $tab.data('previewData', response);\n\n // Update header total count\n self.updateHeaderTotalCount();\n } else {\n $tab.find('.tab-badge').remove();\n }\n },\n error: function() {\n $tab.find('.tab-badge').remove();\n self.updateHeaderTotalCount();\n }\n });\n },\n\n updateHeaderTotalCount: function() {\n var self = this;\n var total = 0;\n\n // Sum up all tab badge counts\n this.$wrapper.find('.target-block-tab .tab-badge').each(function() {\n var $badge = $(this);\n if (!$badge.hasClass('loading')) {\n var count = parseInt($badge.text(), 10);\n if (!isNaN(count)) {\n total += count;\n }\n }\n });\n\n var $totalBadge = this.$wrapper.find('.trait-total-count');\n if (total > 0) {\n $totalBadge.text(total).show();\n } else {\n $totalBadge.hide();\n }\n\n // Update show-all toggle state\n this.updateShowAllToggle();\n },\n\n updateShowAllToggle: function() {\n var $toggle = this.$wrapper.find('.trait-show-all-toggle');\n if (!$toggle.length) return;\n\n var $checkbox = $toggle.find('.show-all-checkbox');\n var hasData = this.$wrapper.find('.target-block-tab.has-data').length > 0;\n\n // If there's data, uncheck (not showing to all), otherwise check\n $checkbox.prop('checked', !hasData);\n },\n\n updateBlockStatus: function($block) {\n var $status = $block.find('.block-status');\n var blockType = $block.data('blockType');\n var blockDef = this.config.blocks[blockType] || {};\n var trans = this.config.trans || {};\n\n var groups = this.getBlockGroups($block);\n\n if (groups.length === 0) {\n var emptyMeansAll = this.config.emptyMeansAll !== false;\n if (emptyMeansAll) {\n $status.text((trans.all || 'All') + ' ' + (blockDef.entity_label_plural || 'items'));\n } else {\n $status.text(trans.nothing_selected || 'Nothing selected');\n }\n } else {\n $status.text(groups.length + ' ' + (groups.length === 1 ? (trans.group || 'group') : (trans.groups || 'groups')));\n }\n },\n\n getEmptyStateText: function($block) {\n var blockType = $block.data('blockType');\n var blockMode = $block.data('mode') || 'multi';\n var blockDef = this.config.blocks[blockType] || {};\n var trans = this.config.trans || {};\n var emptyMeansAll = this.config.emptyMeansAll !== false;\n\n if (blockMode === 'single') {\n return trans.no_item_selected || 'No item selected';\n }\n\n if (emptyMeansAll) {\n return (trans.all || 'All') + ' ' + (blockDef.entity_label_plural || 'items') + ' ' + (trans.included || 'included');\n }\n\n return trans.nothing_selected || 'Nothing selected';\n },\n\n serializeGroup: function($group, blockType) {\n var self = this;\n\n // Include\n var includeMethod = $group.find('.include-method-select').val() || 'all';\n var $includePicker = $group.find('.include-picker');\n var includeValues = this.getPickerValues($includePicker);\n\n // Excludes (multiple rows)\n var excludes = [];\n var $excludesSection = $group.find('.group-excludes.has-excludes');\n if ($excludesSection.length) {\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var excludeMethod = $row.find('.exclude-method-select').val() || null;\n var $excludePicker = $row.find('.exclude-picker');\n var excludeValues = self.getPickerValues($excludePicker);\n\n if (excludeMethod && excludeValues && (Array.isArray(excludeValues) ? excludeValues.length > 0 : true)) {\n excludes.push({\n method: excludeMethod,\n values: excludeValues\n });\n }\n });\n }\n\n var groupData = {\n include: {\n method: includeMethod,\n values: includeValues\n }\n };\n\n if (excludes.length > 0) {\n groupData.excludes = excludes;\n }\n\n // Add modifiers if present\n var modifiers = this.getGroupModifiers($group);\n if (modifiers.limit || modifiers.sort_by) {\n groupData.modifiers = modifiers;\n }\n\n return groupData;\n },\n\n serializeAllBlocks: function($changedRow) {\n var self = this;\n var data = {};\n\n this.$wrapper.find('.target-block').each(function() {\n var $block = $(this);\n var blockType = $block.data('blockType');\n var groups = self.getBlockGroups($block);\n\n // Groups now contain their own modifiers, no block-level modifiers\n if (groups.length > 0) {\n data[blockType] = { groups: groups };\n }\n\n self.updateBlockStatus($block);\n });\n\n // Update hidden input first\n var $input = this.$wrapper.find('input[name=\"' + this.config.name + '\"]');\n $input.val(JSON.stringify(data));\n\n // Then update tab badges (reads from hidden input)\n this.updateTabBadges();\n\n // Debounced update of condition count - only for changed row if specified\n if (this.countUpdateTimeout) {\n clearTimeout(this.countUpdateTimeout);\n }\n this.countUpdateTimeout = setTimeout(function() {\n if ($changedRow && $changedRow.length) {\n // Update the specific row that changed\n self.updateConditionCount($changedRow);\n // Also update the group total count (include - excludes)\n var $group = $changedRow.closest('.selection-group');\n if ($group.length) {\n self.updateGroupTotalCount($group);\n }\n } else {\n // Fallback: update all counts (initial load, structure changes)\n self.updateAllConditionCounts();\n }\n }, 500);\n },\n\n getBlockGroups: function($block) {\n var self = this;\n var groups = [];\n\n $block.find('.selection-group').each(function() {\n var $group = $(this);\n\n // Include\n var includeMethod = $group.find('.include-method-select').val() || 'all';\n var $includePicker = $group.find('.include-picker');\n var includeValues = self.getPickerValues($includePicker);\n\n // Skip groups with invalid include conditions (e.g., \"specific products\" with none selected)\n if (!self.isConditionValid(includeMethod, includeValues, $includePicker)) {\n return true; // continue to next group\n }\n\n // Excludes (multiple rows) - only include valid ones\n var excludes = [];\n var $excludesSection = $group.find('.group-excludes.has-excludes');\n if ($excludesSection.length) {\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var excludeMethod = $row.find('.exclude-method-select').val() || null;\n var $excludePicker = $row.find('.exclude-picker');\n var excludeValues = self.getPickerValues($excludePicker);\n\n // Only include valid exclude conditions\n if (excludeMethod && self.isConditionValid(excludeMethod, excludeValues, $excludePicker)) {\n excludes.push({\n method: excludeMethod,\n values: excludeValues\n });\n }\n });\n }\n\n var groupData = {\n include: {\n method: includeMethod,\n values: includeValues\n }\n };\n\n // Group name (optional, for organizational purposes)\n var groupName = $.trim($group.attr('data-group-name') || '');\n if (groupName) {\n groupData.name = groupName;\n }\n\n if (excludes.length > 0) {\n groupData.excludes = excludes;\n }\n\n // Group-level modifiers\n var modifiers = self.getGroupModifiers($group);\n if (modifiers.limit || modifiers.sort_by) {\n groupData.modifiers = modifiers;\n }\n\n groups.push(groupData);\n });\n\n return groups;\n },\n\n getGroupModifiers: function($group) {\n var limit = $group.find('.group-modifier-limit').val();\n var sortBy = $group.find('.group-modifier-sort').val() || 'sales';\n var $sortDirBtn = $group.find('.group-modifiers .btn-sort-dir');\n var sortDir = $sortDirBtn.data('dir') || 'DESC';\n\n return {\n limit: limit ? parseInt(limit, 10) : null,\n sort_by: sortBy || null,\n sort_dir: sortDir || 'DESC'\n };\n },\n\n getPickerValues: function($picker) {\n var valueType = $picker.attr('data-value-type') || 'entity_search';\n var values = [];\n\n switch (valueType) {\n case 'entity_search':\n $picker.find('.entity-chip').each(function() {\n var id = $(this).data('id');\n values.push(isNaN(id) ? id : Number(id));\n });\n break;\n\n case 'pattern':\n values = this.getPatternTags($picker);\n // Also include draft pattern if it has content (not yet added as tag)\n var $draftInput = $picker.find('.draft-tag .pattern-input');\n var draftPattern = $.trim($draftInput.val());\n if (draftPattern) {\n var draftCaseSensitive = $draftInput.closest('.draft-tag').attr('data-case-sensitive') === '1';\n values.push({\n pattern: draftPattern,\n caseSensitive: draftCaseSensitive\n });\n }\n break;\n\n case 'numeric_range':\n var min = $picker.find('.range-min-input').val();\n var max = $picker.find('.range-max-input').val();\n if (min !== '' || max !== '') {\n values = {\n min: min !== '' ? parseFloat(min) : null,\n max: max !== '' ? parseFloat(max) : null\n };\n }\n break;\n\n case 'date_range':\n var from = $picker.find('.date-from-input').val();\n var to = $picker.find('.date-to-input').val();\n if (from || to) {\n values = {\n from: from || null,\n to: to || null\n };\n }\n break;\n\n case 'select':\n var selectVal = $picker.find('.select-value-input').val();\n if (selectVal) {\n values = [selectVal];\n }\n break;\n\n case 'boolean':\n values = [true];\n break;\n\n case 'multi_numeric_range':\n var ranges = [];\n $picker.find('.range-chip').each(function() {\n var $chip = $(this);\n var minVal = $chip.data('min');\n var maxVal = $chip.data('max');\n ranges.push({\n min: minVal !== '' && minVal !== undefined ? parseFloat(minVal) : null,\n max: maxVal !== '' && maxVal !== undefined ? parseFloat(maxVal) : null\n });\n });\n if (ranges.length > 0) {\n values = ranges;\n }\n break;\n\n case 'multi_select_tiles':\n $picker.find('.tile-option.selected').each(function() {\n values.push($(this).data('value'));\n });\n break;\n\n case 'combination_attributes':\n // Returns object: { mode: 'products'|'combinations', attributes: { groupId: [valueId1, valueId2], ... } }\n var combAttrs = {};\n $picker.find('.comb-attr-value.selected').each(function() {\n var groupId = $(this).data('groupId').toString();\n var valueId = $(this).data('valueId');\n if (!combAttrs[groupId]) {\n combAttrs[groupId] = [];\n }\n combAttrs[groupId].push(valueId);\n });\n if (Object.keys(combAttrs).length > 0) {\n // Get mode: from radio if toggle exists, otherwise from config\n var $combPicker = $picker.find('.combination-attributes-picker');\n var configMode = $combPicker.data('combinationMode') || this.config.combinationMode || 'products';\n var combMode;\n if (configMode === 'toggle') {\n combMode = $picker.find('.comb-mode-radio:checked').val() || 'products';\n } else {\n combMode = configMode;\n }\n values = {\n mode: combMode,\n attributes: combAttrs\n };\n }\n break;\n }\n\n return values;\n },\n\n isConditionValid: function(method, values, $picker) {\n // 'all' method never needs values\n if (method === 'all') {\n return true;\n }\n\n // Boolean methods are always valid (the value is implicit true)\n var valueType = $picker.attr('data-value-type') || 'entity_search';\n if (valueType === 'boolean') {\n return true;\n }\n\n // For other methods, check if values are meaningful\n if (Array.isArray(values)) {\n return values.length > 0;\n }\n\n // For object values (ranges, combination_attributes), check if meaningful\n if (typeof values === 'object' && values !== null) {\n // Special handling for combination_attributes: { mode, attributes }\n if (valueType === 'combination_attributes' && values.attributes !== undefined) {\n return Object.keys(values.attributes).length > 0;\n }\n // For ranges and other objects, check if at least one bound is set\n return Object.keys(values).some(function(key) {\n return values[key] !== null && values[key] !== '';\n });\n }\n\n return false;\n },\n\n updateAllConditionCounts: function() {\n var self = this;\n this.$wrapper.find('.target-block.active .selection-group').each(function() {\n self.updateGroupCounts($(this));\n });\n },\n\n updateGroupCounts: function($group) {\n var self = this;\n\n // Update include count\n var $include = $group.find('.group-include');\n if ($include.length) {\n this.updateConditionCount($include);\n }\n\n // Update each exclude row count\n $group.find('.exclude-row').each(function() {\n self.updateConditionCount($(this));\n });\n\n // Update group total count (include - excludes)\n this.updateGroupTotalCount($group);\n },\n\n updateConditionCount: function($row) {\n var self = this;\n var trans = this.config.trans || {};\n\n // Find the count element - in method-selector-wrapper for include, in exclude-header-row for exclude\n var $countEl = $row.find('.method-selector-wrapper > .condition-match-count, > .exclude-header-row .condition-match-count').first();\n if (!$countEl.length) return;\n\n // Determine if this is an include or exclude row\n var isExclude = $row.hasClass('exclude-row');\n var $methodSelect = isExclude\n ? $row.find('.exclude-method-select')\n : $row.find('.include-method-select');\n\n var method = $methodSelect.val();\n if (!method) {\n $countEl.hide();\n return;\n }\n\n // Get the picker and extract values\n var $picker = isExclude\n ? $row.find('.exclude-picker')\n : $row.find('.include-picker');\n\n var valueType = $picker.data('valueType') || 'none';\n var values = this.getPickerValues($picker, valueType);\n\n // Don't count if no values (except for boolean/all methods)\n var hasNoValues = !values ||\n (Array.isArray(values) && values.length === 0) ||\n (typeof values === 'object' && !Array.isArray(values) && (\n // For combination_attributes, check if attributes object is empty\n (valueType === 'combination_attributes' && values.attributes !== undefined && Object.keys(values.attributes).length === 0) ||\n // For other objects, check if completely empty\n (valueType !== 'combination_attributes' && Object.keys(values).length === 0)\n ));\n if (valueType !== 'none' && valueType !== 'boolean' && hasNoValues) {\n $countEl.hide();\n return;\n }\n\n // Get block type\n var $block = $row.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Show loading\n $countEl.find('.preview-count').html('');\n $countEl.removeClass('clickable no-matches').show();\n\n // Store condition data on badge for popover\n $countEl.data('conditionData', {\n method: method,\n values: values,\n blockType: blockType,\n isExclude: isExclude\n });\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countConditionMatches',\n trait: 'EntitySelector',\n method: method,\n values: JSON.stringify(values),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var count = response.count || 0;\n $countEl.removeClass('no-matches clickable');\n if (count === 0) {\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('no-matches').show();\n } else {\n // Show count, make clickable for preview popover\n $countEl.find('.preview-count').text(count);\n $countEl.addClass('clickable').show();\n }\n } else {\n $countEl.hide().removeClass('clickable');\n }\n },\n error: function() {\n $countEl.hide().removeClass('clickable');\n }\n });\n },\n\n updateGroupTotalCount: function($group) {\n var self = this;\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n var $badge = $group.find('.group-header .group-count-badge');\n var $limitInput = $group.find('.group-modifier-limit');\n\n // Build group data for AJAX\n var groupData = this.serializeGroup($group, blockType);\n\n // Check if include has valid data\n if (!groupData.include || !groupData.include.method) {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n return;\n }\n\n // Show loading\n $badge.html('').show();\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'countGroupItems',\n trait: 'EntitySelector',\n group_data: JSON.stringify(groupData),\n block_type: blockType\n },\n success: function(response) {\n if (response && response.success) {\n var finalCount = response.final_count || 0;\n var excludeCount = response.exclude_count || 0;\n\n // Update badge with eye icon and count\n var badgeHtml = ' ' + finalCount;\n if (excludeCount > 0) {\n badgeHtml += ' (-' + excludeCount + ')';\n }\n $badge.html(badgeHtml);\n $badge.addClass('clickable').show();\n\n // Store group data on badge for preview popover\n $badge.data('groupData', groupData);\n $badge.data('blockType', blockType);\n $badge.data('finalCount', finalCount);\n\n // Update limit placeholder with the count\n $limitInput.attr('placeholder', finalCount);\n\n // Also update the group-preview-badge count (apply limit if set)\n var $previewBadge = $group.find('.group-preview-badge .preview-count');\n if ($previewBadge.length) {\n var limit = parseInt($limitInput.val(), 10);\n var displayCount = (limit > 0 && limit < finalCount) ? limit : finalCount;\n $previewBadge.text(displayCount);\n }\n } else {\n $badge.hide().removeClass('clickable');\n $limitInput.attr('placeholder', '–');\n }\n },\n error: function() {\n $badge.hide();\n $limitInput.attr('placeholder', '–');\n }\n });\n },\n\n // Exclude row management\n addFirstExcludeRow: function($group, $block) {\n var $excludesDiv = $group.find('.group-excludes');\n var trans = this.config.trans || {};\n\n // Build the full excludes structure with first row\n var html = '
';\n html += ' ' + (trans.except || 'EXCEPT') + '';\n html += '
';\n\n html += '
';\n html += this.buildExcludeRowHtml($block, 0);\n html += '
';\n\n html += '';\n html += ' ' + (trans.add_another_exception || 'Add another exception');\n html += '';\n\n $excludesDiv.addClass('has-excludes').html(html);\n this.updateMethodSelectorLock($group, true);\n this.serializeAllBlocks();\n },\n\n addExcludeRow: function($group, $block) {\n var $container = $group.find('.exclude-rows-container');\n\n // Get next exclude index\n var maxIndex = -1;\n $container.find('.exclude-row').each(function() {\n var idx = parseInt($(this).data('excludeIndex'), 10);\n if (idx > maxIndex) maxIndex = idx;\n });\n var excludeIndex = maxIndex + 1;\n\n var html = this.buildExcludeRowHtml($block, excludeIndex);\n $container.append(html);\n\n // Enhance the exclude method select with styled dropdown\n var $newRow = $container.find('.exclude-row[data-exclude-index=\"' + excludeIndex + '\"]');\n this.enhanceMethodSelect($newRow.find('.exclude-method-select'));\n\n this.serializeAllBlocks();\n },\n\n buildExcludeRowHtml: function($block, excludeIndex) {\n var blockType = $block.data('blockType');\n var blockDef = this.config.blocks[blockType] || {};\n var methods = blockDef.selection_methods || {};\n var trans = this.config.trans || {};\n\n // Build exclude method options with optgroups (no \"all\")\n var excludeMethodOptions = this.buildMethodOptions(methods, true);\n\n // Find first non-all method for default search entity\n var firstSearchEntity = blockType;\n var firstValueType = 'entity_search';\n $.each(methods, function(methodKey, methodDef) {\n if (methodKey === 'all') return true;\n firstSearchEntity = methodDef.search_entity || blockType;\n firstValueType = methodDef.value_type || 'entity_search';\n return false; // break\n });\n\n var html = '
';\n\n // Header row with method select wrapped in method-selector-wrapper (same as include)\n html += '
';\n html += '
';\n html += '';\n html += '0';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n\n // Value picker based on first method's value type\n html += this.buildValuePickerHtml('exclude', firstValueType, firstSearchEntity, methods);\n\n html += '
';\n\n return html;\n },\n\n removeExcludeRow: function($excludeRow, $group, $block) {\n var $container = $group.find('.exclude-rows-container');\n var trans = this.config.trans || {};\n\n $excludeRow.remove();\n\n // Check if there are remaining exclude rows\n var remainingRows = $container.find('.exclude-row').length;\n\n if (remainingRows === 0) {\n // Remove entire excludes section and show \"Add exceptions\" button\n var $excludesDiv = $group.find('.group-excludes');\n $excludesDiv.removeClass('has-excludes').html(\n '' +\n ' ' + (trans.add_exceptions || 'Add exceptions') +\n ''\n );\n // Unlock the method selector since no excludes exist\n this.updateMethodSelectorLock($group, false);\n }\n\n this.serializeAllBlocks();\n },\n\n // Method options building\n buildMethodOptions: function(methods, excludeAll) {\n var self = this;\n var trans = this.config.trans || {};\n var html = '';\n\n // Group labels\n var groupLabels = {\n 'select_by': trans.select_by || 'Select by...',\n 'filter_by': trans.filter_by || 'Filter by...'\n };\n\n // Separate methods by group\n var grouped = {};\n var ungrouped = {};\n\n $.each(methods, function(methodKey, methodDef) {\n if (excludeAll && methodKey === 'all') return true; // skip\n\n var group = methodDef.group || '';\n if (group) {\n if (!grouped[group]) {\n grouped[group] = {};\n }\n grouped[group][methodKey] = methodDef;\n } else {\n ungrouped[methodKey] = methodDef;\n }\n });\n\n // Render ungrouped options first\n $.each(ungrouped, function(methodKey, methodDef) {\n html += self.buildMethodOption(methodKey, methodDef);\n });\n\n // Render grouped options with optgroups\n $.each(grouped, function(groupKey, groupMethods) {\n var groupLabel = groupLabels[groupKey] || groupKey.replace(/_/g, ' ');\n html += '';\n });\n\n return html;\n },\n\n buildMethodOption: function(methodKey, methodDef) {\n var html = '';\n return html;\n },\n\n buildValuePickerHtml: function(section, valueType, searchEntity, methods) {\n var trans = this.config.trans || {};\n var pickerClass = section + '-picker';\n var chipsClass = section + '-chips';\n var dataClass = section + '-values-data';\n var html = '';\n\n if (valueType === 'none') {\n html = '
';\n html += '';\n html += '
';\n return html;\n }\n\n html = '
';\n\n switch (valueType) {\n case 'entity_search':\n var noItemsText = trans.no_items_selected || 'No items selected - use search below';\n html += '';\n html += '
';\n html += '';\n html += '';\n html += '';\n html += '
';\n html += '';\n break;\n\n case 'pattern':\n // Build tooltip content for data-details attribute\n var tooltipContent = '' + this.escapeHtml(trans.pattern_help_title || 'Pattern Syntax') + '';\n tooltipContent += '
';\n tooltipContent += '
*' + this.escapeHtml(trans.pattern_help_wildcard || 'any text (wildcard)') + '
' + this.escapeHtml(trans.combination_help_within || 'Within group: OR (Red OR Blue)') + '
';\n combTooltip += '
' + this.escapeHtml(trans.combination_help_between || 'Between groups: AND (Color AND Size)') + '
';\n combTooltip += '
';\n combTooltip += '
';\n\n // Combination mode from config: 'products', 'combinations', or 'toggle'\n var combMode = this.config.combinationMode || 'products';\n var showModeToggle = (combMode === 'toggle');\n var defaultMode = showModeToggle ? 'products' : combMode;\n\n html += '
';\n // Mode toggle: only show when config is 'toggle'\n if (showModeToggle) {\n html += '
';\n html += '';\n html += '';\n html += '
';\n }\n html += '
';\n html += ' ' + this.escapeHtml(trans.loading || 'Loading...') + '';\n html += '
';\n html += '
';\n // Store mode along with attributes: { mode: 'products'|'combinations', attributes: { groupId: [valueIds] } }\n html += '';\n break;\n\n default:\n html += '';\n break;\n }\n\n html += '
';\n return html;\n },\n\n // Sort options\n getSortOptionsArray: function(blockType) {\n var trans = this.config.trans || {};\n\n switch (blockType) {\n case 'products':\n return [\n { value: 'sales', label: trans.sort_bestsellers || 'Best sellers' },\n { value: 'date_add', label: trans.sort_newest || 'Newest' },\n { value: 'price', label: trans.sort_price || 'Price' },\n { value: 'name', label: trans.sort_name || 'Name' },\n { value: 'position', label: trans.sort_position || 'Position' },\n { value: 'quantity', label: trans.sort_stock || 'Stock quantity' },\n { value: 'random', label: trans.sort_random || 'Random' }\n ];\n case 'categories':\n return [\n { value: 'name', label: trans.sort_name || 'Name' },\n { value: 'position', label: trans.sort_position || 'Position' },\n { value: 'product_count', label: trans.sort_products || 'Products count' },\n { value: 'date_add', label: trans.sort_newest || 'Newest' }\n ];\n default:\n return [\n { value: 'name', label: trans.sort_name || 'Name' },\n { value: 'date_add', label: trans.sort_newest || 'Newest' }\n ];\n }\n },\n\n getSortIconClass: function(sortBy, sortDir) {\n var isAsc = (sortDir === 'ASC');\n\n switch (sortBy) {\n case 'name':\n return isAsc ? 'icon-sort-alpha-asc' : 'icon-sort-alpha-desc';\n case 'price':\n case 'quantity':\n case 'product_count':\n return isAsc ? 'icon-sort-numeric-asc' : 'icon-sort-numeric-desc';\n case 'date_add':\n case 'newest_products':\n return isAsc ? 'icon-sort-numeric-asc' : 'icon-sort-numeric-desc';\n case 'sales':\n case 'total_sales':\n return isAsc ? 'icon-sort-amount-asc' : 'icon-sort-amount-desc';\n case 'position':\n return isAsc ? 'icon-sort-numeric-asc' : 'icon-sort-numeric-desc';\n case 'random':\n return 'icon-random';\n default:\n return isAsc ? 'icon-sort-amount-asc' : 'icon-sort-amount-desc';\n }\n },\n\n cycleSortOption: function($btn, blockType) {\n var sortOptions = this.getSortOptionsArray(blockType);\n var currentSort = $btn.data('sort') || 'sales';\n var currentDir = $btn.data('dir') || 'DESC';\n\n // Find current index\n var currentIndex = -1;\n for (var i = 0; i < sortOptions.length; i++) {\n if (sortOptions[i].value === currentSort) {\n currentIndex = i;\n break;\n }\n }\n\n // Cycle: first toggle direction, then move to next sort option\n var newSort, newDir, newLabel;\n if (currentDir === 'DESC') {\n // Toggle to ASC, same sort\n newSort = currentSort;\n newDir = 'ASC';\n } else {\n // Move to next sort option, reset to DESC\n var nextIndex = (currentIndex + 1) % sortOptions.length;\n newSort = sortOptions[nextIndex].value;\n newDir = 'DESC';\n }\n\n // Find label for new sort\n for (var j = 0; j < sortOptions.length; j++) {\n if (sortOptions[j].value === newSort) {\n newLabel = sortOptions[j].label;\n break;\n }\n }\n\n // Update button\n $btn.data('sort', newSort);\n $btn.data('dir', newDir);\n $btn.attr('data-sort', newSort);\n $btn.attr('data-dir', newDir);\n $btn.attr('title', newLabel + ' ' + (newDir === 'DESC' ? '↓' : '↑'));\n $btn.find('i').attr('class', this.getSortIconClass(newSort, newDir));\n },\n\n // Validation\n validate: function() {\n var isRequired = this.$wrapper.data('required') === 1 || this.$wrapper.data('required') === '1';\n if (!isRequired) {\n return true;\n }\n\n // Check if any block has data (groups with selections)\n var hasData = false;\n this.$wrapper.find('.target-block').each(function() {\n if ($(this).find('.selection-group').length > 0) {\n hasData = true;\n return false; // break\n }\n });\n\n if (!hasData) {\n // Show validation error\n this.showValidationError();\n return false;\n }\n\n // Valid - remove any previous error\n this.clearValidationError();\n return true;\n },\n\n showValidationError: function() {\n this.$wrapper.addClass('has-validation-error');\n var message = this.$wrapper.data('required-message') || 'Please select at least one item';\n\n // Remove any existing error\n this.$wrapper.find('.trait-validation-error').remove();\n\n // Add error message after header\n var $error = $('
', {\n class: 'trait-validation-error',\n html: ' ' + message\n });\n this.$wrapper.find('.condition-trait-header').after($error);\n\n // Scroll to error\n $('html, body').animate({\n scrollTop: this.$wrapper.offset().top - 100\n }, 300);\n\n // Expand the trait if collapsed\n if (!this.$wrapper.find('.condition-trait-body').is(':visible')) {\n this.$wrapper.find('.condition-trait-body').slideDown(200);\n this.$wrapper.removeClass('collapsed');\n }\n },\n\n clearValidationError: function() {\n this.$wrapper.removeClass('has-validation-error');\n this.$wrapper.find('.trait-validation-error').remove();\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Methods Module\n * Method dropdown rendering, value pickers, combination picker\n * @partial _methods.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 6760-6848 (initMethodDropdowns, enhanceMethodSelect)\n * 6849-7051 (showMethodDropdownMenu, buildMethodDropdownMenuHtml, closeMethodDropdownMenu)\n * 7053-7138 (populateTiles, applyRangeInputConstraints, showRangeInputError)\n * 7139-7380 (combination picker methods)\n * 7382-7550 (updateMethodInfoPlaceholder, getBuiltInMethodHelp)\n * 7748-7888 (buildSortOptions, updateModifierButtonState, updateMethodSelectorLock)\n *\n * Contains:\n * - initMethodDropdowns() - Initialize styled dropdowns\n * - enhanceMethodSelect() - Convert select to styled dropdown\n * - showMethodDropdownMenu() - Show method selection menu\n * - buildMethodDropdownMenuHtml() - Build menu HTML\n * - closeMethodDropdownMenu() - Close dropdown menu\n * - updateMethodTrigger() - Update trigger display\n * - populateTiles() - Build multi-select tiles\n * - applyRangeInputConstraints() - Set numeric input constraints\n * - showRangeInputError() - Display validation error\n * - loadCombinationAttributeGroups() - Load attribute groups for picker\n * - loadCombinationAttributeValues() - Load values for attribute group\n * - restoreCombinationSelections() - Restore saved combination state\n * - updateCombinationData() - Save combination selection\n * - updateCombinationGroupCounts() - Update selection counts\n * - updateMethodInfoPlaceholder() - Show method help\n * - getBuiltInMethodHelp() - Get help text for methods\n * - buildSortOptions() - Build sort dropdown options\n * - updateModifierButtonState() - Update modifier toggle state\n * - updateMethodSelectorLock() - Lock/unlock method selector\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.methods = {\n\n /**\n * Initialize styled method dropdowns for all method selects\n */\n initMethodDropdowns: function() {\n var self = this;\n this.$wrapper.find('.include-method-select').each(function() {\n self.enhanceMethodSelect($(this));\n });\n this.$wrapper.find('.exclude-method-select').each(function() {\n self.enhanceMethodSelect($(this));\n });\n this.initMethodInfoPlaceholders();\n },\n\n /**\n * Initialize info placeholders for all existing method selects\n */\n initMethodInfoPlaceholders: function() {\n var self = this;\n this.$wrapper.find('.selection-group').each(function() {\n var $group = $(this);\n var $block = $group.closest('.target-block');\n var blockType = $block.data('blockType') || 'products';\n\n // Include method info\n var includeMethod = $group.find('.include-method-select').val() || 'all';\n self.updateMethodInfoPlaceholder($group.find('.method-selector-wrapper'), includeMethod, blockType);\n\n // Exclude methods info\n $group.find('.exclude-row').each(function() {\n var $row = $(this);\n var excludeMethod = $row.find('.exclude-method-select').val();\n if (excludeMethod) {\n self.updateMethodInfoPlaceholder($row.find('.method-selector-wrapper'), excludeMethod, blockType);\n }\n });\n });\n },\n\n /**\n * Enhance a single method select with styled dropdown\n */\n enhanceMethodSelect: function($select) {\n var self = this;\n\n if (!$select.length || $select.data('methodDropdownInit')) {\n return;\n }\n $select.data('methodDropdownInit', true);\n\n $select.addClass('method-select-hidden');\n\n var $selectedOption = $select.find('option:selected');\n var selectedIcon = $selectedOption.data('icon') || 'icon-caret-down';\n var selectedLabel = $selectedOption.text();\n\n var triggerHtml = '
';\n\n var $trigger = $(triggerHtml);\n $select.after($trigger);\n\n $trigger.on('click', function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var $wrapper = $select.closest('.method-selector-wrapper');\n if ($wrapper.hasClass('selector-locked')) {\n return;\n }\n\n self.showMethodDropdownMenu($select, $trigger);\n });\n\n $select.on('change.methodDropdown', function() {\n self.updateMethodTrigger($select, $trigger);\n });\n },\n\n /**\n * Update the trigger display to match current selection\n */\n updateMethodTrigger: function($select, $trigger) {\n var $selectedOption = $select.find('option:selected');\n var selectedIcon = $selectedOption.data('icon') || 'icon-caret-down';\n var selectedLabel = $selectedOption.text();\n\n $trigger.find('.method-trigger-icon').attr('class', selectedIcon + ' method-trigger-icon');\n $trigger.find('.method-trigger-label').text(selectedLabel);\n },\n\n /**\n * Show the method dropdown menu\n */\n showMethodDropdownMenu: function($select, $trigger) {\n var self = this;\n\n this.closeMethodDropdownMenu();\n\n var menuHtml = this.buildMethodDropdownMenuHtml($select);\n var $menu = $(menuHtml);\n\n var triggerOffset = $trigger.offset();\n var triggerWidth = $trigger.outerWidth();\n var triggerHeight = $trigger.outerHeight();\n\n $menu.css({\n position: 'absolute',\n top: triggerOffset.top + triggerHeight + 2,\n left: triggerOffset.left,\n minWidth: triggerWidth,\n zIndex: 10001\n });\n\n $('body').append($menu);\n this.$methodDropdownMenu = $menu;\n this.$methodDropdownSelect = $select;\n this.$methodDropdownTrigger = $trigger;\n\n $menu.on('click', '.method-dropdown-item', function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var value = $(this).data('value');\n $select.val(value).trigger('change');\n self.closeMethodDropdownMenu();\n });\n\n $(document).on('click.methodDropdown', function(e) {\n if (!$(e.target).closest('.method-dropdown-menu, .method-dropdown-trigger').length) {\n self.closeMethodDropdownMenu();\n }\n });\n\n $(document).on('keydown.methodDropdown', function(e) {\n if (e.keyCode === 27) {\n self.closeMethodDropdownMenu();\n }\n });\n },\n\n /**\n * Build the dropdown menu HTML\n */\n buildMethodDropdownMenuHtml: function($select) {\n var self = this;\n var html = '
';\n\n // Render ungrouped options first\n $select.children('option').each(function() {\n var $el = $(this);\n var icon = $el.data('icon') || 'icon-asterisk';\n var label = $el.text();\n var value = $el.val();\n var isSelected = $el.is(':selected');\n\n html += '
';\n html += '';\n html += '' + self.escapeHtml(label) + '';\n if (isSelected) {\n html += '';\n }\n html += '
';\n });\n\n // Render optgroups\n $select.children('optgroup').each(function() {\n var $optgroup = $(this);\n var groupLabel = $optgroup.attr('label') || '';\n\n html += '
';\n html += '
' + self.escapeHtml(groupLabel) + '
';\n html += '
';\n\n $optgroup.children('option').each(function() {\n var $el = $(this);\n var icon = $el.data('icon') || 'icon-cog';\n var label = $el.text();\n var value = $el.val();\n var isSelected = $el.is(':selected');\n\n html += '
';\n html += '';\n html += '' + self.escapeHtml(label) + '';\n if (isSelected) {\n html += '';\n }\n html += '
';\n });\n\n html += '
'; // close items\n html += '
'; // close optgroup\n });\n\n html += '
';\n return html;\n },\n\n /**\n * Close the method dropdown menu\n */\n closeMethodDropdownMenu: function() {\n if (this.$methodDropdownMenu) {\n this.$methodDropdownMenu.remove();\n this.$methodDropdownMenu = null;\n }\n this.$methodDropdownSelect = null;\n this.$methodDropdownTrigger = null;\n $(document).off('click.methodDropdown keydown.methodDropdown');\n },\n\n /**\n * Populate tiles for multi_select_tiles value picker\n */\n populateTiles: function($picker, options, exclusive) {\n var self = this;\n var $container = $picker.find('.multi-select-tiles');\n $container.empty();\n\n if (exclusive) {\n $container.attr('data-exclusive', 'true');\n } else {\n $container.removeAttr('data-exclusive');\n }\n\n $.each(options, function(key, optData) {\n var label = typeof optData === 'object' ? optData.label : optData;\n var icon = typeof optData === 'object' && optData.icon ? optData.icon : null;\n var color = typeof optData === 'object' && optData.color ? optData.color : null;\n\n var tileClass = 'tile-option';\n if (color) {\n tileClass += ' tile-color-' + color;\n }\n\n var $tile = $('', {\n type: 'button',\n class: tileClass,\n 'data-value': key\n });\n\n if (icon) {\n $tile.append($('', { class: icon }));\n }\n $tile.append($('', { class: 'tile-label', text: label }));\n\n $container.append($tile);\n });\n },\n\n /**\n * Apply step/min constraints to numeric range inputs\n */\n applyRangeInputConstraints: function($picker, step, min) {\n var $inputs = $picker.find('.range-min-input, .range-max-input');\n\n if (typeof step !== 'undefined' && step !== null) {\n $inputs.attr('step', step);\n } else {\n $inputs.attr('step', 'any');\n }\n\n if (typeof min !== 'undefined' && min !== null) {\n $inputs.attr('min', min);\n } else {\n $inputs.removeAttr('min');\n }\n },\n\n /**\n * Show error message on range input\n */\n showRangeInputError: function($input, message) {\n var $container = $input.closest('.multi-range-input-row');\n\n $container.find('.range-input-error').remove();\n $container.find('.range-min-input, .range-max-input').removeClass('has-error');\n\n $input.addClass('has-error');\n var $error = $('', {\n class: 'range-input-error',\n text: message\n });\n $container.append($error);\n\n setTimeout(function() {\n $input.removeClass('has-error');\n $error.fadeOut(200, function() {\n $(this).remove();\n });\n }, 3000);\n },\n\n /**\n * Load attribute groups for combination picker\n */\n loadCombinationAttributeGroups: function($picker) {\n var self = this;\n var trans = this.config.trans || {};\n var $container = $picker.find('.combination-groups-container');\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'getAttributeGroups',\n trait: 'TargetConditions'\n },\n success: function(response) {\n $container.empty();\n\n if (!response.success || !response.groups || response.groups.length === 0) {\n $container.html('' +\n self.escapeHtml(trans.no_attribute_groups || 'No attribute groups found') +\n '');\n return;\n }\n\n response.groups.forEach(function(group) {\n var $groupDiv = $('
' + this.escapeHtml(trans.help_combination_within || 'Within group: OR (Red OR Blue)') + '
';\n html += '
' + this.escapeHtml(trans.help_combination_between || 'Between groups: AND (Color AND Size)') + '
';\n html += '
';\n break;\n\n case 'by_carrier':\n html = '' + this.escapeHtml(trans.help_carrier_title || 'By Carrier') + '';\n html += '
' + this.escapeHtml(trans.help_carrier_desc || 'Select items available with specific carriers.') + '
';\n break;\n\n case 'by_condition':\n html = '' + this.escapeHtml(trans.help_condition_title || 'By Condition') + '';\n html += '
' + this.escapeHtml(trans.help_condition_desc || 'Filter by product condition: New, Used, or Refurbished.') + '
';\n break;\n\n case 'by_visibility':\n html = '' + this.escapeHtml(trans.help_visibility_title || 'By Visibility') + '';\n html += '
' + this.escapeHtml(trans.help_visibility_desc || 'Filter by where products are visible in the store.') + '
';\n break;\n\n case 'by_active_status':\n html = '' + this.escapeHtml(trans.help_active_title || 'By Active Status') + '';\n html += '
' + this.escapeHtml(trans.help_active_desc || 'Filter by whether products are enabled or disabled.') + '
';\n break;\n\n case 'by_stock_status':\n html = '' + this.escapeHtml(trans.help_stock_title || 'By Stock Status') + '';\n html += '
' + this.escapeHtml(trans.help_stock_desc || 'Filter by stock availability: In stock, Out of stock, or Low stock.') + '
';\n break;\n\n case 'by_on_sale':\n case 'by_has_specific_price':\n case 'by_is_virtual':\n case 'by_is_pack':\n case 'by_has_combinations':\n case 'by_available_for_order':\n case 'by_online_only':\n case 'by_has_related':\n case 'by_has_customization':\n case 'by_has_attachments':\n case 'by_has_additional_shipping':\n html = '' + this.escapeHtml(trans.help_boolean_title || 'Yes/No Filter') + '';\n html += '
' + this.escapeHtml(trans.help_boolean_desc || 'Filter products by this property.') + '
';\n break;\n\n case 'by_name_pattern':\n case 'by_reference_pattern':\n case 'by_description_pattern':\n case 'by_long_description_pattern':\n case 'by_ean13_pattern':\n case 'by_upc_pattern':\n case 'by_isbn_pattern':\n case 'by_mpn_pattern':\n case 'by_meta_title_pattern':\n case 'by_meta_description_pattern':\n html = '' + this.escapeHtml(trans.help_pattern_title || 'Pattern Matching') + '';\n html += '
' + this.escapeHtml(trans.help_pattern_desc || 'Match text using patterns with wildcards.') + '
{letter} ' + this.escapeHtml(trans.help_pattern_letter || 'single letter A-Z') + '
';\n break;\n\n case 'by_id_range':\n case 'by_price_range':\n case 'by_weight_range':\n case 'by_quantity_range':\n case 'by_position_range':\n html = '' + this.escapeHtml(trans.help_range_title || 'Numeric Range') + '';\n html += '
' + this.escapeHtml(trans.help_range_desc || 'Filter by numeric values within specified ranges.') + '
';\n html += '
' + this.escapeHtml(trans.help_range_tip || 'Leave min or max empty for open-ended ranges.') + '
';\n break;\n\n case 'by_date_added':\n case 'by_date_updated':\n html = '' + this.escapeHtml(trans.help_date_title || 'Date Range') + '';\n html += '
' + this.escapeHtml(trans.help_date_desc || 'Filter by date within a specific period.') + '
';\n break;\n\n default:\n break;\n }\n\n return html;\n },\n\n /**\n * Build sort options HTML for a specific block type\n */\n buildSortOptions: function(blockType) {\n var options = [];\n\n switch (blockType) {\n case 'products':\n options = [\n { value: 'sales', label: 'Best sellers' },\n { value: 'date_add', label: 'Newest' },\n { value: 'price', label: 'Price' },\n { value: 'name', label: 'Name' },\n { value: 'position', label: 'Position' },\n { value: 'quantity', label: 'Stock quantity' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n case 'categories':\n options = [\n { value: 'name', label: 'Name' },\n { value: 'position', label: 'Position' },\n { value: 'product_count', label: 'Product count' },\n { value: 'total_sales', label: 'Best sellers' },\n { value: 'newest_products', label: 'Newest products' },\n { value: 'date_add', label: 'Creation date' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n case 'manufacturers':\n case 'suppliers':\n options = [\n { value: 'name', label: 'Name' },\n { value: 'product_count', label: 'Product count' },\n { value: 'total_sales', label: 'Best sellers' },\n { value: 'newest_products', label: 'Newest products' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n case 'cms':\n case 'cms_categories':\n options = [\n { value: 'name', label: 'Name' },\n { value: 'position', label: 'Position' },\n { value: 'random', label: 'Random' }\n ];\n break;\n\n default:\n options = [\n { value: 'name', label: 'Name' },\n { value: 'random', label: 'Random' }\n ];\n }\n\n var html = '';\n for (var i = 0; i < options.length; i++) {\n html += '';\n }\n\n return html;\n },\n\n /**\n * Update the modifier toggle button state\n */\n updateModifierButtonState: function($group) {\n var limit = $group.find('.group-modifier-limit').val();\n var sortBy = $group.find('.group-modifier-sort').val();\n var $modifiers = $group.find('.group-modifiers');\n var $btn = $group.find('.btn-toggle-modifiers');\n var trans = this.config.trans || {};\n\n $btn.find('.modifier-summary').remove();\n\n if (limit || sortBy) {\n $modifiers.addClass('has-values');\n\n var summary = [];\n if (limit) {\n summary.push((trans.top || 'Top') + ' ' + limit);\n }\n if (sortBy) {\n var sortLabel = $group.find('.group-modifier-sort option:selected').text();\n summary.push(sortLabel);\n }\n\n var $arrow = $btn.find('.toggle-arrow');\n $('' + this.escapeHtml(summary.join(', ')) + '').insertBefore($arrow);\n } else {\n $modifiers.removeClass('has-values');\n }\n },\n\n /**\n * Lock/unlock method selector when excludes are present\n */\n updateMethodSelectorLock: function($group, locked) {\n var $select = $group.find('.include-method-select');\n var $wrapper = $select.closest('.method-selector-wrapper');\n var trans = this.config.trans || {};\n\n if (locked) {\n $select.prop('disabled', true);\n\n if (!$wrapper.length) {\n $select.wrap('');\n $wrapper = $select.parent('.method-selector-wrapper');\n }\n\n $wrapper.addClass('selector-locked');\n if (!$wrapper.find('.mpr-info-wrapper').length) {\n var lockHtml = '' +\n '' +\n '' +\n (trans.remove_excludes_first || 'Remove all exceptions to change selection type') +\n '' +\n '';\n var $countEl = $wrapper.find('.condition-match-count');\n if ($countEl.length) {\n $countEl.before(lockHtml);\n } else {\n $wrapper.append(lockHtml);\n }\n }\n } else {\n $select.prop('disabled', false);\n if ($wrapper.length) {\n $wrapper.removeClass('selector-locked');\n $wrapper.find('.mpr-info-wrapper.lock-indicator').remove();\n } else {\n $select.siblings('.mpr-info-wrapper.lock-indicator').remove();\n }\n }\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Preview Module\n * Preview popover and pattern preview modal\n * @partial _preview.js\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 2906-2942 (updateHeaderTotalCount, updateShowAllToggle)\n * 2943-3051 (showPreviewPopover)\n * 3053-3076 (renderPreviewItems)\n * 3078-3100 (filterPreviewItems)\n * 3102-3183 (loadMorePreviewItems)\n * 3185-3194 (hidePreviewPopover)\n * 3196-3287 (showPatternPreviewModal)\n * 3289-3400 (refreshGroupPreviewIfOpen) - estimated\n * 7592-7700 (showReplaceConfirmation, getCurrentSingleSelection)\n * 7703-7745 (getBlockMode, isBlockSingleMode)\n *\n * Contains:\n * - showPreviewPopover() - Show tab count preview\n * - hidePreviewPopover() - Close preview popover\n * - renderPreviewItems() - Render item list in preview\n * - filterPreviewItems() - Filter preview items by query\n * - loadMorePreviewItems() - Load additional preview items\n * - showPatternPreviewModal() - Pattern match preview modal\n * - refreshGroupPreviewIfOpen() - Refresh preview if open\n * - updateHeaderTotalCount() - Update header total badge\n * - updateShowAllToggle() - Update show-all checkbox state\n * - showReplaceConfirmation() - Single mode replace dialog\n * - getCurrentSingleSelection() - Get current selection in single mode\n * - getBlockMode() - Get block selection mode\n * - isBlockSingleMode() - Check if block is single-select\n * - getEntityTypeLabel() - Get human-readable entity label\n */\n\n(function($) {\n 'use strict';\n\n window._EntitySelectorMixins = window._EntitySelectorMixins || {};\n\n window._EntitySelectorMixins.preview = {\n\n updateHeaderTotalCount: function() {\n var self = this;\n var total = 0;\n\n this.$wrapper.find('.target-block-tab .tab-badge').each(function() {\n var $badge = $(this);\n if (!$badge.hasClass('loading')) {\n var count = parseInt($badge.text(), 10);\n if (!isNaN(count)) {\n total += count;\n }\n }\n });\n\n var $totalBadge = this.$wrapper.find('.trait-total-count');\n if (total > 0) {\n $totalBadge.text(total).show();\n } else {\n $totalBadge.hide();\n }\n\n this.updateShowAllToggle();\n },\n\n updateShowAllToggle: function() {\n var $toggle = this.$wrapper.find('.trait-show-all-toggle');\n if (!$toggle.length) return;\n\n var $checkbox = $toggle.find('.show-all-checkbox');\n var hasData = this.$wrapper.find('.target-block-tab.has-data').length > 0;\n\n $checkbox.prop('checked', !hasData);\n },\n\n showPreviewPopover: function($tab) {\n var previewData = $tab.data('previewData');\n if (!previewData) {\n return;\n }\n\n this.hidePreviewPopover();\n\n var $badge = $tab.find('.tab-badge');\n $badge.addClass('popover-open');\n this.$activeBadge = $badge;\n var items = previewData.items || previewData.products || [];\n this.previewLoadedCount = items.length;\n this.previewBlockType = $tab.data('blockType');\n\n var blockType = this.previewBlockType;\n var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n\n var trans = this.config.trans || {};\n var html = '
';\n\n html += '
';\n html += '' + previewData.count + ' ' + entityLabelPlural + ' ' + (trans.items_matched || 'matched') + '';\n html += '';\n html += '
';\n\n html += '
';\n html += '';\n html += '
';\n\n if (items.length > 0) {\n html += '
';\n html += this.renderPreviewItems(items);\n html += '
';\n\n if (previewData.hasMore) {\n var remaining = previewData.count - items.length;\n html += '';\n }\n } else {\n html += '
' + (trans.no_preview || 'No items to preview') + '
';\n }\n\n html += '
';\n\n var $popover = $(html);\n $('body').append($popover);\n\n this.$previewList = $popover.find('.preview-list');\n this.allPreviewData = previewData;\n\n var self = this;\n $popover.find('.preview-close').on('click', function() {\n self.hidePreviewPopover();\n });\n\n $popover.find('.preview-filter-input').on('input', function() {\n var query = $(this).val().toLowerCase().trim();\n self.filterPreviewItems(query);\n });\n\n $popover.find('.btn-load-more-preview').on('click', function() {\n self.loadMorePreviewItems($tab, $(this));\n });\n\n var badgeOffset = $badge.offset();\n var badgeHeight = $badge.outerHeight();\n var badgeWidth = $badge.outerWidth();\n var popoverWidth = $popover.outerWidth();\n\n var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);\n var minLeft = 10;\n var maxLeft = $(window).width() - popoverWidth - 10;\n leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));\n\n $popover.css({\n position: 'absolute',\n top: badgeOffset.top + badgeHeight + 8,\n left: leftPos,\n zIndex: 10000\n });\n\n // Add show class to trigger visibility\n $popover.addClass('show');\n\n this.$previewPopover = $popover;\n },\n\n renderPreviewItems: function(products) {\n var html = '';\n $.each(products, function(i, product) {\n var itemClass = 'preview-item' + (product.isCombination ? ' is-combination' : '');\n var attrs = (product.attributes || '').toLowerCase();\n html += '
';\n if (product.image) {\n html += '';\n } else {\n html += '';\n }\n html += '
';\n html += '' + product.name + '';\n if (product.attributes) {\n html += '' + product.attributes + '';\n }\n if (product.reference) {\n html += '' + product.reference + '';\n }\n html += '
';\n html += '
';\n });\n return html;\n },\n\n filterPreviewItems: function(query) {\n if (!this.$previewList) return;\n\n var $items = this.$previewList.find('.preview-item');\n\n if (!query) {\n $items.show();\n return;\n }\n\n $items.each(function() {\n var $item = $(this);\n var name = $item.data('name') || '';\n var ref = $item.data('ref') || '';\n var attrs = $item.data('attrs') || '';\n\n if (name.indexOf(query) !== -1 || ref.indexOf(query) !== -1 || attrs.indexOf(query) !== -1) {\n $item.show();\n } else {\n $item.hide();\n }\n });\n },\n\n loadMorePreviewItems: function($tab, $btn) {\n var self = this;\n var blockType = this.previewBlockType;\n\n var $footer = $btn.closest('.preview-footer');\n var $select = $footer.find('.load-more-select');\n var loadCount = parseInt($select.val(), 10) || 20;\n\n var $hiddenInput = this.$wrapper.find('input[name=\"' + this.config.name + '\"]');\n var savedData = {};\n try {\n savedData = JSON.parse($hiddenInput.val() || '{}');\n } catch (e) {\n return;\n }\n\n var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];\n if (groups.length === 0) return;\n\n var data = {};\n data[blockType] = { groups: groups };\n\n $btn.prop('disabled', true).find('i').removeClass('icon-plus').addClass('icon-spinner icon-spin');\n $select.prop('disabled', true);\n\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewTargetConditions',\n trait: 'TargetConditions',\n conditions: JSON.stringify(data),\n block_type: blockType,\n limit: self.previewLoadedCount + loadCount,\n offset: 0\n },\n success: function(response) {\n var items = response.items || response.products || [];\n if (response.success && items.length > 0) {\n self.$previewList.html(self.renderPreviewItems(items));\n self.previewLoadedCount = items.length;\n\n if (response.hasMore) {\n var remaining = response.count - items.length;\n $footer.find('.remaining-count').text(remaining);\n\n var $allOption = $select.find('option:last');\n if ($allOption.val() !== '10' && $allOption.val() !== '20' && $allOption.val() !== '50' && $allOption.val() !== '100') {\n $allOption.val(remaining).text(self.config.trans.all + ' (' + remaining + ')');\n }\n\n $btn.prop('disabled', false).find('i').removeClass('icon-spinner icon-spin').addClass('icon-plus');\n $select.prop('disabled', false);\n } else {\n $footer.remove();\n }\n\n $tab.data('previewData', response);\n self.allPreviewData = response;\n\n var filterQuery = self.$previewPopover.find('.preview-filter-input').val();\n if (filterQuery) {\n self.filterPreviewItems(filterQuery.toLowerCase().trim());\n }\n }\n },\n error: function() {\n $btn.prop('disabled', false).find('i').removeClass('icon-spinner icon-spin').addClass('icon-plus');\n $select.prop('disabled', false);\n }\n });\n },\n\n hidePreviewPopover: function() {\n if (this.$activeBadge) {\n this.$activeBadge.removeClass('popover-open');\n this.$activeBadge = null;\n }\n if (this.$previewPopover) {\n this.$previewPopover.remove();\n this.$previewPopover = null;\n }\n },\n\n showPatternPreviewModal: function(pattern, entityType, caseSensitive, count) {\n var self = this;\n var trans = this.config.trans || {};\n\n var blockConfig = this.config.blocks && this.config.blocks[entityType] ? this.config.blocks[entityType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n var entityLabelSingular = blockConfig.entity_label || 'item';\n\n var html = '
';\n html += '
';\n html += '
';\n html += '';\n html += ' ' + (trans.preview || 'Preview') + ': ' + this.escapeHtml(pattern) + '';\n html += '';\n html += '' + count + ' ' + (count === 1 ? entityLabelSingular : entityLabelPlural) + '';\n html += '';\n html += '
');\n }\n });\n },\n\n refreshGroupPreviewIfOpen: function($group) {\n var self = this;\n\n if (!this.$activeBadge || !this.$previewPopover) {\n return;\n }\n\n // Check if preview is for this group and refresh if needed\n },\n\n /**\n * Show preview popover for condition match count badge\n */\n showConditionPreviewPopover: function($badge) {\n var self = this;\n var conditionData = $badge.data('conditionData');\n\n if (!conditionData) {\n return;\n }\n\n this.hidePreviewPopover();\n\n $badge.addClass('popover-open loading');\n this.$activeBadge = $badge;\n\n var trans = this.config.trans || {};\n var blockType = conditionData.blockType || 'products';\n var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n\n // Fetch preview items from backend\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewConditionItems',\n trait: 'EntitySelector',\n method: conditionData.method,\n values: JSON.stringify(conditionData.values),\n block_type: blockType,\n limit: 10\n },\n success: function(response) {\n $badge.removeClass('loading');\n\n if (response.success) {\n var items = response.items || [];\n self.showItemsPopover($badge, items, response.count, response.hasMore, entityLabelPlural, blockType, 'condition');\n }\n },\n error: function() {\n $badge.removeClass('loading popover-open');\n self.$activeBadge = null;\n }\n });\n },\n\n /**\n * Show preview popover for group count badge\n */\n showGroupPreviewPopover: function($badge, $group, blockType) {\n var self = this;\n\n // If $group not passed, try to find it\n if (!$group) {\n $group = $badge.closest('.selection-group');\n }\n\n if (!blockType) {\n var $block = $badge.closest('.target-block');\n blockType = $block.data('blockType') || 'products';\n }\n\n var groupData = $badge.data('groupData');\n\n if (!groupData) {\n // Try to serialize from DOM\n groupData = this.serializeGroup($group, blockType);\n }\n\n if (!groupData || !groupData.include) {\n return;\n }\n\n this.hidePreviewPopover();\n\n $badge.addClass('popover-open loading');\n this.$activeBadge = $badge;\n\n var trans = this.config.trans || {};\n var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};\n var entityLabelPlural = blockConfig.entity_label_plural || 'items';\n\n // Fetch preview items from backend\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewGroupItems',\n trait: 'EntitySelector',\n group_data: JSON.stringify(groupData),\n block_type: blockType,\n limit: 10\n },\n success: function(response) {\n $badge.removeClass('loading');\n\n if (response.success) {\n var items = response.items || [];\n self.showItemsPopover($badge, items, response.count, response.hasMore, entityLabelPlural, blockType, 'group');\n } else {\n $badge.removeClass('popover-open');\n self.$activeBadge = null;\n }\n },\n error: function() {\n $badge.removeClass('loading popover-open');\n self.$activeBadge = null;\n }\n });\n },\n\n /**\n * Common popover display for both condition and group previews\n */\n showItemsPopover: function($badge, items, totalCount, hasMore, entityLabel, blockType, previewType) {\n var self = this;\n var trans = this.config.trans || {};\n\n var html = '
';\n\n html += '
';\n html += '' + totalCount + ' ' + entityLabel + '';\n html += '';\n html += '
';\n\n if (items.length > 0) {\n html += '
';\n html += this.renderPreviewItems(items);\n html += '
';\n\n if (hasMore) {\n var remaining = totalCount - items.length;\n html += '';\n }\n } else {\n html += '
' + (trans.no_preview || 'No items to preview') + '
';\n }\n\n html += '
';\n\n var $popover = $(html);\n $('body').append($popover);\n\n $popover.find('.preview-close').on('click', function() {\n self.hidePreviewPopover();\n });\n\n // Position popover below badge\n var badgeOffset = $badge.offset();\n var badgeHeight = $badge.outerHeight();\n var badgeWidth = $badge.outerWidth();\n var popoverWidth = $popover.outerWidth();\n\n var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);\n var minLeft = 10;\n var maxLeft = $(window).width() - popoverWidth - 10;\n leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));\n\n var topPos = badgeOffset.top + badgeHeight + 8;\n\n $popover.css({\n position: 'absolute',\n top: topPos,\n left: leftPos,\n zIndex: 10000\n });\n\n // Add show class for CSS transition\n $popover.addClass('show');\n\n this.$previewPopover = $popover;\n },\n\n /**\n * Render preview items HTML\n */\n renderPreviewItems: function(items) {\n var html = '';\n\n for (var i = 0; i < items.length; i++) {\n var item = items[i];\n html += '
';\n\n // Image or icon\n if (item.image) {\n html += '';\n } else {\n html += '
inventory_2
';\n }\n\n // Info\n html += '
';\n html += '
' + this.escapeHtml(item.name || 'Unnamed') + '
';\n\n var meta = [];\n if (item.reference) {\n meta.push('Ref: ' + item.reference);\n }\n if (item.manufacturer) {\n meta.push(item.manufacturer);\n }\n if (item.category) {\n meta.push(item.category);\n }\n if (item.attributes) {\n meta.push(item.attributes);\n }\n\n if (meta.length > 0) {\n html += '
' + this.escapeHtml(meta.join(' • ')) + '
';\n }\n\n html += '
';\n\n // Price or status\n if (typeof item.price !== 'undefined') {\n html += '
' + this.formatPrice(item.price) + '
';\n }\n if (typeof item.active !== 'undefined' && !item.active) {\n html += 'Inactive';\n }\n\n html += '
';\n }\n\n return html;\n },\n\n /**\n * Format price for display\n */\n formatPrice: function(price) {\n if (typeof price !== 'number') {\n price = parseFloat(price) || 0;\n }\n return price.toFixed(2) + ' €';\n },\n\n /**\n * Show preview popover for filter group toggle (attribute/feature groups)\n */\n showFilterGroupPreviewPopover: function($badge, groupId, groupType, groupName) {\n var self = this;\n\n this.hidePreviewPopover();\n\n $badge.addClass('popover-open loading');\n this.$activeBadge = $badge;\n\n var trans = this.config.trans || {};\n var entityLabelPlural = 'products';\n\n // Fetch products matching this attribute/feature group\n $.ajax({\n url: this.config.ajaxUrl,\n type: 'POST',\n dataType: 'json',\n data: {\n ajax: 1,\n action: 'previewFilterGroupProducts',\n trait: 'EntitySelector',\n group_id: groupId,\n group_type: groupType,\n limit: 10\n },\n success: function(response) {\n $badge.removeClass('loading');\n\n if (response.success) {\n var items = response.items || [];\n var totalCount = response.count || 0;\n var hasMore = response.hasMore || false;\n\n self.showFilterGroupItemsPopover($badge, items, totalCount, hasMore, entityLabelPlural, groupName, groupType);\n } else {\n $badge.removeClass('popover-open');\n self.$activeBadge = null;\n }\n },\n error: function() {\n $badge.removeClass('loading popover-open');\n self.$activeBadge = null;\n }\n });\n },\n\n /**\n * Show popover for filter group preview items\n */\n showFilterGroupItemsPopover: function($badge, items, totalCount, hasMore, entityLabel, groupName, groupType) {\n var self = this;\n var trans = this.config.trans || {};\n\n var typeLabel = groupType === 'attribute' ? (trans.attribute || 'Attribute') : (trans.feature || 'Feature');\n var html = '
';\n\n html += '
';\n html += '' + totalCount + ' ' + entityLabel + '';\n html += '';\n html += '
';\n\n if (items.length > 0) {\n html += '
';\n html += this.renderPreviewItems(items);\n html += '
';\n\n if (hasMore) {\n var remaining = totalCount - items.length;\n html += '';\n }\n } else {\n html += '
' + (trans.no_preview || 'No items to preview') + '
';\n }\n\n html += '
';\n\n var $popover = $(html);\n $('body').append($popover);\n\n $popover.find('.preview-close').on('click', function() {\n self.hidePreviewPopover();\n });\n\n // Position popover below badge\n var badgeOffset = $badge.offset();\n var badgeHeight = $badge.outerHeight();\n var badgeWidth = $badge.outerWidth();\n var popoverWidth = $popover.outerWidth();\n\n var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);\n var minLeft = 10;\n var maxLeft = $(window).width() - popoverWidth - 10;\n leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));\n\n var topPos = badgeOffset.top + badgeHeight + 8;\n\n $popover.css({\n position: 'absolute',\n top: topPos,\n left: leftPos,\n zIndex: 10000\n });\n\n $popover.addClass('show');\n\n this.$previewPopover = $popover;\n }\n };\n\n})(jQuery);\n","/**\n * Entity Selector - Core Module\n * Factory, initialization, state management\n * @partial _core.js\n *\n * IMPORTANT: This file must be loaded LAST in the concatenation order\n * as it combines all mixins from other partials.\n *\n * EXTRACTION SOURCE: assets/js/admin/entity-selector.js\n * Lines: 15-55 (createTargetConditionsInstance, state variables)\n * 56-110 (init method)\n * 108-132 (observeNewSelects)\n * 7889-7951 (Factory object, window export, document ready)\n *\n * Contains:\n * - createTargetConditionsInstance() - Factory function\n * - State variable initialization\n * - init() - Main initialization method\n * - observeNewSelects() - MutationObserver for dynamic selects\n * - loadExistingSelections() - Restore saved state\n * - TargetConditions factory object\n * - window.TargetConditions export\n * - Document ready auto-initialization\n */\n\n(function($) {\n 'use strict';\n\n /**\n * Create a new TargetConditions instance\n * Each instance is independent and manages its own wrapper/state\n */\n function createTargetConditionsInstance() {\n // Base instance object with state variables\n var instance = {\n config: {},\n $wrapper: null,\n $dropdown: null,\n activeGroup: null, // { blockType, groupIndex, section: 'include'|'exclude' }\n searchTimeout: null,\n searchResults: [],\n searchTotal: 0,\n searchOffset: 0,\n searchQuery: '',\n isLoading: false,\n loadMoreCount: 20,\n // Sort, filter, view state\n viewMode: 'list',\n currentSort: { field: 'name', dir: 'ASC' },\n refineQuery: '',\n refineNegate: false,\n filters: {\n inStock: false,\n discounted: false,\n priceMin: null,\n priceMax: null,\n attributes: [],\n features: []\n },\n filterableData: null,\n // Search history\n searchHistory: {},\n searchHistoryMax: 10,\n searchHistoryKey: 'targetConditionsSearchHistory',\n // Chips visibility\n maxVisibleChips: 20,\n // Method dropdown references\n $methodDropdownMenu: null,\n $methodDropdownSelect: null,\n $methodDropdownTrigger: null,\n // Preview state\n $previewPopover: null,\n $activeBadge: null,\n $previewList: null,\n previewLoadedCount: 0,\n previewBlockType: null,\n allPreviewData: null,\n // Count update timeout\n countUpdateTimeout: null,\n\n init: function(options) {\n this.config = $.extend({\n id: 'target-conditions',\n name: 'target_conditions',\n namePrefix: 'target_',\n mode: 'multi', // Global mode: 'multi' or 'single'\n blocks: {},\n ajaxUrl: '',\n trans: {}\n }, options);\n\n this.$wrapper = $('[data-entity-selector-id=\"' + this.config.id + '\"]');\n\n if (!this.$wrapper.length) {\n return;\n }\n\n // Global single mode - hide \"Add Group\" buttons\n if (this.config.mode === 'single') {\n this.$wrapper.find('.btn-add-group').hide();\n this.$wrapper.find('.group-excludes').hide();\n this.$wrapper.find('.group-modifiers').hide();\n }\n\n // Add fullwidth class to parent form-group\n var $formGroup = this.$wrapper.closest('.form-group');\n $formGroup.addClass('condition-trait-fullwidth');\n $formGroup.find('.col-lg-offset-3').removeClass('col-lg-offset-3');\n\n this.createDropdown();\n this.bindEvents();\n this.loadExistingSelections();\n this.loadSearchHistory();\n\n // Initialize styled method dropdowns\n this.initMethodDropdowns();\n\n // Watch for dynamically added selects\n this.observeNewSelects();\n\n // Update counts on page load\n var self = this;\n setTimeout(function() {\n self.updateTabBadges();\n self.updateAllConditionCounts();\n }, 100);\n },\n\n observeNewSelects: function() {\n var self = this;\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(mutation) {\n if (mutation.addedNodes.length) {\n $(mutation.addedNodes).find('.include-method-select, .exclude-method-select').each(function() {\n self.enhanceMethodSelect($(this));\n });\n }\n });\n });\n\n observer.observe(this.$wrapper[0], {\n childList: true,\n subtree: true\n });\n },\n\n loadExistingSelections: function() {\n // TODO: Extract full implementation from original\n // Reads JSON from hidden input and populates chips\n }\n };\n\n // Merge all mixins into the instance\n // Each mixin adds its methods to window._EntitySelectorMixins\n var mixins = window._EntitySelectorMixins || {};\n\n // Merge utils mixin\n if (mixins.utils) {\n $.extend(instance, mixins.utils);\n }\n\n // Merge events mixin\n if (mixins.events) {\n $.extend(instance, mixins.events);\n }\n\n // Merge dropdown mixin\n if (mixins.dropdown) {\n $.extend(instance, mixins.dropdown);\n }\n\n // Merge search mixin\n if (mixins.search) {\n $.extend(instance, mixins.search);\n }\n\n // Merge filters mixin\n if (mixins.filters) {\n $.extend(instance, mixins.filters);\n }\n\n // Merge chips mixin\n if (mixins.chips) {\n $.extend(instance, mixins.chips);\n }\n\n // Merge groups mixin\n if (mixins.groups) {\n $.extend(instance, mixins.groups);\n }\n\n // Merge methods mixin\n if (mixins.methods) {\n $.extend(instance, mixins.methods);\n }\n\n // Merge preview mixin\n if (mixins.preview) {\n $.extend(instance, mixins.preview);\n }\n\n return instance;\n }\n\n // Factory object for creating and managing instances\n var TargetConditions = {\n instances: [],\n\n // Create and initialize a new instance\n create: function(options) {\n var instance = createTargetConditionsInstance();\n instance.init(options);\n this.instances.push(instance);\n return instance;\n },\n\n // For backwards compatibility - init creates a new instance\n init: function(options) {\n return this.create(options);\n },\n\n // Validate all instances - returns true if all valid\n validateAll: function() {\n var allValid = true;\n for (var i = 0; i < this.instances.length; i++) {\n if (!this.instances[i].validate()) {\n allValid = false;\n }\n }\n return allValid;\n }\n };\n\n // Export to window\n window.TargetConditions = TargetConditions;\n\n // Auto-initialize on document ready\n $(document).ready(function() {\n // Auto-initialize from data-config attributes on wrapper elements\n $('[data-entity-selector-id]').each(function() {\n var configData = $(this).data('config');\n if (configData) {\n TargetConditions.create(configData);\n }\n });\n\n // Tips box toggle handler\n $(document).on('click', '.target-tips-box .tips-header', function(e) {\n e.preventDefault();\n $(this).closest('.target-tips-box').toggleClass('expanded');\n });\n\n // Form submission validation for required target conditions\n $(document).on('submit', 'form', function(e) {\n var $form = $(this);\n if ($form.find('.target-conditions-trait[data-required]').length > 0) {\n if (!TargetConditions.validateAll()) {\n e.preventDefault();\n return false;\n }\n }\n });\n });\n\n})(jQuery);\n"]}
\ No newline at end of file
diff --git a/sources/js/admin/entity-selector/_events.js b/sources/js/admin/entity-selector/_events.js
index c7e8d8e..8964b2e 100644
--- a/sources/js/admin/entity-selector/_events.js
+++ b/sources/js/admin/entity-selector/_events.js
@@ -1566,6 +1566,10 @@
// Toggle filter group - show values
this.$dropdown.on('click', '.filter-group-toggle', function(e) {
+ // Ignore clicks on the preview badge
+ if ($(e.target).closest('.toggle-count.clickable').length) {
+ return;
+ }
e.preventDefault();
var $btn = $(this);
var groupId = $btn.data('group-id');