Kummitustarinat ovat aina muodissa – Helsingin kummitusjutut kertovat historiasta ja moraalikäsityksistä
Virhe tapahtui prosessoidessa esitysmallia.
The following has evaluated to null or missing:
==> slot.videoFile  [in template "20116#20160#45930" at line 629, column 42]

----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign videoFile = slot.videoFile.ge...  [in template "20116#20160#45930" in macro "printRemainingVideoContents" at line 629, column 21]
	- Reached through: @printRemainingVideoContents articleV...  [in template "20116#20160#45930" at line 273, column 9]
----
1<#----------------------------------------------------------------------------- 
2    INIT 
3------------------------------------------------------------------------------> 
4 
5<#assign serviceContext = staticUtil["com.liferay.portal.kernel.service.ServiceContextThreadLocal"].getServiceContext()> 
6<#assign themeDisplay = serviceContext.getThemeDisplay() /> 
7<#assign javascript_folder = themeDisplay.getPathThemeJavaScript() > 
8 
9 
10 
11<#assign JournalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")> 
12<#assign currentArticle = JournalArticleLocalService.getArticle(groupId, .vars['reserved-article-id'].data) /> 
13<#setting url_escaping_charset="UTF-8"> 
14 
15<#-- Helper variables --> 
16<#assign includeOwlScript = false> 
17 
18<#-- Check if article is viewed in preview mode --> 
19<#if request.parameters?has_content && request.parameters['mvcPath']?has_content> 
20  <#if request.parameters['mvcPath'][0]?has_content> 
21     <#if request.parameters['mvcPath'][0] == '/preview_article_content.jsp'> 
22        <#assign previewMode = true > 
23     </#if> 
24  </#if> 
25</#if> 
26 
27<#-- 
28    Counters for keeping track of now many elements 
29    have been placed with a tag. 
30--> 
31<#global tagReplaceCounter = 0 /> 
32<#assign kainaloTagCounter = 0 /> 
33<#assign infoTagCounter = 0 /> 
34<#assign faktaTagCounter = 0 /> 
35<#assign quoteTagCounter = 0 /> 
36<#assign videoTagCounter = 0 /> 
37<#assign audioTagCounter = 0 /> 
38<#assign carousel1TagCounter = 0 /> 
39<#assign carousel2TagCounter = 0 /> 
40<#assign imageComparisonTagCounter = 0 /> 
41 
42<#-- Article ID --> 
43<#assign articleId = .vars['reserved-article-id'].data> 
44 
45<#-- Article --> 
46<#assign article = JournalArticleLocalService.getArticle(groupId, articleId) /> 
47 
48<#-- Article complete URL --> 
49<#assign serverName = request['server-name'] /> 
50<#assign urlTitle = article.urlTitle?trim /> 
51<#assign articleCompleteUrl = "https://" + serverName + "/-/" + urlTitle /> 
52 
53<#-- available author names : Those authors which have author card --> 
54<#assign authorCardFolderIds = [140767, 140764] /> <#-- Toimittjat, Kolumnistit --> 
55<#assign availableAuthorNames = getAvailableAuthorNames(authorCardFolderIds) /> 
56<#assign authorCardBaseUrl = "/toimittajat?author=" /> 
57 
58<#-- Article title --> 
59<#assign title = .vars['reserved-article-title'].data> 
60 
61<#-- Article lead --> 
62<#assign lead = .vars['reserved-article-description'].data> 
63 
64<#-- Get and format article publish date --> 
65<#assign displayDate = .vars['reserved-article-display-date'].data> 
66 
67    <#-- Save the original page locale for later --> 
68    <#assign originalLocale = locale> 
69 
70    <#-- Set the page locale to the portals default locale --> 
71    <#setting locale = localeUtil.getDefault()> 
72 
73    <#-- Parse the date to a date object --> 
74    <#assign displayDate = displayDate?datetime("EEE, d MMM yyyy HH:mm:ss Z")> 
75 
76    <#-- Set the page locale back to the original page locale --> 
77    <#assign locale = originalLocale> 
78 
79 
80<#-- Article body tags --> 
81<#assign tagKainalo = "[[kainalo]]"> 
82<#assign tagInfo = "[[info]]"> 
83<#assign tagFakta = "[[fakta]]"> 
84<#assign tagQuote = "[[sitaatti]]"> 
85<#assign tagImage = "[[kuva]]"> 
86<#assign tagVideo = "[[video]]"> 
87<#assign tagAudio = "[[audio]]"> 
88<#assign tagCarousel1 = "[[kuvakaruselli1]]"> 
89<#assign tagCarousel2 = "[[kuvakaruselli2]]"> 
90<#assign tagImageComparison = "[[vaihtokuva]]"> 
91 
92<#-- wrapper css classes --> 
93<#assign wrapperCSSKainalo = "article-section article-tail"> 
94<#assign wrapperCSSInfo = "article-box article-info"> 
95<#assign wrapperCSSFakta = "article-box article-fact"> 
96<#assign wrapperCSSQuote = "template-quote"> 
97 
98<#-- Article raw body --> 
99<#assign articleBody = articleBody.getData()> 
100 
101<#if articleTail?has_content> 
102    <#assign articleBody = replaceTags(articleBody, tagKainalo, articleTail, wrapperCSSKainalo)> 
103    <#assign kainaloTagCounter = tagReplaceCounter /> 
104</#if> 
105<#if articleInfo?has_content> 
106    <#assign articleBody = replaceTags(articleBody, tagInfo, articleInfo, wrapperCSSInfo)> 
107    <#assign infoTagCounter = tagReplaceCounter /> 
108</#if> 
109<#if articleFacts?has_content> 
110    <#assign articleBody = replaceTags(articleBody, tagFakta, articleFacts, wrapperCSSFakta)> 
111    <#assign faktaTagCounter = tagReplaceCounter /> 
112</#if> 
113<#if articleQuotes?has_content> 
114    <#assign articleBody = replaceTags(articleBody, tagQuote, articleQuotes, wrapperCSSQuote)> 
115    <#assign quoteTagCounter = tagReplaceCounter /> 
116</#if> 
117<#if articleImages?has_content> 
118    <#assign articleBody = replaceImageTags(articleBody, tagImage, articleImages)> 
119    <#assign articleBody = replaceCarouselTags(articleBody, tagCarousel1, tagCarousel2, articleImages)> 
120</#if> 
121<#if articleVideos?has_content> 
122    <#assign articleBody = replaceVideoTags(articleBody, tagVideo, articleVideos)> 
123    <#assign videoTagCounter = tagReplaceCounter /> 
124</#if> 
125<#if articleAudio?has_content> 
126    <#assign articleBody = replaceAudioTags(articleBody, tagAudio, articleAudio)> 
127    <#assign audioTagCounter = tagReplaceCounter /> 
128</#if> 
129<#if imageComparisons?has_content> 
130    <#assign articleBody = replaceImageComparisonTags(articleBody, tagImageComparison, imageComparisons)> 
131</#if> 
132 
133<#-- Article tags --> 
134<#assign articleTags = .vars['reserved-article-asset-tag-names'].data> 
135 
136 
137<#----------------------------------------------------------------------------- 
138    OUTPUT ARTICLE 
139------------------------------------------------------------------------------> 
140 
141<article> 
142 
143    <#-- Show article url in preview mode --> 
144    <#if previewMode?? && previewMode> 
145	    <div><span>${articleCompleteUrl}</span></div> 
146    </#if> 
147 
148    <#-- Article image(s) --> 
149    <#if articleImages?has_content> 
150        <#assign headerImages = getHeaderImages(articleImages) > 
151        <#assign contentCarouselImages = getContentCarouselImages(articleImages) > 
152    </#if> 
153 
154    <#if contentCarouselImages?has_content> 
155        <#if (contentCarouselImages?size > 1) > 
156            <#assign includeOwlScript = true> 
157        </#if> 
158    </#if> 
159     
160    <#if headerImages?has_content> 
161 
162        <#-- Container with bottom margin --> 
163        <div class="article-header-img"> 
164 
165            <#-- More than one image > create owl-carousel --> 
166            <#if (headerImages?size > 1) > 
167 
168                    <#list headerImages as image> 
169            		    <#if image.getData()?? && image.getData()?has_content> 
170 
171                            <#-- Open carousel container on first image --> 
172                            <#if image?is_first> 
173                                <div class="owl-carousel owl-theme"> 
174 
175                                <#-- Load carousel script at the end of display template --> 
176                                <#assign includeOwlScript = true> 
177                            </#if> 
178 
179                            <#-- Output carousel slides --> 
180                            <div class="item"> 
181                                <#if image.getAttribute("alt")?has_content> 
182                                    <div class="aspect-ratio aspect-ratio-middle aspect-ratio-xs"> 
183                                        <img src="${getThumbnailUrl(image.getData(), 3) }" alt="${image.getAttribute("alt")}" /> 
184                                    </div> 
185                                    <span class="caption">${image.getAttribute("alt")}</span> 
186                                <#else> 
187                                    <div class="aspect-ratio aspect-ratio-middle aspect-ratio-xs"> 
188                                        <img src="${getThumbnailUrl(image.getData(), 3) }" alt="" /> 
189                                    </div> 
190                                </#if> 
191                            </div> 
192 
193                            <#-- Close carousel contaner after last item --> 
194                            <#if image?is_last> 
195                                </div> <#-- div.owl-carousel --> 
196                            </#if> 
197 
198            		    </#if> 
199            	    </#list> 
200 
201            <#else> 
202 
203            <#-- Display a single image without carousel --> 
204            <#list headerImages as image> 
205    		    <#if image.getData()?? && image.getData()?has_content> 
206                    <#if image.getAttribute("alt")?has_content> 
207            	        <img src="${getThumbnailUrl(image.getData(), 3) }" alt="${image.getAttribute("alt")}" /> 
208                        <p class="caption">${image.getAttribute("alt")}</p> 
209                    <#else> 
210            	        <img src="${getThumbnailUrl(image.getData(), 3) }" alt="" /> 
211                   </#if> 
212    		    </#if> 
213    	    </#list> 
214 
215            </#if> 
216 
217        </div> <#-- div.article-header-img --> 
218 
219    </#if> 
220 
221    <#-- R&S sharing buttons --> 
222    <div class="article-sharing"> 
223        <div class="rns-share-plugin"></div> 
224    </div> 
225 
226    <h1>${title}</h1> 
227 
228    <#if lead?? && lead?has_content> 
229        <#-- Remove possible HTML-tags --> 
230        <#assign leadCleaned = htmlUtil.stripHtml(lead) /> 
231        <p class="lead">${leadCleaned}</p> 
232    </#if> 
233 
234    <ul class="list-inline article-meta"> 
235    	<li><span class="date">${displayDate?string["dd.MM.yyyy HH:mm"]}</span></li> 
236 
237    	<#if articleAuthors.authors.getData()?? && articleAuthors.authors.getData()?has_content> 
238            <#assign articleAuthor = articleAuthors.authors.getData()> 
239            <li> 
240	      <span class="author authortext-no-margin author-text"></span> 
241	      <span class="author author-name">${makeAuthorLinks(articleAuthor,availableAuthorNames, authorCardBaseUrl)}</span> 
242            </li> 
243        </#if> 
244 
245    	<#if articleAuthors.photographers.getData()?? && articleAuthors.photographers.getData()?has_content> 
246        	<li> 
247        	    <span class="author author-name author-photo"> 
248        	        ${makeAuthorLinks(articleAuthors.photographers.getData(),availableAuthorNames, authorCardBaseUrl)} 
249    	        </span> 
250        	</li> 
251    	</#if> 
252    </ul> 
253 
254    ${articleBody} 
255 
256    <#-- Output article quotes --> 
257    <#if articleQuotes?has_content && articleQuotes.getSiblings()?has_content> 
258     <@printRemainingTagContents articleQuotes quoteTagCounter wrapperCSSQuote /> 
259    </#if> 
260 
261    <#-- Print article factbox(es) --> 
262    <#if articleFacts?has_content && articleFacts.getSiblings()?has_content> 
263        <@printRemainingTagContents articleFacts faktaTagCounter wrapperCSSFakta /> 
264    </#if> 
265 
266    <#-- Print article infobox(es) --> 
267    <#if articleInfo?has_content && articleInfo.getSiblings()?has_content> 
268        <@printRemainingTagContents articleInfo infoTagCounter wrapperCSSInfo/> 
269    </#if> 
270 
271    <#-- Print article video(s) --> 
272    <#if articleVideos?has_content && articleVideos.getSiblings()?has_content> 
273        <@printRemainingVideoContents articleVideos videoTagCounter  /> 
274    </#if> 
275 
276    <#-- Print remaining audio embeds --> 
277    <#if articleAudio?has_content && articleAudio.getSiblings()?has_content> 
278        <@printRemainingAudioContents articleAudio audioTagCounter  /> 
279    </#if> 
280     
281    <#-- Print article tail(s) --> 
282    <#if articleTail?has_content && articleTail.getSiblings()?has_content> 
283        <@printRemainingTagContents articleTail kainaloTagCounter wrapperCSSKainalo /> 
284    </#if> 
285 
286 
287    <#-- 
288        Output author card for the main author. 
289    --> 
290 
291    <#-- <#if articleAuthors.mainAuthor.getData()?? && articleAuthors.mainAuthor.getData()?has_content> 
292        <#assign authorCard = articleAuthors.mainAuthor.getData()?eval /> 
293        <@liferay_ui["asset-display"] 
294			className=authorCard.className 
295			classPK=getterUtil.getLong(authorCard.classPK, 0) 
296			template="full_content" 
297	    /> 
298    </#if> --> 
299 
300    <#-- react&share buttons --> 
301    <div class="rns"></div> 
302    <script type="text/javascript"> 
303      (function() { 
304    'use strict'; 
305    var a=document.querySelector(".article-meta .date"), 
306        b=b?b.innerHTML:"", 
307        d=document.querySelector("article h1"), 
308        e=document.querySelector("a.author-name"); 
309    var rnsRecommend = function() { window.rnsRecommend() }; 
310    window.rnsData={ 
311        recommenderToggle: '.article-assets', 
312        apiKey:"oyrv5xd6dmwj3lkm", 
313        reactionCallback: rnsRecommend, 
314        maxRecommendations: 3, 
315        date:function(f){ 
316            try{ 
317                var a=f.match(/(\d{1,2})\.(\d{1,2})\.(\d{4})(\s+(\d{1,2}):(\d{2}))*/), 
318        c=new Date(Date.UTC.apply(this,a[4]?[a[3],a[2]-1,a[1],a[5],a[6]]:[a[3],a[2]-1,a[1]]));return c.setHours(c.getHours()-2),c.toISOString()}catch(g){return""}}(b),title:d?d.innerHTML:"",author:e?e.innerHTML:"", 
319    canonicalUrl:window.location.protocol+"//"+window.location.hostname+window.location.pathname}; 
320    b=document.createElement("script"); 
321    b.src="https://cdn.reactandshare.com/plugin/rns.js";document.body.appendChild(b); 
322    b=document.createElement("script"); 
323    b.src="https://cdn.reactandshare.com/recommender/rnsrw.js"; 
324    document.body.appendChild(b); 
325 
326})(); 
327    </script> 
328     
329    <#if articleTags?has_content> 
330        <div class="article-section article-tags"> 
331            <p class="sans text-uppercase">Lisää näistä aiheista:</p> 
332            <ul class="list-inline"> 
333                <#list articleTags?split(",") as tag> 
334                    <#if !tag?starts_with("_")> 
335                        <li><a href="/artikkelit/-/tag/${htmlUtil.escapeURL(tag)}?article=${article.getResourcePrimKey()}" class="tag tag-default">${tag}</a></li> 
336                    </#if> 
337                </#list> 
338            </ul> 
339        </div> 
340    </#if> 
341 
342    <#-- R&S sharing buttons --> 
343    <div class="article-sharing"> 
344        <p class="sans text-uppercase">Jaa tämä artikkeli:</p> 
345        <div class="rns-share-plugin"></div> 
346    </div> 
347 
348    <#-- MORE FROM AUTHOR --> 
349 
350    <#assign hasAuthor = articleAuthors.authors.getData()?? && articleAuthors.authors.getData()?has_content /> 
351    <#assign hasPhotographer = articleAuthors.photographers.getData()?? && articleAuthors.photographers.getData()?has_content /> 
352     
353    <#if hasAuthor || hasPhotographer> 
354        <#assign articleAuthor = articleAuthors.authors.getData()> 
355        <#assign articlePhotographer = articleAuthors.photographers.getData() /> 
356         
357        <#assign authorObjs = [] /> 
358 
359        <#-- Find which authors (author card titles) appears in author field and make list of those... 
360        We need no maintain order of appearance 
361        --> 
362        <#list availableAuthorNames as authorName> 
363            <#assign authorPos = articleAuthor?index_of(authorName) /> 
364            <#assign photographerPos = articlePhotographer?index_of(authorName) /> 
365             
366            <#-- Keep the order... first authors then photographers --> 
367            <#if authorPos != -1 || photographerPos != -1> 
368                <#assign pos = authorPos /> 
369                <#if authorPos == -1 && photographerPos != -1> 
370                    <#assign pos = 1000 + photographerPos /> 
371                </#if> 
372                <#assign authorObj = {"pos" : pos, "name": authorName} /> 
373                <#assign authorObjs = authorObjs + [authorObj] /> 
374            </#if> 
375        </#list> 
376 
377        <#if authorObjs?size gt 0> 
378            <#assign authorObjs = authorObjs?sort_by("pos") /> 
379 
380            <div class="article-tags"> 
381                <p class="sans text-uppercase">Lisää tekijältä:</p> 
382                <ul class="list-inline"> 
383                    <#list authorObjs as authorObj> 
384                        <li> 
385                            <#assign authorSearchURL = "/toimittajat?author=" /> 
386                            <a class="tag tag-default" href="${authorCardBaseUrl}${authorObj.name?url}">${authorObj.name}</a> 
387                        </li>		   
388                    </#list> 
389                </ul> 
390            </div> 
391        </#if> 
392 
393    </#if> 
394 
395 
396    <#-- RELATED CONTENT -->  
397    <#assign assetLinkLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetLinkLocalService") /> 
398    <#assign assetEntryLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetEntryLocalService") /> 
399    <#assign currentArticleResourcePrimKey = currentArticle.getResourcePrimKey() /> 
400    <#assign currentArticleAssetEntry = assetEntryLocalService.getEntry("com.liferay.journal.model.JournalArticle", currentArticleResourcePrimKey) /> 
401    <#assign currentArticleAssetEntryId = currentArticleAssetEntry.getEntryId() /> 
402    <#assign currentArticleRelatedLinks = assetLinkLocalService.getDirectLinks(currentArticleAssetEntryId) /> 
403    <#if currentArticleRelatedLinks?has_content> 
404        <#assign relatedLinks = []> 
405        <#list currentArticleRelatedLinks as related_entry> 
406            <#assign relatedAssetEntryId = related_entry.getEntryId2() /> 
407            <#assign relatedAssetEntry = assetEntryLocalService.getEntry(relatedAssetEntryId) /> 
408            <#assign relatedAssetEntryPrimKey = relatedAssetEntry.getClassPK() /> 
409            <#assign relatedArticle = JournalArticleLocalService.getLatestArticle(relatedAssetEntryPrimKey) /> 
410            <#assign relatedArticleId = relatedArticle.getArticleId() /> 
411            <#assign docXml = saxReaderUtil.read(relatedArticle.getContent()) />	 
412            <#assign image = docXml.valueOf("//dynamic-element[@name='articleImages']/dynamic-content/text()") /> 
413            <#assign linkObject = {"title": relatedArticle.getTitleCurrentValue(),"urlTitle": relatedArticle.getUrlTitle(), "date": relatedArticle.getDisplayDate()?date, "urlImage": image } /> 
414             
415            <#if image?? && image?has_content> 
416 
417            <#else> 
418                <#assign nostokuva = docXml.valueOf("//dynamic-element[@name='nostokuva']/dynamic-content/text()") /> 
419                <#if nostokuva?? && nostokuva?has_content> 
420                    <#assign image = nostokuva /> 
421                    <#assign linkObject = {"title": relatedArticle.getTitleCurrentValue(),"urlTitle": relatedArticle.getUrlTitle(), "date": relatedArticle.getDisplayDate()?date, "urlImage": image } /> 
422                </#if> 
423            </#if> 
424             
425            <#assign relatedLinks += [linkObject] /> 
426        </#list> 
427        <#if relatedLinks?has_content> 
428 
429            <div class="article-assets"> 
430                <h2 class="heading-decor-section">Lue lisää:</h2> 
431                 
432                <#assign relatedLinksSorted = relatedLinks?sort_by("date") /> 
433                <#list relatedLinksSorted?reverse as link> 
434                    <div class="media"> 
435                        <div class="media-left"> 
436                            <a href="/-/${link.urlTitle}" class="sans"> 
437 
438                                <#if link.urlImage?? && link.urlImage?has_content > 
439                                    <img src="${getThumbnailUrl(link.urlImage, 1) }" class="media-object" /> 
440                                <#else> 
441                                    <div class="aspect-ratio aspect-ratio-top aspect-ratio-3-to-2"> 
442                                        <div class="placeholder placeholder-colored"></div>  
443                                    </div> 
444                                </#if> 
445 
446                            </a> 
447                        </div> 
448                        <div class="media-body"> 
449                            <a href="/-/${link.urlTitle}" class="sans">${link.title}</a> 
450                            <span class="date">${link.date}</span> 
451                        </div> 
452                    </div> 
453                </#list> 
454 
455            </div> 
456 
457        </#if> 
458    </#if> 
459 
460    <script src="${javascript_folder}/audioplayer.js"></script> 
461 
462    <#--  NEWSLETTER SUBSCRIPTION BANNER  --> 
463    <div class="article-subscription"> 
464        <div class="visible-md visible-lg"> 
465            <div class="banner-category-d"><h2 class="no-top-margin" style="margin-bottom: 30px;">Tilaa Kirkko ja kaupungin viikoittainen juttukooste</h2> 
466                <form class="form-inline" action="https://kirkkojakaupunki.creamailer.fi/tilaa/59d75acf78807" id="subForm" method="post"> 
467                    <input id="redirect" name="redirect" type="hidden" value="https://kirkkojakaupunki-dev.ch5finland.com/"> 
468                    <input class="form-control" id="Sähköpostiosoite" name="userEmail" placeholder="Sähköpostiosoite"> 
469                    <input id="newsletter-submit-article" class="btn btn-inverse" type="submit" value="Tilaa uutiskirje"> 
470                </form>  
471            </div> 
472        </div> 
473    </div> 
474 
475    <#-- FACEBOOK COMMENTS --> 
476    <#if articleComments?? && getterUtil.getBoolean(articleComments.getData()) == true> 
477        <div id="fb-root"></div> 
478        <script> 
479            (function(d, s, id) { 
480                var js, fjs = d.getElementsByTagName(s)[0]; 
481                if (d.getElementById(id)) return; 
482                js = d.createElement(s); js.id = id; 
483                js.src = "//connect.facebook.net/fi_FI/sdk.js#xfbml=1&version=v2.8&appId=206864833121117"; 
484                fjs.parentNode.insertBefore(js, fjs); 
485            }(document, 'script', 'facebook-jssdk')); 
486        </script> 
487 
488        <h2 class="heading-decor-section">Kommentoi</h2> 
489        <div class="fb-comments" data-href="${articleCompleteUrl}" data-width="725" data-numposts="5"></div> 
490    </#if> 
491 
492</article> 
493 
494 
495<#-- Include script only if owl carousel among content has been built --> 
496 
497<script src="${javascript_folder}/owl.carousel.min.js"></script> 
498 
499<#if includeOwlScript == true> 
500    <script> 
501    	$('.owl-carousel').owlCarousel({ 
502            items: 1, 
503    		loop: true, 
504    		rewind: false, 
505    		margin: 0, 
506    		nav: true, 
507            navText : ['<span class="owl-carousel-nav glyphicon glyphicon-chevron-left"></span>','<span class="owl-carousel-nav glyphicon glyphicon-chevron-right"></span>'], 
508            autoplay:true, 
509            autoplayTimeout:3000, 
510            smartSpeed:1400, 
511            autoplayHoverPause:true 
512    	}); 
513 
514    </script> 
515</#if> 
516 
517<#-- 
518    Convert Youtube links to embedded videos 
519--> 
520<script type="text/javascript"> 
521 
522    $(document).ready(function () { 
523        $(".js-video-embed" ).each(function() { 
524            // Creates an iframe if it's youtube video. Otherwise just shows the original link. 
525            if (getYoutubeVideoId($(this).attr("href"))) { 
526                var div = $("<div>", {"class": "responsive-video"}); 
527                var wrapper = $("<div>", {"class": "responsive-wrapper"}); 
528                wrapper.append('<iframe src="https://www.youtube.com/embed/'+getYoutubeVideoId($(this).attr("href"))+'?rel=0" frameborder="0" allowfullscreen=""></iframe>'); 
529                div.append(wrapper); 
530                $(this).parent().append(div); 
531                $(this).hide(); //iframe is shown, hide the original link 
532
533        }); 
534    }); 
535    function getYoutubeVideoId(url) { 
536        var videoid = url.match(/(?:https?:\/{2})?(?:w{3}\.)?youtu(?:be)?\.(?:com|be)(?:\/watch\?v=|\/)([^\s&]+)/); 
537        if(videoid != null) { 
538           return videoid[1]; 
539        } else { 
540            return ""; 
541
542
543</script> 
544 
545<#--   
546    Create image comparison slider   
547--> 
548<script src="/o/kirkkojakaupunki-site-theme/js/cocoen.js"></script> 
549 
550<script type="text/javascript"> 
551    $(document).ready(function () { 
552        document.querySelectorAll('.cocoen').forEach(function(element){ 
553            var imageComparison = new Cocoen(element); 
554                var sliderOffset = $(element).attr("slider-offset"); 
555                if ($(element).attr("slider-offset") >= 100 || !($(element).attr("slider-offset"))){ 
556                    sliderOffset = 98; 
557                } else if ($(element).attr("slider-offset") == 0) { 
558                    sliderOffset = 2; 
559
560                imageComparison.element.children[0].style.width = sliderOffset+"%"; 
561                imageComparison.dragElement.style.left = sliderOffset+"%"; 
562        }); 
563 
564        // depending on slider offset show either the caption of the first or the second image 
565        $('.cocoen').mousemove(function(event){ 
566            addCaption(this); 
567        }); 
568 
569        // same functionality for touch screens 
570        document.querySelectorAll('.cocoen').forEach(function(element){ 
571            element.addEventListener("touchmove", function() { 
572                addCaption(this); 
573            }); 
574        }); 
575 
576        function addCaption(element) { 
577            var index = $('.cocoen').index(element); 
578            var sliderOffset = parseInt(element.firstElementChild.style.width); 
579            if(sliderOffset < 50){ 
580                $('.caption1').eq(index).hide(); 
581                $('.caption2').eq(index).show(); 
582            } else { 
583                $('.caption2').eq(index).hide(); 
584                $('.caption1').eq(index).show(); 
585
586
587    });     
588     
589</script> 
590 
591 
592<#----------------------------------------------------------------------------- 
593    Helper functions 
594------------------------------------------------------------------------------> 
595 
596<#macro printRemainingTagContents container startAt wrapperCSSClass> 
597    <#local contentSlots = container.getSiblings() /> 
598    <#if contentSlots?has_content && contentSlots?size gt 0> 
599        <#list contentSlots as slot> 
600            <#if slot?index gte startAt> 
601            <#if slot.getData()?? && slot.getData()?has_content> 
602        	    <#switch wrapperCSSClass> 
603        	        <#case 'template-quote'> 
604        	            <div class="article-box article-quote"> 
605        	                <p class="quote-body">${slot.getData()}</p> 
606        	            </div> 
607                	    <#break> 
608            	    <#default> 
609            	        <div class="${wrapperCSSClass}">${slot.getData()}</div> 
610        	    </#switch> 
611            </#if> 
612            </#if> 
613        </#list> 
614    </#if> 
615</#macro> 
616 
617 
618<#-- 
619    Print remainging videos, if any 
620--> 
621<#macro printRemainingVideoContents container startAt> 
622    <#local contentSlots = container.getSiblings() /> 
623    <#if contentSlots?has_content && contentSlots?size gt 0> 
624        <#list contentSlots as slot> 
625            <#if slot?index gte startAt> 
626                <#if slot.URL.getData()?? && slot.URL.getData()?has_content> 
627 
628                    <#assign URL = slot.URL.getData()!"" /> 
629                    <#assign videoFile = slot.videoFile.getData()!"" /> 
630                    <#assign caption = slot.caption.getData()!"" /> 
631                    <#assign embed = videoEmbed(URL, caption, videoFile)!"" /> 
632                    ${embed} 
633 
634                </#if> 
635            </#if> 
636        </#list> 
637    </#if> 
638</#macro> 
639 
640<#-- 
641    Print remainging audio embeds, if any 
642--> 
643<#macro printRemainingAudioContents container startAt> 
644    <#local contentSlots = container.getSiblings() /> 
645    <#if contentSlots?has_content && contentSlots?size gt 0> 
646        <#list contentSlots as slot> 
647            <#if slot?index gte startAt> 
648                <#if slot.audioFile.getData()?? && slot.audioFile.getData()?has_content> 
649                    <#assign description = slot.audioDescription.getData() /> 
650                    <#assign files = slot.audioFile /> 
651                    <#assign embed = audioEmbed(description, files) /> 
652                    ${embed} 
653                </#if> 
654            </#if> 
655        </#list> 
656    </#if> 
657</#macro> 
658 
659<#function replaceTags content tag replacementElement wrapperCSSClass> 
660    <#global tagReplaceCounter = 0 /> 
661    <#if replacementElement?has_content> 
662        <#assign replacementList = replacementElement.getSiblings() > 
663        <#if replacementList?has_content> 
664 
665        	<#list replacementList as cur_replacement> 
666 
667        	    <#switch wrapperCSSClass> 
668        	        <#case 'template-quote'> 
669                	    <#assign replacement> 
670                	        <div class="article-box article-quote"> 
671                	            <p class="quote-body">${cur_replacement.getData()}</p> 
672            	            </div> 
673                	    </#assign> 
674                	    <#break> 
675            	    <#default> 
676                	    <#assign replacement> 
677                	        <div class="${wrapperCSSClass}">${cur_replacement.getData()}</div> 
678                	    </#assign> 
679        	    </#switch> 
680 
681        	    <#if content?index_of(tag) gt -1> 
682            		<#local content = content?replace(tag, replacement, 'f') > 
683            		<#global tagReplaceCounter++ /> 
684        		</#if> 
685        	</#list> 
686        </#if> 
687    </#if> 
688 
689  <#-- Remove "empty" tags--> 
690  <#local content = content?replace(tag, '') > 
691 
692  <#return content > 
693</#function> 
694 
695<#function replaceCarouselTags content tag1 tag2 replacementElement> 
696    <#if replacementElement?has_content> 
697        <#assign replacementList = replacementElement.getSiblings()> 
698        <#assign carousel1Array = []> 
699        <#assign carousel2Array = []> 
700        <#if replacementList?has_content> 
701        	<#list replacementList as cur_image> 
702                <#if cur_image.getData?? && cur_image.getData()?has_content> 
703                    <#if cur_image.position.getData() == "article-image-carousel-1"> 
704                        <#assign carousel1Array = carousel1Array + [createCarouselItem(cur_image)] /> 
705                    </#if> 
706                    <#if cur_image.position.getData() == "article-image-carousel-2"> 
707                        <#assign carousel2Array = carousel2Array + [createCarouselItem(cur_image)] /> 
708                    </#if> 
709                </#if> 
710            </#list> 
711 
712            <#assign replacement1> 
713                <div class="owl-carousel owl-theme"> 
714                    <#list carousel1Array as carousel1> 
715                    <div class="item"> 
716                        ${carousel1} 
717                    </div> 
718                    </#list> 
719                </div> 
720            </#assign> 
721            <#local content = content?replace(tag1, replacement1, 'f') > 
722 
723            <#assign replacement2> 
724                <div class="owl-carousel owl-theme"> 
725                    <#list carousel2Array as carousel2> 
726                    <div class="item"> 
727                        ${carousel2} 
728                    </div> 
729                    </#list> 
730                </div> 
731            </#assign> 
732            <#local content = content?replace(tag2, replacement2, 'f') > 
733 
734        </#if> 
735    </#if> 
736    <#return content /> 
737</#function> 
738 
739<#function createCarouselItem cur_image> 
740    <#assign result = "" /> 
741    <#if cur_image.getAttribute("alt")?has_content> 
742        <#assign result> 
743            <div class="aspect-ratio aspect-ratio-middle aspect-ratio-xs"> 
744                <img src="${getThumbnailUrl(cur_image.getData(), 3) }" alt="${cur_image.getAttribute("alt")}" /> 
745            </div> 
746            <p class="caption">${cur_image.getAttribute("alt")}</p> 
747        </#assign> 
748    <#else> 
749        <#assign result> 
750            <div class="aspect-ratio aspect-ratio-middle aspect-ratio-xs"> 
751                <img src="${getThumbnailUrl(cur_image.getData(), 3) }" alt="" /> 
752            </div> 
753        </#assign> 
754    </#if> 
755    <#return result /> 
756</#function> 
757 
758<#function replaceImageTags content tag replacementElement> 
759    <#if replacementElement?has_content> 
760        <#assign replacementList = replacementElement.getSiblings() > 
761        <#if replacementList?has_content> 
762        	<#list replacementList as cur_image> 
763 
764                <#if cur_image.getData?? && cur_image.getData()?has_content> 
765 
766                    <#-- Skip header images --> 
767                    <#if cur_image.position.getData() != "article-image-header" && cur_image.position.getData() != "article-image-carousel-1" && cur_image.position.getData() != "article-image-carousel-2"> 
768                        <#assign thumbnailSize = 2 > 
769                        <#if cur_image.position.getData() == "article-image-full"> 
770                            <#assign thumbnailSize = 3 > 
771                        </#if> 
772                        <#assign replacement> 
773 
774                            <div class="article-box ${cur_image.position.getData()}"> 
775                                <#if cur_image.getAttribute("alt")?has_content> 
776                                    <img src="${getThumbnailUrl(cur_image.getData(), thumbnailSize) }" alt="${cur_image.getAttribute("alt")}" /> 
777                                    <p class="caption">${cur_image.getAttribute("alt")}</p> 
778                                <#else> 
779                                    <img src="${getThumbnailUrl(cur_image.getData(), thumbnailSize) }" alt="" /> 
780                                </#if> 
781                            </div> 
782                        </#assign> 
783                        <#local content = content?replace(tag, replacement, 'f') > 
784                    </#if> 
785 
786                </#if> 
787 
788        	</#list> 
789        </#if> 
790    </#if> 
791 
792  <#-- Remove "empty" tags--> 
793  <#local content = content?replace(tag, '') > 
794 
795  <#return content > 
796</#function> 
797 
798 
799<#function replaceImageComparisonTags content tag replacementElement> 
800    <#if replacementElement?has_content> 
801        <#assign replacementList = replacementElement.getSiblings() > 
802        <#if replacementList?has_content> 
803            <#list replacementList as cur_imageComparison> 
804                <#if cur_imageComparison.getData??> 
805                    <#assign image1 = cur_imageComparison.image1 /> 
806                    <#assign image2 = cur_imageComparison.image2 /> 
807                    <#if cur_imageComparison.sliderOffset.getData() == "" > 
808                        <#assign offset = 100 /> 
809                    <#else> 
810                        <#assign offset = cur_imageComparison.sliderOffset.getData() /> 
811                    </#if> 
812                    <#assign replacement> 
813                        <#if image1.getData?? && image1.getData()?has_content && image2.getData?? && image2.getData()?has_content> 
814                            <div class="cocoen-theme"> 
815                                <div class="cocoen" slider-offset="${offset}"> 
816                                    <#if image1.getAttribute("alt")?has_content> 
817                                        <img src="${getThumbnailUrl(image1.getData(), 3) }" alt="${image1.getAttribute("alt")}" /> 
818                                    <#else> 
819                                        <img src="${getThumbnailUrl(image1.getData(), 3) }" alt="" /> 
820                                    </#if> 
821                                    <#if image2.getAttribute("alt")?has_content> 
822                                        <img src="${getThumbnailUrl(image2.getData(), 3) }" alt="${image2.getAttribute("alt")}" /> 
823                                    <#else> 
824                                        <img src="${getThumbnailUrl(image2.getData(), 3) }" alt="" /> 
825                                    </#if> 
826                                </div> 
827                                <#if image1.getAttribute("alt")?has_content && image2.getAttribute("alt")?has_content> 
828                                    <#if offset?number lt 50> <!-- pienempi kuin 50, näytä kuvateksti 2 --> 
829                                        <div class="caption2"> 
830                                            <p class="caption"> 
831                                                ${image2.getAttribute("alt")} 
832                                            </p> 
833                                        </div> 
834                                        <div class="caption1" style="display:none"> 
835                                            <p class="caption"> 
836                                                ${image1.getAttribute("alt")} 
837                                            </p> 
838                                        </div> 
839                                    <#else> 
840                                        <div class="caption2" style="display:none"> 
841                                            <p class="caption"> 
842                                                ${image2.getAttribute("alt")} 
843                                            </p> 
844                                        </div> 
845                                        <div class="caption1"> 
846                                            <p class="caption"> 
847                                                ${image1.getAttribute("alt")} 
848                                            </p> 
849                                        </div> 
850                                    </#if> 
851                                </#if> 
852                            </div> 
853                        </#if> 
854                    </#assign> 
855                    <#local content = content?replace(tag, replacement, 'f') > 
856                </#if> 
857            </#list> 
858        </#if> 
859    </#if> 
860    <#-- Remove "empty" tags--> 
861    <#local content = content?replace(tag, '') > 
862 
863    <#return content > 
864</#function> 
865 
866 
867<#function replaceVideoTags content tag replacementElement> 
868    <#global tagReplaceCounter = 0 /> 
869    <#if replacementElement?has_content> 
870        <#assign replacementList = replacementElement.getSiblings() > 
871        <#if replacementList?has_content> 
872 
873            <#global videoListSize = replacementList?size /> 
874 
875        	<#list replacementList as cur_video> 
876                <#assign videoFile = "" /> 
877                <#assign URL = cur_video.URL.getData()!"" /> 
878                <#if (cur_video.videoFile)??> 
879                    <#assign videoFile = cur_video.videoFile.getData()!"" /> 
880                </#if> 
881                <#assign caption = cur_video.caption.getData()!"" /> 
882                 
883                <#if (cur_video.videoFile)?? || URL?has_content> 
884                    <#assign replacement = videoEmbed(URL, caption, videoFile)!"" /> 
885                </#if> 
886                
887                <#if content?index_of(tag) gt -1> 
888                    <#local content = content?replace(tag, replacement, 'f') > 
889                    <#global tagReplaceCounter++ /> 
890                </#if> 
891 
892                <#-- <#local content = content?replace(tag, replacement, 'f') > --> 
893        	</#list> 
894        </#if> 
895    </#if> 
896 
897  <#-- Remove "empty" tags--> 
898  <#local content = content?replace(tag, '') > 
899 
900  <#return content > 
901</#function> 
902 
903 
904<#function replaceAudioTags content tag replacementElement> 
905    <#global tagReplaceCounter = 0 /> 
906    <#if replacementElement?has_content> 
907        <#assign replacementList = replacementElement.getSiblings() > 
908        <#if replacementList?has_content> 
909 
910            <#global audioListSize = replacementList?size /> 
911 
912        	<#list replacementList as cur_audioEmbed> 
913                <#assign description = cur_audioEmbed.audioDescription.getData() /> 
914                <#assign files = cur_audioEmbed.audioFile /> 
915                <#assign replacement = audioEmbed(description, files) /> 
916 
917                <#if content?index_of(tag) gt -1> 
918                    <#local content = content?replace(tag, replacement, 'f') > 
919                    <#global tagReplaceCounter++ /> 
920                </#if> 
921 
922        	</#list> 
923        </#if> 
924    </#if> 
925    <#local content = content?replace(tag, '') > 
926    <#return content > 
927</#function> 
928 
929 
930<#function videoEmbed URL, caption, videoFile> 
931    <#local embed = "" /> 
932 
933    <#if URL?contains("vimeo")> 
934        <#local iframeSrc = "https://player.vimeo.com/video/" /> 
935        <#local videoID = URL?split("/")?last /> 
936		<#local embed> 
937		    <div class="responsive-video"> 
938    			<div class="responsive-wrapper vimeo" id="vimeo-${videoID}" data-embed="${videoID}"> 
939    				<img class="decor-video" alt="Toista video" src="/o/kirkkojakaupunki-site-theme/images/icons/video-decor.svg"> 
940    			</div> 
941				<noscript><a href="${URL}" target="_blank" rel="noopener">Videota</a> ei voida näyttää koska javascript on kytketty pois päältä selaimesta.</noscript> 
942    		</div> 
943		</#local> 
944    <#elseif URL?contains("youtube")> 
945        <#local iframeSrc = "https://www.youtube.com/embed/" /> 
946        <#local videoID = URL?replace("^.*\\?v=([\\w-_]*).*", "$1", "r") /> 
947        <#--<#local videoID = videoID + "?rel=0" />--> 
948		<#local embed> 
949		    <div class="responsive-video"> 
950    			<div class="responsive-wrapper youtube" data-embed="${videoID}"> 
951    				<img class="decor-video" alt="Toista video" src="/o/kirkkojakaupunki-site-theme/images/icons/video-decor.svg"> 
952    			</div> 
953    			<noscript><a href="${URL}" target="_blank" rel="noopener">Videota</a> ei voida näyttää koska javascript on kytketty pois päältä selaimesta.</noscript> 
954			</div> 
955		</#local> 
956    <#elseif videoFile?has_content> 
957        <#local embed> 
958            <div class="responsive-video"> 
959                <video controls controlsList="nodownload" style="max-width:100%"> 
960                <source src="${videoFile}" type="video/mp4"> 
961                    Your browser does not support the video tag. 
962                </video> 
963            </div>  
964        </#local> 
965    <#else> 
966        <#return embed> 
967    </#if> 
968 
969    <#return embed> 
970</#function> 
971 
972 
973<#function audioEmbed description, files> 
974    <#local embed = ""> 
975    <#local audioFiles = [] /> 
976     
977    <#list files.getSiblings() as file>        
978        <#local fileURL = file.getData()!""> 
979        <#if fileURL?has_content> 
980            <#local fileFormat = file.audioFormat.getData()> 
981            <#local fileObject = {"format": fileFormat, "URL": fileURL}> 
982            <#local audioFiles += [fileObject]> 
983        </#if> 
984    </#list> 
985 
986    <#if audioFiles?has_content> 
987        <#local embed> 
988            <div class="audio-player sans"> 
989                <button class="btn btn-link flex-item-center"> 
990                    <i class="icon-play" aria-hidden="true"></i> 
991                </button> 
992                <div class="audio-player-details flex-item-center"> 
993                    <#if description?has_content> 
994                        <p>${description}</p> 
995                    </#if> 
996                    <div class="audio-player-progress"> 
997                        <span class="audio-player-time-display">-:- / -:-</span> 
998                        <div class="audio-player-seekbar"> 
999                            <div class="audio-player-bufferbar"></div> 
1000                            <div class="audio-player-progressbar"></div> 
1001                        </div> 
1002                    </div>                 
1003                </div> 
1004                <audio preload="metadata" loop> 
1005                    <#list audioFiles as file> 
1006                        <source src="${file.URL}" type="${file.format}" /> 
1007                    </#list> 
1008                </audio> 
1009            </div> 
1010        </#local> 
1011    </#if> 
1012 
1013    <#return embed> 
1014</#function> 
1015 
1016 
1017<#function getHeaderImages articleImages> 
1018    <#local headerImages = [] /> 
1019 
1020    <#if articleImages?has_content && articleImages.getSiblings()?has_content> 
1021        <#list articleImages.getSiblings() as cur_image> 
1022            <#if cur_image.position.getData() == 'article-image-header'> 
1023                <#local headerImages = headerImages + [cur_image] /> 
1024            </#if> 
1025        </#list> 
1026    </#if> 
1027 
1028    <#if !headerImages?has_content && articleImages?has_content && articleImages.getSiblings()?has_content > 
1029        <#local headerImages = headerImages + [articleImages.getSiblings()?first] /> 
1030    </#if> 
1031 
1032    <#return headerImages> 
1033</#function> 
1034 
1035<#function getContentCarouselImages articleImages> 
1036 
1037    <#local contentCarouselImages = [] /> 
1038 
1039    <#if articleImages?has_content && articleImages.getSiblings()?has_content> 
1040        <#list articleImages.getSiblings() as cur_image> 
1041            <#if cur_image.position.getData() == 'article-image-carousel-1'> 
1042                <#local contentCarouselImages = contentCarouselImages + [cur_image] /> 
1043            </#if> 
1044            <#if cur_image.position.getData() == 'article-image-carousel-2'> 
1045                <#local contentCarouselImages = contentCarouselImages + [cur_image] /> 
1046            </#if> 
1047        </#list> 
1048    </#if> 
1049 
1050    <#if !contentCarouselImages?has_content && articleImages?has_content && articleImages.getSiblings()?has_content > 
1051        <#local contentCarouselImages = contentCarouselImages + [articleImages.getSiblings()?first] /> 
1052    </#if> 
1053 
1054    <#return contentCarouselImages> 
1055</#function> 
1056 
1057<#-- 
1058    Attempts to get mime type for a file in document library. 
1059 
1060    Parameters: 
1061        fileUrl: A string containig a url to the file. 
1062 
1063    Returns mime type as a string or an empty string. 
1064--> 
1065<#function getMimeType fileUrl> 
1066    <#if fileUrl?? && fileUrl?has_content> 
1067 
1068        <#-- Attempt to parse uuid & groupId from provided Url --> 
1069        <#assign splitUrl = fileUrl?split("/", "r") /> 
1070 
1071        <#if splitUrl?seq_contains("documents") && splitUrl?size gte 6> 
1072            <#attempt> 
1073 
1074                <#assign groupId = splitUrl[2] /> 
1075                <#assign uuid = splitUrl[5] /> 
1076                <#assign uuid = uuid?split("?")[0] /> 
1077 
1078                <#-- Get DLFileEntry --> 
1079                <#assign DLFileEntryLocalService = serviceLocator.findService("com.liferay.document.library.kernel.service.DLFileEntryLocalService") /> 
1080                <#assign fileEntry = DLFileEntryLocalService.fetchDLFileEntryByUuidAndGroupId(uuid, getterUtil.getLong(groupId)) /> 
1081                <#return fileEntry.getMimeType()> 
1082            <#recover> 
1083                <#-- Parsing mime type failed, return empty --> 
1084                <#return ""> 
1085            </#attempt> 
1086 
1087        <#elseif splitUrl?seq_contains("journal") && splitUrl?size gte 4> 
1088            <#attempt> 
1089                <#assign imageId = splitUrl[3]?split("?")[1]?split("=")[1]?split("&")[0] /> 
1090                <#assign ImageLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.ImageLocalService") /> 
1091                <#assign imageType = ImageLocalService.getImage(getterUtil.getLong(imageId)).getType() /> 
1092                <#switch imageType> 
1093                    <#case "gif"> 
1094                        <#return "image/gif"> 
1095                    <#case "svg"> 
1096                        <#return "image/svg"> 
1097                    <#default> 
1098                        <#return imageType> 
1099                </#switch> 
1100            <#recover> 
1101                <#return ""> 
1102            </#attempt> 
1103 
1104        <#else> 
1105            <#-- Parsing image url failed, return empty --> 
1106            <#return ""> 
1107        </#if> 
1108 
1109    <#else> 
1110        <#-- parameter empty or missing, return empty --> 
1111        <#return ""> 
1112    </#if> 
1113</#function> 
1114 
1115<#-- 
1116    Returns thumbnail image url for given image. 
1117    Handles SVG & bitmap formats. 
1118 
1119    Parameters: 
1120        imageUrl: string containing relative url to an image in document library 
1121        thumbnailSize: value for Liferay's imageThumbnail parameter (0-3) 
1122 
1123    Returns image url with appended thumbnail info or an empty string. 
1124 --> 
1125<#function getThumbnailUrl imageUrl thumbnailSize> 
1126    <#if imageUrl?? && imageUrl?has_content> 
1127 
1128        <#-- Attempt to get mime type --> 
1129        <#assign mimeType = getMimeType(imageUrl) /> 
1130 
1131        <#if mimeType?has_content> 
1132 
1133            <#-- Check image mime type --> 
1134            <#switch mimeType> 
1135                <#case "image/svg+xml"> 
1136                    <#-- SVG image -> do not append thumbnail parameter --> 
1137                    <#return imageUrl> 
1138                <#case "image/gif"> 
1139                    <#return imageUrl> 
1140                <#default> 
1141                    <#-- Predume bitmap image -> append thumbnail parameter --> 
1142                    <#if imageUrl?contains("?")> 
1143                        <#assign paramChar = "&" /> 
1144                    <#else> 
1145                        <#assign paramChar = "?" /> 
1146                    </#if> 
1147                    <#return imageUrl + paramChar + "imageThumbnail=" + thumbnailSize /> 
1148            </#switch> 
1149 
1150        </#if> 
1151 
1152    </#if> 
1153</#function> 
1154 
1155<#-- 
1156    Return list of web content titles from given folder 
1157    parameter: 
1158        - authorCardFolderId 
1159--> 
1160<#function getAvailableAuthorNames authorCardFolderIds > 
1161 
1162  <#local authorNames = []>     
1163  <#local seenArticles = [] > 
1164  <#-- Multiple version exists so keep track which articles we have already checked --> 
1165 
1166  <#list authorCardFolderIds as authorCardFolderId> 
1167    <#assign authorCards = JournalArticleLocalService.getArticles(groupId, authorCardFolderId) /> 
1168 
1169    <#if authorCards?has_content> 
1170        <#list authorCards as authorCard> 
1171	    <#if !seenArticles?seq_contains(authorCard.articleId)> 
1172	      <#assign latest = JournalArticleLocalService.getLatestArticle(authorCard.resourcePrimKey) /> 
1173	      <#if latest.getStatus() == 0> 
1174		  <#local authorName = latest.getTitle(locale) /> 
1175		  <#if !authorNames?seq_contains(authorName) > 
1176		      <#local authorNames = authorNames + [authorName] /> 
1177		  </#if> 
1178	      </#if> 
1179	      <#local seenArticles = seenArticles + [authorCard.articleId] /> 
1180	    </#if> 
1181        </#list> 
1182         
1183    </#if> 
1184  </#list> 
1185  <#return authorNames /> 
1186</#function> 
1187 
1188<#-- 
1189    Replaces from given string author names with links to author page 
1190    parameters:  
1191    - authorNameStr : String where replacements is targeted 
1192    - authorNames : seq : list of author names 
1193    - baseUrl : url where author name is appended (as url escaped string) 
1194--> 
1195 
1196<#function makeAuthorLinks authorNameStr authorNames baseUrl > 
1197    <#list authorNames as authorName> 
1198        <#local authorNameInUrl = authorName?url("utf-8") /> 
1199        <#local authorNameStr = authorNameStr?replace(authorName, "<a class=\"author-name\" href=\""+baseUrl +authorNameInUrl + "\">"+authorName+"</a>") /> 
1200    </#list> 
1201    <#return authorNameStr /> 
1202</#function>