Meister - Japanspecialist
Fehler bei der Verarbeitung der Vorlage.
The following has evaluated to null or missing: ==> thisLocationTree [in template "20098#20124#DESTINATION" at line 61, column 25] ---- 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 thisCountry = (thisLocationTr... [in template "20098#20124#DESTINATION" at line 61, column 1] ----
1<!-- Destination detail FTL -->
2
3<#assign envSettings = vtaLibrary.getEnvSettings()>
4<#assign vocDestTypenId = envSettings.vocDestTypenId?number>
5<#assign vocDestLocationId = envSettings.vocDestLocationId?number>
6<#assign urlHelper = vtaLibrary.getUrlHelper()>
7<#assign toursFilterListingUrl = urlHelper + vtaLibrary.getLayoutUrlByCategoryName("Tour filter results listing")>
8
9
10<#-- check disabled -->
11<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")>
12<#assign assetCategoryLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryLocalService") />
13<#assign journalArticleResourceLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleResourceLocalService") />
14<#assign thisJournalArticleId = .vars['reserved-article-id'].data>
15<#assign thisArticleResourcePK = journalArticleResourceLocalService.getArticleResourcePrimKey(groupId,thisJournalArticleId)/>
16<#assign thisCategoryList=assetCategoryLocalService.getCategories("com.liferay.journal.model.JournalArticle",thisArticleResourcePK) >
17<#assign vocAviabilityId = envSettings.vocAviabilityId>
18<#assign thisJournalArticle = journalArticleLocalService.fetchArticle(groupId?number, thisJournalArticleId?string)>
19<#assign thisJournalArticleDefaultLanguageId = thisJournalArticle.getDefaultLanguageId()>
20<#assign thisJournalArticleRPK = thisJournalArticle.getResourcePrimKey()>
21
22<#-- set MAIN IMAGE & GALLERY-->
23<#assign thisMainImage = MainImage>
24<#assign thisGallerList = []>
25<#-- check gallery list -->
26<#list GalleryImage.getSiblings() as cur_image>
27 <#if cur_image.getData() !="">
28 <#assign thisGallerList = thisGallerList + [cur_image]>
29 </#if>
30</#list>
31
32<#-- parse categories -->
33<#assign thisDestinationType = "none">
34<#assign isDisabled = false>
35<#list thisCategoryList as category>
36 <#assign curCatVocId = category.vocabularyId?string>
37 <#-- check Aviability state -->
38 <#if curCatVocId = vocAviabilityId?string>
39 <#if category.getTitle("en_US") = "Disabled">
40 <#assign isDisabled = true>
41 </#if>
42 <#elseif curCatVocId = vocDestTypenId?string>
43 <#assign thisDestinationType = category.getTitle(thisJournalArticleDefaultLanguageId)>
44 <#elseif curCatVocId = vocDestLocationId?string>
45 <#assign thisCountryCat = category>
46 </#if>
47</#list>
48
49<#-- get location tree & country & region & prefecture -->
50<#if thisCountryCat??>
51 <#assign thisLocationTree = []>
52 <#assign thisLocationIdTree = []>
53 <#assign thisTree = thisCountryCat.getTreePath()>
54 <#list thisTree?split("/") as cur_step>
55 <#if cur_step !="">
56 <#assign thisLocationTree = thisLocationTree + [assetCategoryLocalService.fetchCategory(cur_step?number).getTitle(thisJournalArticleDefaultLanguageId)]>
57 <#assign thisLocationIdTree = thisLocationIdTree + [assetCategoryLocalService.fetchCategory(cur_step?number).getCategoryId()]>
58 </#if>
59 </#list>
60</#if>
61<#assign thisCountry = (thisLocationTree[0]??)?then(thisLocationTree[0],"none")>
62<#assign thisRegion = (thisLocationTree[1]??)?then(thisLocationTree[1],"none")>
63<#assign thisPrefecture = (thisLocationTree[2]??)?then(thisLocationTree[2],"none")>
64<!-- ${thisJournalArticle} -->
65
66<#-- set globals for rest widgets on this tour page -->
67<#if thisLocationIdTree?size != 0>
68 <#assign tempString = thisLocationIdTree?join(",")>
69<#else>
70 <#assign tempString = "">
71</#if>
72<!-- SET DESTINATION LOCATION SCOPE ID: "${tempString}" ${request.setAttribute("DEST_LOCATION_SCOPE_ID", "${tempString}")} -->
73<!-- SET DESTINATION ARTICLE ID: "${thisJournalArticleId}" ${request.setAttribute("DEST_ARTICLE_ID", "${thisJournalArticleId}")} -->
74
75
76<#if !isDisabled>
77 <#-- emebed LG resources to the html top -->
78 <@vtaLibrary.lightGalleryInjectTop/>
79
80 <#-- fake breadcrumbs -->
81 <div class="-marginBottom-1">
82 <@printFakeBreadcrumbs/>
83 </div>
84
85 <div id="page-wrapper" class="-Destination -Destination--typeDetail" data-pagetype="destination">
86 <div class="-Destination-inner">
87 <div class="-Destination-head">
88 <header class="-Header -Header--typeH1">
89 <h1 class="-Heading -Heading--typeH1 -Header-heading">${ScreenName.getData()}</h1>
90 <p class="-Subheading -Header-subheading">
91 ${ShortDescription.getData()}
92 </p>
93 </header>
94 </div>
95 <#if themeDisplay.isSignedIn()>
96 <p>
97 <button id="masterButton">Master Data Html</button>
98 <button id="masterButtonWord">Master Data Word DOC</button>
99 </p>
100 <@setmasterData />
101 </#if>
102 <div class="-Destination-body">
103
104 <!-- gray section/ -->
105 <div class="-Section -Section--verticalSpacingMedium -Section--verticalIndentMedium -fullBleed -skin-tertiaryBare">
106 <div class="-Section-inner">
107 <div class="-Container -Container--typeNestedPreserve">
108 <div class="-Tour-card">
109
110
111 <!-- gallery -->
112 <#assign gallerySize = thisGallerList?size + 1>
113 <div class="-GalleryWrapper">
114 <div class="-Gallery -Gallery--typeTile" id="-Gallery">
115 <#-- first big-->
116 <span class="-Gallery-item" data-media-count="${gallerySize} ${translationsUtils.getMessage(locale,'vta.webcontent.photos')}">
117 <img alt="${thisMainImage.getAttribute('alt')}" src="${vtaLibrary.getAdaptiveImageUrl(thisMainImage, 'large')}">
118 </span>
119 <#-- first four from gallery -->
120 <#list thisGallerList as image>
121 <#if image?index lt 4>
122 <span class="-Gallery-item" data-media-count="${gallerySize} ${translationsUtils.getMessage(locale,'vta.webcontent.photos')}">
123 <img loading="lazy" alt="${image.getAttribute('alt')}" src="${vtaLibrary.getAdaptiveImageUrl(image, 'medium')}">
124 </span>
125 </#if>
126 </#list>
127 </div>
128 <script>
129 const lgContainer = document.getElementById('-Gallery');
130 const lgItems = lgContainer.querySelectorAll('.-Gallery-item');
131 const lgGallery = lightGallery(lgContainer, {
132 licenseKey: '9N5TA-AWA8R-H9ZLD-GCJBW',
133 plugins: [lgZoom, lgThumbnail, lgHash],
134 container: '#wrapper',
135 dynamic: true,
136 dynamicEl: [{
137 src: '${vtaLibrary.getAdaptiveImageUrl(thisMainImage, 'big')}',
138 <#--
139 sources: '[{"srcset": "${vtaLibrary.getAdaptiveImageUrl(thisMainImage, 'big')}", "media": "(min-width:1280px)"}, {"srcset": "${vtaLibrary.getAdaptiveImageUrl(thisMainImage, 'medium')}", "media": "(min-width:640px)"}]',
140 -->
141 thumb: '${vtaLibrary.getAdaptiveImageUrl(thisMainImage, 'small')}',
142 subHtml: '<p>${thisMainImage.getAttribute('alt')?js_string!""}</p>'
143 }
144
145 //<#if thisGallerList?size gt 0>
146 // <#list thisGallerList as image>
147 , {
148 src: '${vtaLibrary.getAdaptiveImageUrl(image, 'big')}',
149 <#--
150 sources: '[{"srcset": "${vtaLibrary.getAdaptiveImageUrl(image, 'big')}", "media": "(min-width:1280px)"}, {"srcset": "${vtaLibrary.getAdaptiveImageUrl(image, 'medium')}", "media": "(min-width:640px)"}]',
151 -->
152 thumb: '${vtaLibrary.getAdaptiveImageUrl(image, 'small')}',
153 subHtml: '<p>${(image.getAttribute('alt')!"")?js_string}</p>'
154 }
155 // </#list>
156 //</#if>
157 ],
158 selector: '.-Gallery-item',
159 download: false,
160 speed: 500,
161 thumbnail: true,
162 mobileSettings: {
163 controls: false,
164 showCloseIcon: true,
165 download: false
166 }
167 });
168 lgItems.forEach(function (item, index) {
169 item.addEventListener("click", function () {
170 lgGallery.openGallery(index);
171 });
172 });
173 </script>
174 </div>
175 <!-- /gallery -->
176
177
178
179
180
181 <!-- right panel -->
182 <div class="-Panel -Panel--typeFlyer -Tour-panel">
183 <div class="-boxLayout" data-space="3">
184 <div class="-stackLayout" data-space="1" data-splitafter="1">
185 <div>
186 <strong>
187 <span class="-clusterLayout" data-space="02" data-nowrap="true">
188 <span>
189 <span><i class="-Icon -Icon--tour-type"></i></span>
190 <span> ${thisDestinationType} </span>
191 </span>
192 </span>
193 </strong>
194 <hr class="-Hr -Hr--skinTertiaryBare -Panel-hr">
195 <div class="-stackLayout" data-space="03">
196 <div>
197 <strong>
198 <span class="-clusterLayout" data-space="02" data-nowrap="true">
199 <span>
200 <span><i class="-Icon -Icon--location-2"></i></span>
201 <span> ${translationsUtils.getMessage(locale,'vta.common.labels.location')} </span>
202 </span>
203 </span>
204 </strong>
205 </div>
206 <div>
207 <div class="-clusterLayout" data-space="02" data-nowrap="true">
208 <div>
209 <div>
210 <i class="-Icon -Icon--location-2 -visuallyHidden"></i>
211 </div>
212 <div class="-stackLayout" data-space="05">
213 <#if thisCountry != "none">
214 <div class="-textSize-small"> ${translationsUtils.getMessage(locale,'vta.common.labels.country')}: ${thisCountry} </div>
215 </#if>
216 <#if thisRegion != "none">
217 <div class="-textSize-small"> ${translationsUtils.getMessage(locale,'vta.common.labels.region')}: ${thisRegion} </div>
218 </#if>
219 <#if thisPrefecture != "none">
220 <div class="-textSize-small"> ${translationsUtils.getMessage(locale,'vta.common.labels.prefecture')}: ${thisPrefecture} </div>
221 </#if>
222 </div>
223 </div>
224 </div>
225 </div>
226 </div>
227 </div>
228 <div class="-stackLayout -textJustifyCenter" data-space="02">
229 <span class="-textSize-small"><strong>${translationsUtils.getMessage(locale,'vta.webcontent.ready.to.experience.this.incredible.destination')}</strong></span>
230 <span class="-textSize-small -colorSecondaryPale">${translationsUtils.getMessage(locale,'vta.webcontent.destination.ready.to.experience.paragraph')}</span>
231 <#-- <span class="-textSize-small"><strong>Ready to experience this incredible destination?</strong></span>
232 <span class="-textSize-small -colorSecondaryPale">We offer a range of expertly designed tours, from cultural immersions and scenic explorations to culinary adventures and off-the-beaten-path experiences.</span>
233 <span class="-textSize-small -colorSecondaryPale"> Discover all our tours featuring this destination and start planning your adventure today.</span> -->
234 <a class="-Button -Button--sizeLarge -Button--typePrimary -width-stretch"
235 href='${toursFilterListingUrl}?f%5Bdata-tdest%5D=${thisJournalArticleRPK}'>${translationsUtils.getMessage(locale,'vta.webcontent.view.tours')}</a>
236 </div>
237 </div>
238 </div>
239 </div>
240 <!-- /right panel -->
241 </div>
242 </div>
243 </div>
244 </div>
245 <!-- /gray section -->
246
247 <div class="-Section -Destination-section -Destination-section--typeDescription -gridLayout" data-fragment-md="2of3">
248 <div class="-Section-inner">
249 <div class="-maxWidth-colspan8 -htmlElements">
250 ${Description.getData()}
251 </div>
252 </div>
253 </div>
254 <div class="mb-5"></div>
255 </div>
256 </div>
257 </div>
258
259 <script>
260 AUI().ready(
261 function() {
262 const lgContainer = document.getElementById('-DestinationGallery');
263 lightGallery(lgContainer, {
264 licenseKey: '9N5TA-AWA8R-H9ZLD-GCJBW',
265 plugins: [lgZoom, lgThumbnail, lgHash],
266 selector: '.-Gallery-item',
267 container: '#wrapper',
268 download: false,
269 speed: 500,
270 thumbnail: true,
271 mobileSettings: {
272 controls: false,
273 showCloseIcon: true,
274 download: false
275 }
276 });
277
278 }
279 );
280
281 var rescroll = function() {
282 var assetAnchor = document.querySelector("body:not(.has-control-menu) [id*=portlet_com_liferay_asset_publisher_] .asset-anchor");
283 if( assetAnchor ) {
284 assetAnchor.scrollIntoView();
285 }
286 document.removeEventListener('scroll', rescroll);
287 }
288 document.addEventListener('scroll', rescroll);
289 </script>
290
291<#else>
292 <#-- disabled only -->
293 <p>This Destination is disabled to display.</p>
294 <@liferay_util["html-top"] outputKey="disable-destination">
295 <meta name="robots" content="noindex,nofollow">
296 </@>
297</#if>
298
299<#-- Macros/Functions -->
300
301
302<#macro printFakeBreadcrumbs >
303 <#-- read expandos -->
304 <#-- <#assign group = themeDisplay.getSiteGroup() > -->
305 <#-- <#assign curPageLayout = themeDisplay.getLayout()> -->
306 <#-- <#assign expando = curPageLayout.getExpandoBridge()> -->
307 <#assign fakeParentUrl = vtaLibrary.getLayoutUrlByCategoryName("Destination listing")>
308
309 <#local layoutLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.LayoutLocalService")>
310 <#-- <#assign pageLayoutId = (page.getData()?eval["layoutId"]?number)> -->
311 <#local pageLayout = layoutLocalService.fetchLayoutByFriendlyURL(groupId, false, fakeParentUrl)!"">
312 <#if pageLayout != "">
313 <#local parentLayouts = pageLayout.getAncestors()>
314 <#local allLayouts = parentLayouts + [pageLayout]>
315 </#if>
316 <div class="-marginBottom-1">
317 <div class="-Nav -Nav--typeBreadcrumb -clusterLayout" data-space-breadcrumb="1">
318 <ul class="-Nav-list">
319 <@printBradcrumbItem "Japanspecialist" urlHelper+"/"/>
320 <#if allLayouts??>
321 <#list allLayouts as cur_item>
322 <@printBradcrumbItem cur_item.getName(locale) urlHelper+cur_item.getFriendlyURL()/>
323 </#list>
324 </#if>
325 <@printBradcrumbItem ScreenName.getData() />
326 </ul>
327 </div>
328 </div>
329</#macro>
330
331<#macro printBradcrumbItem name url="">
332 <li class="-Nav-item">
333 <div class="-Nav-itemContents">
334 <#if url !="">
335 <a class="-Nav-link" href="${url}">
336 <span class="-Nav-linkContents">
337 <span class="-Nav-linkContent">
338 ${name}
339 </span>
340 </span>
341 </a>
342 <#else>
343 ${name}
344 </#if>
345 </div>
346 </li>
347</#macro>
348
349
350
351
352
353<#-- embed liferay webcontent (banners) -->
354<#macro embedWc WcId subjectName>
355
356 <#assign
357 JournalArticleService = serviceLocator.findService("com.liferay.journal.service.JournalArticleService")
358 serviceContext = staticUtil["com.liferay.portal.kernel.service.ServiceContextThreadLocal"].getServiceContext()
359 group_id = themeDisplay.getScopeGroupId()?number
360 journalArticle = JournalArticleService.getArticle(group_id, WcId)
361 temp = serviceContext.setAttribute("subject_name", "${subjectName}")
362 />
363 <@liferay_journal["journal-article"]
364 articleId=journalArticle.getArticleId()
365 <#-- ddmTemplateKey="xxxxxxx" -->
366 ddmTemplateKey=journalArticle.getDDMTemplateKey()
367 groupId=journalArticle.getGroupId()
368 wrapperCssClass="gtm-DestinationDetail"
369 />
370</#macro>
371
372
373<#-- print a "featured in" card -->
374<#macro printCard wcData cardInex>
375 <#-- <#local webContentData = jsonFactoryUtil.createJSONObject(tourData.getData()))/> -->
376 <#-- used for back compatibility, for new usage apply commented line above (object type templateNode): -->
377 <#local webContentData = jsonFactoryUtil.createJSONObject(wcData.get("data"))>
378 <#if webContentData.classPK??>
379 <#attempt>
380 <#local classPK = webContentData.classPK?number!""
381 journalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")
382 journalArticle = journalArticleLocalService.getLatestArticle(classPK)!"none"
383 structureId = journalArticle.getDDMStructureId()?string
384 template = vtaLibrary.getTemplateForStructure(structureId,"card")
385 />
386 <#recover>
387 <#local classPK = webContentData.classPK?number!""
388 journalArticle = "none"
389 structureId = "none"
390 template = vtaLibrary.getTemplateForStructure(structureId,"card")
391 />
392 </#attempt>
393 <!-- structure: ${structureId}, template: ${template} -->
394 <#if journalArticle = "none">
395 <!-- BIG ERROR -->
396 <!-- ${webContentData} -->
397 <#elseif journalArticle.status != 3><#-- article is publicated and non expired -->
398
399 <#attempt>
400 <#local thisCode><#-- render an article to string -->
401 <@liferay_journal["journal-article"]
402 articleId=journalArticle.getArticleId()
403 ddmTemplateKey="${template}"
404 groupId=journalArticle.getGroupId()
405 />
406 </#local>
407 <#recover><#-- if render failed -->
408 <#local thisCode>
409 <p>something wrong with this tour:</p>
410 <p>${journalArticle.urlTitle} status: ${journalArticle.status}</p>
411 </#local>
412 </#attempt>
413 <#-- print article if is not disabled -->
414 <#if thisCode?contains('data-tour-state="disabled"')>
415 <!-- tour is DISABLED: ${journalArticle.getTitle()} -->
416 <#else>
417 <div class="-ContentsLayout-content -ContentsLayout-content--size4">
418 <div class="-Tour -Tour--typePreview -Tour--typePreviewMain -TourGroup-tour">
419 ${thisCode}
420 </div>
421 </div>
422 </#if>
423 <#else><#-- article IS expired -->
424 <!-- Card ${cardInex+1}: Tour ${journalArticle.urlTitle} is Expired -->
425 </#if>
426 <#else><#-- article has not a classPK -->
427 <!-- Card ${cardInex+1}: empty, wrong or missing data -->
428 </#if>
429
430</#macro>
431
432<#-- embed - destination detail - master data file export -->
433<#macro setmasterData >
434 <#assign thisMainImage = MainImage>
435 <#assign thisGallerList = GalleryImage.getSiblings()>
436 <#assign thisTitle = ScreenName.getData()>
437 <#assign thisSubHeader = ShortDescription.getData()>
438 <#assign thisLangIdString = thisJournalArticleDefaultLanguageId?split('_')[0]?upper_case >
439 <#assign thisMetaDescription = thisJournalArticle.getDescription()>
440
441 <#-- BUILD TABLES DATA -->
442 <#-- table section -->
443 <#assign masterDataArray = []>
444 <#assign tempObject = {
445 "Content code": ContentID.getData()!"none",
446 "Meta description": thisMetaDescription,
447 "Category": thisDestinationType,
448 "Country": thisCountry,
449 "Region": thisRegion,
450 "Prefecture": thisPrefecture,
451 "Destination name": thisTitle,
452 "Sub header": thisSubHeader,
453 "Description": Description.getData()
454 }>
455 <#assign masterDataArray = masterDataArray + [{"Content data":[tempObject]}]>
456 <#-- /table section -->
457
458 <#-- Gallery -->
459 <#-- <#assign tempObject = [["Image no.","Image file name","Image description"]]> -->
460 <#assign tempObject = []>
461 <#assign imagesList = [thisMainImage] + thisGallerList >
462 <#list imagesList as image>
463 <#assign tempImageNo = 1+image?index>
464 <#assign tempImageFileName = image.getData()?keep_before_last('/')?keep_after_last('/')>
465 <#assign tempImageUrl = image.getData()>
466 <#assign tempImageDescription = image.getAttribute('alt')!"">
467 <#assign tempObject = tempObject + [[tempImageNo, tempImageFileName, tempImageUrl, tempImageDescription]]>
468 </#list>
469 <#assign masterDataGalleryArray = [{"Gallery detail":[tempObject]}]>
470 <#-- /Gallery -->
471
472 <#-- HTML GENERATOR DATA -->
473 <#assign masterData>
474 <html>
475 <head>
476 <title>Destination Master Data "${thisTitle}"</title>
477 <style type="text/css">
478 html body {
479 font-family: monospace;
480 }
481
482 .--master-data > p {
483 margin-bottom: 10px;
484 font-weight: 800;
485 font-size: 1.2em;
486 }
487 .--master-data table {
488 width: 100%;
489 margin-bottom: 20px;
490 border-collapse: collapse;
491 }
492 .--master-data table tr td:first-child {
493 width: 250px;
494 }
495 .--master-data table td {
496 border: 1px solid lightgray;
497 padding: 5px 7px;
498 vertical-align: top;
499 }
500 </style>
501 </head>
502 <body>
503
504 <div class="--master-data">
505
506 <#list masterDataArray as table>
507 <#list table as name,tarray>
508 <p>${name}</p>
509 <#list tarray as table>
510 <table>
511 <tbody>
512 <#list table as k,v>
513 <tr>
514 <td>${k}:</td>
515 <td>${v}</td>
516 </tr>
517 </#list>
518 </tbody>
519 </table>
520 </#list>
521 </#list>
522 </#list>
523
524 <#list masterDataGalleryArray as table>
525 <#list table as name,tarray>
526 <p>${name}</p>
527 <#list tarray as table>
528 <table>
529 <tbody>
530 <tr>
531 <td>Image no.</td>
532 <td>File name</td>
533 <td>Description</td>
534 </tr>
535 <#list table as row>
536 <tr>
537 <td>${row[0]}</td>
538 <td><a href='${row[2]}' target='_blank'>${row[1]}</a></td>
539 <td>${row[3]}</td>
540 </tr>
541 </#list>
542 </tbody>
543 </table>
544 </#list>
545 </#list>
546 </#list>
547
548 </div>
549 </body>
550 </html>
551 </#assign>
552
553 <#assign masterDataJS = masterData?js_string>
554
555 <#-- html generator script -->
556 <script>
557 document.getElementById('masterButton').addEventListener('click', function() {
558 var newWindow = window.open('', '_blank');
559 var htmlContent = `${masterData}`;
560 newWindow.document.write(htmlContent);
561 newWindow.document.close();
562 });
563 </script>
564
565 <#-- word generator script -->
566 <script src="https://unpkg.com/docx@7.1.0/build/index.js"></script>
567
568 <#assign tableCellMargins = "{ top: 20, bottom: 20, left: 80, right: 80 }">
569 <#assign tableCellBorder>
570 {
571 top: { style: docx.BorderStyle.SINGLE, size: 1, color: "000000" },
572 bottom: {style: docx.BorderStyle.SINGLE, size: 1, color: "000000" },
573 left: {style: docx.BorderStyle.SINGLE, size: 1, color: "000000" },
574 right: {style: docx.BorderStyle.SINGLE, size: 1, color: "000000" }
575 }
576 </#assign>
577 <#assign tableBaseFont = 'font: "Calibri", size: 16'>
578
579 <script>
580 function generateWord() {
581 // Vytvoření dokumentu
582 const doc = new docx.Document({
583 sections: [
584 {
585 properties: {
586 page: {
587 margin: {
588 top: 720,
589 right: 720,
590 bottom: 720,
591 left: 720,
592 },
593 },
594 },
595 children: [
596 <@printDocxTables masterDataArray/>
597 <@printDocxTableGallery masterDataGalleryArray/>
598 ],
599 },
600 ],
601 });
602 // Uložení dokumentu
603 docx.Packer.toBlob(doc).then(blob => {
604 const link = document.createElement("a");
605 link.href = URL.createObjectURL(blob);
606 link.download = "Destination-${thisTitle}-${thisLangIdString}.docx";
607 link.click();
608 });
609 };
610
611 document.getElementById("masterButtonWord").addEventListener("click", generateWord);
612 </script>
613</#macro>
614
615<#-- DOCX data print macros -->
616<#macro printDocxTableGallery tables>
617 <#list tables as table>
618 <#list table as name,tarray>
619 <@printDocxParagraph name/>
620 <#list tarray as table>
621 new docx.Table({
622 rows: [
623 new docx.TableRow({
624 children: [
625 <@printDocxTableCell "Img. no." 10/>
626 <@printDocxTableCell "Filename" 50/>
627 <@printDocxTableCell "Description" 40/>
628 ],
629 }),
630 <#list table as row>
631 new docx.TableRow({
632 children: [
633 <@printDocxTableCell row[0] 10/>
634 <@printDocxTableCellHyperlink row[1] row[2] 50/>
635 <@printDocxTableCell row[3] 40/>
636 ],
637 }),
638 </#list>
639 ],
640 width: {
641 size: 100,
642 type: docx.WidthType.PERCENTAGE,
643 },
644 }),
645 <@printDocxParagraph ""/>
646 </#list>
647 </#list>
648 </#list>
649</#macro>
650
651<#macro printDocxTables tables>
652 <#list tables as table>
653 <#list table as name,tarray>
654 <@printDocxParagraph name/>
655 <#list tarray as table>
656 new docx.Table({
657 rows: [
658 <#list table as k,v>
659 new docx.TableRow({
660 children: [
661 <@printDocxTableCell k 25/>
662 <@printDocxTableCell v 75/>
663 ],
664 }),
665 </#list>
666 ],
667 width: {
668 size: 100,
669 type: docx.WidthType.PERCENTAGE,
670 },
671 }),
672 <@printDocxParagraph ""/>
673 </#list>
674 </#list>
675 </#list>
676</#macro>
677
678<#macro printDocxParagraph label>
679 new docx.Paragraph({
680 children: [
681 new docx.TextRun({
682 text: "${label?js_string}",
683 bold: true,
684 ${tableBaseFont},
685 }),
686 ],
687 }),
688</#macro>
689
690<#macro printDocxTableCell data width>
691 <#local paragraphs = textToArray(data)>
692 <#--
693 /* SERVICE PRINTING
694 ${data}
695 */
696 /*<#list paragraphs as paragraph>
697 <#list paragraph as line>
698 ${paragraph?index}-${line?index}: ${line}
699 </#list>
700 </#list>
701 */
702 /* AAQ ${paragraphs?size} */
703 -->
704 new docx.TableCell({
705 children: [
706 <#list paragraphs as cur_par>
707 new docx.Paragraph({
708 children: [
709 <#list cur_par as textLine>
710 new docx.TextRun({
711 text: "${(textLine)?js_string}",
712 ${tableBaseFont},}),
713 <#sep> new docx.TextRun({ text: "", break: 1 }),</#sep>
714 </#list>
715 ],
716 <#sep>
717 spacing: { after: 240, },
718 </#sep>
719 }),
720 </#list>
721 ],
722 margins: ${tableCellMargins},
723 width: {size: ${width},type: docx.WidthType.PERCENTAGE,},
724 borders: ${tableCellBorder},
725 }),
726</#macro>
727
728<#macro printDocxTableCellHyperlink data link width>
729 new docx.TableCell({
730 children: [new docx.Paragraph({
731 children: [
732 new docx.ExternalHyperlink({
733 children: [
734 new docx.TextRun({
735 text: "${data}",
736 ${tableBaseFont},
737 style: "Hyperlink",
738 }),
739 ],
740 link: "https://japanspecialist.com${link}",
741 }),
742 ],
743 })],
744 margins: ${tableCellMargins},
745 width: {size: ${width}, type: docx.WidthType.PERCENTAGE,},
746 borders: ${tableCellBorder},
747 }),
748</#macro>
749
750<#-- convert a field text/richtext to an array of paragraphs and lines -->
751<#function textToArray sourceData>
752 <#local retArray = []>
753 <#local string = sourceData?replace("\\s* ", " ", "r")><#-- replace spaces -->
754 <#local string = string?replace("\\t|\\n", "", "r")><#-- remove tabs, new lines -->
755 <#list string?split("</p>") as cur_paragraph>
756 <#if cur_paragraph?length != 0>
757 <#local cur_parLinesArray = []>
758 <#local cur_paragraphString = cur_paragraph?replace("<br>|<br/>|<br />|</li>", "*EOL*", "r")><#-- set End Of Line -->
759 <#list cur_paragraphString?split("*EOL*") as cur_line>
760 <#local cur_lineString = cur_line?replace("<li>", "• ")><#-- a dot for list item line -->
761 <#local cur_lineString = removeHtmlTags(cur_lineString)><#-- remove rest of html tags -->
762 <#local cur_lineString = cur_lineString?trim><#-- trim start/end whitespaces -->
763 <#if cur_lineString?length != 0>
764 <#local cur_parLinesArray = cur_parLinesArray + [cur_lineString]>
765 </#if>
766 </#list>
767 <#if cur_parLinesArray?size != 0>
768 <#local retArray = retArray + [cur_parLinesArray]>
769 </#if>
770 </#if>
771 </#list>
772 <#return retArray>
773</#function>
774
775<#function removeHtmlTags string>
776 <#local retString = string?replace("<[^>]*>", "", "r")>
777 <#return retString>
778</#function>