Si è verificato un errore nell'elaborarazione del modello.
The following has evaluated to null or missing:
==> thisCardData  [in template "20098#20124#1784553" at line 574, column 10]

----
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 thisCardData?contains("journal-te...  [in template "20098#20124#1784553" in macro "printCard" at line 574, column 5]
	- Reached through: @printCard curEntry, curEntry?index  [in template "20098#20124#1784553" in function "generateHtmlData" at line 390, column 37]
----
1<!-- Tours listing UNI FTL --> 
2<#assign counter = 0> 
3<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") /> 
4<#assign assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryService") /> 
5<#assign thisFilterScope = "${randomNamespace}filter"> 
6 
7<#-- instanceId with id parent layout to allow emebed differrent widget on different pages --> 
8<#assign cur_time = .now> 
9<#assign urlHelper = vtaLibrary.getUrlHelper()> 
10<#assign cacheSufix = urlHelper + "_" + locale> 
11<#assign cur_instanceId = "html_data_" + themeDisplay.getLayout().uuid + cacheSufix> 
12 
13<#-- tours common filters array: --> 
14<#assign filter_tourType = []> 
15<#assign filter_month = []> 
16<#assign filter_destination = []> 
17<#assign filter_price_from = []> 
18<#assign filter_destinationCountry = []> 
19<#assign filter_interests= []> 
20<#assign filter_duration= []> 
21<#assign filter_recommended= []> 
22<#-- excursions specific filters array: --> 
23<#assign filter_estartingpoint= []> 
24<#assign filter_eduration= []> 
25<#assign departureDates= []><#-- currently used only to count dates...--> 
26 
27<#assign data_set=[]> 
28<#assign curYearYY = .now?string('yy')?number> 
29<#assign curMonthMM = .now?string('MM')?number> 
30 
31<#assign envSettings = vtaLibrary.getEnvSettings()> 
32<#assign vocDestTypenId = envSettings.vocDestTypenId?number> 
33<#assign vocPopularityId = envSettings.vocPopularityId?number> 
34<#assign embedTourCardUniId = envSettings.embedTourCardUniId> 
35<#assign structureGuidedTourId = 975893> 
36<#assign currency = "err"> 
37<#assign sectionLabelList = translationsUtils.getMessage(locale,'vta.webcontent.results')?lower_case?cap_first> 
38<#assign sectionLabelFilters = translationsUtils.getMessage(locale,'vta.webcontent.filters')?lower_case?cap_first> 
39<#if vtaUtil??> 
40    <#assign currency = vtaUtil.getCurrencySymbol(request)> 
41</#if> 
42 
43<#-- clear all cache by URL param (use ...url..."?cacheUpdate" ) --> 
44<#assign curUrl = themeDisplay.getURLCurrent()?string> 
45<#if curUrl?contains("?cacheUpdate")> 
46    <#assign temp = freemarkerFilterCache.clearFreemarkerCache()> 
47    <script> 
48        console.log("Force cache update."); 
49    </script> 
50</#if> 
51 
52<#assign showFilerPanel = entries?size gte 5> 
53 
54<#-- check if are only Guided tours in list --> 
55<#assign isGuidedListingOnly = false> 
56<#if entries?has_content> 
57    <#assign cur_guidesTypeCounter = 0> 
58    <#list entries as curEntry> 
59        <#assign cur_renderer=curEntry.getAssetRenderer() /> 
60        <#assign cur_journalArticle=cur_renderer.getArticle() /> 
61        <#assign cur_structureId = cur_journalArticle.getDDMStructureId()?string> 
62        <#if vtaLibrary.getTemplateForStructure(cur_structureId?string,"name") = "guided"> 
63             <#assign cur_guidesTypeCounter = cur_guidesTypeCounter + 1>    
64        </#if> 
65    </#list> 
66    <#assign isGuidedListingOnly = (cur_guidesTypeCounter == entries?size)> 
67</#if> 
68<!-- GUIDED ONLY: ${isGuidedListingOnly?string} --> 
69<#if isGuidedListingOnly> 
70    <#assign sortString = "gu_rec"> 
71<#else> 
72    <#assign sortString = "rec"> 
73</#if> 
74 
75<#-- ################## -->  
76<script src="${themeDisplay.getPathThemeJavaScript()}/vta-filter.js?t=${themeDisplay.getTheme().getTimestamp()}" type="text/javascript" data-senna-track="permanent"></script> 
77 
78 
79<@generateData/> 
80<#assign htmlData = generateHtmlData()> 
81 
82<!-- print html --> 
83${htmlData} 
84 
85<#-- ******** generate data ********* --> 
86<#macro generateData> 
87    <#if entries?has_content> 
88        <#list entries as curEntry> 
89            <@generateCardData curEntry curEntry?index/> 
90        </#list> 
91    </#if> 
92</#macro> 
93 
94 
95<#function generateHtmlData> 
96    <#-- HTML cachable data --> 
97    <#local htmlData> 
98 
99        <#compress> 
100        <style> 
101            .d-tour.hidden, 
102            .results-line .result, 
103            #zeroBanner.hidden, 
104            .results-line[data-results="1"] .results { 
105                display:none; 
106
107 
108            .results-line[data-results="1"] .result { 
109                display:inline; 
110
111 
112            /* default thumbs css */ 
113            .-Tour-swiperThumbs .swiper-slide { 
114                width: 110px; 
115                margin-right: 2px; 
116
117        </style> 
118 
119        <div id="${thisFilterScope}" class="-sidebarLayout -Section -Section--verticalIndentLarge" data-sidewidth="3" data-space="2"   <#--data-direction="row-reverse" data-sideright="true"--> data-switchxsmd="true" data-overflowvisible="true"> 
120            <div> 
121                <#-- filter col --> 
122                <section id="${thisFilterScope}-filter" class="-formElements js-f-col-filter" style="${showFilerPanel?then('','display:none;')}" aria-labelledby="filter-section-label"> 
123                    <h2 class="sr-only" id="filter-section-label">${sectionLabelFilters}</h2> 
124                    <div class="-Collapse -Collapse--xsmdTypeDropdown -Collapse--xsmdExpandFullScreen -formElements"> 
125                        <div class="-Collapse-contents"> 
126                            <div class="-Collapse-content"> 
127                                <div id="collapseFilters" class="-Collapse-collapse collapse" data-expanded-md="true"> 
128                                    <div class="-Panel -Panel--xsmdTypeModalFlyout -Collapse-panel -Collapse-panel--typeModalFlyout"> 
129                                        <div class="-Panel-inner"> 
130                                            <div class="-Panel-head"> 
131                                                <div class="-clusterLayout" data-space="05" data-align="center" data-justify="space-between"> 
132                                                    <div> 
133                                                        <div> 
134                                                            <strong class="-clusterLayout" data-space="02" data-align="center" data-nowrap="true"> 
135                                                                <span> 
136                                                                    <i class="-Icon -Icon--filter" aria-hidden="true"></i><span>${translationsUtils.getMessage(locale,'vta.webcontent.filterBy')}</span> 
137                                                                </span> 
138                                                            </strong> 
139                                                        </div> 
140                                                        <div> 
141                                                            <button id="clearAllButton" type="button" class="-Button -Button--typeLinkSecondary">${translationsUtils.getMessage(locale,'vta.webcontent.clearAll')}</button> 
142                                                        </div> 
143                                                    </div> 
144                                                </div> 
145                                            </div> 
146                                            <div class="-Panel-body"> 
147                                                <div class="-stackLayout" data-space="03"> 
148                                                    <div></div> 
149                                                    <div class="-stackLayout" data-space="3" data-space-xsmd="0"> 
150 
151 
152                                                        <#-- tour type --> 
153                                                        <#if getAllUniqueArray(filter_tourType)?size gt 1> 
154                                                            <#assign curFilterContent> 
155                                                                <@printFilterCheckBoxes filter_tourType "ttype"/> 
156                                                            </#assign> 
157                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.common.labels.tourType')> 
158                                                            <#assign curFilterStyle = ""> 
159                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
160                                                        </#if> 
161 
162                                                        <#-- months --> 
163                                                        <#if filter_month?size gt 0> 
164                                                            <#assign curFilterContent> 
165                                                                <div class="-stackLayout" data-space="01"> 
166                                                                    <div class="-stackLayout" data-space="03"> 
167                                                                        <h4 class="-Heading -Heading--typeH6 -Heading--skinSharp">20${curYearYY}</h4> 
168                                                                        <div><@printFilterDates filter_month "${curYearYY}"/></div> 
169                                                                    </div> 
170                                                                    <div class="-stackLayout" data-space="03"> 
171                                                                        <h4 class="-Heading -Heading--typeH6 -Heading--skinSharp">20${curYearYY+1}</h4> 
172                                                                        <div><@printFilterDates filter_month "${curYearYY+1}"/></div> 
173                                                                    </div> 
174                                                                </div> 
175                                                            </#assign> 
176                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.departureMonth')> 
177                                                            <#assign curFilterStyle = ""> 
178                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
179                                                        </#if> 
180 
181                                                        <#-- ex starting points --> 
182                                                        <#if filter_estartingpoint?size gt 0> 
183                                                            <#assign curFilterContent> 
184                                                                <@printFilterCheckBoxes filter_estartingpoint "estartingp"/> 
185                                                            </#assign> 
186                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.starting.point')> 
187                                                            <#assign curFilterStyle = ""> 
188                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
189                                                        </#if> 
190 
191                                                        <#-- ex duration --> 
192                                                        <#if filter_eduration?size gt 0> 
193                                                            <#assign curFilterContent> 
194                                                                <@printFilterCheckBoxes filter_eduration "eduration"/> 
195                                                            </#assign> 
196                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.duration')> 
197                                                            <#assign curFilterStyle = ""> 
198                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
199                                                        </#if> 
200 
201 
202                                                        <#-- prices --> 
203                                                        <#if filter_price_from?size gt 0> 
204                                                            <#assign curFilterContent> 
205                                                                <div id="rangePrices" class="-Range -stackLayout js-frange" data-space="01"> 
206                                                                    <@printRangeCombo filter_price_from currency "Prices"/> 
207                                                                </div> 
208                                                            </#assign> 
209                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.pricePerPerson')> 
210                                                            <#assign curFilterStyle = "${(isRangePrintable(filter_price_from))?then('','display:none;')}"> 
211                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
212                                                        </#if> 
213 
214                                                        <#-- destinations --> 
215                                                        <#if filter_destination?size gt 0> 
216                                                            <#assign curFilterContent> 
217                                                                <div class="-CollapseGroup -stackLayout" data-space="03"> 
218                                                                    <#-- country --> 
219                                                                    <div> 
220                                                                        <div class="-Collapse -Collapse--typeChevron"> 
221                                                                            <div class="-Collapse-contents"> 
222                                                                                <div class="-Collapse-content"> 
223                                                                                    <div class="-Collapse-head" id="destCollapseHead1"> 
224                                                                                        <button class="-Button--expand -Button--typeBare -Collapse-toggle" data-toggle="collapse" href="#destCollapseItem1" role="button" aria-expanded="true" aria-controls="destCollapseItem1"> 
225                                                                                            <strong class="-Collapse-toggleContents"> 
226                                                                                                <span class="-Collapse-toggleContent">${translationsUtils.getMessage(locale,'vta.common.labels.country')}</span> 
227                                                                                                <span class="-Collapse-toggleIndicator" aria-hidden="true"></span> 
228                                                                                            </strong> 
229                                                                                        </a> 
230                                                                                    </div> 
231                                                                                    <div id="destCollapseItem1" class="-Collapse-collapse collapse show"> 
232                                                                                        <div class="-Collapse-body"> 
233                                                                                            <@printFilterCheckBoxes filter_destinationCountry "tcountry"/> 
234                                                                                        </div> 
235                                                                                    </div> 
236                                                                                </div> 
237                                                                            </div> 
238                                                                        </div> 
239                                                                    </div> 
240 
241                                                                    <#-- tem destinations --> 
242                                                                    <@printDestinationsFilter filter_destination "tdest"/> 
243 
244                                                                </div> 
245                                                            </#assign> 
246                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.destinations')> 
247                                                            <#assign curFilterStyle = ""> 
248                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
249                                                        </#if> 
250 
251                                                        <#-- interest --> 
252                                                        <#if filter_interests?size gt 0> 
253                                                            <#assign curFilterContent> 
254                                                                <@printFilterCheckBoxes filter_interests "tinterests"/> 
255                                                            </#assign> 
256                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.interest')> 
257                                                            <#assign curFilterStyle = ""> 
258                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
259                                                        </#if> 
260 
261 
262                                                        <#-- days --> 
263                                                        <#if filter_duration?size gt 0>  
264                                                            <#assign curFilterContent> 
265                                                                <div id="rangeDurations" class="-Range -stackLayout js-frange" data-space="01"> 
266                                                                    <@printRangeCombo filter_duration "${translationsUtils.getMessage(locale,'vta.webcontent.days')}" "Durations"/> 
267                                                                </div> 
268                                                            </#assign> 
269                                                            <#assign curFilterTitle = translationsUtils.getMessage(locale,'vta.webcontent.tourLength')> 
270                                                            <#assign curFilterStyle = "${(isRangePrintable(filter_duration))?then('','display:none;')}"> 
271                                                            <@printFilterSection curFilterTitle curFilterContent curFilterStyle/> 
272                                                        </#if> 
273 
274 
275                                                    </div> 
276                                                </div> 
277                                            </div> 
278                                            <div class="-Panel-foot -mdHidden"> 
279                                                <div class="-clusterLayout" data-align="center" data-justify="space-between" data-nowrap="true"> 
280                                                    <div> 
281                                                        <div> 
282                                                            <button type="button" data-toggle="collapse" data-target="#collapseFilters" aria-expanded="false" aria-controls="collapseFilters" class="-Button -Button--sizeMediumLarge -Button--typePrimary"> 
283                                                                ${translationsUtils.getMessage(locale,'vta.common.labels.apply')}</button> 
284                                                        </div> 
285                                                        <div> 
286                                                            <button type="button" data-toggle="collapse" data-target="#collapseFilters" aria-expanded="false" aria-controls="collapseFilters" class="-Button -Button--sizeMediumLarge -Button--typeLinkSecondary"> 
287                                                                ${translationsUtils.getMessage(locale,'vta.common.labels.cancel')}</button> 
288                                                        </div> 
289                                                    </div> 
290                                                </div> 
291                                            </div> 
292                                        </div> 
293                                    </div> 
294                                </div> 
295                            </div> 
296                        </div> 
297                    </div> 
298                </section> 
299 
300                <#-- list col --> 
301                <section aria-labelledby="list-section-label"> 
302                    <h2 class="sr-only" id="list-section-label">${sectionLabelList}</h2> 
303                    <div class="-stackLayout" data-space="05"> 
304                        <div class="-clusterLayout" data-space="05" data-align="center" data-justify="space-between"> 
305                            <div> 
306                                <div> 
307                                    <strong class="results-line" data-results="${entries?size}"> 
308                                        <span class="js-f-results">${entries?size}</span> 
309                                        <span class="results">${translationsUtils.getMessage(locale,'vta.webcontent.results')}</span> 
310                                        <span class="result">${translationsUtils.getMessage(locale,'vta.webcontent.result')}</span> 
311                                    </strong> 
312                                </div> 
313                                <div> 
314                                    <div class="-clusterLayout" data-space="1" data-align="center" data-justify="space-between" data-nowrap="true"> 
315                                        <div> 
316 
317                                            <#if showFilerPanel> 
318                                                <div> 
319                                                    <button type="button" class="-Button -Button--typeBare -mdHidden" id="collapseFiltersToggle" data-toggle="collapse" data-target="#collapseFilters" aria-expanded="false" aria-controls="collapseFilters"> 
320                                                        <span class="-clusterLayout" data-space="02" data-align="center" data-nowrap="true"> 
321                                                            <span> 
322                                                                <i class="-Icon -Icon--filter" aria-hidden="true"></i><span> ${translationsUtils.getMessage(locale,'vta.webcontent.filters')} </span> 
323                                                            </span> 
324                                                        </span> 
325                                                    </button> 
326                                                </div> 
327                                            </#if> 
328 
329                                            <div> 
330                                                <div class="-Collapse -Collapse--typeDropdown -Collapse--dropdownJustifyEnd"> 
331                                                    <div class="-Collapse-contents"> 
332                                                        <div class="-Collapse-content"> 
333                                                            <div class="-Collapse-head"> 
334                                                                <button id="collapseSortToggle" type="button" class="-Button -Button--typeBare collapsed" data-toggle="collapse" data-target="#collapseSort" aria-expanded="false" aria-controls="collapseSort" data-collapse-dropdown="true"> 
335                                                                    <span class="-clusterLayout" data-space="02" data-align="center" data-nowrap="true"> 
336                                                                        <span> 
337                                                                            <i class="-Icon -Icon--sort" aria-hidden="true"></i><span> ${translationsUtils.getMessage(locale,'vta.webcontent.sortBy')} </span> 
338                                                                        </span> 
339                                                                    </span> 
340                                                                </button> 
341                                                            </div> 
342                                                            <div id="collapseSort" class="-Collapse-collapse collapse" aria-labelledby="collapseSortToggle" data-dropdown-justify="end" style=""> 
343                                                                <div class="-Panel -Panel--typeFlyout -Collapse-panel -Collapse-panel--typeFlyout"> 
344                                                                    <div class="-Panel-inner"> 
345                                                                        <div class="-Panel-body -formElements"> 
346                                                                            <div class="-stackLayout js-sset" data-space="02"> 
347 
348                                                                            <#assign sortListArray = [ 
349                                                                                {"id":"Recommended", "datasort":"${sortString}", "value":"Recommended", "checked":true, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.recommended')}"}, 
350                                                                                {"id":"PriceLowToHigh", "datasort":"pr_lo", "value":"Price (low to high)", "checked":false, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.priceLowToHigh')}"}, 
351                                                                                {"id":"PriceHighToLow", "datasort":"pr_hi", "value":"Price (high to low)", "checked":false, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.priceHighToLow')}"}, 
352                                                                                {"id":"DepartureEarliestToLatest", "datasort":"de_er", "value":"Departure (earliest to latest)", "checked":false, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.departureEarliestToLatest')}"}, 
353                                                                                {"id":"DepartureLatestToEarliest", "datasort":"de_lt", "value":"Departure (latest to earliest)", "checked":false, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.departureLatestToEarliest')}"}, 
354                                                                                {"id":"DurationShortest", "datasort":"du_sh", "value":"Duration (shortest)", "checked":false, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.durationShortest')}"}, 
355                                                                                {"id":"DurationLongest", "datasort":"du_ln", "value":"Duration (longest)", "checked":false, "label":"${translationsUtils.getMessage(locale,'vta.webcontent.durationLongest')}"} 
356                                                                            ]> 
357                                                                            <#list sortListArray as item> 
358                                                                                <div class="-CustomControl -CustomControl--typeCheckMark js-sitem --focus-w"> 
359                                                                                    <div class="custom-control custom-radio"> 
360                                                                                        <label> 
361                                                                                            <input name="sortBy" data-sort="${item.datasort}" id="${item.id}" type="radio" class="-CustomControlInput custom-control-input js-sitem-input" 
362                                                                                                role="radio" value="${item.value}" ${item.checked?then('checked=""','')}> 
363                                                                                            <span class="custom-control-label"> 
364                                                                                                <span class="custom-control-label-text">${item.label}</span> 
365                                                                                            </span> 
366                                                                                        </label> 
367                                                                                    </div> 
368                                                                                </div> 
369                                                                            </#list> 
370 
371                                                                            </div> 
372                                                                        </div> 
373                                                                    </div> 
374                                                                </div> 
375                                                            </div> 
376                                                        </div> 
377                                                    </div> 
378                                                </div> 
379                                            </div> 
380 
381                                        </div> 
382                                    </div> 
383                                </div> 
384                            </div> 
385                        </div> 
386 
387                        <div id="${thisFilterScope}-list" class="-stackLayout js-f-col-list" data-space="1"> 
388                            <#if entries?has_content> 
389                                <#list entries as curEntry> 
390                                    <@printCard curEntry curEntry?index/> 
391                                </#list> 
392                            </#if> 
393                             
394                            <#-- ********* don't remove - using for service prints --> 
395                            <#-- tourtype: ${filter_tourType?size} --> 
396                            <#-- month: ${filter_month?size} --> 
397                            <#-- destinations: ${filter_destination?size} --> 
398                            <#-- price: ${filter_price_from?size} --> 
399                            <#-- country: ${filter_destinationCountry?size} --> 
400                            <#-- interest: ${filter_interests?size} --> 
401                            <#-- duration: ${filter_duration?size} --> 
402                            <#-- recomended: ${filter_recommended?size} --> 
403                            <#-- ex starting point: ${filter_estartingpoint?size} --> 
404                            <#-- ex duration: ${filter_eduration?size} --> 
405 
406                            <#-- loader --> 
407                            <#--  <div class="-LoaderContainer -LoaderContainer--variantSpinner -LoaderContainer--sizeMedium" data-state="active"></div>  --> 
408                             
409                            <div id="banner" style="display:none;"> 
410                            <#-- marketingBanner_${themeDisplay.getSiteGroupId()} --> 
411                            <#assign thisPrefs = freeMarkerPortletPreferences.getPreferences("portletSetupPortletDecoratorId", "barebone") /> 
412                            <@liferay_portlet["runtime"] 
413                                defaultPreferences="${thisPrefs}" 
414                                portletProviderAction=portletProviderAction.VIEW 
415                                instanceId="marketingBanner_${themeDisplay.getSiteGroupId()}" 
416                                portletName="com_liferay_journal_content_web_portlet_JournalContentPortlet" 
417                                /> 
418                            </div> 
419 
420                            <div id="zeroBanner" class="hidden"> 
421                            <#-- zeroBanner_${themeDisplay.getSiteGroupId()} --> 
422                            <#assign thisPrefs = freeMarkerPortletPreferences.getPreferences("portletSetupPortletDecoratorId", "barebone") /> 
423                            <@liferay_portlet["runtime"] 
424                                defaultPreferences="${thisPrefs}" 
425                                portletProviderAction=portletProviderAction.VIEW 
426                                instanceId="zeroBanner_${themeDisplay.getSiteGroupId()}" 
427                                portletName="com_liferay_journal_content_web_portlet_JournalContentPortlet" 
428                                /> 
429                            </div>  
430 
431                        </div> 
432 
433                    </div> 
434                </section> 
435 
436 
437            </div> 
438        </div> 
439         
440        </#compress> 
441        <@scripts/> 
442    </#local> 
443    <#-- /HTML cachable data -->  
444 
445<#return htmlData> 
446</#function> 
447 
448 
449<#-- ************************************** --> 
450 
451<#-- print filter section --> 
452<#macro printFilterSection title content class=""> 
453    <#if filterSectionCounter??> 
454        <#assign filterSectionCounter = filterSectionCounter + 1> 
455    <#else> 
456        <#assign filterSectionCounter = 1> 
457    </#if> 
458    <div class="-stackLayout" data-space="01" style="${class}" role="group" aria-labelledby="section-head_${filterSectionCounter}"> 
459        <div class="-stackLayout" data-space="04"> 
460            <h3 class="-Heading -Heading--typeH5Immutable -Heading--skinSharp" id="section-head_${filterSectionCounter}">${title}</h3> 
461            <hr class="-Hr"> 
462        </div> 
463        ${content}   
464    </div> 
465</#macro> 
466 
467 
468 
469 
470<#-- get last modification date by structure type --> 
471<#function getModDateForArticle article> 
472    <#local ret = "00000"> 
473    <#if article.DDMStructureId?string = structureGuidedTourId?string> 
474        <#-- get GuidedTour last modification datetime from BE --> 
475        <#if !guidedToursModDatesMap??> 
476            <#local guidedToursModDatesMap = guidedUtil.getLastModifiedMap(request)> 
477        </#if> 
478        <#if guidedToursModDatesMap[article.articleId]??> 
479            <#local ret = guidedToursModDatesMap[article.articleId]> 
480        <#else> 
481            <#-- no data on BE --> 
482            <#local ret = article.modifiedDate?datetime?string> 
483        </#if> 
484    <#else> 
485        <#-- all tours except GuidedTours --> 
486        <#local ret = article.modifiedDate?datetime?string> 
487    </#if> 
488    <#return ret> 
489</#function> 
490 
491 
492<#-- generate data and update/create cache --> 
493<#macro generateCardData curEntry index> 
494    <#local renderer=curEntry.getAssetRenderer() /> 
495    <#local cur_journalArticle=renderer.getArticle() /> 
496    <#local cur_journalArticle_Uuid = cur_journalArticle.uuid?string> 
497    <#local cur_journalArticle_ModDate = getModDateForArticle(cur_journalArticle)> 
498    <#-- articleID: ${cur_journalArticle.getArticleId()} --> 
499    <#local card_id = "${randomNamespace}tc_${index}"> 
500    <#-- cache logic --> 
501        <#if freemarkerFilterCache??> 
502            <#local thisCacheItem = freemarkerFilterCache.getArticleItem(cur_journalArticle_Uuid + cacheSufix)!"null"><#-- read cache date modification date --> 
503 
504            <#if thisCacheItem = "null"> 
505                <#local cur_cacheMessage = "No cache record ...created"> 
506                <#local thisCardData = renderCardData(cur_journalArticle)> 
507            <#elseif cur_journalArticle_ModDate == thisCacheItem.changeDate> 
508                <#local thisCardData = thisCacheItem.content!"null"><#-- read cache data --> 
509                <#if thisCardData != "null"> 
510                    <#--  <#local cur_cacheMessage = "HIT actual">  --> 
511                <#else> 
512                    <#local cur_cacheMessage = "HIT - record empty ...created"> 
513                    <#local thisCardData = renderCardData(cur_journalArticle)> 
514                </#if> 
515            <#else> 
516                <#local cur_cacheMessage = "HIT modified: ${thisCacheItem.changeDate} : ${cur_journalArticle_ModDate}<br>...updated"> 
517                <#local thisCardData = renderCardData(cur_journalArticle)> 
518            </#if> 
519        <#else> 
520            <#local thisCardData = renderCardData(cur_journalArticle)> 
521            <#local cur_cacheMessage = "Cache not installed"> 
522        </#if> 
523    <#-- end cache logic --> 
524 
525    <#local  thisCode = thisCardData> 
526    <#assign data_map = thisCode?split("<-DATA-SPLIT->")> 
527 
528    <#if !thisCode?contains("journal-template-error") && data_map?size gt 1> 
529        <#local currnetDataArray = data_map[1]?eval> 
530        <#local dataString> 
531            <@collectData currnetDataArray card_id/> 
532        </#local> 
533        <#list currnetDataArray as cur_dataArry> 
534            <#local thisJsStringRecord = '{ "id":"${card_id}","inRanges":true,"inScope":true,"sort-date":"",${collectJsString(cur_dataArry)}}'> 
535            <#assign data_set = data_set + [thisJsStringRecord]> 
536        </#list> 
537    </#if> 
538    <#if cur_cacheMessage??> 
539        <script>console.log("cache: ${card_id} ${cur_journalArticle.getTitle(locale)}, (${cur_journalArticle_ModDate}) : ${cur_cacheMessage}");</script> 
540    </#if> 
541</#macro> 
542 
543 
544 
545<#-- print a tour card from cache ONLY--> 
546<#macro printCard curEntry index> 
547    <#local renderer=curEntry.getAssetRenderer() /> 
548    <#local cur_journalArticle=renderer.getArticle() /> 
549    <#local cur_journalArticle_Uuid = cur_journalArticle.uuid?string> 
550    <#local cur_journalArticle_ModDate = getModDateForArticle(cur_journalArticle)>    
551    <#local card_id = "${randomNamespace}tc_${index}"> 
552 
553    <#-- cache logic --> 
554        <#if freemarkerFilterCache??> 
555            <#local thisCacheItem = freemarkerFilterCache.getArticleItem(cur_journalArticle_Uuid + cacheSufix)!"null"><#-- read cache date modification date --> 
556 
557            <#if thisCacheItem = "null"> 
558                <#local cur_cacheMessage = "No cache record ...created"> 
559            <#elseif cur_journalArticle_ModDate == thisCacheItem.changeDate> 
560                <#local thisCardData = thisCacheItem.content!"null"><#-- read cache data --> 
561                <#if thisCardData != "null"> 
562                    <#--  <#local cur_cacheMessage = "HIT actual">  --> 
563                <#else> 
564                    <#local cur_cacheMessage = "HIT - record empty ERRRRRRRR!"> 
565                </#if> 
566            <#else> 
567                <#local cur_cacheMessage = "HIT modified: ${thisCacheItem.changeDate} : ${cur_journalArticle_ModDate}<br>...ERRRRRRRRRR!"> 
568            </#if> 
569        <#else> 
570            <#local cur_cacheMessage = "Cache not installed"> 
571        </#if> 
572    <#-- end cache logic --> 
573 
574    <#if thisCardData?contains("journal-template-error")> 
575        <div id="${card_id}" class="d-tour" > 
576            <div style="background-color:black; color:white; padding:1em;"> 
577                <h2>*** card error ***</h2> 
578                <h4>${cur_journalArticle.getTitle()}</h4> 
579                <a href="${urlHelper}/w/${cur_journalArticle.getUrlTitle()}" target="_blank">OPEN TOUR</a> 
580                <!-- ${cur_journalArticle} --> 
581            </div> 
582            <!-- ${thisCardData} --> 
583        </div> 
584    <#elseif thisCardData?contains("PAST TOUR")> 
585        <!-- PAST TOUR: ${cur_journalArticle.getTitle()} --> 
586        <#--  <div id="${card_id}" class="d-tour" > 
587            <div style="background-color:lightskyblue; color:white; padding:1em;"> 
588                <h2>*** PAST TOUR ***</h2> 
589                <h4>${cur_journalArticle.getTitle()}</h4> 
590                <a href="${urlHelper}/w/${cur_journalArticle.getUrlTitle()}" target="_blank">OPEN TOUR</a> 
591            </div> 
592        </div>  --> 
593    <#elseif !thisCardData?contains("<-DATA-SPLIT->")> 
594        <div id="${card_id}" class="d-tour" > 
595            <div style="background-color:black; color:white; padding:1em;"> 
596                <h2>*** wrong template or webcontent ***</h2> 
597                <h4>${cur_journalArticle.getTitle()}</h4> 
598                <!-- ${cur_journalArticle} --> 
599            </div> 
600        </div> 
601    <#else> 
602        <#local data_map = thisCardData?split("<-DATA-SPLIT->")> 
603        <#--  <p style="font-size: 0.6em;">${thisJsStringRecord?replace(":",": ")?replace(",",", ")} </p>  --> 
604        <div id="${card_id}" class="d-tour js-f-tour-card hidden"><#--${(index gte 2)?then('hidden','')}--> 
605            <#if cur_cacheMessage??> 
606                <script>console.log("*cache: ${card_id} ${cur_journalArticle.getTitle(locale)} : ${cur_cacheMessage}");</script> 
607            </#if> 
608            <#--  style="font-size: 0.6em;">${thisJsStringRecord?replace(":",": ")?replace(",",", ")} --> 
609            <#--  ${thisCardData}  --> 
610            ${data_map[0]}${data_map[3]} 
611        </div> 
612         
613 
614 
615    </#if> 
616</#macro> 
617 
618<#-- render CARD data and write to cache --> 
619<#function renderCardData cur_journalArticle> 
620    <#local thisEntryData> 
621        <@liferay_journal["journal-article"] 
622            articleId=cur_journalArticle.getArticleId() 
623            ddmTemplateKey="${embedTourCardUniId}" 
624            groupId=cur_journalArticle.getGroupId() 
625        /> 
626    </#local> 
627    <#local thisEntryId = cur_journalArticle.uuid?string + cacheSufix> 
628    <#local thisEntryDate = getModDateForArticle(cur_journalArticle)> 
629    <#if freemarkerFilterCache??> 
630        <#local writeMe = freemarkerFilterCache.putArticleItem(thisEntryId, thisEntryDate, thisEntryData)><#-- update cache --> 
631    </#if> 
632    <#return thisEntryData> 
633</#function> 
634 
635<#function collectJsString hash> 
636    <#local retString = ""> 
637    <#list hash as key,val> 
638        <#local retString = retString + '"${key}": ' + (val?is_number)?then('${val}','"${val}"') + (key?is_last)?then('',', ')> 
639    </#list> 
640    <#return retString> 
641</#function> 
642 
643 
644<#-- data collect --> 
645<#macro collectData hashArry id> 
646    <#list hashArry as cur_hash> 
647        <#list cur_hash as key,val> 
648            <#if val?string=""> 
649                <#continue><#-- skip empty val --> 
650            </#if> 
651            ${key}="${val}" 
652            <#if val?contains(",")> 
653                <#assign value = val?split(",")> 
654            <#else> 
655                <#assign value = [val]> 
656            </#if> 
657            <#if key = "data-ttype"> 
658                <#assign filter_tourType = filter_tourType + value/> 
659            <#elseif key = "data-tmonth"> 
660                <#assign filter_month = filter_month + value/> 
661            <#elseif key = "data-tdest"> 
662                <#assign filter_destination = filter_destination + value/> 
663            <#elseif key = "data-tprice"> 
664                <#assign filter_price_from = filter_price_from + value/> 
665            <#elseif key = "data-tcountry"> 
666                <#assign filter_destinationCountry = filter_destinationCountry + value/> 
667            <#elseif key = "data-tinterests"> 
668                <#assign filter_interests = filter_interests + value/> 
669            <#elseif key = "data-tlength"> 
670                <#assign filter_duration = filter_duration + value/> 
671            <#elseif key = "data-trec" && val?string != ""> 
672                <#assign filter_recommended = filter_recommended + value/> 
673            <#elseif key = "data-estartingp" && val != ""> 
674                <#assign filter_estartingpoint = filter_estartingpoint + value/> 
675            <#elseif key = "data-eduration"> 
676                <#assign filter_eduration = filter_eduration + value/> 
677            </#if> 
678        </#list> 
679    </#list> 
680</#macro> 
681 
682<#-- print a range inside combo --> 
683<#macro printRangeCombo array units name> 
684    <#local cur_array = []> 
685    <#local minMaxStringsMapsArry = [{ 
686        "name":"Prices", 
687        "min":translationsUtils.getMessage(locale,'vta.webcontent.rangePricesFrom'), 
688        "max":translationsUtils.getMessage(locale,'vta.webcontent.rangePricesTo') 
689    },{ 
690        "name":"Durations", 
691        "min":translationsUtils.getMessage(locale,'vta.webcontent.rangeTourLengthMin'), 
692        "max":translationsUtils.getMessage(locale,'vta.webcontent.rangeTourLengthMax') 
693    }]> 
694    <#if array?size != 0> 
695        <#list array as item> 
696            <#if item?is_number> 
697                <#-- item is a valid number --> 
698                <#local cur_array = cur_array + [item?number]> 
699            <#else> 
700                <#-- item is not a number! --> 
701                <!-- array: ${array?join(", ")} --> 
702                <!-- item: ${item} --> 
703                <#local cur_array = [0,1]> 
704                <#break> 
705            </#if> 
706        </#list> 
707 
708        <#local rangeMinLabel = (minMaxStringsMapsArry?filter(item -> item.name == name)?size == 1)?then((minMaxStringsMapsArry?filter(item -> item.name == name)[0].min),'Range Min')> 
709        <#local rangeMaxLabel = (minMaxStringsMapsArry?filter(item -> item.name == name)?size == 1)?then((minMaxStringsMapsArry?filter(item -> item.name == name)[0].max),'Range Max')> 
710 
711        <#local cur_min = cur_array?min> 
712        <#local cur_max = cur_array?max> 
713        <#local cur_step = "1"> 
714        <div class="-Range-Value"> 
715            <span class="-Range-fromValue" data-from-value="">${cur_min}</span> 
716            <span class="-Range-fromValueSuffix">${units}</span> 
717            <span class="-Range-valueSeparator">-</span> 
718            <span class="-Range-toValue" data-to-value="">${cur_max}</span> 
719            <span class="-Range-toValueSuffix">${units}</span> 
720        </div> 
721        <div class="-Range-control"> 
722            <input type="range" id="from${name}" name="from${name}" data-from=""  
723                value="${cur_min}" min="${cur_min}" max="${cur_max}" step="${cur_step}" aria-label="${rangeMinLabel}"> 
724            <input type="range" id="to${name}" name="to${name}" data-to=""  
725                value="${cur_max}" min="${cur_min}" max="${cur_max}" step="${cur_step}" aria-label="${rangeMaxLabel}" 
726                style="background: linear-gradient(to right, 
727                var(--_range-control-secondary-color) 0%, 
728                var(--_range-control-secondary-color) 20%, 
729                var(--_range-control-primary-color) 20%, 
730                var(--_range-control-primary-color) 66.66666666666666%, 
731                var(--_range-control-secondary-color) 66.66666666666666%, 
732                var(--_range-control-secondary-color) 100%); z-index: 0;"> 
733        </div> 
734    </#if> 
735 
736</#macro> 
737 
738<#function isRangePrintable array> 
739    <#local cur_array = []> 
740    <#if array?size != 0> 
741        <#list array as item> 
742            <#attempt> 
743                <#-- try --> 
744                <#local cur_array = cur_array + [item?number]> 
745            <#recover> 
746                <#local cur_array = [0,1]> 
747                <#break> 
748            </#attempt> 
749        </#list> 
750        <#if cur_array?min != cur_array?max> 
751            <#return true> 
752        </#if> 
753    </#if> 
754    <#return false> 
755</#function> 
756 
757 
758<#macro printDestinationsFilter array type> 
759    <#-- get array of destinations with types --> 
760    <#local otherTypeName = translationsUtils.getMessage(locale,'vta.webcontent.other')> 
761    <#local popularTypeName = "popular"><#-- default value if no popular tour... --> 
762    <#local existPopulars = false> 
763    <#local existOthers = false> 
764    <#local destArray = []> 
765    <#-- DEST : ${array?size} --> 
766    <#-- DEST : ${array?join(", ")} --> 
767     
768    <#local allUniqueDestIds = getAllUniqueArray(array)> 
769    <#-- UNIQ : ${allUniqueDestIds?size} --> 
770    <#-- UNIQ : ${allUniqueDestIds?join(", ")} --> 
771    <#list allUniqueDestIds as item> 
772        <#local popular = readByClassPkAndVocIdWcCatName(item vocPopularityId "None")><#-- return name or "error" for missing classPk --> 
773        <#if popular != "None" && popular != "error" > 
774            <#local typeName = popular> 
775            <#local popularTypeName = popular> 
776            <#local existPopulars = true> 
777        <#else> 
778            <#local typeName = readByClassPkAndVocIdWcCatName(item vocDestTypenId "${otherTypeName}")> 
779            <#local existOthers = true> 
780        </#if> 
781 
782        <#local destArray = destArray + [{ "typeName":typeName, "destId":item }]> 
783    </#list> 
784 
785    <#-- get array of unique types (labels of sections)--> 
786    <#local allUniqueTypes = []> 
787    <#if existPopulars><#-- add populars at start --> 
788        <#local allUniqueTypes = allUniqueTypes + [popularTypeName]> 
789    </#if> 
790    <#list destArray?sort_by("typeName") as item> 
791        <#if !(allUniqueTypes?seq_contains(item.typeName)) && item.typeName != popularTypeName && item.typeName != otherTypeName> 
792            <#local allUniqueTypes = allUniqueTypes + [item.typeName]> 
793        </#if> 
794    </#list> 
795    <#if existOthers><#-- add populars at end --> 
796        <#local allUniqueTypes = allUniqueTypes + [otherTypeName]> 
797    </#if> 
798     
799    <#-- iterate each type sets --> 
800    <#list allUniqueTypes as cur_item> 
801        <#-- types: ${cur_item} - ${popularTypeName} --> 
802        <#local filteredDestNames = destArray?filter(item -> item.typeName == cur_item)?map(item -> item.destId)> 
803        <#local collapseName = cur_item?replace("[^0-9a-zA-Z_]", "_", "r")> 
804        <#local openDropDown = (cur_item == popularTypeName)> 
805        <div> 
806            <div class="-Collapse -Collapse--typeChevron"> 
807                <div class="-Collapse-contents"> 
808                    <div class="-Collapse-content"> 
809                        <div class="-Collapse-head"> 
810                            <button class="-Button--expand -Button--typeBare -Collapse-toggle" data-toggle="collapse" role="button" aria-expanded="${openDropDown?c}" 
811                                href="#${collapseName}Item" aria-controls="${collapseName}Item"> 
812                                <h4 class="-Collapse-toggleContents -Heading -Heading--typeH6 -Heading--skinSharp"> 
813                                    <span class="-Collapse-toggleContent">${cur_item}</span> 
814                                    <span class="-Collapse-toggleIndicator" aria-hidden="true"></span> 
815                                </h4> 
816                            </button> 
817                        </div> 
818                        <div id="${collapseName}Item" class="-Collapse-collapse collapse ${openDropDown?then('show','')}"> 
819                            <div class="-Collapse-body"> 
820                             
821                            <@printFilterCheckBoxes filteredDestNames type/> 
822 
823                            </div> 
824                        </div> 
825                    </div> 
826                </div> 
827            </div> 
828        </div> 
829 
830    </#list> 
831     
832 
833</#macro> 
834 
835 
836<#function getAllUniqueArray array> 
837    <#-- create array of unique items from array --> 
838    <#local allUniqueItems = []> 
839    <#list array as item> 
840        <#if !(allUniqueItems?seq_contains(item))> 
841            <#local allUniqueItems = allUniqueItems + [item]> 
842        </#if> 
843    </#list> 
844 
845    <#return allUniqueItems> 
846</#function> 
847 
848 
849 
850<#-- filtr checkboxes --> 
851<#macro printFilterCheckBoxes array type> 
852 
853    <#local allUniqueItems = getAllUniqueArray(array)> 
854    <#local printArray = []> 
855    <#list allUniqueItems?sort as item> 
856        <#local screen_name = item> 
857        <#if item?string = ""> 
858            <#continue> 
859        <#elseif type = "tdest"> 
860            <#local screen_name = readByClassPkWebContentField(item,"ScreenName")> 
861        <#elseif type = "ttype"> 
862            <#local langKey = vtaLibrary.getTemplateForStructure(screen_name,"lang")> 
863            <#local screen_name = translationsUtils.getMessage(locale,langKey)> 
864        <#elseif type = "tinterests" || type = "estartingp"> 
865            <#local screen_name = assetCategoryService.fetchCategory(screen_name?number).getTitle(locale)> 
866        <#elseif type = "tcountry" && screen_name != "No country"> 
867            <#local screen_name = assetCategoryService.fetchCategory(screen_name?number).getTitle(locale)> 
868        <#elseif type = "eduration"> 
869            <#switch item?string> 
870            <#case "0"> 
871                <#local screen_name = translationsUtils.getMessage(locale,'vta.webcontent.short.up.2.hrs')> 
872                <#break> 
873            <#case "1"> 
874                <#local screen_name = translationsUtils.getMessage(locale,'vta.webcontent.medium')> 
875                <#break> 
876            <#case "2"> 
877                <#local screen_name = translationsUtils.getMessage(locale,'vta.webcontent.long.8plus.hrs')> 
878                <#break> 
879            <#default> 
880                <#local screen_name = "Unknown"> 
881            </#switch> 
882        </#if> 
883        <#local count = array?filter(it -> it == item)?size > 
884        <#local printArray = printArray + [{"screenName":screen_name, "item":item, "count":count}]> 
885    <#-- ${item}, ${screen_name}, ${count} --> 
886    </#list> 
887 
888    <div class="-stackLayout js-fset" data-ftype="${type}" data-space="04"> 
889        <#list printArray?sort_by("screenName") as item> 
890            <@printFilterCheckboxItem item.item item.screenName item.count type/> 
891        </#list> 
892    </div> 
893</#macro> 
894 
895        <#-- print one checkbox --> 
896        <#macro printFilterCheckboxItem item screen_name count type> 
897            <div class="custom-control custom-checkbox js-fitem"> 
898                <label> 
899                    <input type="checkbox" 
900                        class="-CustomControlInput custom-control-input js-fitem-input" 
901                        data-fname="${item}" 
902                        role="checkbox" value="${screen_name}"> 
903                    <span class="custom-control-label"> 
904                        <span class="custom-control-label-text filter-item">${screen_name}&nbsp;(<span class="-colorSecondaryPale js-fitem-count">${count}</span>)</span> <#-- &nbsp; to prevent orphan a number in the responsive design --> 
905                    </span> 
906                </label> 
907            </div> 
908        </#macro> 
909 
910 
911<#-- month list --> 
912<#macro printFilterDates array year> 
913    <div class="-gridLayout js-fset" data-fragment="1of4" data-space="02" data-overflowvisible="true" data-ftype="tmonth"> 
914        <div> 
915            <#-- ${array?sort?join(", ")} --> 
916            <#list 1..12 as cur_month> 
917            <#local cur_fname = year + "-" + cur_month?left_pad(2, "00")> 
918            <#local cur_is_enabled = array?seq_contains(cur_fname)> 
919            <#if year?number == curYearYY?number && cur_month?number lt curMonthMM?number><#--disable past months--> 
920                <#local cur_is_enabled = false> 
921            </#if> 
922            <#-- *${cur_fname}* --> 
923            <#local cur_temp_date = dateUtil.parseDate("yyyy-MM-dd", "1999-" + cur_month?left_pad(2, "00") + "-01", locale)><#-- fake date 1999-MM-01 --> 
924            <#local cur_month_string = dateUtil.getDate(cur_temp_date, "MMM", locale)> 
925                <div> 
926                    <div class="-CustomControl -CustomControl--typeButton"> 
927                        <div class="custom-control custom-checkbox ${cur_is_enabled?then('js-fitem','')}"> 
928                            <label> 
929                                <input name="departureMonth" 
930                                    type="checkbox" 
931                                    class="-CustomControlInput custom-control-input ${cur_is_enabled?then('js-fitem-input','')}" 
932                                    role="checkbox" value="${cur_month_string}" 
933                                    ${cur_is_enabled?then('data-fname="${cur_fname}"','')} 
934                                    ${cur_is_enabled?then("","disabled")}> 
935                                <span class="custom-control-label"> 
936                                    <span class="custom-control-label-text">${cur_month_string}</span> 
937                                </span> 
938                            </label> 
939                        </div> 
940                    </div> 
941                </div> 
942            </#list> 
943        </div> 
944    </div> 
945</#macro> 
946 
947<#-- read a filed form webcontent --> 
948<#function readByClassPkWebContentField classPK fieldReference> 
949    <#local ret = "*****"> 
950    <#if classPK !=""> 
951        <#local journalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")> 
952        <#local journalArticle = journalArticleLocalService.fetchLatestArticle(classPK?number)> 
953        <#local docXML = saxReaderUtil.read(journalArticle.getDocument().asXML())> 
954        <#local ret = docXML.selectSingleNode("/root/dynamic-element[@field-reference='${fieldReference}']/dynamic-content").getData()> 
955        <#assign counter = counter + 1> 
956    </#if> 
957    <#return ret> 
958</#function> 
959 
960<#-- read a category name form webcontent by classPK a vocabularyId--> 
961<#function readByClassPkAndVocIdWcCatName classPK vocabularyId noCategorySetReturnString> 
962    <#local ret = "error"> 
963    <#if classPK !=""> 
964        <#local assetCategoryLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryLocalService") /> 
965        <#local categoryList=assetCategoryLocalService.getCategories("com.liferay.journal.model.JournalArticle",classPK?number) > 
966         
967        <#-- this category is NOT multioptional (if yes only first item will be returned --> 
968        <#local name = noCategorySetReturnString> 
969        <#list categoryList as category> 
970            <#if category.vocabularyId = vocabularyId> 
971                <#local name = category.getTitle(locale)> 
972            </#if> 
973        </#list> 
974 
975        <#local ret = name > 
976    </#if> 
977    <#return ret> 
978</#function> 
979 
980<#macro scripts> 
981    <#-- min/max price and length --> 
982    <#assign priceArray = []> 
983    <#list filter_price_from as item> 
984        <#if item?string != ""> 
985        <#assign priceArray = priceArray + [item?number]> 
986        </#if> 
987    </#list> 
988    <#if priceArray?size = 0> 
989        <#assign priceArray = [0,1]> 
990    </#if> 
991 
992 
993    <#assign durationArray = []> 
994    <#list filter_duration as item> 
995        <#if item?string != ""> 
996        <#assign durationArray = durationArray + [item?number]> 
997        </#if> 
998    </#list> 
999    <#if durationArray?size = 0> 
1000        <#assign durationArray = [0,1]> 
1001    </#if> 
1002    <script> 
1003 
1004        ;AUI().ready(function() { 
1005            // All data source 
1006            var filterDataArray = [ 
1007                <#list data_set as item> 
1008                    ${item}<#sep>,</#sep> 
1009                </#list> 
1010            ]; 
1011 
1012            var dataObject = { 
1013                thisOrFilters: ["ttype","tmonth"], 
1014                filterDataArray: filterDataArray, 
1015                thisFilterCol: document.getElementById("${thisFilterScope}-filter"), 
1016                thisResultsCol: document.getElementById("${thisFilterScope}-list"), 
1017                rangePricesId: "rangePrices", 
1018                rangeDurationsId: "rangeDurations", 
1019                defaultRangePriceFrom: ${priceArray?min}, 
1020                defaultRangePriceTo: ${priceArray?max}, 
1021                defaultRangeLengthFrom: ${durationArray?min}, 
1022                defaultRangeLengthTo: ${durationArray?max}, 
1023                rangePriceFrom: ${priceArray?min}, 
1024                rangePriceTo: ${priceArray?max}, 
1025                rangeLengthFrom: ${durationArray?min}, 
1026                rangeLengthTo: ${durationArray?max}, 
1027                defaultSort: "${sortString}" 
1028            }; 
1029 
1030            handleRangeComponent(".-Range"); 
1031            startFilter(dataObject); 
1032        }); 
1033 
1034    </script> 
1035 
1036    <#--  <script> // DEBUG SCRIPT 
1037         
1038            var filterDataArray = [ 
1039                <#list data_set as item> 
1040                    ${item}<#sep>,</#sep> 
1041                </#list> 
1042            ]; 
1043 
1044            var dataObject = { 
1045                thisOrFilters: ["ttype","tmonth"], 
1046                filterDataArray: filterDataArray, 
1047                thisFilterCol: document.getElementById("${thisFilterScope}-filter"), 
1048                thisResultsCol: document.getElementById("${thisFilterScope}-list"), 
1049                rangePricesId: "rangePrices", 
1050                rangeDurationsId: "rangeDurations", 
1051                defaultRangePriceFrom: ${priceArray?min}, 
1052                defaultRangePriceTo: ${priceArray?max}, 
1053                defaultRangeLengthFrom: ${durationArray?min}, 
1054                defaultRangeLengthTo: ${durationArray?max}, 
1055                rangePriceFrom: ${priceArray?min}, 
1056                rangePriceTo: ${priceArray?max}, 
1057                rangeLengthFrom: ${durationArray?min}, 
1058                rangeLengthTo: ${durationArray?max}, 
1059                defaultSort: "${sortString}" 
1060            }; 
1061 
1062            //handleRangeComponent('.-Range'); 
1063            //startFilter(dataObject); 
1064 
1065 
1066    </script>  --> 
1067 
1068 
1069 
1070    <script> 
1071 
1072        ;function startSwipers(swiperContainers) { 
1073                    // + init swipers 
1074                function setSwiper(container, index) { 
1075                    let thumbContainer = container.querySelector('.js-swiper-thumb'); 
1076                    let mainContainer = container.querySelector('.js-swiper-main'); 
1077 
1078                    if (!thumbContainer.swiper) { 
1079                        var swiperThumb = new Swiper(thumbContainer, { 
1080                            spaceBetween: 2, 
1081                            speed: 500, 
1082                            grabCursor: true, 
1083                            keyboard: { 
1084                                enabled: true, 
1085                            }, 
1086                            slidesPerView: 3, 
1087                            freeMode: { 
1088                                enabled: true, 
1089                                sticky: true, 
1090                            }, 
1091                            watchSlidesProgress: false, 
1092                        }); 
1093                     
1094                        var swiperMain = new Swiper(mainContainer, { 
1095                            spaceBetween: 2, 
1096                            speed: 500, 
1097                            grabCursor: true, 
1098                            keyboard: { 
1099                                enabled: true, 
1100                            }, 
1101                            navigation: { 
1102                                nextEl: thumbContainer.querySelector('.swiper-button-next'), 
1103                                prevEl: thumbContainer.querySelector('.swiper-button-prev'), 
1104                            }, 
1105                            thumbs: { 
1106                                swiper: swiperThumb, 
1107                            }, 
1108                        }); 
1109 
1110                        // Uložit instance Swiperu, pokud je třeba s nimi dále pracovat 
1111                        thumbContainer.swiperInstance = swiperThumb; 
1112                        mainContainer.swiperInstance = swiperMain; 
1113
1114                    else { 
1115                        console.log(index, "uz existuje"); 
1116
1117                }; 
1118 
1119                var observerOptions = { 
1120                                root: null, // Viewport jako kořen 
1121                                rootMargin: '0px', 
1122                                threshold: 0.1 // Spustí se, když je alespoň 10% prvku viditelné 
1123                            }; 
1124 
1125                var observer = new IntersectionObserver((entries, observer) => { 
1126                    entries.forEach(entry => { 
1127                        if (entry.isIntersecting) { 
1128                            setSwiper(entry.target); 
1129                            observer.unobserve(entry.target); // Přestat sledovat prvek po inicializaci Swiperu 
1130
1131                    }); 
1132                }, observerOptions); 
1133 
1134                swiperContainers.forEach(container => { 
1135                    observer.observe(container); // Začít sledovat každý kontejner 
1136                }); 
1137        }; 
1138 
1139        ;AUI().ready(function() { 
1140            var swContainer = document.querySelectorAll('.js-swipers-container');  
1141            startSwipers(swContainer); 
1142        }); 
1143 
1144    </script> 
1145</#macro>