1<#assign facetId = "facet-" + cpSpecificationOptionsSearchFacetDisplayContext.getParameterName() + "-" + renderResponse.getNamespace() />
2
3<#if !(.globals["rendered_${facetId}"])??>
4 <#global rendered_${facetId} = true />
5
6<#-- Variables -->
7
8 <#assign facetClass = "facet-ctn-combo-search-wrapper" />
9 <#assign paramName = cpSpecificationOptionsSearchFacetDisplayContext.getParameterName() />
10 <#assign isDebug = true />
11
12 <#-- ========================= -->
13 <#-- TOM SELECT framework -->
14 <#-- ========================= -->
15 <@liferay_util["html-top"] outputKey="tom-select">
16 <link href="https://cdn.jsdelivr.net/npm/tom-select@2.6.1/dist/css/tom-select.css" rel="stylesheet">
17 <script src="https://cdn.jsdelivr.net/npm/tom-select@2.6.1/dist/js/tom-select.complete.min.js"></script>
18 </@>
19
20 <#-- ========================= -->
21 <#-- CSS -->
22 <#-- ========================= -->
23 <style>
24
25 /* ===========================
26 Variables de fuente compartidas
27 =========================== */
28 #${facetId} {
29 --ctn-font-family: Inter;
30 --ctn-font-size: 14px;
31 --ctn-font-weight: 400;
32 --ctn-line-height: 18px;
33 --ctn-letter-spacing: 0.5px;
34 --ctn-color: #66757f;
35 }
36
37 /* ===========================
38 Select original — oculto desde el inicio
39 =========================== */
40 #${facetId}-select {
41 appearance: none;
42 -webkit-appearance: none;
43 visibility: hidden;
44 position: absolute;
45 }
46
47 /* ===========================
48 TomSelect — wrapper oculto hasta inicializar
49 =========================== */
50 #${facetId} .ts-wrapper {
51 width: 100%;
52 margin-bottom: 16px;
53 opacity: 0;
54 transition: opacity 0.1s ease;
55 }
56
57 #${facetId} .ts-wrapper .ts-control {
58 padding: 15.5px 16px;
59 font-family: var(--ctn-font-family);
60 font-size: var(--ctn-font-size);
61 font-weight: var(--ctn-font-weight);
62 line-height: var(--ctn-line-height);
63 letter-spacing: var(--ctn-letter-spacing);
64 color: var(--ctn-color);
65 text-align: left;
66 height: 55px;
67 width: 100%;
68 border-radius: 4px;
69 border: none;
70 background-color: #F5F5F5;
71 background-image: url(/documents/d/global/ico-chevron-down-2);
72 background-repeat: no-repeat;
73 background-position: right 1rem center;
74 background-size: 18px 10px;
75 box-shadow: none;
76 cursor: pointer;
77 box-sizing: border-box;
78 }
79
80 #${facetId} .ts-wrapper .ts-control:focus,
81 #${facetId} .ts-wrapper .ts-control:focus-visible {
82 background-image: url(/documents/d/global/ico-chevron-down-2);
83 background-position: right 1rem center;
84 background-size: 18px 10px;
85 outline: none;
86 box-shadow: none;
87 }
88
89 #${facetId} .ts-wrapper .ts-control .item {
90 padding-right: 0.75rem;
91 overflow: hidden;
92 text-overflow: ellipsis;
93 max-width: calc(100% - 0.75rem);
94 }
95
96 /* Ocultar flecha nativa de TomSelect */
97 #${facetId} .ts-wrapper.single .ts-control::after {
98 display: none;
99 }
100
101 /* Input de búsqueda del dropdown */
102 #${facetId} .ts-dropdown .dropdown-input-wrap .dropdown-input {
103 font-family: var(--ctn-font-family);
104 font-size: var(--ctn-font-size);
105 font-weight: var(--ctn-font-weight);
106 line-height: var(--ctn-line-height);
107 letter-spacing: var(--ctn-letter-spacing);
108 color: var(--ctn-color);
109 padding: 8px 16px;
110 border: none;
111 border-bottom: 1px solid #d9d9d9;
112 background-color: #fff;
113 width: 100%;
114 box-sizing: border-box;
115 }
116
117 #${facetId} .ts-dropdown .dropdown-input-wrap .dropdown-input:focus {
118 outline: none;
119 box-shadow: none;
120 }
121
122 /* Opciones del dropdown */
123 #${facetId} .ts-dropdown .ts-dropdown-content .option {
124 font-family: var(--ctn-font-family);
125 font-size: var(--ctn-font-size);
126 font-weight: var(--ctn-font-weight);
127 line-height: var(--ctn-line-height);
128 letter-spacing: var(--ctn-letter-spacing);
129 color: var(--ctn-color);
130 padding: 8px 16px;
131 }
132
133 #${facetId} .ts-dropdown .ts-dropdown-content .option:hover,
134 #${facetId} .ts-dropdown .ts-dropdown-content .option.active {
135 background-color: #6a9bd3;
136 color: #fff;
137 }
138
139 </style>
140
141 <div class="checks-container ${facetClass}" id="${facetId}">
142 <div class="d-flex flex-column w-100">
143 <label class="panel-title mb-2" for="${facetId}-select">
144 ${languageUtil.get(locale, "norma.ctn")}
145 <#if isDebug>
146 <span class="ml-2 font-weight-bold" style="font-size:11px;color:#999;font-weight:normal;">
147 (total options: ${entries?size})
148 </span>
149 </#if>
150 </label>
151
152 <#-- ========================= -->
153 <#-- SELECT UI -->
154 <#-- ========================= -->
155 <select id="${facetId}-select" data-parameter-name="${paramName}">
156 <option value="">${languageUtil.get(locale, "search.cualquiera")}</option>
157 <#list entries?sort_by("displayName") as entry>
158 <option value="${htmlUtil.escape(entry.getDisplayName())}"
159 <#if entry.isSelected()>selected</#if>>
160 ${htmlUtil.escape(entry.getDisplayName())} (${entry.getFrequency()})
161 </option>
162 </#list>
163 </select>
164 </div>
165 </div>
166
167 <#-- ========================= -->
168 <#-- SCRIPT -->
169 <#-- ========================= -->
170 <script>
171
172 (function () {
173 var FACET_ID = '${facetId}';
174 var PARAM_NAME = '${paramName}';
175
176 console.log("FACET_ID:", FACET_ID);
177
178 function applyUrlFilter(value) {
179 var url = new URL(window.location.href);
180 if (value) {
181 url.searchParams.set(PARAM_NAME, value);
182 } else {
183 url.searchParams.delete(PARAM_NAME);
184 }
185 window.location.href = url.toString();
186 }
187
188 function initFacet() {
189 var select = document.getElementById(FACET_ID + '-select');
190 if (!select) return;
191
192 if (select.tomselect) select.tomselect.destroy();
193 if (select.dataset.bound === 'true') return;
194 select.dataset.bound = 'true';
195
196 new TomSelect(select, {
197 allowEmptyOption: true,
198 maxItems: 1,
199 create: false,
200 render: {
201 no_results: function(data, escape) {
202 return '<div class="no-results">${languageUtil.get(locale, "occurrence-not-found")}</div>';
203 }
204 },
205 plugins: {
206 dropdown_input: {}
207 },
208 onDelete: function(value) {
209 this.isDelete = true;
210 },
211 onChange: function(value) {
212 if (value) {
213 this.lastValidValue = value;
214 applyUrlFilter(value);
215 return;
216 }
217 this.lastValidValue = '';
218 applyUrlFilter('');
219 },
220 onInitialize: function() {
221 this.lastValidValue = this.getValue() || '';
222 this.isDelete = false;
223 // Mostrar wrapper cuando TomSelect está listo
224 var wrapper = document.querySelector('#' + FACET_ID + ' .ts-wrapper');
225 if (wrapper) wrapper.style.opacity = '1';
226 }
227 });
228 }
229
230 if (document.readyState === 'loading') {
231 document.addEventListener('DOMContentLoaded', initFacet);
232 } else {
233 initFacet();
234 }
235 })();
236
237 </script>
238
239 </#if>