Ocorreu um erro ao processar o template.
Java method "as.asac.template.tools.DLToolImpl.getThumbnailByJSON(String, String)" threw an exception when invoked on as.asac.template.tools.DLToolImpl object "as.asac.template.tools.DLToolImpl@413c4e62"; see cause exception in the Java stack trace.
----
FTL stack trace ("~" means nesting-related):
- Failed at: #assign slideThumbnail1 = dlTool.getT... [in template "37703#37743#8258493" at line 703, column 81]
----
1<#-- Services -->
2<#assign assetEntryLocalServiceUtil = serviceLocator.findService("com.liferay.asset.kernel.service.AssetEntryLocalService")/>
3<#assign assetLinkLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetLinkLocalService")/>
4<#assign journalArticleResourceServiceUtil = serviceLocator.findService("com.liferay.journal.service.JournalArticleResourceLocalService")/>
5<#assign assetVocabularyLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetVocabularyLocalService") />
6<#assign assetCategoryLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryLocalService")>
7<#assign ddmStructureLocalService = serviceLocator.findService("com.liferay.dynamic.data.mapping.service.DDMStructureLocalService")/>
8
9<#-- Reserved vbles -->
10<#assign title = .vars['reserved-article-title'].data>
11<#assign articleId=.vars["reserved-article-id"].data />
12<#assign description=.vars["reserved-article-description"].data />
13<#assign smallImageUrl=.vars["reserved-article-small-image-url"].data />
14<#assign date=.vars["reserved-article-display-date"].data />
15<#assign request = .vars['request']>
16
17<#-- Init -->
18<#assign assetEntry = journalTool.getAssetEntryByArticleId(groupId, articleId)>
19<#assign journalArticle = journalTool.getJournalArticleByAssetEntry(assetEntry)>
20<#assign resourcePrimKey = journalArticle.getResourcePrimKey()>
21<#assign articleURL = themeDisplay.getURLPortal()+themeDisplay.getURLCurrent()>
22<#assign articleSocialBookmarks = themeDisplay.getThemeSetting("article-social-bookmarks")!>
23<#assign layoutSetBannerPath = layoutTool.getLayoutSetBannerPath(groupId, themeDisplay.getLayout().isPrivateLayout())!>
24<#assign articleMainImageThumbnail1 = dlTool.getThumbnail(smallImageUrl, "1", layoutSetBannerPath)! />
25<#assign articleMainImageThumbnail3 = dlTool.getThumbnail(smallImageUrl, "3", layoutSetBannerPath)! />
26<#assign articleMainImageThumbnail1 = dlTool.getThumbnail(smallImageUrl, "1")! />
27<#assign ddmStructureNameNormalize = "template-${friendlyURLNormalizerTool.normalize(journalArticle.getDDMStructure().getName(localeUtil.getDefault()))}" />
28<#assign group = themeDisplay.getScopeGroup()/>
29<#setting time_zone="Europe/Madrid">
30
31<#-- Settings -->
32<#assign schema = "http://schema.org/Article"/>
33<#assign ddmStructure = journalArticle.getDDMStructure() />
34<#assign structureId = "" />
35<#assign structureKey = "" />
36<#assign filterStructuresIds = ""/>
37<#assign filterStructuresKeys = []>
38<#assign filterStructures = []>
39<#assign filterDDMStructures = []>
40<#if validator.isNotNull(ddmStructure)>
41 <#assign structureId = ddmStructure.getStructureId() />
42 <#assign structureKey = ddmStructure.getStructureKey()/>
43 <#assign filterStructuresIdsKey = "${structureId}[filterStructuresIds]"/>
44 <#assign filterStructuresIdsValue = group.getTypeSettingsProperty(filterStructuresIdsKey)!/>
45 <#if validator.isNotNull(filterStructuresIdsValue)>
46 <#assign filterStructuresIds = getterUtil.getLongValues(stringUtil.split(filterStructuresIdsValue))/>
47 <#list filterStructuresIds as filterStructuresId>
48 <#assign filterStructure = ddmStructureLocalService.fetchDDMStructure(filterStructuresId)/>
49 <#if validator.isNotNull(filterStructure)>
50 <#assign filterStructureKey = filterStructure.getStructureKey()/>
51 <#assign filterStructuresKeys = filterStructuresKeys + [filterStructureKey] >
52 <#assign filterDDMStructures = filterDDMStructures + [filterStructure] >
53 </#if>
54 </#list>
55 </#if>
56 <#assign schemaKey = "${ddmStructure.getStructureKey()}[schema]"/>
57 <#assign schemaValue = group.getTypeSettingsProperty(schemaKey)!/>
58 <#if validator.isNotNull(schemaValue)>
59 <#assign schema = "${schemaValue}"/>
60 </#if>
61</#if>
62
63<#-- Settings Cicloturismo -->
64<#assign tracksModesJSONObject = "" />
65<#assign routeDetailServicesDistance = 5.0 />
66<#assign ddmStructureSettingsJSONObject = "" />
67<#assign templateVblesJSONObject = jsonFactoryUtil.createJSONObject(group.getTypeSettingsProperty("templateVbles"))!/>
68<#if validator.isNotNull(templateVblesJSONObject) && templateVblesJSONObject.has("cicloturismo")>
69 <#assign micrositeJSONObject = templateVblesJSONObject.getJSONObject("cicloturismo")!/>
70 <#assign tracksModesOrderJSONArray = micrositeJSONObject.getJSONArray("tracksModesOrder")!/>
71 <#assign tracksModesJSONObject = micrositeJSONObject.getJSONObject("tracksModes")!/>
72 <#assign ddmStructureSettingsJSONObject = micrositeJSONObject.getJSONObject("structureSettings")!/>
73 <#assign routeDetailServicesDistance = templateVblesJSONObject.getJSONObject("cicloturismo").getDouble("routeDetailServicesDistance")!/>
74</#if>
75
76<#-- Vocabularies -->
77<#assign concejosVocabulary = assetVocabularyLocalService.fetchGroupVocabulary(groupId, "Concejos")! />
78<#assign modeVocabulary = assetVocabularyLocalService.fetchGroupVocabulary(groupId, "Cicloturismo :: Temática/Modalidad")! />
79<#assign routeTypeVocabulary = assetVocabularyLocalService.fetchGroupVocabulary(groupId, "Cicloturismo :: Tipo de Ruta")! />
80<#assign trackVocabulary = assetVocabularyLocalService.fetchGroupVocabulary(groupId, "Cicloturismo :: Recorrido")! />
81<#assign tracksVocabulary = assetVocabularyLocalService.fetchGroupVocabulary(groupId, "Cicloturismo :: Recorridos")! />
82<#assign routeVocabularyIds = [modeVocabulary.getVocabularyId(), routeTypeVocabulary.getVocabularyId() , trackVocabulary.getVocabularyId(), tracksVocabulary.getVocabularyId()] />
83
84<#-- Categories -->
85<#assign concejos = journalTool.getCategories(groupId, articleId, ["Concejos"])/>
86<#assign comarcas = journalTool.getCategoriesNames(groupId, articleId, locale, ["Comarcas"])/>
87<#assign tipoRuta = journalTool.getCategoriesNames(groupId, articleId, locale, ["Cicloturismo :: Tipo de Ruta"])/>
88<#assign modalidad = journalTool.getCategoriesNames(groupId, articleId, locale, ["Cicloturismo :: Temática/Modalidad"])/>
89<#assign tipoRecorrido = journalTool.getCategoriesNames(groupId, articleId, locale, ["Cicloturismo :: Recorrido"])/>
90<#assign tipoRecorridos = journalTool.getCategoriesNames(groupId, articleId, locale, ["Cicloturismo :: Recorridos"])/>
91<#assign dificultad = journalTool.getCategories(groupId, articleId, ["Microsite :: Dificultad"])/>
92<#assign duracion = journalTool.getCategoriesNames(groupId, articleId, locale, ["Cicloturismo :: Duración"])/>
93<#assign routeTypesCategories = assetCategoryTool.getAssetCategoriesByVocabularyName(tracksVocabulary)! />
94
95<#-- Build -->
96<#assign numero = Numero.data>
97<#assign routeTag = "rutacicloturismo${numero}">
98
99<#assign portletId = portletTool.getPortletId(request)!/>
100<#assign namespace = "_"+portletId+"_" />
101<#if Denominacion.data?has_content>
102 <#assign title = Denominacion.data>
103</#if>
104<#assign markersServicesDDMStructureKeys = [] />
105<#assign markersNotices = [] />
106<#assign markersServicesDDMStructureKeys = [] />
107
108<#-- GPX -->
109<#assign gpxRutaPath = ""/>
110<#assign gpxRutaJSONObject = ""/>
111<#assign gpxRoute = ""/>
112<#assign gpxPOIRutaPath = ""/>
113<#assign gpxPOIRutaJSONObject = ""/>
114<#assign gpxPOIRoute = ""/>
115
116<#if validator.isNotNull(Documentos.GPXRuta.data) && Documentos.GPXRuta.getData()!="">
117 <#assign gpxRutaJSONStr = Documentos.GPXRuta.data! />
118 <#assign gpxRutaPath = dlTool.getPathByJSON(gpxRutaJSONStr, themeDisplay.getScopeGroupId())!/>
119 <#assign gpxRutaJSONObject = jsonFactoryUtil.createJSONObject(Documentos.GPXRuta.data)! />
120 <#assign gpxRoute = gpxTool.parser(gpxRutaJSONObject.getLong("classPK"), "Parser", themeDisplay)! />
121
122</#if>
123<#if validator.isNotNull(Documentos.GPXPOIRuta.data) && Documentos.GPXPOIRuta.getData()!="">
124 <#assign gpxPOIRutaJSONStr = Documentos.GPXPOIRuta.data! />
125 <#assign gpxPOIRutaPath = dlTool.getPathByJSON(gpxPOIRutaJSONStr, themeDisplay.getScopeGroupId())!/>
126 <#assign gpxPOIRutaJSONObject = jsonFactoryUtil.createJSONObject(Documentos.GPXPOIRuta.data)! />
127 <#assign gpxPOIRoute = gpxTool.parser(gpxPOIRutaJSONObject.getLong("classPK"), "Parser", themeDisplay)! />
128</#if>
129
130
131
132
133<#-- Near routes -->
134<#assign gpxRoutes = [] />
135<#assign classTypeIds = [structureId]/>
136<#assign routesNearJournalArticles = assetNearTool.getNearJournalArticles(themeDisplay.getScopeGroupId(), assetEntry.getEntryId(), 50.0, classTypeIds, 5, true, [])! />
137<#list routesNearJournalArticles as routeNearJournalArticle>
138
139 <#assign routeNearJournalArticleArticleId = routeNearJournalArticle.getArticleId()! >
140 <#assign routeNearJournalArticleResourcePrimKey = routeNearJournalArticle.getResourcePrimKey()! >
141 <#assign routeNearJournalArticleJSONObject = journalTool.contentXMLtoJSONObject(routeNearJournalArticle.getContentByLocale(locale), locale)/>
142 <#assign routeNearJournalArticleEntryTitle = htmlUtil.escape(routeNearJournalArticle.getTitle(locale)) />
143 <#assign routeNearJournalArticleViewURL = journalTool.getDisplayPage(routeNearJournalArticle, themeDisplay, true) />
144 <#assign routeNearJournalArticleThumbnailPath = routeNearJournalArticle.getSmallImageURL()! />
145 <#assign routeNearJournalArticleThumbnail = dlTool.getThumbnail(routeNearJournalArticleThumbnailPath, "2", layoutSetBannerPath)! />
146
147 <#-- Categories -->
148 <#assign rutaCercanaTipoRuta = "" />
149 <#assign rutaCercanaModalidad = "" />
150 <#assign rutaCercanaTipoRecorrido = "" />
151 <#assign rutaCercanaTipoRecorridos = "" />
152 <#assign rutaCercanaColor = "000" />
153 <#assign journalArticleCategories = assetCategoryLocalService.getCategories("com.liferay.journal.model.JournalArticle", routeNearJournalArticleResourcePrimKey) />
154 <#list journalArticleCategories as journalArticleCategory>
155
156 <#assign vocabularyId = journalArticleCategory.getVocabularyId() />
157 <#assign level = 1 />
158 <#if validator.isNotNull(journalArticleCategory.getAncestors())>
159 <#assign level = journalArticleCategory.getAncestors()?size + 1 />
160 </#if>
161
162 <#if vocabularyId == routeTypeVocabulary.getVocabularyId()>
163 <#assign rutaCercanaTipoRuta = journalArticleCategory.getTitle(locale) />
164 </#if>
165
166 <#if vocabularyId == modeVocabulary.getVocabularyId()>
167 <#assign rutaCercanaModalidad = journalArticleCategory.getTitle(locale) />
168 </#if>
169
170 <#if vocabularyId == trackVocabulary.getVocabularyId()>
171 <#assign rutaCercanaTipoRecorrido = journalArticleCategory.getTitle(locale) />
172 </#if>
173
174 <#if vocabularyId == tracksVocabulary.getVocabularyId()>
175 <#if level == 1>
176 <#assign type = assetCategoryTool.getCategoryProperty(journalArticleCategory.getCategoryId(), "type") />
177 <#if type != "links">
178 <#assign rutaCercanaColor = assetCategoryTool.getCategoryProperty(journalArticleCategory.getCategoryId(), "color") />
179 <#assign rutaCercanaTipoRecorridos = journalArticleCategory.getTitle(locale) />
180 </#if>
181 </#if>
182 </#if>
183
184 </#list>
185
186 <#assign rutaCercanaIbp = routeNearJournalArticleJSONObject.getString("IBP")! />
187 <#assign rutaCercanaDistancia = routeNearJournalArticleJSONObject.getString("Distancia")! />
188 <#assign rutaCercanaInicio = routeNearJournalArticleJSONObject.getString("Inicio")! />
189 <#assign rutaCercanaFinalizacion = routeNearJournalArticleJSONObject.getString("Finalizacion")! />
190 <#assign rutaCercanaGpxRuta = routeNearJournalArticleJSONObject.getJSONObject("Documentos").getString("GPXRuta")! />
191 <#assign rutaCercanaGpxPOIRuta = routeNearJournalArticleJSONObject.getJSONObject("Documentos").getString("GPXPOIRuta")! />
192 <#assign rutaCercanaKmlRuta = routeNearJournalArticleJSONObject.getJSONObject("Documentos").getString("KMLRuta")! />
193 <#assign rutaCercanaDenominacion = routeNearJournalArticleJSONObject.getString("Denominacion")! />
194 <#if validator.isNotNull(rutaCercanaDenominacion)>
195 <#assign routeNearJournalArticleEntryTitle = rutaCercanaDenominacion !/>
196 </#if>
197
198 <#assign rutaCercanaInicioFinalizacion = rutaCercanaInicio! />
199 <#if validator.isNotNull(rutaCercanaFinalizacion)>
200 <#assign rutaCercanaInicioFinalizacion = rutaCercanaInicio + " - " + rutaCercanaFinalizacion !/>
201 </#if>
202
203 <#if validator.isNotNull(rutaCercanaGpxRuta)>
204 <#assign gpxRutaJSONObject = jsonFactoryUtil.createJSONObject(rutaCercanaGpxRuta)! />
205 <#assign jsonGPX = gpxTool.parser(gpxRutaJSONObject.getLong("classPK"), "Parser", themeDisplay)! />
206
207 <#assign jsonGPX = jsonGPX.put("articleId", routeNearJournalArticleArticleId)! />
208 <#assign jsonGPX = jsonGPX.put("color", rutaCercanaColor)! />
209 <#assign jsonGPX = jsonGPX.put("url", routeNearJournalArticleViewURL)! />
210 <#assign jsonGPX = jsonGPX.put("title", routeNearJournalArticleEntryTitle)! />
211 <#assign jsonGPX = jsonGPX.put("image", routeNearJournalArticleThumbnail)! />
212 <#assign jsonGPX = jsonGPX.put("startEnd", rutaCercanaInicioFinalizacion)! />
213 <#assign jsonGPX = jsonGPX.put("routeTypes", rutaCercanaTipoRecorridos)! />
214 <#assign jsonGPX = jsonGPX.put("ibp", rutaCercanaIbp)! />
215 <#assign jsonGPX = jsonGPX.put("mode", rutaCercanaModalidad)! />
216 <#assign jsonGPX = jsonGPX.put("distance", rutaCercanaDistancia)! />
217
218 <#assign gpxRoutes = gpxRoutes + [jsonGPX] />
219 </#if>
220
221</#list>
222
223<#-- ALT destacada -->
224<#assign altImgDestacada = title />
225<#if AltImagenDestacada ??>
226 <#if validator.isNotNull(AltImagenDestacada.getData())>
227 <#assign altImgDestacada = AltImagenDestacada.getData() />
228 </#if>
229</#if>
230
231<article class="template template-cicloturismo template-layout-map template-route template-${ddmStructureNameNormalize} position-relative" role="article" itemscope itemtype="http://schema.org/TravelAction">
232
233 <div class="container">
234 <div class="row no-gutters">
235 <div class="col-md-5 col-12 col-sidebar">
236
237 <h2 class="article-title" itemprop="name">${title}</h2>
238
239 <div id="article-display-container" class="hide">
240 <button id="close-article-display" type="button" class="btn btn-light">
241 <span class="fas fa-times"><span class="hide-accessible">${languageUtil.get(locale, "close")}</span></span>
242 </button>
243 <div id="article-display"></div>
244 </div>
245
246 <div id="search-container">
247
248 <#if validator.isNotNull(description)>
249 <div class="article-description" itemprop="description">
250 ${htmlUtil.extractText(description)}
251 </div>
252 </#if>
253
254 <#if Avisos.TituloAviso.getSiblings()?has_content>
255 <#assign noticeCoordinatesIndex = 1 />
256 <#list Avisos.TituloAviso.getSiblings() as tituloAviso>
257
258 <#-- Schduler -->
259 <#assign fechaPublicacion = ""/>
260 <#assign fechaExpiracion = ""/>
261 <#assign nowDateTime = .now?long />
262 <#assign scheduler = true />
263 <#if validator.isNotNull(tituloAviso.FechaPublicacionAviso.getData()) && validator.isNotNull(tituloAviso.FechaPublicacionAviso.HoraPublicacionAviso.getData())>
264 <#assign fechaPublicacion = "${tituloAviso.FechaPublicacionAviso.getData()} ${tituloAviso.FechaPublicacionAviso.HoraPublicacionAviso.getData()}"/>
265 <#assign fechaPublicacion = fechaPublicacion?datetime("yyyy-MM-dd HH:mm:ss")/>
266
267 <#assign fechaPublicacion = fechaPublicacion?long/>
268 </#if>
269 <#if validator.isNotNull(tituloAviso.FechaExpiracionAviso.getData()) && validator.isNotNull(tituloAviso.FechaExpiracionAviso.HoraExpiracionAviso.getData())>
270 <#assign fechaExpiracion = "${tituloAviso.FechaExpiracionAviso.getData()} ${tituloAviso.FechaExpiracionAviso.HoraExpiracionAviso.getData()}"/>
271 <#assign fechaExpiracion = fechaExpiracion?datetime("yyyy-MM-dd HH:mm:ss")/>
272 <#assign fechaExpiracion = fechaExpiracion?long/>
273 </#if>
274
275 <#-- Filter -->
276 <#if validator.isNull(tituloAviso.getData()) >
277 <#assign scheduler = false />
278 </#if>
279 <#if validator.isNotNull(fechaPublicacion) && validator.isNotNull(fechaExpiracion)>
280 <#if !((nowDateTime gte fechaPublicacion) && (nowDateTime lte fechaExpiracion))>
281 <#assign scheduler = false />
282 </#if>
283 </#if>
284
285 <#if scheduler>
286
287 <#assign routeAlertCssClass = "route-alert alert ${tituloAviso.TipoAviso.getData()} mb-3 alert-dismissible fade hide"/>
288
289 <#assign markerNoticeCoordinates = (tituloAviso.CoordenadasAviso??)?then(tituloAviso.CoordenadasAviso.getData(),'') />
290 <#if validator.isNotNull(markerNoticeCoordinates)>
291 <#assign noticeCoordinatesIndex = noticeCoordinatesIndex + 1 />
292 <#assign routeAlertCssClass = routeAlertCssClass + " route-alert-coordinates"/>
293 </#if>
294
295 <div id="route-${articleId}-alert-coordinates-${noticeCoordinatesIndex}" class="${routeAlertCssClass}" role="alert">
296
297 <#assign markerNoticeIcon = "fa-solid fa-triangle-exclamation" />
298 <div class="alert-title-wrapper">
299 <span class="alert-icon">
300 <#switch tituloAviso.TipoAviso.getData()>
301 <#case "alert-info">
302 <i class="fa-solid fa-info"><!--icon--></i>
303 <#assign markerNoticeIcon = "fa-solid fa-info" />
304 <#break>
305 <#case "alert-success">
306 <i class="fa-regular fa-circle-check"><!--icon--></i>
307 <#assign markerNoticeIcon = "fa-solid fa-check" />
308 <#break>
309 <#case "alert-warning">
310 <i class="fa-solid fa-triangle-exclamation"><!--icon--></i>
311 <#assign markerNoticeIcon = "fa-solid fa-triangle-exclamation" />
312 <#break>
313 <#case "alert-danger">
314 <i class="fa-solid fa-ban"><!--icon--></i>
315 <#assign markerNoticeIcon = "fa-solid fa-ban" />
316 <#break>
317 <#default>
318 <i class="${markerNoticeIcon}"><!--icon--></i>
319 </#switch>
320 </span>
321
322 <#if validator.isNotNull(markerNoticeCoordinates)>
323 <#assign markerNotice = {"id": noticeCoordinatesIndex, "title": tituloAviso.getData(), "description": tituloAviso.DescripcionAviso.getData(), "type": tituloAviso.TipoAviso.getData(), "icon": markerNoticeIcon, "coordinates": markerNoticeCoordinates} />
324 <#assign markersNotices = arrayUtil.append(markersNotices, markerNotice) />
325 </#if>
326
327 <#if validator.isNotNull(tituloAviso.getData())>
328 <p class="alert-title">${stringUtil.replace(tituloAviso.getData(),"\n", "<br/>")}</p>
329 </#if>
330 </div>
331
332 <#if validator.isNotNull(tituloAviso.DescripcionAviso.getData())>
333 <div class="alert-description">${tituloAviso.DescripcionAviso.getData()}</div>
334 </#if>
335
336 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
337 <span aria-hidden="true">×</span>
338 </button>
339 </div>
340 </#if>
341 </#list>
342 </#if>
343
344 <#assign slideImagesCount = 0 />
345 <#assign slideImagesSize = Visualizador.Imagen.getSiblings()?size />
346 <#if Visualizador.Imagen.getSiblings()?has_content || validator.isNotNull(smallImageUrl)>
347 <div id="article-carousel" class="carousel slide carousel-fade carousel-article" data-ride="carousel" data-interval="5000">
348 <span aria-hidden="true" class="loading-animation loading-bg"></span>
349 <div class="carousel-inner">
350 <#if validator.isNotNull(smallImageUrl)>
351 <div class="carousel-item active aspect-ratio-bg-cover" style="background-image: url(${articleMainImageThumbnail3});">
352 <img class="hide" src="${articleMainImageThumbnail1}" alt="${altImgDestacada}" title="${altImgDestacada}"/>
353 </div>
354 <#assign slideImagesCount = slideImagesCount + 1 />
355 </#if>
356 <#list 0..2 as item>
357 <#if item < Visualizador.Imagen.getSiblings()?size >
358 <#assign Slide = Visualizador.Imagen.getSiblings()[item]!/>
359 <#if Slide?? && validator.isNotNull(Slide) && Slide.data?? && validator.isNotNull(Slide.data)>
360
361 <#assign slideThumbnail1 = dlTool.getThumbnailByJSON(Slide.data, "1")! />
362 <#assign slideThumbnail3 = dlTool.getThumbnailByJSON(Slide.data, "3")! />
363 <#assign slideTitle = "${languageUtil.get(request, 'image')} ${title}" />
364 <#assign slideAlt = slideTitle />
365 <#if Slide.TituloImagen?? && Slide.TituloImagen.data?has_content>
366 <#assign slideTitle = Slide.TituloImagen.data />
367 <#assign slideAlt = slideTitle />
368 </#if>
369 <#if Slide.AltImagen?? && validator.isNotNull(Slide.AltImagen.getData())>
370 <#assign slideAlt = Slide.AltImagen.getData() />
371 </#if>
372 <#else>
373 <#continue>
374 </#if>
375 <div class="carousel-item aspect-ratio-bg-cover" style="background-image: url(${slideThumbnail3});">
376 <img class="hide" src="${slideThumbnail1}" alt="${slideAlt}" title="${slideTitle}"/>
377 </div>
378 <#assign slideImagesCount = slideImagesCount + 1 />
379 </#if>
380 </#list>
381 </div>
382 <a class="carousel-control-prev" href="#article-carousel" data-slide="prev">
383 <span class="carousel-control-prev-icon" aria-hidden="true"><!-- ${languageUtil.get(request, "previous")} --></span>
384 <span class="hide-accessible">${languageUtil.get(request, "previous")}</span>
385 </a>
386 <a class="carousel-control-next" href="#article-carousel" data-slide="next">
387 <span class="carousel-control-next-icon" aria-hidden="true"><!-- ${languageUtil.get(request, "next")}--></span>
388 <span class="hide-accessible">${languageUtil.get(request, "next")}</span>
389 </a>
390 <ol class="carousel-indicators d-none">
391 <#assign index = 0 />
392 <#list 1..slideImagesCount as item>
393 <li data-target="#article-carousel" data-slide-to="${index}" <#if index==0> class="active"</#if>></li>
394 <#assign index = index + 1 />
395 </#list>
396 </ol>
397 </div>
398 </#if>
399
400 <div class="article-data-wrapper">
401 <#if validator.isNotNull(concejos) || validator.isNotNull(Distancia.getData()) || validator.isNotNull(dificultad) || validator.isNotNull(DesnivelAcumulado.getData()) || validator.isNotNull(AltitudMaxima.getData())
402 || validator.isNotNull(AltitudMaxima.getData()) || validator.isNotNull(AltitudMinima.getData()) || validator.isNotNull(IBP.getData()) || validator.isNotNull(tipoRuta) || validator.isNotNull(modalidad)
403 || validator.isNotNull(tipoRecorrido) || getterUtil.getBoolean(Transporte.Retorno.getData())>
404
405 <#if validator.isNotNull(PoblacionesPrincipales.getData())>
406 <ul class="article-list list-unstyled article-list-info">
407 <li class="article-list-item">
408 <span class="fas fa-map-marker-alt">
409 <span class="hide-accessible">${languageUtil.get(request,"address")}</span>
410 </span>
411 <span class="field-wrapper" itemprop="address">
412 <span class="text d-block important">${PoblacionesPrincipales.getData()}</span>
413 <#assign zoneNames = [] />
414 <#if concejos?size gt 0>
415 <#list concejos as concejo>
416 <#if concejo.getParentCategoryId() == 0>
417 <#if !zoneNames?seq_contains("${concejo.getTitle(locale)}")>
418 <#assign zoneNames = zoneNames + ["${concejo.getTitle(locale)}"]/>
419 </#if>
420 </#if>
421 </#list>
422 <#if validator.isNotNull(zoneNames)>
423 <span class="text zones d-block">${zoneNames?join(", ")}</span>
424 </#if>
425 </#if>
426 </span>
427 </li>
428 </ul>
429 </#if>
430
431 <div class="article-info-table">
432 <div class="article-info-table-row">
433 <div class="article-info-table-cell">
434 <ul class="article-list list-unstyled article-list-info">
435 <#if validator.isNotNull(Distancia.getData())>
436 <li class="article-list-item">
437 <span class="fas fa-ruler-horizontal">
438 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-distancia")}</span>
439 </span>
440 <span class="field-wrapper">
441 <span class="field">${languageUtil.get(request, "infoasturias-distancia")}:</span>
442 <span class="text text-featured">${Distancia.getData()} kms</span>
443 </span>
444 </li>
445 </#if>
446 <#if validator.isNotNull(dificultad) && dificultad?has_content>
447 <li class="article-list-item">
448 <span class="fas fa-layer-group">
449 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-dificultad")}</span>
450 </span>
451 <span class="field-wrapper">
452 <span class="field">${languageUtil.get(request, "infoasturias-dificultad")}:</span>
453 <span class="text">${dificultad[0].getTitle(locale)}</span>
454 </span>
455 </li>
456 </#if>
457 <#if validator.isNotNull(DesnivelAcumulado.getData())>
458 <li class="article-list-item">
459 <span class="fas fa-chart-line">
460 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-ascenso-acumulado")}</span>
461 </span>
462 <span class="field-wrapper">
463 <span class="field">${languageUtil.get(request, "infoasturias-route-ascenso-acumulado")}:</span>
464 <span class="text">${DesnivelAcumulado.data} m</span>
465 </span>
466 </li>
467 </#if>
468 <#if validator.isNotNull(AltitudMaxima.getData())>
469 <li class="article-list-item">
470 <span class="fas fa-ruler-vertical">
471 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-altitud-maxima")}</span>
472 </span>
473 <span class="field-wrapper">
474 <span class="field">${languageUtil.get(request, "infoasturias-route-altitud-maxima")}:</span>
475 <span class="text">${AltitudMaxima.data} m</span>
476 </span>
477 </li>
478 </#if>
479 <#if validator.isNotNull(AltitudMinima.getData())>
480 <li class="article-list-item">
481 <span class="fas fa-ruler-vertical">
482 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-altitud-minima")}</span>
483 </span>
484 <span class="field-wrapper">
485 <span class="field">${languageUtil.get(request, "infoasturias-route-altitud-minima")}:</span>
486 <span class="text">${AltitudMinima.data} m</span>
487 </span>
488 </li>
489 </#if>
490 <#if validator.isNotNull(IBP.getData())>
491 <li class="article-list-item">
492 <span class="fas fa-mountain">
493 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-ibp-index")}</span>
494 </span>
495 <span class="field-wrapper">
496 <span class="field">${languageUtil.get(request, "infoasturias-route-ibp-index")}:</span>
497 <span class="text">${IBP.data}</span>
498 </span>
499 </li>
500 </#if>
501 </ul>
502 </div>
503 <div class="article-info-table-cell">
504 <ul class="article-list list-unstyled article-list-info">
505 <#if validator.isNotNull(tipoRecorridos)>
506 <li class="article-list-item">
507 <span class="fas fa-bicycle">
508 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-recorrido")}</span>
509 </span>
510 <span class="field-wrapper">
511 <span class="field">${tipoRecorridos}</span>
512 </span>
513 </li>
514 </#if>
515 <#if validator.isNotNull(modalidad)>
516 <li class="article-list-item">
517 <span class="fas fa-bicycle">
518 <span class="hide-accessible">${modeVocabulary.getDescription(locale)}</span>
519 </span>
520 <span class="field-wrapper">
521 <span class="field">${modeVocabulary.getDescription(locale)}:</span>
522 <span class="text">${modalidad}</span>
523 </span>
524 </li>
525 </#if>
526 <#if validator.isNotNull(tipoRecorrido)>
527 <li class="article-list-item">
528 <span class="fas fa-route">
529 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-tipo-recorrido")}</span>
530 </span>
531 <span class="field-wrapper">
532 <span class="field">${languageUtil.get(request, "infoasturias-route-tipo-recorrido")}:</span>
533 <span class="text">${tipoRecorrido}</span>
534 </span>
535 </li>
536 </#if>
537 <li class="article-list-item">
538 <span class="fas fa-train">
539 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-retorno-ferrocarril")}</span>
540 </span>
541 <span class="field-wrapper">
542 <span class="field">${languageUtil.get(request, "infoasturias-route-retorno-ferrocarril")}:</span>
543 <#if getterUtil.getBoolean(Transporte.Retorno.getData())>
544 <span class="text">${languageUtil.get(locale, "yes")}</span>
545 <#else>
546 <span class="text">${languageUtil.get(locale, "no")}</span>
547 </#if>
548 </span>
549 </li>
550 <#if validator.isNotNull(Transporte.Empresa.getData()) && getterUtil.getBoolean(Transporte.Retorno.getData())>
551 <li class="article-list-item">
552 <span class="fas fa-train">
553 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-retorno-ferrocarril")}</span>
554 </span>
555 <span class="field-wrapper">
556 <span class="field">${Transporte.Empresa.getData()}
557 <#if validator.isNotNull(Transporte.WebInformativa.getData())>
558 <#list Transporte.WebInformativa.getSiblings() as web>
559 <a class="fas fa-external-link-alt" href="${web.getData()}" onclick="this.target='_blank'" title="${languageUtil.get(locale, 'go-to')} ${web.getData()}">
560 <span class="hide-accessible">${web.getData()}</span>
561 </a>
562 </#list>
563 </#if>
564 </span>
565 </span>
566 </li>
567 </#if>
568 </ul>
569 </div>
570 </div>
571
572 <div class="article-info-table-row">
573 <div class="article-info-table-cell">
574 <ul class="article-list list-unstyled article-list-info">
575 <#if validator.isNotNull(Inicio.getData())>
576 <li class="article-list-item">
577 <span class="fas fa-map-marker">
578 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-lugar-inicio")}</span>
579 </span>
580 <span class="field-wrapper">
581 <span class="field">${languageUtil.get(request, "infoasturias-route-lugar-inicio")}:</span>
582 <span class="text">${Inicio.getData()}</span>
583 </span>
584 </li>
585 </#if>
586 <#if validator.isNotNull(Finalizacion.getData())>
587 <li class="article-list-item">
588 <span class="fas fa-map-marker">
589 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-lugar-finalizacion")}</span>
590 </span>
591 <span class="field-wrapper">
592 <span class="field">${languageUtil.get(request, "infoasturias-route-lugar-finalizacion")}:</span>
593 <span class="text">${Finalizacion.getData()}</span>
594 </span>
595 </li>
596 </#if>
597 <#if validator.isNotNull(duracion)>
598 <li class="article-list-item">
599 <span class="fas fa-stopwatch">
600 <span class="hide-accessible">${languageUtil.get(request,"infoasturias-route-duracion-estimada")}</span>
601 </span>
602 <span class="field-wrapper">
603 <span class="field">${languageUtil.get(request, "infoasturias-route-duracion-estimada")}:</span>
604 <span class="text">${duracion}</span>
605 </span>
606 </li>
607 </#if>
608
609 </ul>
610 </div>
611 <div class="article-info-table-cell">
612 <#if validator.isNotNull(Documentos.GPXRuta.getData()) || validator.isNotNull(Documentos.GPXPOIRuta.getData()) || validator.isNotNull(Documentos.KMLRuta.getData())>
613 <ul class="article-list article-list-documents">
614 <#if validator.isNotNull(Documentos.GPXRuta.getData())>
615 <li class="article-list-item">
616 <span class="field-wrapper">
617 <a class="btn btn-border btn-inline-block btn-thin" href="${Documentos.GPXRuta.getData()}" onclick="this.target='_blank'" title="${languageUtil.get(request, 'infoasturias-download')} GPX">
618 <i class="fas fa-file-download"><!--icon--></i> ${languageUtil.format(request, "infoasturias-route-format", "GPX")}
619 </a>
620 </span>
621 </li>
622 </#if>
623 <#if validator.isNotNull(Documentos.GPXPOIRuta.getData())>
624 <li class="article-list-item">
625 <span class="field-wrapper">
626 <a class="btn btn-border btn-inline-block btn-thin" href="${Documentos.GPXPOIRuta.getData()}" onclick="this.target='_blank'" title="${languageUtil.get(request, 'infoasturias-download')} POI GPX">
627 <i class="fas fa-file-download"><!--icon--></i> ${languageUtil.format(request, "infoasturias-poi-format", "GPX") }
628 </a>
629 </span>
630 </li>
631 </#if>
632 <#if validator.isNotNull(Documentos.KMLRuta.getData())>
633 <li class="article-list-item">
634 <span class="field-wrapper">
635 <a class="btn btn-border btn-inline-block btn-thin" href="${Documentos.KMLRuta.getData()}" onclick="this.target='_blank'" title="${languageUtil.get(request, 'infoasturias-download')} KML">
636 <i class="fas fa-file-download"><!--icon--></i> ${languageUtil.format(request, "infoasturias-route-format", "KML")}
637 </a>
638 </span>
639 </li>
640 </#if>
641 </ul>
642 </#if>
643 </div>
644 </div>
645 </#if>
646
647 </div>
648
649 <div class="leaflet-elevation-wrapper" id="elevation-div-${articleId}">
650 <div class="btn-route-ctrl-wrapper">
651 <button id="userLocation" type="button" class="btn-circle-icon btn-route-ctrl btn-route-ctrl-location text-white active bottom d-md-none">
652 <span class="fa-solid fa-location-crosshairs"><span class="hide-accessible">${languageUtil.format(request, "infoasturias-route-format", "KMZ")}</span>
653 </button>
654 <button id="toggleElevation" type="button" class="btn-circle-icon btn-route-ctrl btn-route-ctrl-elevation btn-selected text-white active bottom d-md-none">
655 <span class="fa-solid fa-chart-line"><span class="hide-accessible">${languageUtil.format(request, "infoasturias-route-format", "KMZ")}</span>
656 </button>
657 </div>
658 </div>
659
660 </div>
661
662 <#if validator.isNotNull(DescripcionCorta.getData()) || validator.isNotNull(DescripcionLarga.getData())>
663 <div class="article-text-wrapper article-panel-wrapper article-panel-wrapper-white">
664
665 <div class="article-social-bookmarks article-social-bookmarks-circle text-right">
666 <@liferay_social_bookmarks["bookmarks"]
667 className="com.liferay.journal.model.JournalArticle"
668 classPK=assetEntry.getEntryId()
669 displayStyle="menu"
670 target="_blank"
671 title=title
672 types=articleSocialBookmarks
673 url="${articleURL}"
674 />
675 </div>
676
677 <div class="article-text article-panel">
678
679 <#if validator.isNotNull(DescripcionCorta.getData())>
680 <div class="article-short-description">${DescripcionCorta.getData()}</div>
681 </#if>
682 <#if validator.isNotNull(DescripcionLarga.getData()) || validator.isNotNull(Observaciones.getData())>
683 <div class="article-long-description-wrapper">
684
685 <#if validator.isNotNull(DescripcionLarga.getData())>
686 <div class="article-long-description">${DescripcionLarga.getData()}</div>
687 </#if>
688
689 <#if validator.isNotNull(Observaciones.getData())>
690 <div class="article-observations">${Observaciones.getData()}</div>
691 </#if>
692 </div>
693 </#if>
694
695 <#assign slideImagesCount = slideImagesCount - 1 />
696 <#if slideImagesSize gt slideImagesCount >
697 <#assign index = 0 />
698 <div id="article-carousel-round" class="carousel slide carousel-fade carousel-article" data-ride="carousel" data-interval="5000">
699 <span aria-hidden="true" class="loading-animation loading-bg"></span>
700 <div class="carousel-inner">
701 <#list slideImagesCount..slideImagesSize-1 as item>
702 <#assign Slide = Visualizador.Imagen.getSiblings()[item]/>
703 <#assign slideThumbnail1 = dlTool.getThumbnailByJSON(Slide.data, "1")! />
704 <#assign slideThumbnail3 = dlTool.getThumbnailByJSON(Slide.data, "3")! />
705 <#assign slideTitle = "${languageUtil.get(request, 'image')} ${title}" />
706 <#assign slideAlt = slideTitle />
707 <#if Slide.TituloImagen.data?has_content>
708 <#assign slideTitle = Slide.TituloImagen.data />
709 <#assign slideAlt = slideTitle />
710 </#if>
711 <#if Slide.AltImagen?? && validator.isNotNull(Slide.AltImagen.getData())>
712 <#assign slideAlt = Slide.AltImagen.getData() />
713 </#if>
714 <div class="carousel-item aspect-ratio-bg-cover <#if index==0> active</#if>" style="background-image: url(${slideThumbnail3});">
715 <img class="hide" src="${slideThumbnail1}" alt="${slideAlt}" title="${slideTitle}"/>
716 </div>
717 <#assign index = index + 1 />
718 </#list>
719 </div>
720
721 <#if (index>1)>
722 <a class="carousel-control-prev" href="#article-carousel-round" data-slide="prev">
723 <span class="carousel-control-prev-icon" aria-hidden="true"><!-- ${languageUtil.get(request, "previous")} --></span>
724 <span class="hide-accessible">${languageUtil.get(request, "previous")}</span>
725 </a>
726 <a class="carousel-control-next" href="#article-carousel-round" data-slide="next">
727 <span class="carousel-control-next-icon" aria-hidden="true"><!-- ${languageUtil.get(request, "next")}--></span>
728 <span class="hide-accessible">${languageUtil.get(request, "next")}</span>
729 </a>
730 <ol class="carousel-indicators d-none">
731 <#assign index = 0 />
732 <#list slideImagesCount..slideImagesSize-1 as item>
733 <li data-target="#article-carousel-round" data-slide-to="${index}" <#if index==0> class="active"</#if>></li>
734 <#assign index = index + 1 />
735 </#list>
736 </ol>
737 </#if>
738 </div>
739 </#if>
740 </div>
741 </div>
742 </#if>
743
744 <#-- PDI -->
745 <#assign arrayPDIs = [] />
746 <#if PDI.getSiblings()?has_content && validator.isNotNull(PDI.getSiblings()[0]) && (PDI.getSiblings()[0].JournalPDI.data?has_content || PDI.getSiblings()[0].TituloPDI.data?has_content)>
747 <div class="article-panel-wrapper">
748 <div class="article-panel">
749 <h3 class="title-section">${languageUtil.get(request,'infoasturias-pois')}</h3>
750 <div class="slide-wrapper">
751 <div id="slick-pdi" class="slick slick-slider">
752 <#assign pdiCount = 0 />
753 <#list PDI.getSiblings() as pdi>
754 <#assign journalPDIComarcas = "" />
755 <#assign pdiJSONObject = "" />
756 <#assign pdiArticleId = "" />
757 <#assign pdiURL = "#" />
758 <#assign pdiTitle = "" />
759 <#assign pdiImgAlt = "" />
760 <#assign pdiImgTitle = "" />
761 <#assign pdiDescription = "" />
762 <#assign smallImageThumbnail2 = "" />
763 <#if validator.isNotNull(pdi.JournalPDI.getData()) || (validator.isNotNull(pdi.TituloPDI.getData()) && validator.isNotNull(pdi.TituloPDI.ImagenPDI.getData()))>
764 <#if validator.isNotNull(pdi.JournalPDI.getData())>
765 <#assign pdiJSON = pdi.JournalPDI.data?eval/>
766 <#assign journalPDI = journalTool.getJournalArticleByResourcePrimKey(getterUtil.getLong(pdiJSON.classPK))/>
767 <#if validator.isNotNull(journalPDI)>
768 <#assign pdiAssetEntry = journalTool.getAssetEntryByArticleId(journalPDI.getGroupId(), journalPDI.getArticleId())/>
769 <#if validator.isNotNull(pdiAssetEntry)>
770 <#assign journalPDIComarcas = journalTool.getCategoriesNames(groupId, journalPDI.getArticleId(), locale, ["Comarcas"])/>
771 <#assign pdiURL = assetPublisherTool.getAssetViewURL(renderRequest, renderResponse, pdiAssetEntry) />
772 <#assign smallImageThumbnail2 = dlTool.getThumbnail(journalPDI.getSmallImageURL(), "2", layoutSetBannerPath)! />
773 <#assign pdiArticleId = journalPDI.getArticleId() />
774 <#assign pdiId = journalPDI.getArticleId() />
775 <#assign pdiTitle = journalPDI.getTitle(locale)! />
776 <#assign pdiDescription = stringUtil.shorten(htmlUtil.extractText(journalPDI.getDescription(locale)), 150)! />
777 <#assign pdiCoordinates = journalTool.getJournalArticleField(groupId, journalPDI.getArticleId(), "Coordenadas")! />
778
779 <#assign pdiJSONObject = jsonFactoryUtil.createJSONObject()! />
780 <#assign pdiJSONObject = pdiJSONObject.put("articleId", journalPDI.getArticleId())! />
781 <#assign pdiJSONObject = pdiJSONObject.put("title", pdiTitle)! />
782 <#assign pdiJSONObject = pdiJSONObject.put("description", pdiDescription)! />
783 <#assign pdiJSONObject = pdiJSONObject.put("subtitle", journalPDIComarcas)! />
784 <#assign pdiJSONObject = pdiJSONObject.put("image", smallImageThumbnail2)! />
785 <#assign pdiJSONObject = pdiJSONObject.put("url", pdiURL)! />
786 <#assign pdiJSONObject = pdiJSONObject.put("coordinates", pdiCoordinates)! />
787 <#assign pdiJSONObject = pdiJSONObject.put("icon", "")! />
788 <#if pdi.IconFontAwesomePDI?? && validator.isNotNull(pdi.IconFontAwesomePDI.getData())>
789 <#assign pdiJSONObject = pdiJSONObject.put("icon", pdi.IconFontAwesomePDI.getData())! />
790 </#if>
791 </#if>
792 </#if>
793 <#elseif validator.isNotNull(pdi.TituloPDI.getData()) && validator.isNotNull(pdi.TituloPDI.ImagenPDI.getData())>
794
795 <#assign pdiId = pdiCount! />
796 <#assign pdiTitle = pdi.TituloPDI.getData()! />
797 <#assign pdiImgAlt = pdi.TituloPDI.getData()! />
798 <#assign pdiImgTitle = pdi.TituloPDI.getData()! />
799 <#assign pdiCoordinates = pdi.TituloPDI.CoordenadasPDI.getData()! />
800 <#assign smallImageThumbnail2 = dlTool.getThumbnail(pdi.TituloPDI.ImagenPDI.getData(), "2", layoutSetBannerPath)! />
801 <#if pdi.TituloPDI.ImagenPDI.TitleImagenPDI??>
802 <#if validator.isNotNull(pdi.TituloPDI.ImagenPDI.TitleImagenPDI.getData())>
803 <#assign pdiImgTitle = pdi.TituloPDI.ImagenPDI.TitleImagenPDI.getData()/>
804 </#if>
805 </#if>
806 <#if pdi.TituloPDI.ImagenPDI.AltImagenPDI??>
807 <#if validator.isNotNull(pdi.TituloPDI.ImagenPDI.AltImagenPDI.getData())>
808 <#assign pdiImgAlt = pdi.TituloPDI.ImagenPDI.AltImagenPDI.getData()/>
809 </#if>
810 </#if>
811 <#assign pdiJSONObject = jsonFactoryUtil.createJSONObject()! />
812 <#assign pdiJSONObject = pdiJSONObject.put("articleId", pdiId)! />
813 <#assign pdiJSONObject = pdiJSONObject.put("title", pdiTitle)! />
814 <#assign pdiJSONObject = pdiJSONObject.put("description", "")! />
815 <#assign pdiJSONObject = pdiJSONObject.put("subtitle", "")! />
816 <#assign pdiJSONObject = pdiJSONObject.put("image", smallImageThumbnail2)! />
817 <#assign pdiJSONObject = pdiJSONObject.put("url", "")! />
818 <#assign pdiJSONObject = pdiJSONObject.put("coordinates", pdiCoordinates)! />
819 <#assign pdiJSONObject = pdiJSONObject.put("icon", "")! />
820 <#if pdi.IconFontAwesomePDI?? && validator.isNotNull(pdi.IconFontAwesomePDI.getData())>
821 <#assign pdiJSONObject = pdiJSONObject.put("icon", pdi.IconFontAwesomePDI.getData())! />
822 </#if>
823 </#if>
824 <#if validator.isNotNull(pdiJSONObject)>
825 <#assign arrayPDIs = arrayPDIs + [pdiJSONObject] />
826 </#if>
827
828 <div class="slide">
829 <a class="card poi" href="${pdiURL}" data-articleid="${pdiArticleId}" data-id="poi-${pdiId}" title="${languageUtil.format(request, 'go-to-x', htmlUtil.escape(pdiTitle))}">
830 <span class="d-block image-wrapper aspect-ratio-bg-cover aspect-ratio-4-to-3" style="background-image: url(${smallImageThumbnail2});">
831 <img class="hide-accessible" src="${smallImageThumbnail2}" alt="${pdiImgAlt}" />
832 <#if validator.isNotNull(pdiDescription)>
833 <span class="card-hover">
834 <span class="card-hover-text" itemprop="description">
835 ${pdiDescription}
836 </span>
837 </span>
838 </#if>
839 </span>
840 <span class="card-body">
841 <span class="card-title">${pdiTitle}</span>
842 <#if validator.isNotNull(journalPDIComarcas)>
843 <span class="card-subtitle">${journalPDIComarcas}</span>
844 </#if>
845 </span>
846 </a>
847 </div>
848 <#assign pdiCount = pdiCount + 1 />
849 </#if>
850 </#list>
851 </div>
852 </div>
853 </div>
854 </div>
855
856 <script type="text/javascript">
857
858 // bootstrap 4 breakpoints
859 var breakpoint${namespace} = {
860 // small screen / phone
861 sm: 576,
862 // medium screen / tablet
863 md: 768,
864 // large screen / desktop
865 lg: 992,
866 // extra large screen / wide desktop
867 xl: 1200
868 };
869
870 // bootstrap 4 responsive multi column slick carousel
871 $('#slick-pdi').slick({
872 autoplay: false,
873 autoplaySpeed: 1000,
874 draggable: true,
875 pauseOnHover: false,
876 infinite: false,
877 dots: false,
878 arrows: true,
879 speed: 1000,
880 mobileFirst: true,
881 slidesToShow: 1,
882 slidesToScroll: 1,
883 centerMode: false,
884 responsive: [{
885 breakpoint: breakpoint${namespace}.sm,
886 settings: {
887 slidesToShow: 1,
888 slidesToScroll: 1
889 }
890 },
891 {
892 breakpoint: breakpoint${namespace}.md,
893 settings: {
894 slidesToShow: 2,
895 slidesToScroll: 1
896 }
897 },
898 {
899 breakpoint: breakpoint${namespace}.lg,
900 settings: {
901 slidesToShow: 2,
902 slidesToScroll: 1
903 }
904 },
905 {
906 breakpoint: breakpoint${namespace}.xl,
907 settings: {
908 slidesToShow: 2,
909 slidesToScroll: 1
910 }
911 }
912 ]
913 });
914 </script>
915 </#if>
916
917 <#-- Services -->
918 <#assign servicesNearJournalArticles = [] />
919 <div id="services-panel" class="article-panel-wrapper article-panel-services hide">
920 <div class="article-panel">
921 <h3 class="title-section">${languageUtil.get(request,'infoasturias-route-services')}</h3>
922
923 <div class="filter-categories mb-4">
924
925 <#list filterDDMStructures as filterDDMStructure>
926
927 <#assign filterStructureCustomNameKey = "${filterDDMStructure.getStructureId()}[customName]"/>
928 <#assign filterStructureCustomNameValue = group.getTypeSettingsProperty(filterStructureCustomNameKey)!/>
929
930 <#assign filterStructureKey = filterDDMStructure.getStructureKey()! />
931 <#assign filterStructureName = filterDDMStructure.getName(locale) />
932 <#assign filterStructureDescription = filterDDMStructure.getDescription(locale) />
933
934
935 <#if validator.isNotNull(filterStructureDescription)>
936 <#assign filterStructureName = filterStructureDescription! />
937 </#if>
938
939 <#if validator.isNotNull(filterStructureCustomNameValue)>
940 <#assign filterStructureName = languageUtil.get(request, filterStructureCustomNameValue)! />
941 </#if>
942
943 <a class="button-vocabulary-structure btn btn-border btn-thin mb-1 disabled-service" href="#" id="button-vocabulary-structure-id-${filterStructureKey}" data-vocabulary-structure-id="${filterStructureKey}">${filterStructureName}</a>
944
945 </#list>
946
947 </div>
948
949 <div id="services-entries-container" class="slide-wrapper lfr-spa-loading">
950 <div class="lfr-spa-loading-spinner" style="position: absolute;"></div>
951 <ul class="slider slick slick-slider pl-0"></ul>
952 <@liferay_aui["script"] use="aui-base">
953 $(function() {
954 $(".slider").slick({
955 arrows: true,
956 dots: false,
957 slidesToShow: 2,
958 slidesToScroll: 1,
959 mobileFirst: false,
960 centerMode: false,
961 infinite: false,
962 responsive: [{
963 breakpoint: breakpoint${namespace}.sm,
964 settings: {
965 slidesToShow: 1,
966 slidesToScroll: 1
967 }
968 },
969 {
970 breakpoint: breakpoint${namespace}.md,
971 settings: {
972 slidesToShow: 2,
973 slidesToScroll: 1
974 }
975 },
976 {
977 breakpoint: breakpoint${namespace}.lg,
978 settings: {
979 slidesToShow: 2,
980 slidesToScroll: 1
981 }
982 },
983 {
984 breakpoint: breakpoint${namespace}.xl,
985 settings: {
986 slidesToShow: 2,
987 slidesToScroll: 1
988 }
989 }
990 ]
991 });
992 });
993 </@>
994 </div>
995 </div>
996 </div>
997
998 <#if validator.isNotNull(routesNearJournalArticles) && routesNearJournalArticles?size gt 0>
999 <div class="article-panel-wrapper article-panel-wrapper-white template-routes">
1000 <div class="article-panel">
1001 <h3 class="title-section">${languageUtil.get(request,'infoasturias-routes-near-here')}</h3>
1002 <div class="slide-wrapper">
1003 <div id="slick-near" class="slick slick-slider">
1004 <#list routesNearJournalArticles as currentJournalArticle>
1005 <#assign viewURL = journalTool.getDisplayPage(currentJournalArticle, themeDisplay, true)/>
1006 <#assign smallImageThumbnail2 = dlTool.getThumbnail(currentJournalArticle.getSmallImageURL(), "2", layoutSetBannerPath)! />
1007 <#assign routeTitle = currentJournalArticle.getTitle(locale)/>
1008 <#assign denominacion = journalTool.getJournalArticleField(currentJournalArticle.getGroupId(), currentJournalArticle.getArticleId(), "Denominacion", locale)/>
1009 <#assign assetEntry = journalTool.getAssetEntryByArticleId(groupId, articleId)>
1010 <#if validator.isNotNull(denominacion)>
1011 <#assign routeTitle = denominacion />
1012 </#if>
1013 <div class="slide">
1014 <a class="card route-near" data-id="route-near-${currentJournalArticle.getArticleId()}" href="${viewURL}" title="${languageUtil.format(request, 'go-to-x', routeTitle)}">
1015 <span class="d-block image-wrapper aspect-ratio-bg-cover aspect-ratio-4-to-3" style="background-image: url('${smallImageThumbnail2}');">
1016 <img class="hide-accessible" src="${smallImageThumbnail2}" alt="${routeTitle}">
1017 <#if validator.isNotNull(htmlUtil.extractText(currentJournalArticle.getDescription(locale)))>
1018 <span class="card-hover">
1019 <span class="card-hover-text" itemprop="description">
1020 ${stringUtil.shorten(htmlUtil.extractText(currentJournalArticle.getDescription(locale)), 150)}
1021 </span>
1022 </span>
1023 </#if>
1024 </span>
1025 <span class="card-body">
1026 <span class="card-title">${routeTitle}</span>
1027 <span class="card-subtitle">
1028 <#-- <span class="d-block">${currentJournalArticle.getVersion()} Kms</span>-->
1029 <#assign currentJournalArticleConcejos = journalTool.getCategoriesNames(groupId, currentJournalArticle.getArticleId(), locale, ["Concejos"])/>
1030 <#if validator.isNotNull(currentJournalArticleConcejos)>
1031 <#assign currentJournalArticleConcejos = stringUtil.replace(currentJournalArticleConcejos,",",", ") />
1032 <span class="d-block">${currentJournalArticleConcejos}</span>
1033 </#if>
1034 </span>
1035 </span>
1036 </a>
1037 </div>
1038 </#list>
1039 </div>
1040 </div>
1041 </div>
1042 </div>
1043
1044 <script type="text/javascript">
1045
1046 // bootstrap 4 breakpoints
1047 var breakpoint${namespace} = {
1048 // small screen / phone
1049 sm: 576,
1050 // medium screen / tablet
1051 md: 768,
1052 // large screen / desktop
1053 lg: 992,
1054 // extra large screen / wide desktop
1055 xl: 1200
1056 };
1057
1058 // bootstrap 4 responsive multi column slick carousel
1059 $('#slick-near').slick({
1060 autoplay: false,
1061 autoplaySpeed: 1000,
1062 draggable: true,
1063 pauseOnHover: false,
1064 infinite: false,
1065 dots: false,
1066 arrows: true,
1067 speed: 1000,
1068 mobileFirst: true,
1069 slidesToShow: 1,
1070 slidesToScroll: 1,
1071 centerMode: false,
1072 responsive: [{
1073 breakpoint: breakpoint${namespace}.sm,
1074 settings: {
1075 slidesToShow: 1,
1076 slidesToScroll: 1
1077 }
1078 },
1079 {
1080 breakpoint: breakpoint${namespace}.md,
1081 settings: {
1082 slidesToShow: 2,
1083 slidesToScroll: 1
1084 }
1085 },
1086 {
1087 breakpoint: breakpoint${namespace}.lg,
1088 settings: {
1089 slidesToShow: 2,
1090 slidesToScroll: 1
1091 }
1092 },
1093 {
1094 breakpoint: breakpoint${namespace}.xl,
1095 settings: {
1096 slidesToShow: 2,
1097 slidesToScroll: 1
1098 }
1099 }
1100 ]
1101 });
1102 </script>
1103 </#if>
1104 </div>
1105 </div>
1106
1107 <div class="col-md-7 col-12 col-map d-md-inline-block d-none">
1108 <div id="map" class="lfr-spa-loading">
1109 <div class="lfr-spa-loading-spinner" style="position: absolute;"></div>
1110
1111 <#if validator.isNotNull(filterStructuresIds)>
1112 <div id="map-filter" class="hide">
1113 <div class="vocabularies">
1114 <#list filterStructuresIds as filterStructuresId>
1115 <#assign filterStructure = ddmStructureLocalService.fetchDDMStructure(filterStructuresId)/>
1116 <#if validator.isNotNull(filterStructure)>
1117 <#assign filterStructureKey = filterStructure.getStructureKey()/>
1118 <#assign markersServicesDDMStructureKeys = arrayUtil.append(markersServicesDDMStructureKeys, filterStructureKey) />
1119 <#assign filterStructureFontAwesomeKey = "${filterStructure.getStructureId()}[fontAwesome]"/>
1120 <#assign filterStructureFontAwesomeValue = group.getTypeSettingsProperty(filterStructureFontAwesomeKey)!/>
1121 <#assign filterStructureVocabularyKey = "${filterStructure.getStructureId()}[vocabularyId]"/>
1122 <#assign filterStructureVocabularyValue = getterUtil.getLong(group.getTypeSettingsProperty(filterStructureVocabularyKey))!/>
1123 <#assign filterStructurevocabularyLevelCategoriesKey = "${filterStructure.getStructureId()}[vocabularyLevelCategories]"/>
1124 <#assign filterStructurevocabularyLevelCategoriesValue = group.getTypeSettingsProperty(filterStructurevocabularyLevelCategoriesKey)!1/>
1125 <#assign filterStructurevocabularyCategoryIdsKey = "${filterStructure.getStructureId()}[vocabularyCategoryIds]"/>
1126 <#assign filterStructurevocabularyCategoryIdsValue = group.getTypeSettingsProperty(filterStructurevocabularyCategoryIdsKey)!/>
1127 <#assign filterStructurevocabularyTagsKey = "${filterStructure.getStructureId()}[vocabularyTags]"/>
1128 <#assign filterStructurevocabularyTagsValue = group.getTypeSettingsProperty(filterStructurevocabularyTagsKey)!/>
1129 <#assign filterStructureCustomNameKey = "${filterStructure.getStructureId()}[customName]"/>
1130 <#assign filterStructureCustomNameValue = group.getTypeSettingsProperty(filterStructureCustomNameKey)!/>
1131 <#assign filterStructureStructureIdsKey = "${filterStructure.getStructureId()}[filterStructuresIds]"/>
1132 <#assign filterStructureStructureIdsValues = group.getTypeSettingsProperty(filterStructureStructureIdsKey)!/>
1133
1134 <#-- Cicloturismo Settings -->
1135 <#assign filterStructureCardSubtitleCategoryIdsValue = "" />
1136 <#if validator.isNotNull(ddmStructureSettingsJSONObject) && ddmStructureSettingsJSONObject.has(filterStructureName)>
1137
1138 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).has("icon")>
1139 <#assign filterStructureFontAwesomeValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getString("icon")/>
1140 </#if>
1141
1142 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).has("label")>
1143 <#assign filterStructureCustomNameValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getString("label")/>
1144 </#if>
1145
1146 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).has("cardSubtitleCategoryIds")>
1147 <#assign filterStructureCardSubtitleCategoryIdsValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getString("cardSubtitleCategoryIds")/>
1148 </#if>
1149
1150 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).has("filters")>
1151
1152 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").has("vocabularyId")>
1153 <#assign filterStructureVocabularyValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").getLong("vocabularyId")/>
1154 </#if>
1155
1156 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").has("vocabularyLevelCategories")>
1157 <#assign filterStructurevocabularyLevelCategoriesValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").getString("vocabularyLevelCategories", "1")/>
1158 </#if>
1159
1160 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").has("vocabularyCategoryIds")>
1161 <#assign filterStructurevocabularyCategoryIdsValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").getString("vocabularyCategoryIds")/>
1162 </#if>
1163
1164 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").has("vocabularyTags")>
1165 <#assign filterStructurevocabularyTagsValue = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").getString("vocabularyTags")/>
1166 </#if>
1167
1168 <#if ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").has("filterStructuresIds")>
1169 <#assign filterStructureStructureIdsValues = ddmStructureSettingsJSONObject.getJSONObject(filterStructureName).getJSONObject("filters").getString("filterStructuresIds")/>
1170 </#if>
1171
1172 </#if>
1173
1174 </#if>
1175
1176 <#assign filterStructureStructureKeys = [filterStructureKey]/>
1177 <#if validator.isNotNull(filterStructureStructureIdsValues)>
1178 <#list stringUtil.split(filterStructureStructureIdsValues) as filterStructureStructureIdsValue>
1179 <#assign ddmStructure = ddmStructureLocalService.fetchDDMStructure(getterUtil.getLong(filterStructureStructureIdsValue))! />
1180 <#if validator.isNotNull(ddmStructure)>
1181 <#assign filterStructureStructureKeys = filterStructureStructureKeys + [ddmStructure.getStructureKey()]/>
1182 </#if>
1183 </#list>
1184 </#if>
1185
1186 <#assign filterStructureJSONObject = jsonFactoryUtil.createJSONObject()>
1187 <#assign filterStructureJSONObject = filterStructureJSONObject.put("structureId", filterStructuresId)! />
1188 <#assign filterStructureJSONObject = filterStructureJSONObject.put("structureKey", filterStructureKey)! />
1189 <#assign filterStructureJSONObject = filterStructureJSONObject.put("fontAwesome", filterStructureFontAwesomeValue)! />
1190 <#assign filterStructureJSONObject = filterStructureJSONObject.put("vocabularyId", filterStructureVocabularyValue)! />
1191 <#assign filterStructureJSONObject = filterStructureJSONObject.put("vocabularyLevelCategories", filterStructurevocabularyLevelCategoriesValue)! />
1192 <#assign filterStructureJSONObject = filterStructureJSONObject.put("vocabularyCategoryIds", filterStructurevocabularyCategoryIdsValue)! />
1193 <#assign filterStructureJSONObject = filterStructureJSONObject.put("vocabularyTags", filterStructurevocabularyTagsValue)! />
1194 <#assign filterStructureJSONObject = filterStructureJSONObject.put("cardSubtitleCategoryIds", filterStructureCardSubtitleCategoryIdsValue)! />
1195 <#assign filterStructureJSONObject = filterStructureJSONObject.put("name", filterStructure.getName(locale))! />
1196 <#assign filterStructureJSONObject = filterStructureJSONObject.put("customName", filterStructureCustomNameValue)! />
1197 <#assign filterStructureJSONObject = filterStructureJSONObject.put("description", filterStructure.getDescription(locale))! />
1198 <#assign filterStructureJSONObject = filterStructureJSONObject.put("structureKeys", stringUtil.merge(filterStructureStructureKeys))! />
1199 <#assign filterStructures = filterStructures + [filterStructureJSONObject] />
1200
1201 <#assign filterStructureName = filterStructure.getName(locale) />
1202 <#assign filterStructureDescription = filterStructure.getDescription(locale) />
1203
1204 <#if validator.isNotNull(filterStructureDescription)>
1205 <#assign filterStructureName = filterStructureDescription! />
1206 </#if>
1207
1208 <#if validator.isNotNull(filterStructureCustomNameValue)>
1209 <#assign filterStructureName = languageUtil.get(request, filterStructureCustomNameValue)! />
1210 </#if>
1211
1212 <div class="vocabulary-wrapper disabled-service" title="${filterStructureName}" data-structurekey="${filterStructure.getStructureKey()}">
1213 <div class="vocabulary" id="vocabulary-structure-id-${filterStructure.getStructureKey()}" data-vocabulary-structure-id="${filterStructure.getStructureKey()}">
1214 <span class="icon ${filterStructureFontAwesomeValue}"><span class="hide-accessible">${filterStructureName}</span></span>
1215 </div>
1216 <#if validator.isNotNull(filterStructureVocabularyValue)>
1217
1218 <#assign filterStructureVocabulary = assetVocabularyLocalService.fetchAssetVocabulary(filterStructureVocabularyValue)! />
1219 <#assign filterStructureVocabularyCategories = assetCategoryTool.getAssetCategoriesByVocabulary(filterStructureVocabulary, getterUtil.getInteger(filterStructurevocabularyLevelCategoriesValue))! />
1220
1221 <#if validator.isNotNull(filterStructureVocabularyCategories)>
1222 <div class="categories">
1223 <#list filterStructureVocabularyCategories as filterStructureVocabularyCategory>
1224 <div class="category category-${filterStructureVocabularyCategory.getCategoryId()} hide">
1225 <input type="checkbox" name="category-${filterStructureVocabularyCategory.getCategoryId()}" id="category-${filterStructureVocabularyCategory.getCategoryId()}" data-id="${filterStructureVocabularyCategory.getCategoryId()}" />
1226 <label for="category-${filterStructureVocabularyCategory.getCategoryId()}">${filterStructureVocabularyCategory.getTitle(locale)}</label>
1227 </div>
1228 </#list>
1229 </div>
1230 </#if>
1231 </#if>
1232 </div>
1233 </#if>
1234 </#list>
1235 </div>
1236 </div>
1237 </#if>
1238 </div>
1239 </div>
1240 </div>
1241 </div>
1242
1243</article>
1244
1245<@liferay_aui["script"] use="aui-base, anim, aui-io-request, cookie, async-queue, node-event-simulate">
1246
1247 var mapZoom = ${getterUtil.getInteger(mapZoom, 12)};//MapZoom
1248 var mapLat = ${getterUtil.getString(mapLat, "43.362597693870434")};//MapLat
1249 var mapLng = ${getterUtil.getString(mapLng, "-5.846235457402242")};//MapLng
1250 var osm = new L.TileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
1251 {
1252 attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
1253 }
1254 );
1255
1256 var map = new L.map('map', {center: [${gpxRoute.get("centerLatLon")}], zoom: mapZoom, zoomControl: false, minZoom: 9, bounceAtZoomLimits: false, layers: [osm]});
1257 map.doubleClickZoom.disable();
1258 map.whenReady(function(){
1259 A.one('#map').removeClass('lfr-spa-loading');
1260 });
1261
1262 //Map Height
1263 mapFullHeight(scroll=true, map);
1264
1265 //FilterStructures
1266 var fontAwesomeIconClassCSS = [];
1267 <#list filterStructures as filterStructure>
1268 fontAwesomeIconClassCSS['${filterStructure["structureKey"]}'] = {
1269 cssClass:'${filterStructure["fontAwesome"]}',
1270 vocabularyId: ${filterStructure["vocabularyId"]},
1271 vocabularyLevelCategories: ${filterStructure["vocabularyLevelCategories"]},
1272 vocabularyTags: '${filterStructure["vocabularyTags"]}',
1273 cardSubtitleCategoryIds: '${filterStructure["cardSubtitleCategoryIds"]}'
1274 };
1275 </#list>
1276
1277 //ServiceMarkers
1278 var serviceMarkers = [];
1279 var markersServicesGroups = {};
1280 var servicesContainer = A.one('#services-entries-container');
1281 var mapFilter = A.one('#map-filter');
1282 var servicesPanel = A.one('#services-panel');
1283
1284 Liferay.provide(window,'journalArticlesResourcesCount', function(deltaParam, structureKeys, anyCategoryIds, allCategoryIds, anyTagNames, allTagNames, vocabularyIds){
1285 var url = '/o/asac-web-services/ws/journalArticlesResourcesCount';
1286 A.io.request(url, {
1287 method: 'GET',
1288 type: 'JSON',
1289 data: {
1290 companyId: ${companyId},
1291 groupId: ${groupId},
1292 structureKeys: structureKeys,
1293 anyCategoryIds: assetAnyCategoryIds,
1294 allCategoryIds: assetAllCategoryIds,
1295 anyTagNames: anyTagNames,
1296 allTagNames: allTagNames,
1297 coordinates: '[${gpxRoute.get("coordinatesLatLonSplit")}]',
1298 coordinatesDistance: ${routeDetailServicesDistance}
1299 },
1300 on: {
1301 success: function() {
1302 var count = this.get('responseData');
1303 if(count>deltaParam){
1304 var pages = Math.ceil(count/deltaParam);
1305 for(var cur = 0; cur < pages; cur++){
1306 journalArticlesResources(cur, deltaParam, structureKeys, anyCategoryIds, allCategoryIds, anyTagNames, allTagNames, vocabularyIds, count);
1307 }
1308 }else{
1309 var cur = -1;
1310 var delta = -1;
1311 journalArticlesResources(cur, deltaParam, structureKeys, anyCategoryIds, allCategoryIds, anyTagNames, allTagNames, vocabularyIds, count);
1312 }
1313 }
1314 }
1315 });
1316 });
1317
1318 Liferay.provide(window,'journalArticlesResources', function(cur, delta, structureKeys, anyCategoryIds, allCategoryIds, anyTagNames, allTagNames, vocabularyIds, total){
1319 var structureKey = structureKeys.split(',')[0];
1320 var url = '/o/asac-web-services/ws/journalArticlesResources';
1321 A.io.request(url, {
1322 method: 'GET',
1323 type: 'JSON',
1324 data: {
1325 companyId: ${companyId},
1326 groupId: ${groupId},
1327 structureKeys: structureKeys,
1328 anyCategoryIds: anyCategoryIds,
1329 allCategoryIds: allCategoryIds,
1330 anyTagNames: anyTagNames,
1331 allTagNames: allTagNames,
1332 coordinates: '[${gpxRoute.get("coordinatesLatLonSplit")}]',
1333 coordinatesDistance: ${routeDetailServicesDistance},
1334 projectionAssetCategoriesVocabularyIds: vocabularyIds,
1335 cur: cur,
1336 delta: delta,
1337 },
1338 on: {
1339 success: function() {
1340 var vocabularyId = 0;
1341 var points = JSON.parse(this.get('responseData'));
1342 if(points && points.length>0){
1343 var slickAddHTML = '';
1344 for(var index in points) {
1345
1346 var point = points[index];
1347 var articleId = point.articleId;
1348 var title = point.title;
1349 var descriptionText = point.descriptionText;
1350 var assetCategories = point.assetCategories;
1351 var subTypeId = point.subTypeId; //structureKey
1352 var subTypeName = point.subTypeName; //structureName
1353 var coordinates = point.coordinates;
1354 var detailURL = point.detailURL;
1355 var detailFullURL = point.detailFullURL;
1356 if(detailFullURL!='')
1357 detailURL = detailFullURL;
1358 var image = point.image;
1359 var imageThumbnail2 = point.imageThumbnail2;
1360 var icon = fontAwesomeIconClassCSS[subTypeId].cssClass;
1361 var vocabularyId = (vocabularyId==0) ? fontAwesomeIconClassCSS[subTypeId].vocabularyId : vocabularyId;
1362 var vocabularyLevelCategories = fontAwesomeIconClassCSS[subTypeId].vocabularyLevelCategories;
1363 var cardSubtitleCategoryIds = fontAwesomeIconClassCSS[subTypeId].cardSubtitleCategoryIds;
1364 var concejosVocabularyId = ${concejosVocabulary.getVocabularyId()};
1365 var pointGroups = [];
1366
1367 const fontAwesomeIcon = L.divIcon({
1368 className: 'marker-wrapper',
1369 html: "<div class='marker-icon-blue'><i class='"+icon+"'><!-- icon--></i></div>",
1370 iconSize: [26, 30],
1371 iconAnchor: [13, 30]
1372 });
1373
1374 if(coordinates!=''){
1375 var latLng = coordinates.split(',');
1376 if(!isNaN(latLng[0]) && !isNaN(latLng[1])){
1377 var pointGroup = '';
1378 var categoryTitle = '';
1379 var categoryId = '';
1380 var categoryConcejos = [];
1381 var categoryIds = [];
1382 var categoryTitles = [];
1383 var pointGroups = [];
1384 for(var assetCategoriesIndex in assetCategories) {
1385
1386 var assetCategory = assetCategories[assetCategoriesIndex];
1387 if(assetCategory){
1388
1389 categoryId = assetCategory.categoryId;
1390 categoryTitle = assetCategory.title;
1391
1392 //Concejos
1393 if(assetCategory.vocabularyId==concejosVocabularyId){
1394 if(!categoryConcejos.includes(assetCategory.title))
1395 categoryConcejos.push(assetCategory.title);
1396 }
1397
1398 if(assetCategory.vocabularyId==vocabularyId){
1399
1400 //Filter
1401 if(vocabularyLevelCategories && vocabularyLevelCategories>0){
1402 var level = assetCategory.level;
1403 if(vocabularyLevelCategories!=level)
1404 continue;
1405 }
1406
1407 if(markersServicesGroups && markersServicesGroups[categoryId]){
1408 pointGroup = markersServicesGroups[categoryId];
1409 }else{
1410 var pointGroup = L.markerClusterGroup({
1411 maxClusterRadius: 100,
1412 showCoverageOnHover: false,
1413 //zoomToBoundsOnClick: false,
1414 //spiderfyOnMaxZoom: false,
1415 iconCreateFunction: function(cluster) {
1416 var childMarkers = cluster.getAllChildMarkers();
1417 var n = 0;
1418 for (var i = 0; i < childMarkers.length; i++) {
1419 n += 1;
1420 }
1421 return L.divIcon({
1422 className: 'marker-wrapper',
1423 html: "<div class='marker-circle'>"+n+"</i></div>",
1424 iconSize: [26, 30],
1425 iconAnchor: [13, 5]
1426 });
1427 }
1428 });
1429 markersServicesGroups[categoryId] = pointGroup;
1430 }
1431
1432 if(pointGroup)
1433 pointGroups.push(pointGroup);
1434
1435 if(categoryTitle!='' && !categoryTitles.includes(categoryTitle)){
1436 if(cardSubtitleCategoryIds=='' || (cardSubtitleCategoryIds.split(",").includes(categoryId)))
1437 categoryTitles.push(categoryTitle);
1438 }
1439
1440 if(categoryId!='' && !categoryIds.includes(categoryId))
1441 categoryIds.push(categoryId);
1442
1443 var serviceFilterCategory = A.one('.categories .category-'+categoryId)
1444 if(serviceFilterCategory)
1445 serviceFilterCategory.show();
1446 }
1447 }
1448 }
1449
1450 var popupContentTemplate = '<a data-articleid="'+articleId+'" href="'+detailURL+'" class="popup popup-service">'+
1451 '<span class="popup-image-wrapper" style="background-image: url('+imageThumbnail2+');"><!-- image--></span>'+
1452 '<span class="popup-body">'+
1453 '<span class="popup-subtitle">'+categoryTitles.join()+'</span>'+
1454 '<span class="popup-title">'+title+'</span>'+
1455 '<span class="popup-desciption">'+descriptionText+'</span>'+
1456 '</span>'+
1457 '</a>';
1458
1459 var newNodeObject = A.Node.create(popupContentTemplate);
1460 newNodeObject.on('click', function(event){
1461 event.preventDefault();
1462 var nodeArticleId = this.attr('data-articleid');
1463 ${namespace}getArticleDisplay(nodeArticleId);
1464 });
1465
1466 var marker = L.marker([latLng[0],latLng[1]],
1467 {
1468 "icon": fontAwesomeIcon,
1469 "title": title
1470 }
1471 );
1472 marker.articleId='service-'+articleId;
1473 marker.bindPopup(newNodeObject.getDOMNode());
1474 marker.on('popupopen', function(e) {
1475 map.panTo(this.getLatLng());
1476 });
1477 marker.on('popupclose', function(e) {
1478 ${namespace}closeArticleDisplay();
1479 });
1480 //markersServicesGroup.addLayer(marker);
1481
1482 for(var pointGroupsIndex in pointGroups) {
1483 var pointGroup = pointGroups[pointGroupsIndex];
1484 if(pointGroup)
1485 pointGroup.addLayer(marker);
1486 }
1487
1488 serviceMarkers.push(marker);
1489
1490 //CreateObject
1491 var entry = A.Node.create('<div class="slide service-structure service-structure-'+subTypeId+' '+categoryIds.map(id => 'service-category-' + id).join(' ')+'"></div>');
1492 var anchor = A.Node.create('<a onclick="event.preventDefault(); ${namespace}getArticleDisplay('+articleId+');" class="card service item-card" data-articleid="'+articleId+'" data-id="service-'+articleId+'" href="'+detailURL+'" title="'+title+'"></a>');
1493 var anchorImageWrapper = A.Node.create('<span class="d-block image-wrapper aspect-ratio-bg-cover aspect-ratio-4-to-3"></span>');
1494 if(descriptionText!=''){
1495 var anchorImageWrapperHover = A.Node.create('<span class="card-hover"></span>');
1496 var anchorImageWrapperHoverDescription = A.Node.create('<span class="card-hover-text" itemprop="description">'+descriptionText+'</span>');
1497 anchorImageWrapperHover.append(anchorImageWrapperHoverDescription);
1498 anchorImageWrapper.append(anchorImageWrapperHover);
1499 }
1500 var anchorImage = A.Node.create('<img class="" src="'+imageThumbnail2+'" alt="'+title+'" loading="lazy" onload="this.parentElement.style.backgroundImage = \'url(\'+this.src+\')\'; this.classList.add(\'hide-accessible\');" />');
1501 var anchorBody = A.Node.create('<span class="card-body"></span>');
1502 var anchorTitle = A.Node.create('<span class="card-title">'+title+'</span>');
1503 var anchorCategories = A.Node.create('<span class="card-categories">'+categoryTitles.join()+'</span>');
1504 var anchorConcejos = A.Node.create('<span class="card-subtitle">'+categoryConcejos.join()+'</span>');
1505
1506 anchorImageWrapper.append(anchorImage);
1507 anchor.append(anchorImageWrapper);
1508 anchorBody.append(anchorTitle);
1509 anchorBody.append(anchorCategories);
1510 anchorBody.append(anchorConcejos);
1511 anchor.append(anchorBody);
1512
1513 entry.append(anchor);
1514
1515 slickAddHTML += '<li class="service-structure-'+subTypeId+' '+categoryIds.map(id => 'service-category-' + id).join(' ')+'">'+entry.outerHTML()+'</li>';
1516 }
1517 }
1518 }
1519 $('.slider').slick('slickAdd', slickAddHTML);
1520
1521 A.all('.card.service').each(function(item){
1522 item.on('mouseover', function(event){
1523 var articleId = item.getAttribute("data-id");
1524 ${namespace}markerServicePopup(articleId, true);
1525 });
1526 item.on('mouseout', function(event){
1527 var articleId = item.getAttribute("data-id");
1528 ${namespace}markerServicePopup(articleId, false);
1529 });
1530 });
1531
1532 var vocabularyWrapper = A.one('.vocabulary-wrapper[data-structurekey="' + structureKey + '"]');
1533 var vocabularyButtonWrapper = A.one('.filter-categories .button-vocabulary-structure[data-vocabulary-structure-id="' + structureKey + '"]');
1534 if(vocabularyWrapper){
1535 vocabularyWrapper.addClass("selectable");
1536 vocabularyWrapper.one('.vocabulary').on('click', function(){
1537 if($(window).width() > 768)
1538 ${namespace}toggleMarkersServicesStructure(structureKey);
1539 else
1540 vocabularyWrapper.toggleClass('hover');
1541
1542 });
1543 vocabularyWrapper.removeClass("disabled-service");
1544 if(vocabularyButtonWrapper)
1545 vocabularyButtonWrapper.removeClass("disabled-service");
1546 }
1547 }
1548
1549 if(serviceMarkers && serviceMarkers.length>0){
1550 if(servicesPanel)
1551 servicesPanel.show();
1552 if(mapFilter)
1553 mapFilter.show();
1554 }
1555 }
1556 }
1557 });
1558 });
1559
1560 <#list filterStructures as filterStructure>
1561
1562 var structureKeys = '${filterStructure["structureKeys"]}';
1563 var assetAnyCategoryIds = '${filterStructure["vocabularyCategoryIds"]}';
1564 var assetAllCategoryIds = '';
1565 var assetAnyTags = '';
1566 var assetAllTags = '';
1567 var vocabularyIds = '${filterStructure["vocabularyId"]},${concejosVocabulary.getVocabularyId()}';
1568 var delta = 500;
1569 journalArticlesResourcesCount(delta, structureKeys, assetAnyCategoryIds, assetAllCategoryIds, assetAnyTags, assetAllTags, vocabularyIds);
1570 servicesContainer.removeClass('lfr-spa-loading');
1571
1572 </#list>
1573
1574 //Filter categories
1575 //console.log(markersServicesGroups);
1576 A.all('.categories input').each(function(item){
1577 item.on('click', function(){
1578
1579 var categoryIds = [];
1580 var categoryIdsCssClass = '';
1581 var vocabularyWrapper = item.ancestor('.vocabulary-wrapper');
1582 var vocabulary = vocabularyWrapper.one('.vocabulary');
1583 var categoryId = item.getAttribute('data-id');
1584 var structureId = vocabulary.getAttribute('data-vocabulary-structure-id');
1585 var button = A.one('#button-vocabulary-structure-id-'+structureId);
1586 var pointsGroup = markersServicesGroups[categoryId];
1587
1588 if(pointsGroup){
1589 if(item.attr('checked')){
1590 map.addLayer(pointsGroup);
1591 }else{
1592 map.removeLayer(pointsGroup);
1593 }
1594 }
1595 if(item.attr('checked')){
1596 vocabularyWrapper.addClass('selected');
1597 button.addClass('selected');
1598 }else{
1599 var flag = true;
1600 var categories = vocabularyWrapper.all('.categories input').each(function(index){
1601 if(index.attr('checked'))
1602 flag = false;
1603 });
1604 if(flag){
1605 vocabularyWrapper.removeClass('selected');
1606 button.removeClass('selected');
1607 }
1608 }
1609
1610 A.all('.categories input').each(function(index){
1611 if(index.attr('checked')){
1612 var categoryId = index.getAttribute('data-id');
1613 categoryIds.push('.service-category-'+categoryId);
1614 }
1615 });
1616
1617 $(".slider").slick('slickUnfilter');
1618 categoryIdsCssClass = categoryIds.join();
1619 if(categoryIdsCssClass!='')
1620 $(".slider").slick('slickFilter', categoryIdsCssClass);
1621
1622 });
1623 });
1624
1625 //Filter services
1626 A.all('.button-vocabulary-structure').each(function(item){
1627 item.on('click', function(event){
1628 event.preventDefault();
1629 var structureId = item.attr('data-vocabulary-structure-id');
1630 if($(window).width() > 768)
1631 ${namespace}toggleMarkersServicesStructure(structureId);
1632 });
1633 });
1634
1635 //Route
1636 var routesPolylines = [];
1637 var routesPolylinesGroup = L.featureGroup();
1638 var routesNearPolylinesGroup = L.layerGroup();
1639 const fontAwesomeRouteStartIcon = L.divIcon({
1640 className: 'marker-wrapper',
1641 html: "<div class='marker-icon marker-icon-start marker-icon-start-min'><i class='fas fa-bicycle'><!-- icon--></i></div>",
1642 iconSize: [26, 30],
1643 iconAnchor: [13, 5]
1644 });
1645 const fontAwesomeRouteEndIcon = L.divIcon({
1646 className: 'marker-wrapper',
1647 html: "<div class='marker-icon marker-icon-end marker-icon-end-min'><i class='fas fa-bicycle'><!-- icon--></i></div>",
1648 iconSize: [26, 30],
1649 iconAnchor: [13, 30]
1650 });
1651 const fontAwesomeRouteNearIcon = L.divIcon({
1652 className: 'marker-wrapper',
1653 html: "<div class='marker-icon marker-icon-near marker-icon-near-min'><i class='fas fa-bicycle'><!-- icon--></i></div>",
1654 iconSize: [26, 30],
1655 iconAnchor: [13, 5]
1656 });
1657
1658 <#if gpxRoute?has_content>
1659
1660 <#assign gpxRoute = gpxRoute.put("articleId", articleId)! />
1661 <#assign gpxRoute = gpxRoute.put("color", "000")! />
1662 <#assign gpxRoute = gpxRoute.put("url", "")! />
1663 <#assign gpxRoute = gpxRoute.put("title", title)! />
1664
1665 var popupTextStartTemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-subtitle">${languageUtil.get(request, 'infoasturias-route-start')}</span><span class="popup-title">${htmlUtil.escape(Inicio.getData())}</span></span></span>';
1666 var popupTextEndTemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-subtitle">${languageUtil.get(request, 'infoasturias-route-end')}</span><span class="popup-title">${htmlUtil.escape(Finalizacion.getData())}</span></span></span>';
1667
1668 //Markers Route Start/End
1669 var latLng = '${gpxRoute.get("coordinatesStart")}';
1670 latLng = latLng.replaceAll(' ', '');
1671 latLng = latLng.split(',');
1672 var markerRouteStart = L.marker([latLng[0],latLng[1]],
1673 {
1674 "icon": fontAwesomeRouteStartIcon,
1675 "title": '${languageUtil.format(request, 'infoasturias-route-start-x', '${htmlUtil.escape(gpxRoute.get("title"))}')}'
1676 }
1677 ).bindPopup(popupTextStartTemplate).addTo(map);
1678 var latLng = '${gpxRoute.get("coordinatesEnd")}';
1679 latLng = latLng.replaceAll(' ', '');
1680 latLng = latLng.split(',');
1681 var markerRouteEnd = L.marker([latLng[0],latLng[1]],
1682 {
1683 "icon": fontAwesomeRouteEndIcon,
1684 "title": '${languageUtil.format(request, 'infoasturias-route-end-x', '${htmlUtil.escape(gpxRoute.get("title"))}')}'
1685 }
1686 ).bindPopup(popupTextEndTemplate).addTo(map);
1687
1688 //POIs
1689 var poiMarkers = [];
1690 <#if arrayPDIs?has_content>
1691 <#list arrayPDIs as arrayPDI>
1692 var poiArticleId = '${arrayPDI.get("articleId")}';
1693 var latLng = '${arrayPDI.get("coordinates")}';
1694 var url = '${arrayPDI.get("url")}';
1695 var image = '${arrayPDI.get("image")}';
1696 var title = '${htmlUtil.escape(arrayPDI.get("title"))}';
1697 var description = '${htmlUtil.escape(arrayPDI.get("description"))}';
1698 var subtitle = '${htmlUtil.escape(arrayPDI.get("subtitle"))}';
1699 var icon = 'fas fa-info';
1700 <#if arrayPDI.get("icon")?has_content>
1701 var icon = '${arrayPDI.get("icon")}';
1702 </#if>
1703 if(latLng){
1704
1705 latLng = latLng.replaceAll(' ', '');
1706 latLng = latLng.split(',');
1707
1708 var fontAwesomeRoutePOIIcon = L.divIcon({
1709 className: 'marker-wrapper',
1710 html: "<div class='marker-icon marker-icon-poi marker-icon-poi-min'><i class='"+icon+"'><!-- icon--></i></div>",
1711 iconSize: [26, 30],
1712 iconAnchor: [13, 5]
1713 });
1714
1715 var popupContentTemplate = '<a data-articleid="'+poiArticleId+'" href="'+url+'" class="popup popup-service">'+
1716 '<span class="popup-image-wrapper" style="background-image: url('+image+');"><img src="'+image+'"/></span>'+
1717 '<span class="popup-body">'+
1718 '<span class="popup-subtitle">'+subtitle+'</span>'+
1719 '<span class="popup-title">'+title+'</span>'+
1720 '<span class="popup-desciption">'+description+'</span>'+
1721 '</span>'+
1722 '</a>';
1723
1724 var newNodeObject = A.Node.create(popupContentTemplate);
1725 newNodeObject.on('click', function(event){
1726 event.preventDefault();
1727 var nodeArticleId = this.attr('data-articleid');
1728 ${namespace}getArticleDisplay(nodeArticleId);
1729 });
1730
1731 var marker = L.marker([latLng[0],latLng[1]],
1732 {
1733 "icon": fontAwesomeRoutePOIIcon,
1734 "title": title
1735 }
1736 );
1737 marker.articleId = 'poi-'+poiArticleId;
1738 marker.bindPopup(newNodeObject.getDOMNode()).addTo(map);
1739 marker.on('popupopen', function(e) {
1740 map.panTo(this.getLatLng());
1741 });
1742 marker.getPopup().on('remove', function() {
1743 ${namespace}closeArticleDisplay();
1744 });
1745
1746 poiMarkers.push(marker);
1747 }
1748 </#list>
1749 </#if>
1750 A.all('.card.poi').each(function(item){
1751 item.on('mouseover', function(event){
1752 var articleId = item.getAttribute("data-id");
1753 ${namespace}markerPopup(articleId, true);
1754 });
1755 item.on('mouseout', function(event){
1756 var articleId = item.getAttribute("data-id");
1757 ${namespace}markerPopup(articleId, false);
1758 });
1759 });
1760
1761 //RouteNears
1762 routesNearPolylines = [];
1763 <#list gpxRoutes as gpxRoute>
1764 var polylinePopupHTML = '<a href="${gpxRoute.get("url")}" class="popup">'+
1765 '<span class="popup-image-wrapper" style="background-image: url(${gpxRoute.get("image")});"><img src="${gpxRoute.get("image")}"/>'+
1766 <#--'<span class="ribbon ribbon-circle"><span class="ribbon-text ">${gpxRoute.get("distance")}</span><span class="ribbon-text ribbon-text-meta">km</span></span>'+-->
1767 '</span>'+
1768 '<span class="popup-body">'+
1769 '<span class="popup-title" style="color: #${gpxRoute.get("color")};">${htmlUtil.escape(gpxRoute.get("title"))}</span>'+
1770 '<span class="d-block"><span class="icon fas fa-map-marker-alt"><span class="hide-accessible">${languageUtil.get(request, "infoasturias-route-lugar-inicio-fin")}</span></span> <span class="value important text-uppercase">${htmlUtil.escape(gpxRoute.get("startEnd"))}</span></span>'+
1771 '<span class="d-block"><span class="icon fas fa-bicycle"><span class="hide-accessible">${languageUtil.get(request, "infoasturias-route-recorridos")}</span></span> <span class="value">${htmlUtil.escape(gpxRoute.get("routeTypes"))}</span></span>'+
1772 '<span class="d-block"><span class="icon fas fa-mountain"><span class="hide-accessible">${languageUtil.get(request, "infoasturias-route-ibp-index")}</span></span> <span class="important">IBP Index: </span> <span class="value">${gpxRoute.get("ibp")}</span></span>'+
1773 '<span class="d-block"><span class="icon fas fa-bicycle"><span class="hide-accessible">${languageUtil.get(request, "mode")}</span></span> <span class="value">${gpxRoute.get("mode")}</span></span>'+
1774 '</span>'+
1775 '</a>';
1776 var polyline = L.polyline(${gpxRoute.get("coordinates")}, {color: '#cacaca', opacity: 1, weight: 3, className: "bordered-polyline"}).bindPopup(polylinePopupHTML);
1777 polyline.articleId = 'route-near-${gpxRoute.get("articleId")}';
1778 polyline.flag = true;
1779 polyline.on('mouseover', function(e) {
1780 var layer = e.target;
1781 layer.setStyle({
1782 color: '#cacaca',
1783 opacity: 1,
1784 weight: 5
1785 });
1786 layer.bringToFront();
1787 });
1788 polyline.on('mouseout', function(e) {
1789 if(this.flag){
1790 var layer = e.target;
1791 layer.setStyle({
1792 color: '#cacaca',
1793 opacity: 0.9,
1794 weight: 3
1795 });
1796 }
1797 });
1798 polyline.on('click', function(e) {
1799 var popup = this.getPopup();
1800 var layer = e.target;
1801 layer.setStyle({
1802 color: '#cacaca',
1803 opacity: 1,
1804 weight: 5
1805 });
1806 this.flag = false;
1807 layer.bringToFront();
1808 popup.setLatLng(this.getCenter());
1809 popup.openPopup();
1810 map.setView(this.getCenter());
1811 var pixelesCenter = map.latLngToContainerPoint(this.getCenter());
1812 pixelesCenter.y -= map.getSize().y * 0.2;
1813 var centerMap = map.containerPointToLatLng(pixelesCenter);
1814 map.setView(centerMap);
1815 });
1816 polyline.on('popupclose', function(e) {
1817 var layer = e.target;
1818 layer.setStyle({
1819 color: '#cacaca',
1820 opacity: 0.9,
1821 weight: 3
1822 });
1823 });
1824 routesNearPolylines.push(polyline);
1825
1826 var popupTextStartTemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-subtitle">${languageUtil.get(request, 'infoasturias-route-start')}</span><span class="popup-title">${htmlUtil.escape(gpxRoute.get("title"))}</span></span></span>';
1827 var popupTextEndTemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-subtitle">${languageUtil.get(request, 'infoasturias-route-end')}</span><span class="popup-title">${htmlUtil.escape(gpxRoute.get("title"))}</span></span></span>';
1828
1829 //Markers Route Near Start/End
1830 var latLng = '${gpxRoute.get("coordinatesStart")}';
1831 latLng = latLng.replaceAll(' ', '');
1832 latLng = latLng.split(',');
1833 var markerRouteStart = L.marker([latLng[0],latLng[1]],
1834 {
1835 "icon": fontAwesomeRouteNearIcon,
1836 "title": '${languageUtil.format(request, 'infoasturias-route-start-x', '${htmlUtil.escape(gpxRoute.get("title"))}')}'
1837 }
1838 ).bindPopup(popupTextStartTemplate).addTo(routesNearPolylinesGroup);
1839 var latLng = '${gpxRoute.get("coordinatesEnd")}';
1840 latLng = latLng.replaceAll(' ', '');
1841 latLng = latLng.split(',');
1842 var markerRouteEnd = L.marker([latLng[0],latLng[1]],
1843 {
1844 "icon": fontAwesomeRouteNearIcon,
1845 "title": '${languageUtil.format(request, 'infoasturias-route-end-x', '${htmlUtil.escape(gpxRoute.get("title"))}')}'
1846 }
1847 ).bindPopup(popupTextEndTemplate).addTo(routesNearPolylinesGroup);
1848
1849 routesPolylinesGroup.addLayer(polyline);
1850 routesNearPolylinesGroup.addLayer(polyline);
1851
1852 </#list>
1853 //List
1854 A.all('.route-near').each(function(item){
1855 item.on('mouseover', function(event){
1856 var articleId = item.getAttribute("data-id");
1857 ${namespace}polylinePopup(articleId, true);
1858 });
1859 item.on('mouseout', function(event){
1860 var articleId = item.getAttribute("data-id");
1861 ${namespace}polylinePopup(articleId, false);
1862 });
1863 });
1864
1865 var gropedOverlayslehen = {
1866 "${languageUtil.get(locale, "infoasturias-routes-near")}": routesNearPolylinesGroup
1867 }
1868 var layerControl = L.control.layers('', gropedOverlayslehen, {
1869 collapsed: false,
1870 position:'topleft'
1871 });
1872 layerControl.addTo(map);
1873
1874 //Elevation
1875
1876 var elevation_options = {
1877
1878 // Default chart colors: theme lime-theme, magenta-theme, ...
1879 theme: "custom-theme",
1880
1881 useHeightIndicator: true,
1882
1883 // Chart container outside/inside map container
1884 detached: true,
1885
1886 // if (detached), the elevation chart container
1887 elevationDiv: "#elevation-div-${articleId}",
1888
1889 // if (!detached) autohide chart profile on chart mouseleave
1890 autohide: false,
1891
1892 // if (!detached) initial state of chart profile control
1893 collapsed: false,
1894
1895 // if (!detached) control position on one of map corners
1896 position: "topright",
1897
1898 // Toggle close icon visibility
1899 closeBtn: false,
1900
1901 // Autoupdate map center on chart mouseover.
1902 followMarker: true,
1903
1904 // Autoupdate map bounds on chart update.
1905 autofitBounds: false,
1906
1907 // Chart distance/elevation units.
1908 imperial: false,
1909
1910 // [Lat, Long] vs [Long, Lat] points. (leaflet default: [Lat, Long])
1911 reverseCoords: false,
1912
1913 // Acceleration chart profile: true || "summary" || "disabled" || false
1914 acceleration: false,
1915
1916 // Slope chart profile: true || "summary" || "disabled" || false
1917 slope: false,
1918
1919 // Speed chart profile: true || "summary" || "disabled" || false
1920 speed: false,
1921
1922 // Altitude chart profile: true || "summary" || "disabled" || false
1923 altitude: true,
1924
1925 // Display time info: true || "summary" || false
1926 time: false,
1927
1928 // Display distance info: true || "summary" || false
1929 distance: true,
1930
1931 // Summary track info style: "inline" || "multiline" || false
1932 summary: false,
1933
1934 // Download link: "link" || false || "modal"
1935 downloadLink: false,
1936
1937 // Toggle chart ruler filter
1938 ruler: true,
1939
1940 // Toggle chart legend filter
1941 legend: false,
1942
1943 // Toggle "leaflet-almostover" integration
1944 almostOver: true,
1945
1946 // Toggle "leaflet-distance-markers" integration
1947 distanceMarkers: false,
1948
1949 // Toggle "leaflet-edgescale" integration
1950 edgeScale: false,
1951
1952 // Toggle "leaflet-hotline" integration
1953 hotline: true,
1954
1955 // Display track datetimes: true || false
1956 timestamps: false,
1957
1958 // Display track waypoints: true || "markers" || "dots" || false
1959 waypoints: true,
1960
1961 // Toggle custom waypoint icons: true || { associative array of <sym> tags } || false
1962 wptIcons: false,
1963
1964 // Toggle waypoint labels: true || "markers" || "dots" || false
1965 wptLabels: false,
1966
1967 // Render chart profiles as Canvas or SVG Paths
1968 preferCanvas: false,
1969
1970 height: 200,
1971 };
1972
1973 ${namespace}initializeElevation(map, elevation_options);
1974
1975 //Center
1976 var routesMainPolyline = L.polyline(${gpxRoute.get("coordinates")});
1977 routesPolylinesGroup.addLayer(routesMainPolyline);
1978 map.fitBounds(routesMainPolyline.getBounds());
1979
1980 //Enabled/Disabled routesNearPolylinesGroup
1981 let previousBounds = null;
1982 map.on('overlayadd', function (e) {
1983 if (e.layer === routesNearPolylinesGroup) {
1984 previousBounds = map.getBounds();
1985 const groupBounds = routesPolylinesGroup.getBounds();
1986 if (groupBounds.isValid())
1987 map.fitBounds(groupBounds);
1988 }
1989 });
1990 map.on('overlayremove', function (e) {
1991 if (e.layer === routesNearPolylinesGroup && previousBounds) {
1992 map.fitBounds(previousBounds);
1993 previousBounds = null;
1994 }
1995 });
1996
1997 <#assign poiImages = {
1998 "Beach": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/playa.png",
1999 <#--"Bike Trail": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/rutaini-ew.png",-->
2000 <#--"Bike Trail": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/rutaini-we.png",-->
2001 <#--"Building": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/ciudad.png",-->
2002 "City Hall": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/ferrocarril.png",
2003 <#--"Civil": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/rutafin.png",-->
2004 <#--"Flag, Green": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/ini-vv.png",-->
2005 <#--"Flag, Red": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/fin-vv.png",-->
2006 "Light": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/faro.png",
2007 <#--"Navaid, Blue": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/cultural.png",-->
2008 <#--"Navaid, Green": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/natural.png",-->
2009 <#--"Navaid, Red": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/warning.png",-->
2010 <#--"Residence": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/pueblo.png",-->
2011 "Scenic Area": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/paisaje.png",
2012 "Summit": "/o/turismo-asturias-theme/css/images/cicloturismo/pois/cumbre.png"
2013 }>
2014 <#assign poiFontAwesome = {
2015 "": "fas fa-info",
2016 "Beach": "fas fa-umbrella-beach",
2017 <#--"Bike Trail": "",-->
2018 <#--"Bike Trail": "",-->
2019 <#--"Building": "",-->
2020 "City Hall": "fas fa-train",
2021 <#--"Civil": "",-->
2022 <#--"Flag, Green": "",-->
2023 <#--"Flag, Red": "",-->
2024 "Light": "fas fa-monument",
2025 <#--"Navaid, Blue": "",-->
2026 <#--"Navaid, Green": "",-->
2027 <#--"Navaid, Red": "",-->
2028 <#--"Residence": "",-->
2029 "Scenic Area": "fas fa-camera",
2030 "Summit": "fas fa-mountain"
2031 }>
2032
2033 <#if validator.isNotNull(gpxPOIRoute)>
2034 <#if gpxPOIRoute.has("wpts") && validator.isNotNull(gpxPOIRoute.has("wpts"))>
2035 <#assign wptJSONArray = jsonFactoryUtil.createJSONArray(gpxPOIRoute.get("wpts"))! />
2036 <#list 0..wptJSONArray.length() as i>
2037 <#assign wptJSONObject = wptJSONArray.get(i)! />
2038 <#if validator.isNotNull(wptJSONObject)>
2039
2040 <#assign wptName = wptJSONObject.get("name")! />
2041 <#assign wptSym = wptJSONObject.get("sym")! />
2042 <#assign wptLat = wptJSONObject.get("lat")! />
2043 <#assign wptLon = wptJSONObject.get("lon")! />
2044 <#assign wptEle = wptJSONObject.get("ele")! />
2045 <#assign wptSymImage = poiImages[wptSym]! />
2046 <#assign wptSymFontAwesome = poiFontAwesome[wptSym]! />
2047 <#if validator.isNotNull(wptSymFontAwesome)>
2048
2049 var divIcon = L.divIcon({
2050 className: 'marker-wrapper',
2051 html: "<div class='marker-icon marker-icon-poi marker-icon-poi-min'><i class='${wptSymFontAwesome}'><!-- icon--></i></div>",
2052 iconSize: [26, 30],
2053 iconAnchor: [13, 30]
2054 });
2055 var popupPOITemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-title">${htmlUtil.escape(wptName)}</span></span></span>';
2056 var marker = L.marker([${wptLat}, ${wptLon}],
2057 {
2058 "icon": divIcon,
2059 "title": '${htmlUtil.escape(wptName)}'
2060 }
2061 ).bindPopup(popupPOITemplate).addTo(map);
2062 marker.on('popupopen', function(e) {
2063 map.panTo(this.getLatLng());
2064 });
2065 </#if>
2066 </#if>
2067 </#list>
2068 </#if>
2069
2070 <#-- TODO -->
2071 <#assign dlFileEntryGPXPOI = dlTool.getDLFileEntryByPath(Documentos.GPXPOIRuta.data)!/>
2072 <#if validator.isNotNull(dlFileEntryGPXPOI)>
2073 <#assign document = saxReaderUtil.read(dlFileEntryGPXPOI.getContentStream())/>
2074 <#assign root = document.getRootElement()/>
2075 <#assign trks = root.elements("trk")!>
2076 <#if validator.isNotNull(trks)>
2077 <#list trks as trk>
2078 <#assign trkName = trk.elementText("name")!>
2079 <#assign trkseg = trk.element("trkseg")!>
2080 <#if validator.isNotNull(trkseg)>
2081 <#assign trkpts = trkseg.elements("trkpt")!>
2082 <#if validator.isNotNull(trkpts)>
2083 var trksegsLatLngs = [];
2084 <#list trkpts as trkpt>
2085 <#assign trksegLat = trkpt.attributeValue("lat")!>
2086 <#assign trksegLon = trkpt.attributeValue("lon")!>
2087 <#if validator.isNotNull(trksegLat) && validator.isNotNull(trksegLon)>
2088 var trksegsLatLng = [${trksegLat}, ${trksegLon}];
2089 trksegsLatLngs.push(trksegsLatLng);
2090 </#if>
2091 </#list>
2092 if(trksegsLatLngs.length>0){
2093 var popupGpxPOITemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-title">${htmlUtil.escape(trkName)}</span></span></span>';
2094 var trkPolyline = L.polyline(trksegsLatLngs, {color: '#006db0', dashArray: '5, 10', lineCap: 'square', opacity: 1, weight: 5, className: "bordered-polyline-white"}).bindPopup(popupGpxPOITemplate).addTo(map);
2095 }
2096 </#if>
2097 </#if>
2098 </#list>
2099 </#if>
2100 </#if>
2101 </#if>
2102
2103 <#--Notices-->
2104 <#if validator.isNotNull(markersNotices) && markersNotices?size gt 0>
2105 const markersNotices = {};
2106 <#list markersNotices as markersNotice>
2107
2108 <#if validator.isNotNull(markersNotice)>
2109
2110 (function() {
2111
2112 const id = '${markersNotice.id}';
2113 var notice = A.one('#route-${articleId}-alert-coordinates-' + id);
2114 if(notice){
2115
2116 //SessionStorage
2117 if (!sessionStorage.getItem(id)) {
2118
2119 notice.show();
2120 notice.addClass('show');
2121
2122 //Marker
2123 var divIcon = L.divIcon({
2124 className: 'marker-wrapper',
2125 html: "<div class='marker-circle marker-notice marker-notice-${markersNotice.type}'><i class='${markersNotice.icon}'><!-- icon--></i></div>",
2126 iconSize: [26, 30],
2127 iconAnchor: [13, 30]
2128 });
2129 var popupPOITemplate = '<span class="popup popup-service"><span class="popup-body"><span class="popup-title">${htmlUtil.escape(htmlUtil.extractText(markersNotice.title))}</span><span class="popup-text">${htmlUtil.escape(htmlUtil.extractText(markersNotice.description))}</span></span></span>';
2130 var marker = L.marker([${markersNotice.coordinates}],
2131 {
2132 "icon": divIcon,
2133 "title": '${htmlUtil.escape(htmlUtil.extractText(markersNotice.title))}'
2134 }
2135 ).bindPopup(popupPOITemplate).addTo(map);
2136 marker.on('popupopen', function(e) {
2137 map.panTo(this.getLatLng());
2138 });
2139 markersNotices[id] = marker;
2140
2141 //Notice
2142 notice.on('hover', function(){
2143 markersNotices[id].openPopup();
2144 map.panTo(markersNotices[id].getLatLng());
2145 });
2146 var close = notice.one('.close');
2147 if(close){
2148 close.on('click', function(){
2149 sessionStorage.setItem(id, 'true');
2150 });
2151 }
2152 }
2153 }
2154 })();
2155
2156 </#if>
2157
2158 </#list>
2159 </#if>
2160
2161 //Functions
2162 function ${namespace}initializeElevation(map, elevation_options) {
2163
2164 const controlElevation = L.control.elevation(elevation_options).addTo(map);
2165
2166 //Fixed random hotline route map error not rendering
2167 const hotlineLayer = L.hotline(${gpxRoute.get("coordinates")}, {
2168 min: ${gpxRoute.get("elevationMin")},
2169 max: ${gpxRoute.get("elevationMax")},
2170 palette: {
2171 0.0: 'green',
2172 0.5: 'yellow',
2173 1.0: 'red'
2174 },
2175 weight: 5,
2176 outlineColor: 'black',
2177 outlineWidth: 1
2178 }).addTo(map);
2179
2180 controlElevation.load('${gpxRutaPath}');
2181 }
2182
2183 function ${namespace}markerPopup(articleId, hover){
2184 for (var i in poiMarkers){
2185 var marker = poiMarkers[i];
2186 var id = marker.articleId;
2187 if (id == articleId){
2188 if(hover){
2189 marker.openPopup();
2190 map.panTo(marker.getLatLng());
2191 }else{
2192 //marker.closePopup();
2193 }
2194 };
2195 }
2196 }
2197
2198 function ${namespace}markerServicePopup(articleId, hover){
2199 for (var i in serviceMarkers){
2200 var marker = serviceMarkers[i];
2201 var id = marker.articleId;
2202 if (id == articleId){
2203 if(hover){
2204 map.addLayer(marker);
2205 marker.openPopup();
2206 map.panTo(marker.getLatLng());
2207 }else{
2208 //map.removeLayer(marker);
2209 //marker.closePopup();
2210 }
2211 };
2212 }
2213 }
2214
2215 function ${namespace}polylinePopup(articleId, hover){
2216 for (var i in routesNearPolylines){
2217 var polyline = routesNearPolylines[i];
2218 if (map.hasLayer(routesNearPolylinesGroup)){
2219 var id = polyline.articleId;
2220 if (id == articleId){
2221 if(hover){
2222 polyline.openPopup();
2223 polyline.setStyle({
2224 weight: 5,
2225 opacity: 1
2226 });
2227 map.panTo(polyline.getCenter());
2228 polyline.bringToFront();
2229 }else{
2230 polyline.setStyle({
2231 weight: 3,
2232 opacity: 0.9
2233 });
2234 polyline.closePopup();
2235 }
2236 }
2237 }
2238 }
2239 }
2240
2241 function ${namespace}toggleMarkersServicesStructure(structureId){
2242
2243 var item = A.one('#vocabulary-structure-id-'+structureId);
2244 var button = A.one('#button-vocabulary-structure-id-'+structureId);
2245 if(item){
2246
2247 var vocabularyWrapper = item.ancestor('.vocabulary-wrapper');
2248 if(!vocabularyWrapper.hasClass('selected')){
2249 vocabularyWrapper.all('.categories input').attr('checked','');
2250 vocabularyWrapper.all('.categories input').each(function(cat){
2251 cat.simulate('click');
2252 });
2253 vocabularyWrapper.addClass('selected');
2254 if(button){
2255 button.addClass('selected');
2256 }
2257 }else{
2258 vocabularyWrapper.all('.categories input').attr('checked','checked');
2259 vocabularyWrapper.all('.categories input').each(function(cat){
2260 cat.simulate('click');
2261 });
2262 vocabularyWrapper.removeClass('selected');
2263 if(button){
2264 button.removeClass('selected');
2265 var allNoSelectedButtons = true;
2266 A.all('.button-vocabulary-structure').each(function(item){
2267 if(item.hasClass('selected'))
2268 allNoSelectedButtons = false;
2269 });
2270 }
2271 }
2272 }
2273 }
2274
2275 Liferay.provide(window, '${namespace}closeArticleDisplay', function(){
2276 A.one("#article-display-container").hide('fadeOut');
2277 A.one("#search-container").show('fadeIn');
2278 });
2279
2280 Liferay.provide(window, '${namespace}openArticleDisplay', function(){
2281 A.one("#search-container").hide();
2282 A.one("#article-display-container").show('fadeIn');
2283
2284 //Map
2285 var articleDisplayContainerMap = A.one("#article-display-container").one('.article-section-map script[type="text/javascript"]');
2286 if(articleDisplayContainerMap)
2287 eval(articleDisplayContainerMap.html());
2288
2289 //Scroll
2290 var to = A.one('#article-display-container');
2291 if(to){
2292 var position = 100;
2293 var toggleMap = A.one('#toggle-map');
2294 if(toggleMap && toggleMap.hasClass('active')){
2295 position = 0;
2296 to = A.one('body');
2297 }
2298 var anim = new A.Anim({
2299 duration: 0.2,
2300 node: A.getWin(),
2301 to: {
2302 scroll: [0, to.getY() - position]
2303 }
2304 }).run();
2305 }
2306 });
2307
2308 Liferay.provide(window, '${namespace}getArticleDisplay', function(articleId){
2309
2310 var url = "${themeDisplay.getURLPortal()+themeDisplay.getLayout().getFriendlyURL(locale)}?p_p_id=${themeDisplay.getPortletDisplay().getId()}&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=journalDisplayContent&p_p_cacheability=cacheLevelPage&_${themeDisplay.getPortletDisplay().getId()}_articleId="+articleId;
2311 A.io.request(url, {
2312 method: 'GET',
2313 type: 'HTML',
2314 on: {
2315 success: function() {
2316 var journalArticleContentDisplay = this.get('responseData');
2317 journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("col-md-6", "col-12");
2318 journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("article-info-wrapper", "");
2319 journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("article-info-table", "");
2320 journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("article-info-table-row", "");
2321 journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("article-info-table-cell", "");
2322 journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("article-info", "article-info m-0 px-4 pt-4");
2323 //journalArticleContentDisplay = journalArticleContentDisplay.replaceAll("article-section-map", "article-section-map hide");
2324 A.one("#article-display").html(journalArticleContentDisplay);
2325 ${namespace}openArticleDisplay();
2326 }
2327 }
2328 });
2329 });
2330
2331 </#if>
2332
2333 var closeArticleDisplayNode = A.one("#close-article-display");
2334 if(closeArticleDisplayNode){
2335 closeArticleDisplayNode.on('click', function(event) {
2336 ${namespace}closeArticleDisplay();
2337 });
2338 }
2339
2340 A.all(".template-layout-map .item-card").each(function(item) {
2341 item.on("click", function(event) {
2342 event.preventDefault();
2343 var articleId = item.attr("data-articleid");
2344 ${namespace}getArticleDisplay(articleId);
2345 });
2346 });
2347
2348 //Map Mobile Toggle
2349 mapMobileToggle('${languageUtil.get(request, "infoasturias-abrir-mapa")}','${languageUtil.get(request, "infoasturias-cerrar-mapa")}', map, '.leaflet-elevation-wrapper');
2350 var toggleMap = A.one('#toggle-map');
2351 if(toggleMap){
2352 toggleMap.on('click', function(event){
2353 A.one('.template-layout-map').toggleClass('template-layout-map-mobile');
2354 A.one('#content').toggleClass('content-map-mobile');
2355 map.closePopup();
2356 if(this.hasClass('active')){
2357 ${namespace}closeArticleDisplay();
2358 //Scroll
2359 var to = A.one('body');
2360 if(to){
2361 var anim = new A.Anim({
2362 duration: 0.2,
2363 node: A.getWin(),
2364 to: {
2365 scroll: [0, to.getY()-100]
2366 }
2367 }).run();
2368 }
2369 }
2370 });
2371 }
2372
2373 /* Location */
2374 let userMarkerShadow = null;
2375 let userMarker = null;
2376 let currentPosition = null;
2377 function ${namespace}onUserLocationFound(e) {
2378 const baseColor = '#0f53ff';
2379 currentPosition = e.latlng;
2380 if (!userMarker) {
2381 userMarkerShadow = L.circleMarker(e.latlng, {radius: 15, color: null, fillColor: baseColor, fillOpacity: 0.3, interactive: false}).addTo(map);
2382 userMarker = L.circleMarker(e.latlng, {radius: 7, color: '#fff', fillColor: baseColor, fillOpacity: 1, weight: 2}).addTo(map);
2383 map.setView(currentPosition, 16);
2384 }else{
2385 userMarkerShadow.setLatLng(e.latlng);
2386 userMarker.setLatLng(e.latlng);
2387 }
2388 }
2389 var userLocationNode = A.one("#userLocation");
2390 if(userLocationNode){
2391 userLocationNode.on('click', function(){
2392 if(this.hasClass('btn-selected')){
2393 this.removeClass('btn-selected');
2394 currentPosition = null;
2395 if (userMarker) {
2396 map.removeLayer(userMarker);
2397 userMarker = null;
2398 }
2399 if (userMarkerShadow) {
2400 map.removeLayer(userMarkerShadow);
2401 userMarkerShadow = null;
2402 }
2403 map.stopLocate();
2404 }else{
2405 if(currentPosition){
2406 map.setView(currentPosition, 16);
2407 }else{
2408 map.locate({setView: false, maxZoom: 16, watch: true, enableHighAccuracy: true});
2409 map.on('locationfound', ${namespace}onUserLocationFound);
2410 this.addClass('btn-selected');
2411 }
2412 }
2413 });
2414 }
2415
2416 /* Toggle elevation */
2417 var toggleElevationNode = A.one("#toggleElevation");
2418 if(toggleElevationNode){
2419 var elevationPanel = A.one("#elevation-div-${articleId} .elevation-control");
2420 toggleElevationNode.on('click', function(){
2421 if (!elevationPanel.hasClass('elevation-control-hide')) {
2422 elevationPanel.addClass('elevation-control-hide');
2423 this.removeClass('btn-selected');
2424 } else {
2425 elevationPanel.removeClass('elevation-control-hide');
2426 this.addClass('btn-selected');
2427 }
2428 });
2429 }
2430
2431 /* Center Map Services */
2432 function fitToVisibleMarkerGroups(map, markersServicesGroups) {
2433
2434 //Init
2435 let bounds = null;
2436
2437 for (const key in markersServicesGroups) {
2438 if (markersServicesGroups.hasOwnProperty(key)) {
2439 const group = markersServicesGroups[key];
2440
2441 if (map.hasLayer(group) && group.getLayers().length > 0) {
2442 const groupBounds = group.getBounds();
2443 if (bounds) {
2444 bounds.extend(groupBounds);
2445 } else {
2446 bounds = groupBounds;
2447 }
2448 }
2449 }
2450 }
2451
2452 if (bounds) {
2453 map.fitBounds(bounds, { padding: [50, 50] });
2454 }
2455 }
2456
2457</@>