Japanspecialist | Resultados

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