Festività
Si è verificato un errore nell'elaborarazione del modello.
The following has evaluated to null or missing: ==> curExtraSearchField.inputAspect [in template "20097#20123#76602" at line 108, column 94] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: #if curExtraSearchField.inputAspect =... [in template "20097#20123#76602" at line 108, column 89] - Reached through: @ricerca_components["ricerca-form"] s... [in template "20097#20123#76602" at line 58, column 33] ----
1<#-- instance id -->
2<#assign instanceId = themeDisplay.getPortletDisplay().getId()?keep_after("INSTANCE_") />
3
4<#-- Ricavo servizi utili in seguito -->
5<#-- Servizio per i layout di pagina -->
6<#assign layoutLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.LayoutLocalService") />
7<#-- Servizio utile per ricavare i documenti della DM -->
8<#assign dlFileEntryLocalService = serviceLocator.findService('com.liferay.document.library.kernel.service.DLFileEntryLocalService') />
9
10<#-- Etichette -->
11<#-- eventi -->
12<#assign label_eventi = languageUtil.get(locale, "label_eventi") />
13<#assign label_evento = languageUtil.get(locale, "label_evento") />
14<#assign ricerca_extra_field_place = languageUtil.get(locale, "ricerca_extra_field_place") />
15<#assign ricerca_extra_field_place_placeholder = languageUtil.get(locale, "ricerca_extra_field_place_placeholder") />
16<#-- generiche -->
17<#assign label_filtro_cosa = languageUtil.get(locale, "label_filtro_cosa") />
18<#assign label_placeholder_filtro_cosa = languageUtil.get(locale, "label_placeholder_filtro_cosa") />
19<#assign label_filtro_quando = languageUtil.get(locale, "label_filtro_quando") />
20<#assign label_placeholder_filtro_quando = languageUtil.get(locale, "label_placeholder_filtro_quando") />
21<#assign label_button_cerca = languageUtil.get(locale, "label_button_cerca") />
22<#assign label_button_cerca_su_mappa = languageUtil.get(locale, "label_button_cerca_su_mappa") />
23<#assign label_categorie = languageUtil.get(locale, "label_categorie") />
24<#assign label_seleziona = languageUtil.get(locale, "label_seleziona") />
25<#assign label_data_dal = languageUtil.get(locale, "label_data_dal") />
26<#assign label_data_al = languageUtil.get(locale, "label_data_al") />
27<#assign label_cambia_data = languageUtil.get(locale, "label_cambia_data") />
28<#assign label_vai_dettaglio = languageUtil.get(locale, "label_vai_dettaglio") />
29<#assign label_leggi_tutto = languageUtil.get(locale, "label_leggi_tutto") />
30<#assign label_aggiungi_lista_viaggio = languageUtil.get(locale, "label_aggiungi_lista_viaggio") />
31<#-- datepicker -->
32<#assign label_datepicker_oggi = languageUtil.get(locale, "label_datepicker_oggi") />
33<#assign label_datepicker_domani = languageUtil.get(locale, "label_datepicker_domani") />
34<#assign label_datepicker_prossimi_7_giorni = languageUtil.get(locale, "label_datepicker_prossimi_7_giorni") />
35<#assign label_datepicker_questo_mese = languageUtil.get(locale, "label_datepicker_questo_mese") />
36<#assign label_datepicker_scegli = languageUtil.get(locale, "label_datepicker_scegli") />
37<#assign label_datepicker_annulla = languageUtil.get(locale, "label_datepicker_annulla") />
38<#assign label_datepicker_da = languageUtil.get(locale, "label_datepicker_da") />
39<#assign label_datepicker_a = languageUtil.get(locale, "label_datepicker_a") />
40<#assign label_datepicker_giorni_settimana = languageUtil.get(locale, "label_datepicker_giorni_settimana") />
41<#assign label_datepicker_mesi_anno = languageUtil.get(locale, "label_datepicker_mesi_anno") />
42<#assign label_scarica_formato_csv = languageUtil.get(locale, "label_scarica_formato_csv") />
43
44<#-- Inclusione widget template con macros e relativi servizi -->
45<#include "${templatesPath}/RICERCA_COMMON_MACROS" />
46
47<#-- html -->
48<div class="col-12">
49 <div class="search-template search-template-eventi">
50
51 <#-- da qui inizia l'html così come da mockup: solo modalita desktop -->
52 <div class="search-form-container search-form-container-desktop py-3">
53 <#-- aggiunta classe m-0 -->
54 <div class="row m-0">
55 <div class="col-12">
56
57 <#-- form con ricerca testuale, per data, e pulsanti -->
58 <@ricerca_components["ricerca-form"] searchUrl="${searchUrl}" method="get" id="search-eventi-form-desktop">
59
60 <#-- contenitore con sfondo -->
61 <div class="search-form">
62
63 <#-- campo hidden per ricerca senza risultati -->
64 <input type="hidden" name="searchSubmit" value="true">
65
66 <#-- campo hidden per ordinamento: non usato -->
67 <#--
68 <input type="hidden" value="${searchInput.orderBy}" name="orderBy" id="orderByInputHiddenDesktop">
69 -->
70
71 <#-- campo hidden per cambio vista: non usato -->
72 <#--
73 <input type="hidden" value="${viewTypeKey}${ricercaPortletConfig.configViewParamsSeparator}${viewTypeValue}" name="viewParams" id="input-viewParams-viewType">
74 -->
75
76 <#-- inizio barra filtri orizzontatli -->
77 <div class="form-row align-items-center">
78
79 <#if ricercaPortletConfig.configInputqTitleLabel != "">
80 <#assign label_filtro_cosa = ricercaPortletConfig.configInputqTitleLabel />
81 </#if>
82
83 <#-- campo di ricerca testuale -->
84 <div class="col-12 <#if searchInput.extraSearchFields?has_content || (ricercaPortletConfig.configShowCategoriesFilterInSearchbar == true)>col-md mb-md-2<#else>col-md</#if> text-uppercase search-form-title">
85 <label for="input-ricerca-q" class="mb-0">${label_filtro_cosa}</label>
86 <@ricerca_components["ricerca-input-q"] cssClass="form-control"
87 value="${searchInput.q}"
88 placeholder="${label_placeholder_filtro_cosa}">
89 </@>
90 <#if SUGGERIMENTI_RICERCA_CONTENT?? && SUGGERIMENTI_RICERCA_CONTENT !="">
91 ${SUGGERIMENTI_RICERCA_CONTENT}
92 </#if>
93 </div>
94
95 <#-- campo di ricerca per località: campo dinamico prelevato da configurazione -->
96 <#if searchInput.extraSearchFields?has_content>
97 <#list searchInput.extraSearchFields as curExtraSearchField >
98 <#assign curExtraSearchFieldValue = "" />
99 <#if curExtraSearchField.value?has_content>
100 <#assign curExtraSearchFieldValue = curExtraSearchField.value />
101 </#if>
102
103 <#assign curExtraSearchFieldName = curExtraSearchField.fieldNamePrefix+curExtraSearchField.field />
104 <#assign curExtraSearchFieldLabel = curExtraSearchField.fieldLabel />
105
106 <div id="${curExtraSearchFieldName}_container" class="col-12 col-md text-uppercase search-form-extra-field mb-md-2">
107 <label for="${curExtraSearchFieldName}" class="mb-0">${curExtraSearchFieldLabel}</label>
108 <#if curExtraSearchField.inputAspect = "OPTIONS">
109 <select class="form-control" id="${curExtraSearchFieldName}" name="${curExtraSearchFieldName}" value="${curExtraSearchFieldValue}">
110 <option value="">${label_seleziona}</option>
111 <#assign keyName = curExtraSearchField.field />
112 <#assign selectOptions = selectsItemsLabels[keyName] />
113 <#if selectOptions?has_content>
114 <#list selectOptions as opt>
115 <#assign isSelected = "" />
116 <#if curExtraSearchFieldValue?string?lower_case == opt?lower_case>
117 <#assign isSelected = "selected" />
118 </#if>
119 <option value="${opt}" ${isSelected}>${opt}</option>
120 </#list>
121 </#if>
122 </select>
123 <#else>
124 <input type="text" class="form-control" id="${curExtraSearchFieldName}" name="${curExtraSearchFieldName}" value="${curExtraSearchFieldValue}" placeholder="${label_placeholder_filtro_cosa}">
125 </#if>
126 </div>
127
128 <#if curExtraSearchField.autoCompleteUrl?? && curExtraSearchField.autoCompleteUrl != "">
129 <#if curExtraSearchField.inputAspect = "TEXTFIELD">
130 <script>
131 $('#${curExtraSearchFieldName}').autocomplete({
132 paramName: 'q',
133 appendTo: '#${curExtraSearchFieldName}_container',
134 serviceUrl: '${curExtraSearchField.autoCompleteUrl}',
135 dataType: 'json',
136 transformResult: function(response) {
137 return {
138 suggestions: $.map(response.data, function(dataItem) {
139 return dataItem.displayName;
140 })
141 };
142 }
143 });
144 </script>
145 </#if>
146 </#if>
147 </#list>
148 </#if>
149
150 <#if ricercaPortletConfig.configSearchbarCategoriesFieldLabel != "">
151 <#assign label_categorie = ricercaPortletConfig.configSearchbarCategoriesFieldLabel />
152 </#if>
153
154 <#if (ricercaPortletConfig.configShowCategoriesFilterInSearchbar == true)>
155 <#-- visualizzo searchbar categories -->
156 <#if (searchbarCategoriesAsKeyValue?size > 0)>
157 <div class="col-12 col-md text-uppercase search-form-extra-field mb-md-2">
158 <label for="searchbar-select-ricerca-categorie" class="mb-0">${label_categorie}</label>
159 <select name="categoryIdsSearchbar" class="form-control" id="searchbar-select-ricerca-categorie">
160 <option value="">${label_seleziona}</option>
161 <#list searchbarCategoriesAsKeyValue?keys as prop>
162 <#assign isSelected = "" />
163 <#if searchInput.categoryIdsSearchbar?has_content>
164 <#list searchInput.categoryIdsSearchbar as categoryId>
165 <#if categoryId?string == prop>
166 <#assign isSelected = "selected" />
167 </#if>
168 </#list>
169 </#if>
170 <option value="${prop}" ${isSelected}>${searchbarCategoriesAsKeyValue[prop]}</option>
171 </#list>
172 </select>
173 </div>
174 </#if>
175 <#-- visualizzo searchbar extra categories -->
176 <#if categoriesExtraSearchFieldsObject?has_content>
177 <#list categoriesExtraSearchFieldsObject as curVoc>
178 <div class="col-12 col-md text-uppercase search-form-extra-field mb-md-2">
179 <label for="searchbar-select-ricerca-categorie-${curVoc.vocabularyId}" class="mb-0">
180 ${curVoc.vocabularyLabel}
181 </label>
182 <select name="categoryIdsSearchbar" class="form-control" id="searchbar-select-ricerca-categorie-${curVoc.vocabularyId}">
183 <option value="">
184 ${label_seleziona}
185 </option>
186 <#list curVoc.categories?keys as curCat>
187 <#assign isSelected="" />
188 <#if searchInput.categoryIdsSearchbar?has_content>
189 <#list searchInput.categoryIdsSearchbar as categoryId>
190 <#if categoryId?string == curCat>
191 <#assign isSelected="selected" />
192 </#if>
193 </#list>
194 </#if>
195 <option value="${curCat}" ${isSelected}>
196 ${curVoc.categories[curCat]}
197 </option>
198 </#list>
199 </select>
200 </div>
201 </#list>
202 </#if>
203 </#if>
204
205 <#-- campo di ricerca per range di date -->
206 <#-- il date picker imposta sempre una data di inizio ed una di fine, con cui valorizzo i campi nascosti che servono per la ricerca -->
207 <#if ricercaPortletConfig.configShowSearchByDates == true>
208 <#assign currentDatepickerValue = "" />
209 <#assign currentDateFromValue = "" />
210 <#assign currentDateToValue = "" />
211 <#if searchInput.dateFrom?has_content && searchInput.dateTo?has_content>
212 <#assign currentDatepickerValue = '${dateUtil.getDate(searchInput.dateFrom?date, "dd/MM/yyyy", locale)} - ${dateUtil.getDate(searchInput.dateTo?date, "dd/MM/yyyy", locale)}' />
213 <#assign currentDateFromValue = '${dateUtil.getDate(searchInput.dateFrom?date, "dd/MM/yyyy", locale)}' />
214 <#assign currentDateToValue = '${dateUtil.getDate(searchInput.dateTo?date, "dd/MM/yyyy", locale)}' />
215 </#if>
216 <div class="col-12 col-md text-uppercase search-form-date mb-md-2">
217 <label for="date-range-desktop" class="mb-0"><#if ricercaPortletConfig.configDateSearchFieldLabel != "">${ricercaPortletConfig.configDateSearchFieldLabel}<#else>${label_filtro_quando}</#if></label>
218 <input id="date-range-desktop" type="text" placeholder="${label_placeholder_filtro_quando}" class="form-control" value="${currentDatepickerValue}" autocomplete="off"/>
219 <#-- campi hidden che vengono valorizzati sull'onchange del datepicker -->
220 <input id="date-range-desktop-from" name="dateFrom" type="hidden" value="${currentDateFromValue}">
221 <input id="date-range-desktop-to" name="dateTo" type="hidden" value="${currentDateToValue}">
222 </div>
223 </#if>
224
225 <#-- pulsante di ricerca -->
226 <div class="col-12 col-md-2 search-form-button">
227 <button type="submit" class="btn-dark btn-block"><span class="fa fa-search mr-1" aria-hidden="true"></span>${label_button_cerca}</button>
228 </div>
229
230 <#-- codice aggiunto per la ricerca geo su mappa, funziona con la variabile impostata a true nell'init -->
231 <#assign latValue="" />
232 <#if searchInput.lat?has_content>
233 <#assign latValue="${searchInput.lat}" />
234 </#if>
235 <#assign lngValue="" />
236 <#if searchInput.lng?has_content>
237 <#assign lngValue="${searchInput.lng}" />
238 </#if>
239 <#assign distanceValue="" />
240 <#if searchInput.distance?has_content>
241 <#assign distanceValue="${searchInput.distance}" />
242 </#if>
243
244 <#-- variabili per gestire accessibilità e visualizzazione mappa, nel caso in cui cè una ricerca geo in atto -->
245 <#assign statusCollapse = "" />
246 <#assign statusCollapseAria = "false" />
247 <#if (searchInput.lat?has_content) && (searchInput.lng?has_content) && (searchInput.distance?has_content)>
248 <#assign statusCollapse = "show" />
249 <#assign statusCollapseAria = "true" />
250 </#if>
251
252 <#-- pulsante per visualizzare la mappa nascosta -->
253 <div class="col-12 col-md-3 search-form-map-button">
254 <button class="container-fluid position-relative transition btn-dark btn-map" type="button" data-toggle="collapse" data-target="#map-container-desktop" aria-expanded="${statusCollapseAria}" aria-controls="map-container-desktop">
255 <span class="position-relative"><span class="fa fa-map-marker mr-1" aria-hidden="true"></span>${label_button_cerca_su_mappa}</span>
256 </button>
257 </div>
258 </div>
259
260 <#-- richiamo taglib mappa: ha il suo html base -->
261 <#-- rich-map: wrapper class for rich marker -->
262 <div id="map-container-desktop" class="rich-map-container collapse my-4 ${statusCollapse}">
263 <@ricerca_components["ricerca-map"]>
264 </@>
265 </div>
266 </div>
267
268 <#-- IMPORTANTE: inizializzo la mappa, da fare subito dopo la chiusura della taglib -->
269 <#-- poichè il form ha un id custom, lo riporto come parametro nell'init -->
270 <script>
271 TglSearchMap.init({
272 centerLatitude: 43.3285259,
273 centerLongitude: 13.0509109,
274 initialZoom: 13,
275 geoSearch: true,
276 searchFormId: "search-eventi-form-desktop",
277 submitOnGeoSearch: true
278 });
279 </script>
280
281 <#-- nel caso di una ricerca geo, passo alla mappa i valori impostati nelle variabili sopra create-->
282 <script type="text/javascript">
283 TglSearchMap.setSearchCircle('${latValue}', '${lngValue}', '${distanceValue}');
284 </script>
285
286 </@>
287 </div>
288 </div>
289 </div>
290
291 <#if entries?has_content>
292 <#list entries as curEntry>
293
294 <#-- sezione divisa in due colonne: categorie e lista risultati -->
295 <div id="search-results" class="search-results">
296
297 <#-- aggiunta classe m-0 -->
298 <div class="row m-0">
299
300 <#-- ricerca per categorie -->
301 <#if (ricercaPortletConfig.configSearchByCategories == true) && (ricercaPortletConfig.configShowCategoriesFilterInSidebar == true) && (categoriesAsKeyValue?size > 0)>
302
303 <#-- setto una variabile booleana per far partire gli accordion o aperti o chiusi a seconda della configurazione -->
304 <#assign vocabulariesCollapsed = false />
305 <#if ricercaPortletConfig.configStartWithCollapsedVocabularies?? && ricercaPortletConfig.configStartWithCollapsedVocabularies == true>
306 <#assign vocabulariesCollapsed = true />
307 </#if>
308
309 <#-- modificato da col-md-3 a col-lg-3 -->
310 <div class="col-12 col-lg-3 search-filters-container">
311
312 <div class="search-filters filters-desktop">
313 <#-- caso di ricerca per categorie multiple -->
314 <#if ricercaPortletConfig.configSelectMultipleCategories == true>
315 <#-- caso di visualizzazione di tutte le categorie -->
316 <#if ricercaPortletConfig.allVocabulariesCategories == true>
317 <#-- caso di elenco di categorie e sottocategorie indentate con nome vocabolario - sfrutta macro presente nel template RICERCA_COMMON_MACROS -->
318 <#if ricercaPortletConfig.configAllowVocabulariesLabelFilter == true>
319 <span class="d-flex align-items-center justify-content-between text-uppercase" data-toggle="collapse" data-target="#list-filters" role="button" aria-expanded="true" aria-controls="list-filters">
320 <span>${label_categorie}
321 <#if searchInput.categoryIds?has_content>
322 <span class="badge">${searchInput.categoryIds?size}</span>
323 </#if>
324 </span>
325 </span>
326 <div id="list-filters" class="list-filters collapse show mt-4">
327 <ul class="list-unstyled">
328 <#list hierarchicalVocabulariesOptions as voKey, voValue>
329 <li class="mb-2">
330 <a class="accordion-title h4" href="#accordion-content_${voKey}" data-toggle="collapse" aria-expanded="<#if !vocabulariesCollapsed>true<#else>false</#if>">
331 ${voValue.value.label}
332 </a>
333 <div id="accordion-content_${voKey}" class="accordion-content collapse <#if !vocabulariesCollapsed>show</#if>">
334 <@getAllCategoriesDesktop voValue.children />
335 </div>
336 </li>
337 </#list>
338 </ul>
339 </div>
340 <#else>
341 <#-- caso di elenco categorie e sottocategorie indentate ma senza nome vocabolario - sfrutta macro presente nel template RICERCA_COMMON_MACROS -->
342 <#if hierarchicalCategoriesOptions?? && hierarchicalCategoriesOptions?has_content>
343 <span class="d-flex align-items-center justify-content-between text-uppercase" data-toggle="collapse" data-target="#list-filters" role="button" aria-expanded="true" aria-controls="list-filters">
344 <span>${label_categorie}
345 <#if searchInput.categoryIds?has_content>
346 <span class="badge">${searchInput.categoryIds?size}</span>
347 </#if>
348 </span>
349 </span>
350 <div id="list-filters" class="list-filters collapse show mt-4">
351 <#-- ciclo sulle categorie -->
352 <@getAllCategoriesDesktop hierarchicalCategoriesOptions />
353 </div>
354 </#if>
355 </#if>
356 <#else>
357 <#-- caso di categorie selezionate manualmente dalla select di configurazione -->
358 <#-- caso di elenco di categorie e sottocategorie indentate con nome vocabolario - sfrutta macro presente nel template RICERCA_COMMON_MACROS -->
359 <#if ricercaPortletConfig.configAllowVocabulariesLabelFilter == true>
360 <span class="d-flex align-items-center justify-content-between text-uppercase" data-toggle="collapse" data-target="#list-filters" role="button" aria-expanded="true" aria-controls="list-filters">
361 <span>${label_categorie}
362 <#if searchInput.categoryIds?has_content>
363 <span class="badge">${searchInput.categoryIds?size}</span>
364 </#if>
365 </span>
366 </span>
367 <div id="list-filters" class="list-filters collapse show mt-4">
368 <ul class="list-unstyled">
369 <#list flatVocabulariesAndCategoriesAsKeyValueForMultiSelect as voKey, voValue>
370 <li class="mb-2">
371 <a class="accordion-title h4" href="#accordion-content_${voKey}" data-toggle="collapse" aria-expanded="<#if !vocabulariesCollapsed>true<#else>false</#if>">
372 ${voValue.value.label}
373 </a>
374 <div id="accordion-content_${voKey}" class="accordion-content collapse <#if !vocabulariesCollapsed>show</#if>">
375 <@getAllCategoriesDesktop voValue.children />
376 </div>
377 </li>
378 </#list>
379 </ul>
380 </div>
381 <#else>
382 <#-- caso di elenco categorie e sottocategorie indentate ma senza nome vocabolario - sfrutta macro presente nel template RICERCA_COMMON_MACROS -->
383 <#if flatCategoriesAsKeyValueForMultiSelect?? && flatCategoriesAsKeyValueForMultiSelect?has_content>
384 <span class="d-flex align-items-center justify-content-between text-uppercase" data-toggle="collapse" data-target="#list-filters" role="button" aria-expanded="true" aria-controls="list-filters">
385 <span>${label_categorie}
386 <#if searchInput.categoryIds?has_content>
387 <span class="badge">${searchInput.categoryIds?size}</span>
388 </#if>
389 </span>
390 </span>
391 <div id="list-filters" class="list-filters collapse show mt-4">
392 <@getAllCategoriesDesktop flatCategoriesAsKeyValueForMultiSelect />
393 </div>
394 </#if>
395 </#if>
396 </#if>
397 <#else>
398 <#-- visualizzo una select singola -->
399 <label for="select-ricerca-categorie" class="d-block text-uppercase mb-4">${label_categorie}</label>
400 <select name="categoryIds" class="form-control" id="select-ricerca-categorie">
401 <option value="">${label_seleziona}</option>
402 <#list categoriesAsKeyValue?keys as prop>
403 <#assign isSelected = "" />
404 <#if searchInput.categoryIds?has_content>
405 <#list searchInput.categoryIds as categoryId>
406 <#if categoryId?string == prop>
407 <#assign isSelected = "selected" />
408 </#if>
409 </#list>
410 </#if>
411 <option value="${prop}" ${isSelected}>${categoriesAsKeyValue[prop]}</option>
412 </#list>
413 </select>
414 </#if>
415 </div>
416 </div>
417 </#if>
418
419 <#-- lista risultati -->
420 <#-- modificato da col-md-9 a col-lg-9 -->
421 <#if (ricercaPortletConfig.configSearchByCategories == true) && (ricercaPortletConfig.configShowCategoriesFilterInSidebar == true) && (categoriesAsKeyValue?size > 0)>
422 <div class="col-12 col-lg-9 p-0 search-list-results-container">
423 <#else>
424 <div class="col-12 p-0 search-list-results-container">
425 </#if>
426 <#-- numero risultati + range di ricerca corrente + pulsante cambio data -->
427 <#-- aggiunta classe m-0 -->
428 <#if (ricercaPortletConfig.configShowResultNumber == true) ||
429 (ricercaPortletConfig.configShowResultTitle == true && ricercaPortletConfig.configResultTitleLabel != "") ||
430 (ricercaPortletConfig.configShowSearchByDates == true) ||
431 (ricercaPortletConfig.configCanExportSearchResults == true)>
432 <div class="row search-list-results-setting m-0">
433 <div class="col-10 col-sm-10 col-md-10 col-lg-10 col-xl-8 d-flex align-items-center">
434 <#if (ricercaPortletConfig.configShowResultNumber == true) || (ricercaPortletConfig.configShowResultTitle == true && ricercaPortletConfig.configResultTitleLabel != "")>
435 <div class="d-inline-block mb-0 position-relative h3 search-list-results-number">
436 <#if ricercaPortletConfig.configShowResultNumber == true>${curEntry.paging.totalRecordsCount} </#if><#if ricercaPortletConfig.configShowResultTitle == true && ricercaPortletConfig.configResultTitleLabel != "">${ricercaPortletConfig.configResultTitleLabel}</#if>
437 </div>
438 </#if>
439
440 <#if ricercaPortletConfig.configShowSearchByDates == true>
441 <#if searchInput.dateFrom?has_content && searchInput.dateTo?has_content>
442 <div class="d-inline-block">
443 <span class="d-block search-list-results-date-range">${label_data_dal} ${dateUtil.getDate(searchInput.dateFrom?date, "dd/MM/yyyy", locale)} ${label_data_al} ${dateUtil.getDate(searchInput.dateTo?date, "dd/MM/yyyy", locale)}</span>
444 <a class="position-relative tit-link arrow-right transition" href="javascript:void(0);" title="${label_cambia_data}" onclick="$('#date-range-desktop').focus()">${label_cambia_data}</a>
445 </div>
446 </#if>
447 </#if>
448 </div>
449
450 <#if ricercaPortletConfig.configCanExportSearchResults == true>
451 <div class="col-2 col-sm-2 col-md-2 col-lg-2 col-xl-4">
452 <button onclick="downloadCsv('${ricercaPortletConfig.configExportCsvUrl}')" class="btn btn-secondary btn-sm float-right" title="${label_scarica_formato_csv}"><span class="fa-solid fa-download" aria-hidden="true"></span></button>
453 </div>
454 </#if>
455 </div>
456 </#if>
457
458 <#if curEntry.records?has_content>
459 <#-- GRIGLIA: solo questa modalita, per cui non vengono utilizzati i vari controlli per lo switch -->
460 <#-- contenitori vista griglia -->
461 <div class="search-list-results grid-view">
462 <div class="grid-view-container">
463 <#-- aggiunta classe m-0 -->
464 <div class="row row-cols-2 row-cols-sm-2 row-cols-md-2 row-cols-lg-3 list-results m-0">
465
466 <#-- ciclo sugli elementi restituiti dalla ricerca -->
467 <#list curEntry.records as record>
468 <#if record.metadata?has_content>
469
470 <#-- assegno alla variabile il titolo di liferay o di struttura, ripulito dai caratteri accentati, da usare come alt o title -->
471 <#assign titoloScheda = "" />
472 <#if record.title?has_content>
473 <#assign titoloScheda = htmlUtil.escapeAttribute(record.title) />
474 </#if>
475 <#if record.metadata.eventTitle?has_content && record.metadata.eventTitle.value?has_content>
476 <#assign titoloScheda = htmlUtil.escapeAttribute(record.metadata.eventTitle.value) />
477 </#if>
478
479 <#-- singolo elemento -->
480 <div class="col position-relative">
481 <#-- funzione aggiungi a trip planner: visualizzo il cuore solo se esistono le coordinate -->
482 <#-- creo variabile di appoggio, poiche devo eventualmente anche eliminare l'angolo bianco della card che sta sotto -->
483 <#-- al contrario dei template, qui i valori delle coordinate sono numeri e non stringhe -->
484 <#assign existLatLong = false />
485 <#if (record.latitude?has_content && record.latitude != 0) && (record.longitude?has_content && record.longitude != 0)>
486 <#assign existLatLong = true />
487 <span class="fa-regular fa-heart transition" title="${label_aggiungi_lista_viaggio}" data-id="idPoi_${record.entryClassPk}"></span>
488 </#if>
489
490 <#-- cè bisogno che esista un tag a: per cui verifico che esista l'url altrimenti imposto l'href con javascript:void(0) -->
491 <#if record.detailUrl?has_content>
492 <a href="${record.detailUrl}" class="d-block result-container" title="${label_vai_dettaglio} ${titoloScheda}">
493 <#else>
494 <a href="javascript:void(0);" class="d-block result-container" title="${label_vai_dettaglio} ${titoloScheda}">
495 </#if>
496 <#-- aggiunta classe m-0 -->
497 <div class="row d-flex justify-content-center align-items-center position-relative card-container <#if !existLatLong>no-fa-heart</#if> transition m-0">
498
499 <#-- richiamo l'immagine: fa parte di un fieldset ripetibile, e potrebbe essere una sequenza o una semplice stringa -->
500 <#-- creo una variabile di appoggio per l'url dell'img da usare nella mappa -->
501 <#assign mapImageUrlJs = "" />
502 <#if record.metadata.eventImage?has_content && record.metadata.eventImage.value?has_content>
503 <#if record.metadata.eventImage.value?is_sequence>
504 <#assign numImg = 0 />
505 <#list record.metadata.eventImage.value as curImage>
506 <#if curImage?? && curImage?has_content>
507 <#attempt>
508 <#assign curImageJson = jsonFactoryUtil.createJSONObject(curImage) />
509 <#if curImageJson?? && curImageJson?has_content && curImageJson.uuid?? && curImageJson.groupId??>
510 <#assign numImg = numImg + 1 />
511 <#assign curImageDLFileEntry = dlFileEntryLocalService.getFileEntryByUuidAndGroupId(curImageJson.uuid,curImageJson.groupId?number) />
512 <#assign curImageUrl = "/documents/"+groupId+"/"+curImageDLFileEntry.getFolderId()+"/"+curImageDLFileEntry.getFileName()+"/"+curImageJson.uuid />
513 <#assign mapImageUrlJs = curImageUrl />
514
515 <div class="col-12 p-0 m-0">
516 <div class="position-relative image-container transition">
517 <img src="${curImageUrl}" class="image-preview-object-fit" alt="${titoloScheda}">
518 </div>
519 </div>
520
521 </#if>
522 <#recover>
523 <#-- in caso di problemi sull'immagine, non visualizzo nulla -->
524 </#attempt>
525 </#if>
526 <#if numImg == 1>
527 <#break>
528 </#if>
529 </#list>
530 <#else>
531 <#attempt>
532 <#assign imageJson = jsonFactoryUtil.createJSONObject(record.metadata.eventImage.value) />
533 <#if imageJson?? && imageJson?has_content && imageJson.uuid?? && imageJson.groupId??>
534 <#assign imageDLFileEntry = dlFileEntryLocalService.getFileEntryByUuidAndGroupId(imageJson.uuid,imageJson.groupId?number) />
535 <#assign imageUrl = "/documents/"+groupId+"/"+imageDLFileEntry.getFolderId()+"/"+imageDLFileEntry.getFileName()+"/"+imageJson.uuid />
536 <#assign mapImageUrlJs = imageUrl />
537
538 <div class="col-12 p-0 m-0">
539 <div class="position-relative image-container transition">
540 <img src="${imageUrl}" class="image-preview-object-fit" alt="${titoloScheda}">
541 </div>
542 </div>
543 </#if>
544 <#recover>
545 <#-- in caso di problemi sull'immagine, non visualizzo nulla -->
546 </#attempt>
547 </#if>
548 </#if>
549
550 <#-- testi -->
551 <div class="col-md-12 p-3">
552 <div class="text-center text-container">
553
554 <#-- ricavo le date di inizio e fine evento -->
555 <#-- data di inizio evento -->
556 <#if record.metadata.eventStartDate?has_content && record.metadata.eventStartDate.value?has_content>
557 <#assign eventStartDate_DateObj = dateUtil.parseDate("yyyy-MM-dd", record.metadata.eventStartDate.value, locale) />
558 <#assign eventStartDate_str = dateUtil.getDate(eventStartDate_DateObj, "dd MMMM yyyy", locale) />
559
560 <#if validator.isNotNull(eventStartDate_str) && eventStartDate_str != "">
561 <div class="text-uppercase search-field-date">
562 ${eventStartDate_str}
563
564 <#-- data di fine evento -->
565 <#if record.metadata.eventEndDate?has_content && record.metadata.eventEndDate.value?has_content && record.metadata.eventStartDate.value != record.metadata.eventEndDate.value>
566 <#assign eventEndDate_DateObj = dateUtil.parseDate("yyyy-MM-dd", record.metadata.eventEndDate.value, locale) />
567 <#assign eventEndDate_Str = dateUtil.getDate(eventEndDate_DateObj, "dd MMMM yyyy", locale) />
568 <#if validator.isNotNull(eventEndDate_Str) && eventEndDate_Str != "">
569 <span>-</span>
570 ${eventEndDate_Str}
571 </#if>
572 </#if>
573 </div>
574 </#if>
575 </#if>
576
577 <#-- titolo di struttura -->
578 <#if record.metadata.eventTitle?has_content && record.metadata.eventTitle.value?has_content>
579 <div class="mt-3 transition tit-link check-highlight">
580 ${record.metadata.eventTitle.value?trim}
581 </div>
582 </#if>
583
584 <#-- luogo -->
585 <#assign mapAddressJs = "" />
586 <#if record.metadata.eventAddressCity?has_content && record.metadata.eventAddressCity.value?has_content>
587 <#assign mapAddressJs = record.metadata.eventAddressCity.value />
588 <div class="mb-3 search-extra-field-place">
589 <span class="fa fa-map-marker" aria-hidden="true"></span> <strong class="ml-1 text-uppercase">${record.metadata.eventAddressCity.value}</strong>
590 </div>
591 </#if>
592
593 <#-- leggi tutto -->
594 <div class="sub-link">
595 ${label_leggi_tutto} <span class="fa fa-angle-right transition" aria-hidden="true"></span>
596 </div>
597
598 <#-- ******************************* CATEGORIE - COMMENTATO ******************************* -->
599 <#-- QUESTO CODICE È COMMENTATO, POICHÈ LE CATEGORIE NN SONO PREVISTE NEI MOCKUP, MA POTREBBE ESSERE SEMPRE UTILE -->
600
601 <#-- metodo tramite record (ricerca) -->
602 <#-- recupero l'elenco delle categorie dall'oggetto record anzichè passando dall'articolo -->
603 <#--
604 <#if record.categories?? && (record.categories?size > 0)>
605 <#list record.categories as key, value>
606 <#if (key?? && key != 0) && (value?? && value != "")>
607 <div class="chip chip-simple chip-outline-secondary chip-no-link">
608 <span class="chip-label">${value}</span>
609 </div>
610 </#if>
611 </#list>
612 </#if>
613 -->
614
615 <#-- categorie: metodo tramite api -->
616 <#--
617 <#assign categorie = []>
618 <#assign categorie = getListCategoryByArticlePrimKey(record.entryClassPk) />
619 <#if categorie?? && (categorie?size > 0)>
620 <#list categorie as cur_cat>
621 <#if validator.isNotNull(cur_cat) && cur_cat != "">
622 <div class="chip chip-simple chip-outline-secondary chip-no-link">
623 <span class="chip-label">${cur_cat.getTitle(locale)}</span>
624 </div>
625 </#if>
626 </#list>
627 </#if>
628 -->
629 <#-- ******************************* CATEGORIE - COMMENTATO ******************************* -->
630
631 </div>
632 </div>
633 <#-- fine testi -->
634
635 </div>
636 </a>
637 </div>
638 <#-- fine singolo elemento -->
639
640 <#-- valorizzo il marker sulla mappa, se esiste latitudine e longitudine -->
641 <#if (record.latitude?has_content && record.latitude != 0) && (record.longitude?has_content && record.longitude != 0)>
642 <script>
643 var marker = L.marker(L.latLng([${record.latitude},${record.longitude}]));
644
645 var infoBox = "";
646 // apertura contenitore infobox e card
647 infoBox += "<div class='info-box'><div class='card bg-white m-0 border-0 shadow-none'>";
648 // immagine
649 <#if mapImageUrlJs?? && mapImageUrlJs != "">
650 infoBox += "<div class='card-img-wrapper'><img src='${mapImageUrlJs}' class='card-img-top' alt='${titoloScheda}'></div>";
651 </#if>
652 // inizio body
653 infoBox += "<div class='card-body p-2'>"
654 //titolo
655 infoBox += "<h2 class='card-title mb-2'><a href='${record.detailUrl}' title='${label_vai_dettaglio} ${titoloScheda}'>${titoloScheda}</a></h2>"
656 // indirizzo
657 <#if mapAddressJs?? && mapAddressJs != "">
658 infoBox += "<p class='mt-0 mb-2'><span class='fa fa-map-marker mr-1'></span><strong>${mapAddressJs}</strong></p>"
659 </#if>
660 // fine body
661 infoBox += "</div>"
662 // fine contenitore infobox e card
663 infoBox += "</div></div>"
664
665 var popup = marker.bindPopup(infoBox);
666 TglSearchMap.addMarker(marker);
667 </script>
668 </#if>
669
670 </#if>
671 </#list>
672 <#-- fine ciclo -->
673
674 </div>
675 </div>
676 </div>
677 <#-- FINE GRIGLIA -->
678 </#if>
679 <#-- fine curEntry -->
680
681 <#-- paginazione mediante taglib-->
682 <#-- aggiunta classe m-0 -->
683 <div class="row mb-0">
684 <div class="col-12 text-center">
685 <@ricerca_components["ricerca-pagination"]
686 currentPage=curEntry.paging.page?number
687 totalPages=curEntry.paging.totalPagesCount?number
688 paginationUrl="${portletURL}"></@>
689 </div>
690 </div>
691
692 </div>
693 </div>
694 </div>
695
696 </#list>
697 </#if>
698
699 </div>
700</div>
701
702<script>
703 // rangedatepickerdesktop
704 <#if ricercaPortletConfig.configShowSearchByDates == true>
705 $(function () {
706 var options = {};
707 options.ranges = {
708 '${label_datepicker_oggi}': [moment()],
709 '${label_datepicker_domani}': [moment().add(1, 'days'), moment().add(1, 'days')],
710 '${label_datepicker_prossimi_7_giorni}': [moment(), moment().add(7, 'days')],
711 '${label_datepicker_questo_mese}': [moment().startOf('month'), moment().endOf('month')],
712 };
713 options.locale = {
714 format: 'DD/MM/YYYY',
715 separator: ' - ',
716 applyLabel: '${label_datepicker_scegli}',
717 cancelLabel: '${label_datepicker_annulla}',
718 fromLabel: '${label_datepicker_da}',
719 toLabel: '${label_datepicker_a}',
720 //customRangeLabel: 'Personalizzato',
721 daysOfWeek: [${label_datepicker_giorni_settimana}],
722 monthNames: [${label_datepicker_mesi_anno}],
723 firstDay: 1
724 };
725 options.alwaysShowCalendars = true;
726 options.autoApply = true;
727 options.autoUpdateInput= false;
728 options.minDate = new Date();
729 $('input[id="date-range-desktop"]').daterangepicker(options, function (start, end, label) { });
730 });
731
732 // sull'onchange valorizzo i due campi hidden che servono per la ricerca
733 $('#date-range-desktop').on('apply.daterangepicker change', function(ev, picker) {
734 if (picker){
735 $(this).val(picker.startDate.format('DD/MM/YYYY') + ' - ' + picker.endDate.format('DD/MM/YYYY'));
736 $('#date-range-desktop-from').val(picker.startDate.format('DD/MM/yyyy'));
737 $('#date-range-desktop-to').val(picker.endDate.format('DD/MM/yyyy'));
738 $('.search-template-eventi #search-eventi-form-desktop').submit();
739 }else{
740 var completeDate = ev.target.value;
741 var singleDates = completeDate.split(' - ');
742 $('#date-range-desktop-from').val(singleDates[0]);
743 $('#date-range-desktop-to').val(singleDates[1]);
744 $('.search-template-eventi #search-eventi-form-desktop').submit();
745 }
746 });
747 </#if>
748
749 $(document).ready(function(){
750 // carico la mappa
751 TglSearchMap.loadMap(true);
752
753 // scroll fino a ricerca
754// $('html, body').animate({
755// scrollTop: $(".search-template-eventi").offset().top - 120
756// }, 500);
757
758 // quando il container collapsed viene visualizzato, ricostruisco la mappa e applico il fitbounds, oltre che a visualizzare il popover, se non ancora visualizzato
759 $('#map-container-desktop').on('shown.bs.collapse', function () {
760 TglSearchMap.getMap().invalidateSize();
761 TglSearchMap.fitBounds();
762
763 // popover on draw circle function
764 if( $('.leaflet-draw-draw-circle').length === 1){
765 if (sessionStorage.getItem('showedPopoverMap') == undefined) {
766 showTooltipOnMap('.search-template-eventi .leaflet-draw-draw-circle');
767 }
768 if(isShowedPopover){
769 hideTooltipOnMap('.search-template-eventi .leaflet-draw-draw-circle','body');
770 }
771 }
772 });
773
774 // leggo i parametri dall'url: se esiste showMap ed è uguale a true, apro il collapse che contiene la mappa
775 // succede se arrivo dal template form_ricerca (form fittizia)
776 let searchParams = new URLSearchParams(window.location.search)
777 if (searchParams.has('showMap')){
778 let searchParamShowMap = searchParams.get('showMap');
779 if (searchParamShowMap == 'true'){
780 $('#map-container-desktop').collapse('show');
781 }
782 }
783 if (searchParams.has('changeDate')){
784 let searchParamShowMap = searchParams.get('changeDate');
785 if (searchParamShowMap == 'true'){
786 $('#date-range-desktop').focus();
787 }
788 }
789
790 <#-- js per filtri categorie -->
791 <#if (ricercaPortletConfig.configSearchByCategories == true) && (categoriesAsKeyValue?size > 0)>
792 <#-- filtri categorie multiple -->
793 <#if ricercaPortletConfig.configSelectMultipleCategories == true>
794 /*bind checkbox category_*/
795 $('.search-template-eventi input[id^="category_"]').click(function(){
796 var $currentElem = $( this );
797 if(!$currentElem.prop('checked')){
798 $(".search-template-eventi #search-eventi-form-desktop #form_"+$currentElem.attr('id')).remove();
799 }
800 else{
801 $(".search-template-eventi #search-eventi-form-desktop #form_"+$currentElem.attr('id')).remove();
802 var input = '<input class="mr-2 hide" style="display:none" type="checkbox" name="'+$currentElem.attr('name')+'" id="form_'+$currentElem.attr('id')+'" value="'+$currentElem.val()+'" checked="">';
803 $('.search-template-eventi #search-eventi-form-desktop .search-form').append(input);
804 }
805 $('.search-template-eventi #search-eventi-form-desktop').submit();
806 });
807 /*initialize checkbox category_*/
808 $('.search-template-eventi input[id^="category_"]').each(function(){
809 var $currentElem = $( this );
810 if($currentElem.prop('checked')){
811 $(".search-template-eventi #search-eventi-form-desktop #form_"+$currentElem.attr('id')).remove();
812 var input = '<input class="mr-2 hide" style="display:none" type="checkbox" name="'+$currentElem.attr('name')+'" id="form_'+$currentElem.attr('id')+'" value="'+$currentElem.val()+'" checked="">';
813 $('.search-template-eventi #search-eventi-form-desktop .search-form').append(input);
814 }
815 });
816
817 <#else>
818
819 <#-- filtri categorie singola -->
820 /*bind checkbox category_*/
821 $('.search-template-eventi #select-ricerca-categorie').on('change', function() {
822 var $currentElem = $(this);
823 var optionVal = $currentElem.val();
824
825 if(optionVal===undefined || optionVal==null || optionVal==''){
826 $(".search-template-eventi #search-eventi-form-desktop input[id^='form_']").remove();
827 }
828 else{
829 if ($('.search-template-eventi #select-ricerca-categorie option[value=optionVal]').is(':selected')){
830 $(".search-template-eventi #search-eventi-form-desktop input[id^='form_']").remove();
831 }else{
832 $(".search-template-eventi #search-eventi-form-desktop input[id^='form_']").remove();
833 var input = '<input class="mr-2 hide" style="display:none;" type="checkbox" name="'+$currentElem.attr('name')+'" id="form_'+$currentElem.attr('id')+'" value="'+optionVal+'" checked="">';
834 $('.search-template-eventi #search-eventi-form-desktop .search-form').append(input);
835 }
836 }
837 $('.search-template-eventi #search-eventi-form-desktop').submit();
838 });
839 /*initialize checkbox category_*/
840 $('.search-template-eventi #select-ricerca-categorie option').each(function(){
841 var $currentElem = $( this );
842 var optionVal = $currentElem.val();
843 if(optionVal!==undefined && optionVal!=null && optionVal!=''){
844 if($currentElem.is(':selected')){
845 $(".search-template-eventi #search-eventi-form-desktop input[id^='form_']").remove();
846 var input = '<input class="mr-2 hide" style="display:none;" type="checkbox" name="'+$currentElem.attr('name')+'" id="form_'+$currentElem.attr('id')+'" value="'+$currentElem.val()+'" checked="">';
847 $('.search-template-eventi #search-eventi-form-desktop .search-form').append(input);
848 }
849 }
850 });
851 </#if>
852 </#if>
853
854 });
855</script>