An error occurred while processing the template.
Can't convert this string to number: "" The blamed expression: ==> targetPK?number [in template "78320283025323#20119#36294" at line 76, column 70] ---- FTL stack trace ("~" means nesting-related): - Failed at: #assign articleTarget = JournalArticl... [in template "78320283025323#20119#36294" at line 76, column 1] ----
1<script src="https://cdnjs.cloudflare.com/ajax/libs/openseadragon/3.0.0/openseadragon.min.js"></script>
2
3<#assign journalArticleResourceLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleResourceLocalService") />
4<#assign JournalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") />
5<#assign journalArticleId = .vars['reserved-article-id'].data />
6<#assign articleResourcePrimaryKey = journalArticleResourceLocalService.getArticleResourcePrimKey(themeDisplay.getScopeGroupId(), journalArticleId) />
7<#assign article = JournalArticleLocalService.getLatestArticle(articleResourcePrimaryKey?number)>
8<#assign language = themeDisplay.getLanguageId()>
9<#assign LanguageUtil = staticUtil["com.liferay.portal.kernel.language.LanguageUtil"]>
10<#assign locale = themeDisplay.getLocale()>
11<#assign targetPK = request.getParameter("targetPK")?default("")>
12<#assign percorsoPK = request.getParameter("percorsoPK")?default("")>
13<#assign isPercorsoAttivo = true >
14<#if !percorsoPK?has_content>
15 <#assign percorsoPK = getPercorsoBasePK()!>
16 <#assign isPercorsoAttivo = false >
17</#if>
18
19<#assign expando = article.getExpandoBridge().getAttribute("Artista")!>
20<#-- Assicurati che la stringa JSON non sia nulla o vuota -->
21
22<#assign resourcePrimKeyArtista = extractFieldFromExpando(expando, "resourcePrimKeyArtista")/>
23
24<#assign articleArtista = JournalArticleLocalService.getLatestArticle(resourcePrimKeyArtista?number)>
25
26<#assign NomeArtista = extractContents(language, articleArtista.getContent()?xml, "NomeArtista")>
27<#assign CategoriaArtista = extractContents(language, articleArtista.getContent()?xml, "CategoriaArtista")>
28<#assign ImmagineProfilo = extractContents(language, articleArtista.getContent()?xml, "ImmagineProfilo")>
29<#assign ImmagineProfiloStr = "">
30<#assign ImmagineProfiloJsonObj = "">
31<#if ImmagineProfilo?has_content && ImmagineProfilo[0]?has_content>
32 <#assign ImmagineProfiloStr = (ImmagineProfilo[0])?replace(""", "\"", "r")>
33 <#assign ImmagineProfiloJsonObj = jsonFactoryUtil.createJSONObject(ImmagineProfiloStr)>
34</#if>
35<#assign DescrizioneBreveArtista = extractContents(language, articleArtista.getContent()?xml, "DescrizioneBreveArtista")>
36<#assign expandoOpereCorrelate = article.getExpandoBridge().getAttribute("OpereCorrelate")>
37<#assign webcontentsOpereCorrelate = extractFieldFromExpando(expandoOpereCorrelate, "webcontents")/>
38
39<#assign articlePercorso = JournalArticleLocalService.getLatestArticle(percorsoPK?number)>
40<#assign expandoWebcontentsPercorso = articlePercorso.getExpandoBridge().getAttribute("WebcontentsPercorso")>
41<#assign webcontentsPercorso = extractFieldFromExpando(expandoWebcontentsPercorso, "webcontents")/>
42<#assign artistaURL = friendlyURL?keep_before_last("/") + "/web/guest/artisti/-/asset_publisher/rppf/content/" + articleArtista.getUrlTitle() + "?percorsoPK="+percorsoPK + "&targetPK=" + targetPK>
43
44<#assign hasMedia = false>
45<#if MultimediaGroupOpera.getSiblings()?has_content && MultimediaGroupOpera.MultimediaOpera?has_content && MultimediaGroupOpera.MultimediaOpera.getData()?has_content >
46 <#assign hasMedia = true>
47</#if>
48
49<#assign isTotemMode = false>
50<#assign session = themeDisplay.getRequest().getSession()>
51<#assign isTotemMode = session.getAttribute("isTotemMode")!false>
52
53<#assign ImmaginePrincipaleOpera = "">
54<#if ImmaginiPrincipaliOpera.getSiblings()?has_content>
55 <#-- Effettuo un ciclo per vedere se esiste un'immagine principale targetizzata, ed un eventuale secondo ciclo per cercare un'immagine principale non targetizzata (default) -->
56 <#list ImmaginiPrincipaliOpera.getSiblings() as cur_ImmaginiPrincipaliOpera>
57 <#if (cur_ImmaginiPrincipaliOpera.ImmaginePrincipaleOpera.getData())?? && cur_ImmaginiPrincipaliOpera.ImmaginePrincipaleOpera.getData() != "">
58 <#if (cur_ImmaginiPrincipaliOpera.IdTargetImmaginePrincipaleOpera.getData())??>
59 <#if targetPK == cur_ImmaginiPrincipaliOpera.IdTargetImmaginePrincipaleOpera.getData() >
60 <#assign ImmaginePrincipaleOpera = cur_ImmaginiPrincipaliOpera.ImmaginePrincipaleOpera>
61 </#if>
62 </#if>
63 </#if>
64 </#list>
65 <#if !(ImmaginePrincipaleOpera?has_content)>
66 <#list ImmaginiPrincipaliOpera.getSiblings() as cur_ImmaginiPrincipaliOpera>
67 <#if (cur_ImmaginiPrincipaliOpera.ImmaginePrincipaleOpera.getData())?? && cur_ImmaginiPrincipaliOpera.ImmaginePrincipaleOpera.getData() != "">
68 <#if !(cur_ImmaginiPrincipaliOpera.IdTargetImmaginePrincipaleOpera.getData()?has_content) >
69 <#assign ImmaginePrincipaleOpera = cur_ImmaginiPrincipaliOpera.ImmaginePrincipaleOpera>
70 </#if>
71 </#if>
72 </#list>
73 </#if>
74</#if>
75
76<#assign articleTarget = JournalArticleLocalService.getLatestArticle(targetPK?number)>
77<#assign NomeTarget = extractContents(language, articleTarget.getContent()?xml, "NomeTarget")>
78
79<script>console.log("isTotemMode=${isTotemMode?c!}")</script>
80<style>
81.component-title {
82 display:none;
83 }
84 h3 {
85 margin-top: 40px;
86 }
87 h2 {
88 font-size: 2rem;
89 font-family:var(--font-family-montserrat-bold);
90 }
91 strong {
92 font-family:var(--font-family-montserrat-regular);
93 }
94 a {
95 font-family:var(--font-family-montserrat-regular);
96 color:var(--link-color);
97 }
98 .informazioniOpera .column1 {
99 width: 500px;
100 }
101 .informazioniOpera .column2 {
102 width: 100%;
103 margin: 0 40px;
104 }
105 .informazioniOpera .column3 {
106 width: 500px;
107 }
108 .sezArtista {
109 border: 1px solid white;
110 border-radius:var(--border-radius);
111 padding: 15px;
112 }
113 .schedaTecnica {
114 background-color: white;
115 font-family:var(--font-family-montserrat-thin);
116 color: black; line-height: 1.7;
117 padding-bottom: 30px;
118 display: flex;
119 font-size: var(--font-size-base);
120 }
121 .schedaTecnica .column1 {
122 width: 30%;
123 min-width: 400px;
124 padding-right: 40px;
125 }
126 .schedaTecnica .column2 {
127 min-width: 400px;
128 width: 60%;
129 }
130 .schedaTecnica .etichetta {
131 font-family:var(--font-family-montserrat-bold);
132 }
133 .schedaTecnica .valore {
134 position: relative;
135 padding-bottom: 32px;
136 font-family:var(--font-family-montserrat-regular);
137 }
138
139 .schedaTecnica .valore:not(:last-of-type):after {
140 content: "";
141 display: block;
142 border-top: 1px solid #000;
143 position: absolute;
144 bottom: 0;
145 left: 0;
146 width: 100%;
147 padding-bottom: 16px;
148 }
149 .swiper {
150 width: 100%;
151 height: 800px;
152 }
153 .swiper-slide {
154 text-align: center;
155 font-size: 18px;
156 background: #fff;
157 display: flex;
158 justify-content: center;
159 align-items: center;
160 background: transparent;
161 }
162
163 .swiper-slide img {
164 border: 2px solid white;
165 object-fit: cover;
166 width: 100%;
167 height: 350px;
168 max-width: 100%;
169 -ms-transform: translate(-50%, -50%);
170 -webkit-transform: translate(-50%, -50%);
171 -moz-transform: translate(-50%, -50%);
172 transform: translate(-50%, -50%);
173 position: absolute;
174 left: 50%;
175 top: 175px;
176 }
177
178 .altreOperePercorso {
179 height: 100%;
180 width: calc(100% - 152px);
181 margin-left: 75px;
182 position: relative;
183 display: block;
184 text-align: left;
185 margin-top: 80px;
186 }
187
188 .swiper-button-next {
189 margin-top: 0px;
190 position: absolute;
191 top: 180px;
192 right: -65px;
193 width: 45px;
194 height: 45px;
195 transform: translateY(-50%);
196 }
197
198 .swiper-button-prev {
199 position: absolute;
200 top: 180px;
201 left: -65px;
202 width: 45px;
203 height: 45px;
204 transform: translateY(-50%);
205 margin-top: 0px;
206 }
207
208 .swiper-button-next:after, .swiper-button-prev:after {
209 font-family: swiper-icons;
210 font-size: var(--swiper-navigation-size);
211 text-transform: none !important;
212 letter-spacing: 0;
213 font-variant: initial;
214 line-height: 1;
215 font-weight: bold;
216 font-size: 80px;
217 color: white;
218 }
219 .swiper-content {
220 font-size: var(--font-size-base);
221 position: relative;
222 top: 75px;
223 height: 260px;
224 text-align: left;
225 width: 80%;
226 }
227
228 .swiper-content h3 {
229 margin-bottom: 16px;
230 text-transform:uppercase;
231 }
232
233 .swiper-content div {
234 border-top: 1px solid #ffffff85;
235 padding: 8px 0px;
236 }
237 #immaginePrincipaleOpera {
238 width: 100%;
239 object-fit: cover; /* Assicura che l'immagine riempia il contenitore senza distorsioni */
240 object-position: center; /* Centra l'immagine verticalmente e orizzontalmente */
241}
242
243.immaginePrincipaleOperaContainer {
244 position: relative;
245 width: 100%;
246 height: calc(100vh - 70px);
247 overflow: hidden;
248 background-attachment: fixed;
249 background-position: center;
250 background-repeat: no-repeat;
251 background-size: cover;
252 box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.8);
253 margin-top: 70px; /* Aggiunge il margine superiore di 70px */
254 z-index: 9;
255}
256
257#zoomInButton {
258 border-radius: 50px;
259 font-weight: bold;
260 color: white;
261 background: #2c2c2c;
262 border: 0px;
263 font-size: 39px;
264 width: 40px;
265 height: 40px;
266 line-height: 0px;
267 padding: 10px;
268}
269
270#zoomOutButton {
271 border-radius: 50px;
272 font-weight: bold;
273 color: white;
274 background: #2c2c2c;
275 border: 0px;
276 font-size: 39px;
277 width: 40px;
278 height: 40px;
279 line-height: 0px;
280 padding: 10px;
281 padding-bottom: 14px;
282}
283
284#zoomSlider {
285 position: relative;
286 bottom: 3px;
287 right: 44px;
288 z-index: 100;
289 height: 100px;
290 transform: rotate(270deg);
291 margin: 28px 0px;
292}
293
294.zoomPanel {
295 background: #070605;
296 opacity: 0.8;
297 z-index: 9;
298 position: absolute;
299 right: 25px;
300 bottom: 50px;
301 display: block;
302 border-radius: 10px;
303 width: 56px;
304 text-align: center;
305 padding: 8px;
306 padding-top: 12px;
307 box-shadow: -1px 5px 15px #000;
308}
309
310.audioGuideToggle {
311 background: #070605;
312 opacity: 0.8;
313 position: absolute;
314 right: 110px;
315 bottom: 50px;
316 display: block;
317 border-radius: 50px;
318 width: 60px;
319 height: 60px;
320 text-align: center;
321 padding: 10px 10px;
322 box-shadow: -1px 5px 15px #000;
323 border: 2px solid transparent;
324 cursor: pointer;
325 z-index: 1000;
326}
327
328.audioGuideToggle.play {
329 border: 2px solid #2676e7;
330}
331
332.audioGuideToggle img{
333 position: relative;
334 bottom: 4px;
335}
336
337/* Stile iniziale per audioStatus */
338#audioStatus {
339 display: none;
340 position: absolute;
341 right: 180px;
342 bottom: 45px;
343 transform: translateY(-50%); /* Per centrare verticalmente */
344 background-color: rgba(0, 0, 0, 0.8); /* Colore di sfondo con trasparenza */
345 color: white;
346 font-size: 1rem;
347 border-radius: 50px; /* Bordo arrotondato */
348 animation: fadeInFromRight 0.5s ease-out; /* Animazione di fade-in da destra */
349 width: max-content;
350 height: 34px;
351 text-align: center;
352 padding: 1px 10px;
353 box-shadow: 3px 6px 15px #000;
354 border: 2px solid transparent;
355}
356
357.etichettaCarosello {
358 position: absolute;
359 right: 22px;
360 top: 24px;
361 padding: 8px 30px;
362 border-radius: 12px;
363 font-size: 1.5rem;
364 background: #0000007a;
365 font-family:var(--font-family-montserrat-regular);
366}
367
368/* Animazione per fadeInFromRight */
369@keyframes fadeInFromRight {
370 0% {
371 opacity: 0;
372 transform: translateX(50%);
373 }
374 101% {
375 opacity: 1;
376 transform: translateX(0);
377 }
378}
379
380#panzoom img {
381 position: relative;
382 bottom: 60px;
383 width: 100%;
384 height: auto;
385 transform: translateY(-30px);
386}
387
388#loadingOverlay {
389 position: absolute;
390 top: 0;
391 left: 0;
392 width: 100%;
393 height: 100%;
394 background-color: rgba(0, 0, 0, 0.5);
395 display: flex;
396 justify-content: center;
397 align-items: center;
398 z-index: 1000;
399 }
400
401 .loading-text {
402 color: white;
403 font-size: 24px;
404 font-weight: bold;
405 animation: pulse 1.5s infinite;
406 }
407
408.scrollDownLinkArrow {
409 margin-right: 70px;
410 position: relative;
411 bottom: 0px;
412 color: #e0e0e0;
413 padding: 1px 18px;
414 /* border-bottom: 4px solid #e0e0e0; */
415 text-align: center;
416 font-size: 26px;
417 line-height: 1rem;
418 background: #000000b5;
419 padding: 12px 20px;
420 border-radius: 8px;
421}
422.scrollDownLink {
423 margin-right: 70px;
424 position: relative;
425 bottom: 0px;
426 color: #e0e0e0;
427 padding: 1px 18px;
428 border-bottom: 4px solid #e0e0e0;
429 text-align: center;
430 font-size: 26px;
431}
432
433 .scrollDownLink p {
434 margin-bottom: 0px;
435 margin-top: 2px;
436 }
437
438
439.scrollDownLink:hover {
440 text-decoration: none;
441 color: inherit;
442}
443
444.infoOperaSuImmaginePrincipale {
445 position: absolute;
446 bottom: 0;
447 left: 0px;
448 padding-left: 35px;
449 padding-bottom: 50px;
450 color: #e0e0e0;
451 width: 100%;
452 background: linear-gradient(to top, rgb(0 0 0 / 87%), rgba(0, 0, 0, 0))
453}
454
455.infoOperaSuImmaginePrincipale .nomeArtista {
456font-family: var(--font-family-montserrat-italic);
457 position: relative;
458 top: 14px;
459}
460
461.infoOperaSuImmaginePrincipale .titoloOpera {
462 font-size: 3rem;
463 font-family: var(--font-family-montserrat-italic);
464 margin-bottom: 0px;
465 position: relative;
466 top: 8px;
467}
468
469.btnBack {
470 color: white;
471 background: #000000a1;
472 border-radius: 13px;
473 padding: 12px 16px;
474}
475
476.btnBack:hover {
477 color: white;
478 text-decoration:none;
479}
480
481 @keyframes pulse {
482 0% { opacity: 0.5; }
483 50% { opacity: 1; }
484 100% { opacity: 0.5; }
485 }
486
487 .informazioniOpera {
488 display:flex;
489 margin:40px var(--margin);
490 margin-top: 80px;
491 }
492 .multimedia {
493 background-color: #191919;
494 font-family:var(--font-family-montserrat-thin);
495 color: black;
496 line-height: 1.7;
497 padding-bottom: 30px
498 }
499 .multimedia video {
500 width: 30% !important;
501 margin-right: 2%;
502 }
503 .video-container {
504 display: flex;
505 flex-wrap: wrap;
506 gap: 60px;
507 justify-content: center; /* Già presente */
508 align-items: center; /* Aggiunto per centrare verticalmente */
509 padding: 0 40px;
510 margin: 0 auto;
511 width: 100%; /* Aggiunto per occupare tutto lo spazio disponibile */
512}
513
514.video-wrapper {
515 flex: 0 0 calc(50% - 30px);
516 min-width: 280px;
517 display: flex;
518 justify-content: center;
519 align-items: center;
520}
521
522.video-wrapper video {
523 width: 100% !important;
524 height: auto;
525 margin: 0;
526 max-height: 600px;
527}
528
529 #scrollDownArrow {
530 display: none;
531 }
532
533 @media screen and (max-width: 768px) {
534 .btnBackHeader {
535 display:none;
536 }
537 .btnBack {
538 margin-left: -60px;
539 font-size: 1.2rem;
540 }
541 .titoloOpera {
542 font-size:1.5rem !important;
543 top: 18px;
544 line-height: 2.2rem;
545 width:80%;
546 }
547 .immaginePrincipaleOperaContainer {
548 width: 100%;
549 height: 90vh;
550 }
551 #openseadragon {
552 width: 100% !important;
553 height: 90vh !important;
554 max-height: 90vh !important;
555 }
556 .audioSection {
557 position: absolute;
558 bottom: 265px;
559 right: -74px;
560 }
561 .audioStatus {
562 right: 88px !important;
563 bottom: 110px !important;
564 }
565 #scrollDownLinkDescrizione, #scrollDownLinkSchedaTecnica, #scrollDownLinkAltreOperePercorso, #scrollDownLinkMultimedia {
566 display: none;
567 }
568 #scrollDownArrow {
569 display: block;
570 font-size: 1.3rem;
571 }
572 #scrollDownArrow p{
573 margin-bottom: 0rem;
574 }
575 .zoomPanel {
576 bottom: 150px;
577 }
578
579 .audioGuideToggle {
580 bottom: 75px;
581 }
582 .multimedia {
583 margin: 0;
584 padding: 0px !important;
585 }
586 .multimedia video {
587 width: 85% !important;
588 }
589 .multimedia h1 {
590 margin-left: 40px;
591 }
592 .video-container {
593 flex-direction: column;
594 padding: 20px;
595 align-content:center;
596 text-align:center;
597 }
598
599 .video-wrapper {
600 flex: 0 0 100%;
601 }
602
603 .video-wrapper video {
604 width: 100% !important;
605 }
606 .informazioniOpera {
607 flex-direction: column;
608 margin: 0;
609 margin-top: 65px;
610 }
611 .informazioniOpera .column1,
612 .informazioniOpera .column2,
613 .informazioniOpera .column3 {
614 width: 100%;
615 margin: 0;
616 padding: 0 20px;
617 margin-bottom: 30px;
618 }
619
620 .informazioniOpera h1 {
621 font-size: 2.5rem !important;
622 }
623
624 .informazioniOpera .column2 {
625 order: 1;
626 }
627
628 .informazioniOpera .column3 {
629 order: 2;
630 }
631
632 .informazioniOpera .column1 {
633 order: 3;
634 margin-top: -30px;
635 }
636 .schedaTecnica {
637 margin: 0px;
638 padding: 0px !important;
639 }
640 .informazioniOpera .schedaTecnica {
641 margin: 0;
642 flex-direction: column;
643 }
644
645 .schedaTecnica .column1,
646 .schedaTecnica .column2 {
647 width: 100%;
648 min-width: unset;
649 }
650
651 .schedaTecnica .column2 {
652 margin-top: 30px;
653 }
654 .infoOperaSuImmaginePrincipale {
655 padding-left: 14px;
656 }
657 .infoOperaSuImmaginePrincipale .nomeArtista {
658 margin-bottom: 74px;
659 width:80%;
660 }
661 .schedaTecnica .column1 {
662 width: 0px;
663 display:none;
664 }
665 .schedaTecnica > div {
666 width: 100%;
667 }
668 .imgSchedaTecnica {
669 display:none;
670 }
671 .schedaTecnica h1 {
672 padding-bottom: 0px !important;
673 padding: 0px 20px
674 }
675 .schedaTecnica h1 {
676 padding-bottom: 0px;
677 padding-left: 20px;
678 padding-right: 20px;
679 margin-left: 30px;
680 }
681 .schedaTecnica .column2 .valore {
682 padding-left: 50px;
683 padding-right: 50px;
684 }
685 .schedaTecnica .column2 .etichetta {
686 padding-left: 50px;
687 padding-right: 50px;
688 }
689
690 .schedaTecnica .etichetta {
691 font-size: 1.2rem;
692 }
693 .schedaTecnica .valore {
694 font-size: 1.2rem;
695 }
696
697 .altreOperePercorso {
698 height: 100%;
699 width: 80%;
700 margin-left: unset;
701 position: relative;
702 display: block;
703 text-align: left;
704 margin: 40px;
705 }
706
707 .swiper-content {
708 top: 70px;
709 width: 100%;
710 }
711
712 .swiper-content h3 {
713 font-size: 1.4rem;
714 font-family:var(--font-family-montserrat-bold);
715 }
716
717 .swiper-content div {
718 font-size: 1.3rem
719 }
720
721 }
722
723 .secondary-image {
724 transition: transform 0.2s ease;
725 cursor: pointer;
726}
727
728.secondary-image:hover {
729 transform: scale(1.02);
730}
731
732.download {
733 color: white;
734 background: #000000a1;
735 border-radius: 13px;
736 padding: 16px 20px 16px 20px;
737 background: #968d83;
738 top: 25px;
739 position: relative;
740 font-size: 1.6rem;
741 z-index: 1000;
742}
743.pdf-container {
744 width: 100%;
745 margin: 20px 0;
746}
747
748.pdf-page {
749 margin: 10px 0;
750 box-shadow: 0 2px 5px rgba(0,0,0,0.2);
751 border-radius:var(--border-radius);
752}
753
754.pdf-controls {
755 margin: 10px 0;
756 text-align: center;
757}
758
759.pdf-button {
760 background: #2c2c2c;
761 color: white;
762 border: none;
763 padding: 8px 15px;
764 margin: 0 5px;
765 border-radius: 4px;
766 cursor: pointer;
767}
768
769#loadingOverlay {
770 position: absolute;
771 top: 0;
772 left: 0;
773 width: 100%;
774 height: 100%;
775 background-color: rgba(0, 0, 0, 0.5);
776 display: flex;
777 justify-content: center;
778 align-items: center;
779 z-index: 1000;
780}
781
782.loading-text {
783 color: white;
784 font-size: 24px;
785 font-weight: bold;
786 animation: pulse 1.5s infinite;
787}
788
789#download {
790 text-align: center;
791 margin-top:22px;
792}
793
794.download-pdf {
795 background: #968D76;
796 color: white;
797 padding: 12px 24px;
798 border-radius: 10px;
799}
800
801.img-caa {
802 border-radius: 8px;
803 margin-bottom: 20px;
804}
805
806@keyframes pulse {
807 0% { opacity: 0.5; }
808 50% { opacity: 1; }
809 100% { opacity: 0.5; }
810}
811
812.goToVideoLis {
813 background: #070605;
814 opacity: 0.8;
815 z-index: 9;
816 position: absolute;
817 right: 110px;
818 bottom: 50px;
819 display: block;
820 border-radius: 50px;
821 width: auto;
822 min-width: 120px;
823 height: 60px;
824 text-align: center;
825 padding: 10px 20px;
826 box-shadow: -1px 5px 15px #000;
827 border: 2px solid transparent;
828 cursor: pointer;
829 color: white;
830 font-size: 1.2rem;
831 font-weight: bold;
832 display: flex;
833 align-items: center;
834 justify-content: center;
835}
836
837.goToVideoLis:hover {
838 border: 2px solid #ffffff;
839 opacity: 1;
840}
841
842@media screen and (max-width: 768px) {
843 .goToVideoLis {
844 position: absolute;
845 right: 90px;
846 bottom: 115px;
847 font-size: 1rem;
848 min-width: 0;
849 width: max-content;
850 padding: 12px 15px;
851 height: 50px;
852 z-index: 1000;
853 display: block;
854 visibility: visible;
855 }
856
857 .zoomPanel {
858 position: absolute;
859 bottom: 100px;
860 right: 15px;
861 z-index: 1000;
862 display: block;
863 visibility: visible;
864 }
865
866 .audioGuideToggle {
867 position: absolute;
868 bottom: 115px;
869 right: 87px;
870 z-index: 1000;
871 display: block;
872 visibility: visible;
873 }
874}
875</style>
876<div style="font-family:var(--font-family-montserrat-thin); font-size: var(--font-size-base); color: var(--text-color-light); line-height: 1.7;margin-top: -7px;">
877 <div style="margin:25px var(--margin); z-index: 10; position: absolute;">
878 <a href="#" class="btnBack" onclick="javascript:history.back();">${LanguageUtil.get(locale, "navigazione.indietro")!}</a>
879 </div>
880 <div id="immaginePrincipaleOperaContainer" class="immaginePrincipaleOperaContainer">
881 <div id="openseadragon" style="width: 100%; height: 100vh;"></div>
882 <div class="audioSection">
883 <div id="audioStatus" class="audioStatus"></div>
884 <#if !isTotemMode>
885 <#if targetPK == "53099">
886 <div class="goToVideoLis" id="goToVideoLis" onclick="goToVideoLIS()">
887 Video LIS
888 </div>
889 <#else>
890 <div class="audioGuideToggle" id="audioGuideToggle" onclick="toggleAudio()">
891 <img src="/documents/d/guest/cuffie" alt="${LanguageUtil.get(locale, "opera.immagineprincipale")!}">
892 </div>
893 </#if>
894 </#if>
895 </div>
896 <div class="zoomPanel">
897 <div><button id="zoomInButton">+</button></div>
898 <div><input type="range" id="zoomSlider" min="1" max="4" step="0.1" value="1"></div>
899 <div><button id="zoomOutButton">-</button></div>
900 </div>
901 <div class="infoOperaSuImmaginePrincipale">
902 <p class="titoloOpera">${TitoloOpera.getData()}</p>
903 <p class="nomeArtista">${NomeArtista[0]!}</p>
904 </div>
905 <div style="display: flex; position:absolute;bottom:0; right: 14%;">
906 <a href="#informazioniOpera" id="scrollDownLinkDescrizione" class="scrollDownLink">
907 ${LanguageUtil.get(locale, "tab_opera_descrizione")!}
908 </a>
909
910 <#if hasMedia>
911 <a href="#multimedia" id="scrollDownLinkMultimedia" class="scrollDownLink">
912 ${LanguageUtil.get(locale, "tab_opera_multimedia")!}
913 </a>
914 </#if>
915
916 <a href="#schedaTecnica" id="scrollDownLinkSchedaTecnica" class="scrollDownLink">
917 ${LanguageUtil.get(locale, "tab_opera_scheda")!}
918 </a>
919
920 <a href="#informazioniOpera" id="scrollDownArrow" class="scrollDownLinkArrow">
921 <p>${LanguageUtil.get(locale, "tab_opera_descrizione")!}</p>
922 <svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
923 <path d="M7 10L12 15L17 10" stroke="#e0e0e0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
924 </svg>
925 </a>
926
927 <#if isPercorsoAttivo>
928 <a href="#altreOperePercorso" id="scrollDownLinkAltreOperePercorso" class="scrollDownLink">
929 ${LanguageUtil.get(locale, "tab_opera_altreopere")!}
930 </a>
931 </#if>
932 </div>
933 </div>
934
935 <div id="informazioniOpera" class="informazioniOpera">
936 <div class="column1">
937 <div class="sezArtista">
938 <div style="display: flex;">
939 <#if ImmagineProfiloStr?has_content && ImmagineProfiloJsonObj?has_content>
940 <div style="width: 130px; height: 130px; min-width: 130px; min-height: 130px; margin-right: 20px; border-radius: 50%; overflow: hidden; background-image: url('<#if (ImmagineProfiloJsonObj.url)?? && ImmagineProfiloJsonObj.url != "">${ImmagineProfiloJsonObj.url}</#if>'); background-size: cover; background-position: center;"></div>
941 </#if>
942 <div>
943 <p style="font-family:var(--font-family-montserrat-bold); margin-bottom: -8px;">${NomeArtista[0]!}</p>
944 <p>${CategoriaArtista[0]!}</p>
945 </div>
946 </div>
947 <div style="margin-top: 15px;">
948 <p>${DescrizioneBreveArtista[0]!}</p>
949 <div style="margin-top:15px; text-align: right;">
950 <a href="${artistaURL!}">${LanguageUtil.get(locale, "opera.schedaartista")!}</a>
951 </div>
952 </div>
953 </div>
954 </div>
955 <div class="column2">
956 <#if (TitoloOpera.getData())??>
957 <div style="display: flex; justify-content: space-between; align-items: center;">
958 <h1 style="text-transform:uppercase; font-size: 4rem; font-family:var(--font-family-montserrat-regular); margin-bottom: 20px">${TitoloOpera.getData()}</h1>
959 <span style="font-size: 1.2rem; font-family: var(--font-family-montserrat-regular);">
960 Target: ${NomeTarget[0]!}
961 </span>
962 </div>
963 </#if>
964 <div style="margin-top: 15px;">
965 <h2>${LanguageUtil.get(locale, "opera.posizione")!}</h2>
966 <p><#if (PosizioneOpera.getData())??>
967 ${PosizioneOpera.getData()}
968 </#if>
969 </p>
970 </div>
971 <#if DescrizioniOpera?has_content>
972 <#if targetPK?has_content>
973 <#if DescrizioniOpera.getSiblings()?has_content>
974 <#list DescrizioniOpera.getSiblings() as cur_DescrizioniOpera>
975 <#if (cur_DescrizioniOpera.IdTargetDescrizioneOpera.getData())??>
976 <#if targetPK == cur_DescrizioniOpera.IdTargetDescrizioneOpera.getData()>
977 <#if (cur_DescrizioniOpera.DescrizioneOpera.getData())??>
978 ${cur_DescrizioniOpera.DescrizioneOpera.getData()!}
979 </#if>
980 <#if (cur_DescrizioniOpera.AudioguidaOpera.getData())?? && !isTotemMode>
981 <audio style="margin-top: 30px;" id="myAudio" controls>
982 <source src="${cur_DescrizioniOpera.AudioguidaOpera.getData()!}">
983 Your browser does not support the audio element.
984 </audio>
985 </#if>
986 </#if>
987 </#if>
988 </#list>
989 </#if>
990 <#else>
991 <#if (DescrizioniOpera.DescrizioneOpera.getData())??>
992 ${DescrizioniOpera.DescrizioneOpera.getData()}
993 </#if>
994 </#if>
995 </#if>
996 </div>
997
998 <div class="column3">
999 <#if ImmaginiOpera?has_content>
1000 <#if ImmaginiOpera.getSiblings()?has_content>
1001 <#list ImmaginiOpera.getSiblings() as cur_ImmaginiOpera>
1002 <#if (cur_ImmaginiOpera.ImmagineOpera.getData())?? && cur_ImmaginiOpera.ImmagineOpera.getData() != "">
1003 <#if targetPK == cur_ImmaginiOpera.IdTargetImmagineOpera.getData() || "" == cur_ImmaginiOpera.IdTargetImmagineOpera.getData()>
1004 <img
1005 style="border-radius:var(--border-radius); margin-bottom:6px; cursor: pointer;"
1006 alt="${cur_ImmaginiOpera.ImmagineOpera.getAttribute("alt")}"
1007 data-fileentryid="${cur_ImmaginiOpera.ImmagineOpera.getAttribute("fileEntryId")}"
1008 src="${cur_ImmaginiOpera.ImmagineOpera.getData()}"
1009 onclick="swapImages(this)"
1010 class="secondary-image"
1011 />
1012 </#if>
1013 </#if>
1014 <#if (cur_ImmaginiOpera.DescrizioneImmagineOpera.getData())??>
1015 <#if targetPK == cur_ImmaginiOpera.IdTargetImmagineOpera.getData() || "" == cur_ImmaginiOpera.IdTargetImmagineOpera.getData()>
1016 <p style="margin-bottom:18px">${cur_ImmaginiOpera.DescrizioneImmagineOpera.getData()}</p>
1017 </#if>
1018 </#if>
1019 </#list>
1020 </#if>
1021 </#if>
1022 </div>
1023 </div>
1024</div>
1025
1026<#if MultimediaGroupOpera.getSiblings()?has_content && hasMedia>
1027 <div id="multimedia" class="multimedia" style="padding:40px var(--margin);">
1028 <div>
1029 <h1 style="font-family:var(--font-family-montserrat-regular); padding-top:30px; padding-bottom: 40px; color: white;">MULTIMEDIA</h1>
1030 <div class="multimedia">
1031 <div class="video-container">
1032 <#list MultimediaGroupOpera.getSiblings() as cur_MultimediaGroupOpera>
1033 <#if (cur_MultimediaGroupOpera.IdTargetMultimediaOpera.getData())??>
1034 <#if targetPK == cur_MultimediaGroupOpera.IdTargetMultimediaOpera.getData() || "" == cur_MultimediaGroupOpera.IdTargetMultimediaOpera.getData()>
1035 <#if cur_MultimediaGroupOpera.MultimediaOpera.getData()?has_content>
1036 <div class="video-wrapper">
1037 <video controls>
1038 <source src="${cur_MultimediaGroupOpera.MultimediaOpera.getData()!}">
1039 Your browser does not support the video tag.
1040 </video>
1041 </div>
1042 </#if>
1043 </#if>
1044 </#if>
1045 </#list>
1046 </div>
1047 </div>
1048 </div>
1049 </div>
1050</#if>
1051
1052
1053
1054<div id="schedaTecnica" class="schedaTecnica" style="padding:40px var(--margin);">
1055 <div style="width:100%">
1056 <h1 style="font-family:var(--font-family-montserrat-regular); padding-top:30px; padding-bottom: 40px;">${LanguageUtil.get(locale, "opera.schedatecnica")!}</h1>
1057 <div class="schedaTecnica" >
1058 <#if (ImmaginePrincipaleOpera)??>
1059 <div class="column1">
1060 <img id="imgSchedaTecnica" style="border-radius:var(--border-radius); width: 100%; border:2px solid black" alt="" src="<#if ImmaginePrincipaleOpera?is_hash && ImmaginePrincipaleOpera.getData??>${ImmaginePrincipaleOpera.getData()}<#else>${ImmaginePrincipaleOpera!}</#if>" />
1061 </div>
1062 </#if>
1063 <div class="column2">
1064 <#if (NumeroInventarioOpera.getData())??>
1065 <div class="etichetta">
1066 ${LanguageUtil.get(locale, "opera.numinventario")!}
1067 </div>
1068 <div class="valore">
1069 ${NumeroInventarioOpera.getData()!}
1070 </div>
1071 </#if>
1072 <#if (TitoloOpera.getData())??>
1073 <div class="etichetta">
1074 ${LanguageUtil.get(locale, "opera.titoloopera")!}
1075 </div>
1076 <div class="valore">
1077 ${TitoloOpera.getData()!}
1078 </div>
1079 </#if>
1080 <#if (NomeArtista[0])??>
1081 <div class="etichetta">
1082 ${LanguageUtil.get(locale, "opera.autore")!}
1083 </div>
1084 <div class="valore">
1085 ${NomeArtista[0]!}
1086 </div>
1087 </#if>
1088 <#if (PeriodoOpera.getData())??>
1089 <div class="etichetta">
1090 ${LanguageUtil.get(locale, "opera.periodo")!}
1091 </div>
1092 <div class="valore">
1093 ${PeriodoOpera.getData()!}
1094 </div>
1095 </#if>
1096 <#if (TecnicaOpera.getData())??>
1097 <div class="etichetta">
1098 ${LanguageUtil.get(locale, "opera.tecnica")!}
1099 </div>
1100 <div class="valore">
1101 ${TecnicaOpera.getData()!}
1102 </div>
1103 </#if>
1104 <#if (SupportoOpera.getData())??>
1105 <div class="etichetta">
1106 ${LanguageUtil.get(locale, "opera.supporto")!}
1107 </div>
1108 <div class="valore">
1109 ${SupportoOpera.getData()!}
1110 </div>
1111 </#if>
1112 <#if (DimensioniOpera.getData())??>
1113 <div class="etichetta">
1114 ${LanguageUtil.get(locale, "opera.dimensioni")!}
1115 </div>
1116 <div class="valore">
1117 ${DimensioniOpera.getData()!}
1118 </div>
1119 </#if>
1120 <#if (ProvenienzaOpera.getData())??>
1121 <div class="etichetta">
1122 ${LanguageUtil.get(locale, "opera.provenienza")!}
1123 </div>
1124 <div class="valore">
1125 ${ProvenienzaOpera.getData()!}
1126 </div>
1127 </#if>
1128 </div>
1129 </div>
1130 </div>
1131</div>
1132
1133 <#if isPercorsoAttivo>
1134 <div id="altreOperePercorso" class="altreOperePercorso" style="font-family:var(--font-family-montserrat-thin); color: var(--text-color-light); line-height: 1.7;">
1135 <h1 style="font-family:var(--font-family-montserrat-regular);">${LanguageUtil.get(locale, "percorso.altreopere")!}</h1>
1136 <div class="altreOperePercorso">
1137 <div class="swiper mySwiper">
1138 <div class="swiper-wrapper">
1139 <#if webcontentsPercorso?is_enumerable>
1140 <#list webcontentsPercorso as webcontent>
1141 <#assign resourcePrimKeyWebContent = webcontent.resourcePrimKey/>
1142 <#assign webcontentArticlePercorso = JournalArticleLocalService.getLatestArticle(resourcePrimKeyWebContent?number)>
1143 <#if isOpera(webcontentArticlePercorso)>
1144 <#assign TitoloOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "TitoloOpera")>
1145 <#assign ImmagineOperaPercorso = extractImageJson(language, webcontentArticlePercorso.getContent()?string, targetPK)>
1146
1147 <#assign ImmagineOperaPercorsoJsonObj = jsonFactoryUtil.createJSONObject(ImmagineOperaPercorso)>
1148 <#assign articleOperaPercorsoURL = friendlyURL?keep_before_last("/") + "/web/guest/opere/-/asset_publisher/khcq/content/" + webcontentArticlePercorso.getUrlTitle() + "?percorsoPK="+percorsoPK + "&targetPK=" + targetPK>
1149 <#assign TecnicaOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "TecnicaOpera")>
1150 <#assign DimensioniOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "DimensioniOpera")>
1151 <#assign PeriodoOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "PeriodoOpera")>
1152
1153 <#assign expandoArtistaOperaCorrelata = webcontentArticlePercorso.getExpandoBridge().getAttribute("Artista")>
1154 <#assign resourcePrimKeyArtistaOperaCorrelata = extractFieldFromExpando(expandoArtistaOperaCorrelata, "resourcePrimKeyArtista")/>
1155 <#assign articleArtistaOperaCorrelata = JournalArticleLocalService.getLatestArticle(resourcePrimKeyArtistaOperaCorrelata?number)>
1156 <#assign NomeArtistaOperaCorrelata = extractContents(language, articleArtistaOperaCorrelata.getContent()?xml, "NomeArtista")>
1157 <div class="swiper-slide" data-swiper-parallax="-23%">
1158 <a href="${articleOperaPercorsoURL!}#immaginePrincipaleOperaContainer">
1159 <img alt="${TitoloOperaPercorso[0]!}" src="<#if ImmagineOperaPercorsoJsonObj?? && (ImmagineOperaPercorsoJsonObj.url)?? && ImmagineOperaPercorsoJsonObj.url != "">${ImmagineOperaPercorsoJsonObj.url!}</#if>"></img>
1160 </a>
1161 <div class="swiper-content">
1162 <h3>${TitoloOperaPercorso[0]!}</h3>
1163 <div>${LanguageUtil.get(locale, "opera.artista")!}: ${NomeArtistaOperaCorrelata[0]!}</div>
1164 <div>${LanguageUtil.get(locale, "opera.tecnica.corta")!}: ${TecnicaOperaPercorso[0]!}</div>
1165 <div>${LanguageUtil.get(locale, "opera.dimensioni.corta")!}: ${DimensioniOperaPercorso[0]!}</div>
1166 <div>${LanguageUtil.get(locale, "opera.periodo.corta")!}: ${PeriodoOperaPercorso[0]!}</div>
1167 </div>
1168 <#if resourcePrimKeyWebContent?number == articleResourcePrimaryKey?number>
1169 <div id="operaCorrente" class="etichettaCarosello">${LanguageUtil.get(locale, "operaCorrente")!}</div>
1170 </#if>
1171 </div>
1172 </#if>
1173 </#list>
1174 </#if>
1175 </div>
1176 </div>
1177 <div class="swiper-button-next"></div>
1178 <div class="swiper-button-prev"></div>
1179 </div>
1180 </div>
1181 </#if>
1182
1183 <div id="friendlyURL">
1184 ${friendlyURL}
1185 </div>
1186
1187
1188</div>
1189
1190<#assign journalArticleResourceLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleResourceLocalService") />
1191<#assign JournalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") />
1192<#assign journalArticleId = .vars['reserved-article-id'].data />
1193<#assign articleResourcePrimaryKey = journalArticleResourceLocalService.getArticleResourcePrimKey(themeDisplay.getScopeGroupId(), journalArticleId) />
1194
1195<#function extractFieldFromExpando expando fieldName>
1196 <#attempt>
1197 <#if expando?has_content>
1198 <#assign jsonExpando = expando?eval>
1199 <#return jsonExpando[fieldName]>
1200 <#else>
1201 <#return "">
1202 </#if>
1203 <#recover>
1204 <#return "">
1205 </#attempt>
1206</#function>
1207
1208<#-- Questa funzione restituisce un array di dynamic-element relativo al field-reference specificato -->
1209<#function extractContents language, xml, fieldReference, start=0>
1210 <#-- Cercare il tag di apertura del dynamic-element con il field-reference specificato -->
1211 <#assign startPos = xml?index_of(fieldReference, start)>
1212 <#if startPos != -1>
1213 <#-- Trovare l'inizio del contenuto nella lingua corretta-->
1214 <#assign startDynamic = xml?index_of(language, startPos)>
1215 <#if startDynamic != -1>
1216 <#assign startContent = startDynamic + (language?length)>
1217
1218 <#-- Trovare gli indici di inizio e fine del CDATA -->
1219 <#assign startCdata = xml?index_of("CDATA[", startContent) + "CDATA["?length>
1220 <#assign endCdata = xml?index_of("]]", startCdata)>
1221
1222 <#-- Estrai il contenuto CDATA -->
1223 <#assign content = xml?substring(startCdata, endCdata)>
1224 <#-- Controllo la presenza di altri valori di fieldReference -->
1225 <#assign nextIndex = xml?index_of(fieldReference, endCdata)>
1226 <#if nextIndex != -1>
1227 <#-- Continua la ricerca in modo ricorsivo -->
1228 <#return [content] + extractContents(language, xml, fieldReference, nextIndex)>
1229 <#else>
1230 <#return [content]>
1231 </#if>
1232 <#else>
1233 <#return []>
1234 </#if>
1235 <#else>
1236 <#return []>
1237 </#if>
1238</#function>
1239
1240<#function extractImageJson language, xml, targetPK, start=0>
1241 <#assign result = "">
1242 <#assign foundExactMatch = false>
1243 <#assign foundEmptyTarget = "">
1244 <#assign scanStart = start>
1245
1246 <#-- Primo passaggio: Scansiona tutto per trovare un match esatto -->
1247 <#list 0..100 as iteration> <#-- Limite di sicurezza per evitare loop infiniti -->
1248 <#assign fieldsetStart = xml?index_of("ImmaginiPrincipaliOpera", scanStart)>
1249 <#if fieldsetStart == -1>
1250 <#break>
1251 </#if>
1252
1253 <#assign targetStart = xml?index_of("IdTargetImmaginePrincipaleOpera", fieldsetStart)>
1254 <#assign idTarget = "">
1255
1256 <#if targetStart != -1>
1257 <#assign targetContentStart = xml?index_of("CDATA[", targetStart) + "CDATA["?length>
1258 <#assign targetContentEnd = xml?index_of("]]", targetContentStart)>
1259
1260 <#if targetContentStart != -1 && targetContentEnd != -1>
1261 <#assign idTarget = xml?substring(targetContentStart, targetContentEnd)?trim>
1262 </#if>
1263 </#if>
1264
1265 <#if idTarget == targetPK>
1266 <#assign foundExactMatch = true>
1267 <#break>
1268 </#if>
1269
1270 <#if (idTarget?is_string && idTarget == "") || (idTarget?is_number && idTarget == 0)>
1271 <#if (foundEmptyTarget?is_string && foundEmptyTarget == "") || (foundEmptyTarget?is_number && foundEmptyTarget == 0)>
1272 <#assign finalStart = fieldsetStart>
1273 </#if>
1274 </#if>
1275
1276 <#assign scanStart = xml?index_of("field-reference=\"ImmaginiPrincipaliOpera\"", fieldsetStart + 1)>
1277 <#if scanStart == -1>
1278 <#break>
1279 </#if>
1280 </#list>
1281
1282 <#-- Secondo passaggio: Se ha trovato un match esatto, usa quello. Altrimenti usa il primo con target vuoto. -->
1283 <#assign finalStart = fieldsetStart>
1284 <#if !foundExactMatch && foundEmptyTarget?string != "">
1285 <#assign finalStart = foundEmptyTarget>
1286 </#if>
1287
1288 <#if finalStart != -1>
1289 <#assign fieldsetEnd = xml?index_of("</dynamic-element>", finalStart) + "</dynamic-element>"?length>
1290 <#assign fieldsetXml = xml?substring(finalStart, fieldsetEnd)>
1291
1292 <#assign imageStart = fieldsetXml?index_of("field-reference=\"ImmaginePrincipaleOpera\"")>
1293
1294 <#if imageStart != -1>
1295 <#assign imageContentStart = fieldsetXml?index_of("CDATA[", imageStart) + "CDATA["?length>
1296 <#assign imageContentEnd = fieldsetXml?index_of("]]", imageContentStart)>
1297
1298 <#if imageContentStart != -1 && imageContentEnd != -1>
1299 <#assign result = fieldsetXml?substring(imageContentStart, imageContentEnd)?trim>
1300 </#if>
1301 </#if>
1302 </#if>
1303
1304 <#return result>
1305</#function>
1306
1307<#function isOpera webcontentArticle>
1308 <#assign webContentXML = webcontentArticle.getContent()?xml>
1309 <#return webContentXML?index_of("TitoloOpera") != -1>
1310</#function>
1311
1312<#function getPercorsoBasePK()>
1313 <#assign percorsoBasePK = "">
1314 <#assign articles = JournalArticleLocalService.getArticles()>
1315 <#assign ddmStructureLocalService = serviceLocator.findService("com.liferay.dynamic.data.mapping.service.DDMStructureLocalService")>
1316 <#-- Itera sugli articoli e filtra quelli con la struttura Percorso -->
1317 <#list articles as article>
1318 <#-- Ottieni l'ID della struttura -->
1319 <#assign ddmStructureId = article.getDDMStructureId()>
1320
1321 <#-- Ottieni la struttura utilizzando l'ID -->
1322 <#assign ddmStructure = ddmStructureLocalService.getDDMStructure(ddmStructureId)>
1323
1324 <#-- Ottieni il nome della struttura -->
1325 <#assign structureName = ddmStructure.getName(locale)>
1326 <#if structureName == "Percorso">
1327 <#assign PercorsoBase = extractContents(language, article.getContent()?xml, "PercorsoBase")>
1328 <#if (PercorsoBase[0]?has_content && "true"==PercorsoBase[0])>
1329 <#assign percorsoBasePK = article.getResourcePrimKey()>
1330 </#if>
1331 </#if>
1332 </#list>
1333 <#return percorsoBasePK>
1334</#function>
1335
1336<script>
1337window.isZoomingOut = false;
1338if (typeof swiper === 'undefined') {
1339 let swiper = new Swiper('.swiper', {
1340 slidesPerView: 1,
1341 spaceBetween: 30,
1342 freeMode: true,
1343 navigation: {
1344 nextEl: '.swiper-button-next',
1345 prevEl: '.swiper-button-prev',
1346 },
1347 breakpoints: {
1348 // Quando la larghezza della finestra è inferiore a 768px
1349 768: {
1350 slidesPerView: 3,
1351 }
1352 }
1353 });
1354
1355 // mette l'etichetta all'opera precedente e successiva a quella attuale
1356 let operaCorrente = document.getElementById('operaCorrente');
1357
1358 if (operaCorrente) {
1359 let swiperSlide = operaCorrente.closest('.swiper-slide');
1360
1361 if (swiperSlide) {
1362 let swiperInstance = swiper; // Assicurati di avere l'istanza di Swiper
1363 let slideIndex = Array.from(swiperSlide.parentNode.children).indexOf(swiperSlide);
1364
1365 // Calcola l'indice per centrare l'elemento
1366 let centerIndex = slideIndex - 1; // Poiché visualizzi 3 immagini, sottrai 1 per centrare
1367
1368 // Scorri fino all'elemento centrale
1369 swiperInstance.slideTo(centerIndex);
1370
1371 let previousSlide = swiperSlide.previousElementSibling;
1372 let nextSlide = swiperSlide.nextElementSibling;
1373
1374 if (previousSlide) {
1375 let label = document.createElement('div');
1376 label.className = 'etichettaCarosello';
1377 label.textContent = '${LanguageUtil.get(locale, "operaPrecedente")!}';
1378 previousSlide.appendChild(label);
1379 }
1380
1381 if (nextSlide) {
1382 let label = document.createElement('div');
1383 label.className = 'etichettaCarosello';
1384 label.textContent = '${LanguageUtil.get(locale, "operaSuccessiva")!}';
1385 nextSlide.appendChild(label);
1386 }
1387 }
1388 }
1389
1390let viewer = OpenSeadragon({
1391 id: "openseadragon",
1392 prefixUrl: "https://cdnjs.cloudflare.com/ajax/libs/openseadragon/3.0.0/images/",
1393 tileSources: {
1394 type: 'image',
1395 url: "<#if ImmaginePrincipaleOpera?is_hash && ImmaginePrincipaleOpera.getData??>${ImmaginePrincipaleOpera.getData()}<#else>${ImmaginePrincipaleOpera!}</#if>"
1396 },
1397 showNavigationControl: false,
1398 showNavigator: true,
1399 navigatorPosition: "TOP_RIGHT",
1400 navigatorSizeRatio: 0.3,
1401 defaultZoomLevel: 1,
1402 minZoomLevel: 1,
1403 maxZoomLevel: 10,
1404 visibilityRatio: 1,
1405 homeFillsViewer: true,
1406 constrainDuringPan: true,
1407 autoResize: true,
1408 wrapHorizontal: false,
1409 animationTime: 0.5,
1410 preserveViewport: true,
1411 preserveImageSizeOnResize: false
1412});
1413
1414// Controllo se il dispositivo è mobile per cambiare il comportamento dell'immagine
1415function isMobile() {
1416 return window.innerWidth <= 768;
1417}
1418
1419// Funzione di adattamento per mobile
1420function adjustImageForMobile() {
1421 if (isMobile()) {
1422 const container = document.getElementById('openseadragon');
1423 const viewport = viewer.viewport;
1424
1425 // Imposta l'altezza del container al 100% dell'altezza del viewport
1426 container.style.height = '100vh';
1427
1428 // Calcola il rapporto di aspetto dell'immagine
1429 const image = viewer.world.getItemAt(0);
1430 const imageAspect = image.getContentSize().x / image.getContentSize().y;
1431
1432 // Calcola il rapporto di aspetto del viewport
1433 const viewportAspect = container.clientWidth / container.clientHeight;
1434
1435 // Imposta lo zoom in base al rapporto di aspetto
1436 if (imageAspect > viewportAspect) {
1437 viewport.fitVertically();
1438 } else {
1439 viewport.fitHorizontally();
1440 }
1441 }
1442}
1443
1444// Esegui la funzione all'inizio e quando la finestra cambia dimensione
1445window.addEventListener('load', adjustImageForMobile);
1446window.addEventListener('resize', adjustImageForMobile);
1447
1448// Aggiorna il range dello slider in base al maxZoomLevel
1449document.getElementById('zoomSlider').setAttribute('max', viewer.maxZoomLevel);
1450document.getElementById('openseadragon').addEventListener('wheel', function(event) {
1451 // Se è un pinch (gesture di zoom), non interferire con l'evento
1452 if (event.ctrlKey || event.deltaMode !== WheelEvent.DOM_DELTA_PIXEL) {
1453 return;
1454 }
1455
1456 // Se è uno scroll normale con due dita, previeni il comportamento di default
1457 // e forza lo scroll della pagina solo se non siamo su mobile
1458 if (!isMobile()) {
1459 event.preventDefault();
1460 window.scrollBy({
1461 top: event.deltaY * 3,
1462 behavior: 'auto'
1463 });
1464 }
1465}, { passive: false });
1466// Funzione per lo scambio delle immagini
1467function swapImages(clickedImg) {
1468
1469 let mainImageUrl = viewer.world.getItemAt(0).source.url;
1470 let clickedImageUrl = clickedImg.src;
1471
1472 // Aggiorna OpenSeadragon con la nuova immagine
1473 viewer.open({
1474 type: 'image',
1475 url: clickedImageUrl
1476 });
1477
1478 // Aggiorna l'immagine secondaria con quella che era principale
1479 clickedImg.src = mainImageUrl;
1480
1481 // Aggiorna anche gli attributi alt e data-fileentryid se necessario
1482 let mainAlt = clickedImg.getAttribute('alt');
1483 let mainFileEntryId = clickedImg.getAttribute('data-fileentryid');
1484
1485 // Forza il refresh del viewer
1486 viewer.forceRedraw();
1487}
1488
1489viewer.addHandler('open', function() {
1490 // Adatta l'immagine in base al dispositivo - versione semplificata
1491 setTimeout(function() {
1492 viewer.viewport.goHome(true);
1493 }, 100);
1494
1495 var viewport = viewer.viewport;
1496 var imageSize = viewer.world.getItemAt(0).getContentSize();
1497
1498 // Calcola la nuova posizione centrale
1499 var newCenter = new OpenSeadragon.Point(
1500 0.5, // Mantieni il centro orizzontale
1501 1 / 3 // Sposta il centro verticale a 1/3 dell'altezza
1502 );
1503
1504 // Converti la posizione in coordinate di visualizzazione
1505 var newCenterViewport = viewport.imageToViewportCoordinates(newCenter.x * imageSize.x, newCenter.y * imageSize.y);
1506
1507 // Imposta il nuovo centro
1508 viewport.panTo(newCenterViewport);
1509});
1510
1511// Rimuoviamo tutto il codice DOMContentLoaded precedente
1512document.addEventListener("DOMContentLoaded", function() {
1513 // Implementazione autoplay del primo video quando è visibile
1514 const videoContainer = document.querySelector('.video-container');
1515 if (videoContainer) {
1516 const firstVideoWrapper = videoContainer.querySelector('.video-wrapper');
1517 if (firstVideoWrapper) {
1518 const firstVideo = firstVideoWrapper.querySelector('video');
1519 if (firstVideo) {
1520 // Aggiungiamo attributo muted per consentire l'autoplay nella maggior parte dei browser
1521 firstVideo.muted = true;
1522
1523 // Creiamo un observer per rilevare quando il video diventa visibile
1524 const observer = new IntersectionObserver((entries) => {
1525 entries.forEach(entry => {
1526 if (entry.isIntersecting) {
1527 // Il video è visibile, avvia la riproduzione
1528 firstVideo.play().catch(e => console.log("Autoplay non riuscito:", e));
1529 // Smettiamo di osservare dopo il primo avvio
1530 observer.unobserve(firstVideo);
1531 }
1532 });
1533 }, { threshold: 0.5 }); // Il video deve essere visibile almeno al 50%
1534
1535 // Inizia ad osservare il video
1536 observer.observe(firstVideo);
1537 }
1538 }
1539 }
1540});
1541
1542// Funzione semplificata per toggleAudio
1543function toggleAudio() {
1544 var audio = document.getElementById('myAudio');
1545 var audioButton = document.getElementById('audioGuideToggle');
1546 var audioStatus = document.getElementById('audioStatus');
1547
1548 if (!audio) {
1549 console.error("Elemento audio non trovato");
1550 audioStatus.style.display = 'block';
1551 audioStatus.textContent = 'Audio non disponibile';
1552 setTimeout(function() {
1553 audioStatus.style.display = 'none';
1554 }, 3000);
1555 return;
1556 }
1557
1558 console.log("Toggle audio. Stato attuale:", audio.paused ? "In pausa" : "In riproduzione");
1559
1560 if (audio.paused) {
1561 audioButton.classList.add('play');
1562 audioStatus.style.display = 'block';
1563 audioStatus.textContent = 'in riproduzione';
1564
1565 // Tentiamo di riprodurre l'audio
1566 var playPromise = audio.play();
1567
1568 if (playPromise !== undefined) {
1569 playPromise.then(_ => {
1570 console.log("Riproduzione avviata con successo");
1571 })
1572 .catch(error => {
1573 console.error("Errore nella riproduzione:", error);
1574 audioButton.classList.remove('play');
1575 audioStatus.textContent = 'Errore riproduzione';
1576 });
1577 }
1578 } else {
1579 audioButton.classList.remove('play');
1580 audioStatus.style.display = 'block';
1581 audioStatus.textContent = 'in pausa';
1582 audio.pause();
1583 }
1584}
1585
1586// Assicuriamoci che il pulsante audioGuideToggle abbia l'evento click
1587document.addEventListener('DOMContentLoaded', function() {
1588 var audioGuideToggle = document.getElementById('audioGuideToggle');
1589 if (audioGuideToggle) {
1590 // Rimuoviamo tutti gli event listener precedenti
1591 var newAudioGuideToggle = audioGuideToggle.cloneNode(true);
1592 audioGuideToggle.parentNode.replaceChild(newAudioGuideToggle, audioGuideToggle);
1593
1594 // Aggiungiamo l'onclick direttamente
1595 newAudioGuideToggle.onclick = toggleAudio;
1596 console.log("Event listener aggiunto al pulsante audioGuideToggle");
1597 } else {
1598 console.error("Pulsante audioGuideToggle non trovato");
1599 }
1600});
1601
1602document.getElementById('scrollDownLinkDescrizione').addEventListener('click', function(event) {
1603 event.preventDefault();
1604 let informazioniOpera = document.getElementById('informazioniOpera');
1605 if (informazioniOpera) {
1606 const yOffset = -100; // Offset negativo per scrollare più in basso
1607 const y = informazioniOpera.getBoundingClientRect().top + window.pageYOffset + yOffset;
1608 window.scrollTo({top: y, behavior: 'smooth'});
1609 }
1610});
1611
1612document.getElementById('scrollDownLinkMultimedia')?.addEventListener('click', function(event) {
1613 event.preventDefault();
1614 let multimedia = document.getElementById('multimedia');
1615 if (multimedia) {
1616 const yOffset = -60;
1617 const y = multimedia.getBoundingClientRect().top + window.pageYOffset + yOffset;
1618 window.scrollTo({top: y, behavior: 'smooth'});
1619 }
1620});
1621
1622document.getElementById('scrollDownLinkSchedaTecnica').addEventListener('click', function(event) {
1623 event.preventDefault();
1624 let schedaTecnica = document.getElementById('schedaTecnica');
1625 if (schedaTecnica) {
1626 const yOffset = -40;
1627 const y = schedaTecnica.getBoundingClientRect().top + window.pageYOffset + yOffset;
1628 window.scrollTo({top: y, behavior: 'smooth'});
1629 }
1630});
1631
1632document.getElementById('scrollDownLinkAltreOperePercorso').addEventListener('click', function(event) {
1633 event.preventDefault();
1634 let altreOperePercorso = document.getElementById('altreOperePercorso');
1635 if (altreOperePercorso) {
1636 const yOffset = -100;
1637 const y = altreOperePercorso.getBoundingClientRect().top + window.pageYOffset + yOffset;
1638 window.scrollTo({top: y, behavior: 'smooth'});
1639 }
1640});
1641
1642let isAdjusting = false; // Aggiungi questa variabile globale
1643
1644function checkZoomContain() {
1645 if (isAdjusting) return;
1646
1647 let scale = viewer.viewport.getZoom();
1648
1649 if (scale <= 1) {
1650 if (!isZoomingOut) {
1651 isAdjusting = true;
1652 isZoomingOut = true;
1653 viewer.viewport.goHome(true);
1654 setTimeout(() => {
1655 isAdjusting = false;
1656 }, 100);
1657 }
1658 } else {
1659 isZoomingOut = false;
1660 }
1661}
1662
1663viewer.addHandler('zoom', function(event) {
1664 let zoomLevel = viewer.viewport.getZoom();
1665 document.getElementById('zoomSlider').value = zoomLevel;
1666
1667 // Usa requestAnimationFrame per limitare la frequenza dei controlli
1668 requestAnimationFrame(() => {
1669 checkZoomContain();
1670 });
1671});
1672
1673 // Aggiungi eventi per i pulsanti di zoom
1674 document.getElementById('zoomInButton').addEventListener('click', function() {
1675 viewer.viewport.zoomBy(1.2);
1676 viewer.viewport.applyConstraints();
1677 });
1678
1679document.getElementById('zoomOutButton').addEventListener('click', function() {
1680 let currentZoom = viewer.viewport.getZoom();
1681 if (currentZoom > 1) {
1682 viewer.viewport.zoomBy(0.8);
1683 viewer.viewport.applyConstraints();
1684 }
1685});
1686
1687document.getElementById('zoomSlider').addEventListener('input', function() {
1688 let zoomValue = Math.max(1, parseFloat(this.value));
1689 viewer.viewport.zoomTo(zoomValue);
1690});
1691
1692}
1693
1694function goToVideoLIS() {
1695 // Scorri fino alla sezione multimedia
1696 let multimedia = document.getElementById('multimedia');
1697 if (multimedia) {
1698 const yOffset = -60;
1699 const y = multimedia.getBoundingClientRect().top + window.pageYOffset + yOffset;
1700 window.scrollTo({top: y, behavior: 'smooth'});
1701 }
1702}
1703
1704document.getElementById('openseadragon').addEventListener('click', function(event) {
1705 event.preventDefault();
1706 event.stopPropagation();
1707 return false;
1708});
1709
1710// Aggiungiamo un nuovo event listener per touchstart per prevenire lo scroll su mobile
1711document.getElementById('openseadragon').addEventListener('touchstart', function(event) {
1712 event.preventDefault();
1713 event.stopPropagation();
1714 return false;
1715}, { passive: false });
1716</script>
1717
1718<input type="hidden" id="pkOperaHidden" value="${articleResourcePrimaryKey!}">