Se ha producido un error al procesar la plantilla.
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@33526454"; see cause exception in the Java stack trace.

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