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