Si è verificato un errore nell'elaborarazione del modello.
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: 78%;
700 margin-left: unset;
701 position: relative;
702 display: block;
703 text-align: left;
704 margin: 40px;
705 justify-items: center;
706 }
707
708 .swiper-content {
709 top: 70px;
710 width: 100%;
711 }
712
713 .swiper-content h3 {
714 font-size: 1.4rem;
715 font-family:var(--font-family-montserrat-bold);
716 }
717
718 .swiper-content div {
719 font-size: 1.3rem
720 }
721
722 }
723
724 .secondary-image {
725 transition: transform 0.2s ease;
726 cursor: pointer;
727}
728
729.secondary-image:hover {
730 transform: scale(1.02);
731}
732
733.download {
734 color: white;
735 background: #000000a1;
736 border-radius: 13px;
737 padding: 16px 20px 16px 20px;
738 background: #968d83;
739 top: 25px;
740 position: relative;
741 font-size: 1.6rem;
742 z-index: 1000;
743}
744.pdf-container {
745 width: 100%;
746 margin: 20px 0;
747}
748
749.pdf-page {
750 margin: 10px 0;
751 box-shadow: 0 2px 5px rgba(0,0,0,0.2);
752 border-radius:var(--border-radius);
753}
754
755.pdf-controls {
756 margin: 10px 0;
757 text-align: center;
758}
759
760.pdf-button {
761 background: #2c2c2c;
762 color: white;
763 border: none;
764 padding: 8px 15px;
765 margin: 0 5px;
766 border-radius: 4px;
767 cursor: pointer;
768}
769
770#loadingOverlay {
771 position: absolute;
772 top: 0;
773 left: 0;
774 width: 100%;
775 height: 100%;
776 background-color: rgba(0, 0, 0, 0.5);
777 display: flex;
778 justify-content: center;
779 align-items: center;
780 z-index: 1000;
781}
782
783.loading-text {
784 color: white;
785 font-size: 24px;
786 font-weight: bold;
787 animation: pulse 1.5s infinite;
788}
789
790#download {
791 text-align: center;
792 margin-top:22px;
793}
794
795.download-pdf {
796 background: #968D76;
797 color: white;
798 padding: 12px 24px;
799 border-radius: 10px;
800}
801
802.img-caa {
803 border-radius: 8px;
804 margin-bottom: 20px;
805}
806
807@keyframes pulse {
808 0% { opacity: 0.5; }
809 50% { opacity: 1; }
810 100% { opacity: 0.5; }
811}
812
813.goToVideoLis {
814 background: #070605;
815 opacity: 0.8;
816 z-index: 9;
817 position: absolute;
818 right: 110px;
819 bottom: 50px;
820 display: block;
821 border-radius: 50px;
822 width: auto;
823 min-width: 120px;
824 height: 60px;
825 text-align: center;
826 padding: 10px 20px;
827 box-shadow: -1px 5px 15px #000;
828 border: 2px solid transparent;
829 cursor: pointer;
830 color: white;
831 font-size: 1.2rem;
832 font-weight: bold;
833 display: flex;
834 align-items: center;
835 justify-content: center;
836}
837
838.goToVideoLis:hover {
839 border: 2px solid #ffffff;
840 opacity: 1;
841}
842
843@media screen and (max-width: 768px) {
844 .goToVideoLis {
845 position: absolute;
846 right: 90px;
847 bottom: 115px;
848 font-size: 1rem;
849 min-width: 0;
850 width: max-content;
851 padding: 12px 15px;
852 height: 50px;
853 z-index: 1000;
854 display: block;
855 visibility: visible;
856 }
857
858 .zoomPanel {
859 position: absolute;
860 bottom: 100px;
861 right: 15px;
862 z-index: 1000;
863 display: block;
864 visibility: visible;
865 }
866
867 .audioGuideToggle {
868 position: absolute;
869 bottom: 115px;
870 right: 87px;
871 z-index: 1000;
872 display: block;
873 visibility: visible;
874 }
875}
876</style>
877<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;">
878 <div style="margin:25px var(--margin); z-index: 10; position: absolute;">
879 <a href="#" class="btnBack" onclick="javascript:history.back();">${LanguageUtil.get(locale, "navigazione.indietro")!}</a>
880 </div>
881 <div id="immaginePrincipaleOperaContainer" class="immaginePrincipaleOperaContainer">
882 <div id="openseadragon" style="width: 100%; height: 100vh;"></div>
883 <div class="audioSection">
884 <div id="audioStatus" class="audioStatus"></div>
885 <#if !isTotemMode>
886 <#if targetPK == "53099">
887 <div class="goToVideoLis" id="goToVideoLis" onclick="goToVideoLIS()">
888 Video LIS
889 </div>
890 <#else>
891 <div class="audioGuideToggle" id="audioGuideToggle" onclick="toggleAudio()">
892 <img src="/documents/d/guest/cuffie" alt="${LanguageUtil.get(locale, "opera.immagineprincipale")!}">
893 </div>
894 </#if>
895 </#if>
896 </div>
897 <div class="zoomPanel">
898 <div><button id="zoomInButton">+</button></div>
899 <div><input type="range" id="zoomSlider" min="1" max="4" step="0.1" value="1"></div>
900 <div><button id="zoomOutButton">-</button></div>
901 </div>
902 <div class="infoOperaSuImmaginePrincipale">
903 <p class="titoloOpera">${TitoloOpera.getData()}</p>
904 <p class="nomeArtista">${NomeArtista[0]!}</p>
905 </div>
906 <div style="display: flex; position:absolute;bottom:0; right: 14%;">
907 <a href="#informazioniOpera" id="scrollDownLinkDescrizione" class="scrollDownLink">
908 ${LanguageUtil.get(locale, "tab_opera_descrizione")!}
909 </a>
910
911 <#if hasMedia>
912 <a href="#multimedia" id="scrollDownLinkMultimedia" class="scrollDownLink">
913 ${LanguageUtil.get(locale, "tab_opera_multimedia")!}
914 </a>
915 </#if>
916
917 <a href="#schedaTecnica" id="scrollDownLinkSchedaTecnica" class="scrollDownLink">
918 ${LanguageUtil.get(locale, "tab_opera_scheda")!}
919 </a>
920
921 <a href="#informazioniOpera" id="scrollDownArrow" class="scrollDownLinkArrow">
922 <p>${LanguageUtil.get(locale, "tab_opera_descrizione")!}</p>
923 <svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
924 <path d="M7 10L12 15L17 10" stroke="#e0e0e0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
925 </svg>
926 </a>
927
928 <#if isPercorsoAttivo>
929 <a href="#altreOperePercorso" id="scrollDownLinkAltreOperePercorso" class="scrollDownLink">
930 ${LanguageUtil.get(locale, "tab_opera_altreopere")!}
931 </a>
932 </#if>
933 </div>
934 </div>
935
936 <div id="informazioniOpera" class="informazioniOpera">
937 <div class="column1">
938 <div class="sezArtista">
939 <div style="display: flex;">
940 <#if ImmagineProfiloStr?has_content && ImmagineProfiloJsonObj?has_content>
941 <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>
942 </#if>
943 <div>
944 <p style="font-family:var(--font-family-montserrat-bold); margin-bottom: -8px;">${NomeArtista[0]!}</p>
945 <p>${CategoriaArtista[0]!}</p>
946 </div>
947 </div>
948 <div style="margin-top: 15px;">
949 <p>${DescrizioneBreveArtista[0]!}</p>
950 <div style="margin-top:15px; text-align: right;">
951 <a href="${artistaURL!}">${LanguageUtil.get(locale, "opera.schedaartista")!}</a>
952 </div>
953 </div>
954 </div>
955 </div>
956 <div class="column2">
957 <#if (TitoloOpera.getData())??>
958 <div style="display: flex; justify-content: space-between; align-items: center;">
959 <h1 style="text-transform:uppercase; font-size: 4rem; font-family:var(--font-family-montserrat-regular); margin-bottom: 20px">${TitoloOpera.getData()}</h1>
960 <span style="font-size: 1.2rem; font-family: var(--font-family-montserrat-regular);">
961 Target: ${NomeTarget[0]!}
962 </span>
963 </div>
964 </#if>
965 <div style="margin-top: 15px;">
966 <h2>${LanguageUtil.get(locale, "opera.posizione")!}</h2>
967 <p><#if (PosizioneOpera.getData())??>
968 ${PosizioneOpera.getData()}
969 </#if>
970 </p>
971 </div>
972 <#if DescrizioniOpera?has_content>
973 <#if targetPK?has_content>
974 <#if DescrizioniOpera.getSiblings()?has_content>
975 <#list DescrizioniOpera.getSiblings() as cur_DescrizioniOpera>
976 <#if (cur_DescrizioniOpera.IdTargetDescrizioneOpera.getData())??>
977 <#if targetPK == cur_DescrizioniOpera.IdTargetDescrizioneOpera.getData()>
978 <#if (cur_DescrizioniOpera.DescrizioneOpera.getData())??>
979 ${cur_DescrizioniOpera.DescrizioneOpera.getData()!}
980 </#if>
981 <#if (cur_DescrizioniOpera.AudioguidaOpera.getData())?? && !isTotemMode>
982 <audio style="margin-top: 30px;" id="myAudio" controls>
983 <source src="${cur_DescrizioniOpera.AudioguidaOpera.getData()!}">
984 Your browser does not support the audio element.
985 </audio>
986 </#if>
987 </#if>
988 </#if>
989 </#list>
990 </#if>
991 <#else>
992 <#if (DescrizioniOpera.DescrizioneOpera.getData())??>
993 ${DescrizioniOpera.DescrizioneOpera.getData()}
994 </#if>
995 </#if>
996 </#if>
997 </div>
998
999 <div class="column3">
1000 <#if ImmaginiOpera?has_content>
1001 <#if ImmaginiOpera.getSiblings()?has_content>
1002 <#list ImmaginiOpera.getSiblings() as cur_ImmaginiOpera>
1003 <#if (cur_ImmaginiOpera.ImmagineOpera.getData())?? && cur_ImmaginiOpera.ImmagineOpera.getData() != "">
1004 <#if targetPK == cur_ImmaginiOpera.IdTargetImmagineOpera.getData() || "" == cur_ImmaginiOpera.IdTargetImmagineOpera.getData()>
1005 <img
1006 style="border-radius:var(--border-radius); margin-bottom:6px; cursor: pointer;"
1007 alt="${cur_ImmaginiOpera.ImmagineOpera.getAttribute("alt")}"
1008 data-fileentryid="${cur_ImmaginiOpera.ImmagineOpera.getAttribute("fileEntryId")}"
1009 src="${cur_ImmaginiOpera.ImmagineOpera.getData()}"
1010 onclick="swapImages(this)"
1011 class="secondary-image"
1012 />
1013 </#if>
1014 </#if>
1015 <#if (cur_ImmaginiOpera.DescrizioneImmagineOpera.getData())??>
1016 <#if targetPK == cur_ImmaginiOpera.IdTargetImmagineOpera.getData() || "" == cur_ImmaginiOpera.IdTargetImmagineOpera.getData()>
1017 <p style="margin-bottom:18px">${cur_ImmaginiOpera.DescrizioneImmagineOpera.getData()}</p>
1018 </#if>
1019 </#if>
1020 </#list>
1021 </#if>
1022 </#if>
1023 </div>
1024 </div>
1025</div>
1026
1027<#if MultimediaGroupOpera.getSiblings()?has_content && hasMedia>
1028 <div id="multimedia" class="multimedia" style="padding:40px var(--margin);">
1029 <div>
1030 <h1 style="font-family:var(--font-family-montserrat-regular); padding-top:30px; padding-bottom: 40px; color: white;">MULTIMEDIA</h1>
1031 <div class="multimedia">
1032 <div class="video-container">
1033 <#list MultimediaGroupOpera.getSiblings() as cur_MultimediaGroupOpera>
1034 <#if (cur_MultimediaGroupOpera.IdTargetMultimediaOpera.getData())??>
1035 <#if targetPK == cur_MultimediaGroupOpera.IdTargetMultimediaOpera.getData() || "" == cur_MultimediaGroupOpera.IdTargetMultimediaOpera.getData()>
1036 <#if cur_MultimediaGroupOpera.MultimediaOpera.getData()?has_content>
1037 <div class="video-wrapper">
1038 <video controls>
1039 <source src="${cur_MultimediaGroupOpera.MultimediaOpera.getData()!}">
1040 Your browser does not support the video tag.
1041 </video>
1042 </div>
1043 </#if>
1044 </#if>
1045 </#if>
1046 </#list>
1047 </div>
1048 </div>
1049 </div>
1050 </div>
1051</#if>
1052
1053
1054
1055<div id="schedaTecnica" class="schedaTecnica" style="padding:40px var(--margin);">
1056 <div style="width:100%">
1057 <h1 style="font-family:var(--font-family-montserrat-regular); padding-top:30px; padding-bottom: 40px;">${LanguageUtil.get(locale, "opera.schedatecnica")!}</h1>
1058 <div class="schedaTecnica" >
1059 <#if (ImmaginePrincipaleOpera)??>
1060 <div class="column1">
1061 <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>" />
1062 </div>
1063 </#if>
1064 <div class="column2">
1065 <#if (NumeroInventarioOpera.getData())??>
1066 <div class="etichetta">
1067 ${LanguageUtil.get(locale, "opera.numinventario")!}
1068 </div>
1069 <div class="valore">
1070 ${NumeroInventarioOpera.getData()!}
1071 </div>
1072 </#if>
1073 <#if (TitoloOpera.getData())??>
1074 <div class="etichetta">
1075 ${LanguageUtil.get(locale, "opera.titoloopera")!}
1076 </div>
1077 <div class="valore">
1078 ${TitoloOpera.getData()!}
1079 </div>
1080 </#if>
1081 <#if (NomeArtista[0])??>
1082 <div class="etichetta">
1083 ${LanguageUtil.get(locale, "opera.autore")!}
1084 </div>
1085 <div class="valore">
1086 ${NomeArtista[0]!}
1087 </div>
1088 </#if>
1089 <#if (PeriodoOpera.getData())??>
1090 <div class="etichetta">
1091 ${LanguageUtil.get(locale, "opera.periodo")!}
1092 </div>
1093 <div class="valore">
1094 ${PeriodoOpera.getData()!}
1095 </div>
1096 </#if>
1097 <#if (TecnicaOpera.getData())??>
1098 <div class="etichetta">
1099 ${LanguageUtil.get(locale, "opera.tecnica")!}
1100 </div>
1101 <div class="valore">
1102 ${TecnicaOpera.getData()!}
1103 </div>
1104 </#if>
1105 <#if (SupportoOpera.getData())??>
1106 <div class="etichetta">
1107 ${LanguageUtil.get(locale, "opera.supporto")!}
1108 </div>
1109 <div class="valore">
1110 ${SupportoOpera.getData()!}
1111 </div>
1112 </#if>
1113 <#if (DimensioniOpera.getData())??>
1114 <div class="etichetta">
1115 ${LanguageUtil.get(locale, "opera.dimensioni")!}
1116 </div>
1117 <div class="valore">
1118 ${DimensioniOpera.getData()!}
1119 </div>
1120 </#if>
1121 <#if (ProvenienzaOpera.getData())??>
1122 <div class="etichetta">
1123 ${LanguageUtil.get(locale, "opera.provenienza")!}
1124 </div>
1125 <div class="valore">
1126 ${ProvenienzaOpera.getData()!}
1127 </div>
1128 </#if>
1129 </div>
1130 </div>
1131 </div>
1132</div>
1133
1134 <#if isPercorsoAttivo>
1135 <div id="altreOperePercorso" class="altreOperePercorso" style="font-family:var(--font-family-montserrat-thin); color: var(--text-color-light); line-height: 1.7;">
1136 <h1 style="font-family:var(--font-family-montserrat-regular);">${LanguageUtil.get(locale, "percorso.altreopere")!}</h1>
1137 <div class="altreOperePercorso">
1138 <div class="swiper mySwiper">
1139 <div class="swiper-wrapper">
1140 <#if webcontentsPercorso?is_enumerable>
1141 <#list webcontentsPercorso as webcontent>
1142 <#assign resourcePrimKeyWebContent = webcontent.resourcePrimKey/>
1143 <#assign webcontentArticlePercorso = JournalArticleLocalService.getLatestArticle(resourcePrimKeyWebContent?number)>
1144 <#if isOpera(webcontentArticlePercorso)>
1145 <#assign TitoloOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "TitoloOpera")>
1146 <#assign ImmagineOperaPercorso = extractImageJson(language, webcontentArticlePercorso.getContent()?string, targetPK)>
1147
1148 <#assign ImmagineOperaPercorsoJsonObj = jsonFactoryUtil.createJSONObject(ImmagineOperaPercorso)>
1149 <#assign articleOperaPercorsoURL = friendlyURL?keep_before_last("/") + "/web/guest/opere/-/asset_publisher/khcq/content/" + webcontentArticlePercorso.getUrlTitle() + "?percorsoPK="+percorsoPK + "&targetPK=" + targetPK>
1150 <#assign TecnicaOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "TecnicaOpera")>
1151 <#assign DimensioniOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "DimensioniOpera")>
1152 <#assign PeriodoOperaPercorso = extractContents(language, webcontentArticlePercorso.getContent()?xml, "PeriodoOpera")>
1153
1154 <#assign expandoArtistaOperaCorrelata = webcontentArticlePercorso.getExpandoBridge().getAttribute("Artista")>
1155 <#assign resourcePrimKeyArtistaOperaCorrelata = extractFieldFromExpando(expandoArtistaOperaCorrelata, "resourcePrimKeyArtista")/>
1156 <#assign articleArtistaOperaCorrelata = JournalArticleLocalService.getLatestArticle(resourcePrimKeyArtistaOperaCorrelata?number)>
1157 <#assign NomeArtistaOperaCorrelata = extractContents(language, articleArtistaOperaCorrelata.getContent()?xml, "NomeArtista")>
1158 <div class="swiper-slide" data-swiper-parallax="-23%">
1159 <a href="${articleOperaPercorsoURL!}#immaginePrincipaleOperaContainer">
1160 <img alt="${TitoloOperaPercorso[0]!}" src="<#if ImmagineOperaPercorsoJsonObj?? && (ImmagineOperaPercorsoJsonObj.url)?? && ImmagineOperaPercorsoJsonObj.url != "">${ImmagineOperaPercorsoJsonObj.url!}</#if>"></img>
1161 </a>
1162 <div class="swiper-content">
1163 <h3>${TitoloOperaPercorso[0]!}</h3>
1164 <div>${LanguageUtil.get(locale, "opera.artista")!}: ${NomeArtistaOperaCorrelata[0]!}</div>
1165 <div>${LanguageUtil.get(locale, "opera.tecnica.corta")!}: ${TecnicaOperaPercorso[0]!}</div>
1166 <div>${LanguageUtil.get(locale, "opera.dimensioni.corta")!}: ${DimensioniOperaPercorso[0]!}</div>
1167 <div>${LanguageUtil.get(locale, "opera.periodo.corta")!}: ${PeriodoOperaPercorso[0]!}</div>
1168 </div>
1169 <#if resourcePrimKeyWebContent?number == articleResourcePrimaryKey?number>
1170 <div id="operaCorrente" class="etichettaCarosello">${LanguageUtil.get(locale, "operaCorrente")!}</div>
1171 </#if>
1172 </div>
1173 </#if>
1174 </#list>
1175 </#if>
1176 </div>
1177 </div>
1178 <div class="swiper-button-next"></div>
1179 <div class="swiper-button-prev"></div>
1180 </div>
1181 </div>
1182 </#if>
1183
1184 <div id="friendlyURL">
1185 ${friendlyURL}
1186 </div>
1187
1188
1189</div>
1190
1191<#assign journalArticleResourceLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleResourceLocalService") />
1192<#assign JournalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") />
1193<#assign journalArticleId = .vars['reserved-article-id'].data />
1194<#assign articleResourcePrimaryKey = journalArticleResourceLocalService.getArticleResourcePrimKey(themeDisplay.getScopeGroupId(), journalArticleId) />
1195
1196<#function extractFieldFromExpando expando fieldName>
1197 <#attempt>
1198 <#if expando?has_content>
1199 <#assign jsonExpando = expando?eval>
1200 <#return jsonExpando[fieldName]>
1201 <#else>
1202 <#return "">
1203 </#if>
1204 <#recover>
1205 <#return "">
1206 </#attempt>
1207</#function>
1208
1209<#-- Questa funzione restituisce un array di dynamic-element relativo al field-reference specificato -->
1210<#function extractContents language, xml, fieldReference, start=0>
1211 <#-- Cercare il tag di apertura del dynamic-element con il field-reference specificato -->
1212 <#assign startPos = xml?index_of(fieldReference, start)>
1213 <#if startPos != -1>
1214 <#-- Trovare l'inizio del contenuto nella lingua corretta-->
1215 <#assign startDynamic = xml?index_of(language, startPos)>
1216 <#if startDynamic != -1>
1217 <#assign startContent = startDynamic + (language?length)>
1218
1219 <#-- Trovare gli indici di inizio e fine del CDATA -->
1220 <#assign startCdata = xml?index_of("CDATA[", startContent) + "CDATA["?length>
1221 <#assign endCdata = xml?index_of("]]", startCdata)>
1222
1223 <#-- Estrai il contenuto CDATA -->
1224 <#assign content = xml?substring(startCdata, endCdata)>
1225 <#-- Controllo la presenza di altri valori di fieldReference -->
1226 <#assign nextIndex = xml?index_of(fieldReference, endCdata)>
1227 <#if nextIndex != -1>
1228 <#-- Continua la ricerca in modo ricorsivo -->
1229 <#return [content] + extractContents(language, xml, fieldReference, nextIndex)>
1230 <#else>
1231 <#return [content]>
1232 </#if>
1233 <#else>
1234 <#return []>
1235 </#if>
1236 <#else>
1237 <#return []>
1238 </#if>
1239</#function>
1240
1241<#function extractImageJson language, xml, targetPK, start=0>
1242 <#assign result = "">
1243 <#assign foundExactMatch = false>
1244 <#assign foundEmptyTarget = "">
1245 <#assign scanStart = start>
1246
1247 <#-- Primo passaggio: Scansiona tutto per trovare un match esatto -->
1248 <#list 0..100 as iteration> <#-- Limite di sicurezza per evitare loop infiniti -->
1249 <#assign fieldsetStart = xml?index_of("ImmaginiPrincipaliOpera", scanStart)>
1250 <#if fieldsetStart == -1>
1251 <#break>
1252 </#if>
1253
1254 <#assign targetStart = xml?index_of("IdTargetImmaginePrincipaleOpera", fieldsetStart)>
1255 <#assign idTarget = "">
1256
1257 <#if targetStart != -1>
1258 <#assign targetContentStart = xml?index_of("CDATA[", targetStart) + "CDATA["?length>
1259 <#assign targetContentEnd = xml?index_of("]]", targetContentStart)>
1260
1261 <#if targetContentStart != -1 && targetContentEnd != -1>
1262 <#assign idTarget = xml?substring(targetContentStart, targetContentEnd)?trim>
1263 </#if>
1264 </#if>
1265
1266 <#if idTarget == targetPK>
1267 <#assign foundExactMatch = true>
1268 <#break>
1269 </#if>
1270
1271 <#if (idTarget?is_string && idTarget == "") || (idTarget?is_number && idTarget == 0)>
1272 <#if (foundEmptyTarget?is_string && foundEmptyTarget == "") || (foundEmptyTarget?is_number && foundEmptyTarget == 0)>
1273 <#assign finalStart = fieldsetStart>
1274 </#if>
1275 </#if>
1276
1277 <#assign scanStart = xml?index_of("field-reference=\"ImmaginiPrincipaliOpera\"", fieldsetStart + 1)>
1278 <#if scanStart == -1>
1279 <#break>
1280 </#if>
1281 </#list>
1282
1283 <#-- Secondo passaggio: Se ha trovato un match esatto, usa quello. Altrimenti usa il primo con target vuoto. -->
1284 <#assign finalStart = fieldsetStart>
1285 <#if !foundExactMatch && foundEmptyTarget?string != "">
1286 <#assign finalStart = foundEmptyTarget>
1287 </#if>
1288
1289 <#if finalStart != -1>
1290 <#assign fieldsetEnd = xml?index_of("</dynamic-element>", finalStart) + "</dynamic-element>"?length>
1291 <#assign fieldsetXml = xml?substring(finalStart, fieldsetEnd)>
1292
1293 <#assign imageStart = fieldsetXml?index_of("field-reference=\"ImmaginePrincipaleOpera\"")>
1294
1295 <#if imageStart != -1>
1296 <#assign imageContentStart = fieldsetXml?index_of("CDATA[", imageStart) + "CDATA["?length>
1297 <#assign imageContentEnd = fieldsetXml?index_of("]]", imageContentStart)>
1298
1299 <#if imageContentStart != -1 && imageContentEnd != -1>
1300 <#assign result = fieldsetXml?substring(imageContentStart, imageContentEnd)?trim>
1301 </#if>
1302 </#if>
1303 </#if>
1304
1305 <#return result>
1306</#function>
1307
1308<#function isOpera webcontentArticle>
1309 <#assign webContentXML = webcontentArticle.getContent()?xml>
1310 <#return webContentXML?index_of("TitoloOpera") != -1>
1311</#function>
1312
1313<#function getPercorsoBasePK()>
1314 <#assign percorsoBasePK = "">
1315 <#assign articles = JournalArticleLocalService.getArticles()>
1316 <#assign ddmStructureLocalService = serviceLocator.findService("com.liferay.dynamic.data.mapping.service.DDMStructureLocalService")>
1317 <#-- Itera sugli articoli e filtra quelli con la struttura Percorso -->
1318 <#list articles as article>
1319 <#-- Ottieni l'ID della struttura -->
1320 <#assign ddmStructureId = article.getDDMStructureId()>
1321
1322 <#-- Ottieni la struttura utilizzando l'ID -->
1323 <#assign ddmStructure = ddmStructureLocalService.getDDMStructure(ddmStructureId)>
1324
1325 <#-- Ottieni il nome della struttura -->
1326 <#assign structureName = ddmStructure.getName(locale)>
1327 <#if structureName == "Percorso">
1328 <#assign PercorsoBase = extractContents(language, article.getContent()?xml, "PercorsoBase")>
1329 <#if (PercorsoBase[0]?has_content && "true"==PercorsoBase[0])>
1330 <#assign percorsoBasePK = article.getResourcePrimKey()>
1331 </#if>
1332 </#if>
1333 </#list>
1334 <#return percorsoBasePK>
1335</#function>
1336
1337<script>
1338window.isZoomingOut = false;
1339if (typeof swiper === 'undefined') {
1340 let swiper = new Swiper('.swiper', {
1341 slidesPerView: 1,
1342 spaceBetween: 30,
1343 freeMode: true,
1344 navigation: {
1345 nextEl: '.swiper-button-next',
1346 prevEl: '.swiper-button-prev',
1347 },
1348 breakpoints: {
1349 // Quando la larghezza della finestra è inferiore a 768px
1350 768: {
1351 slidesPerView: 3,
1352 }
1353 }
1354 });
1355
1356 // mette l'etichetta all'opera precedente e successiva a quella attuale
1357 let operaCorrente = document.getElementById('operaCorrente');
1358
1359 if (operaCorrente) {
1360 let swiperSlide = operaCorrente.closest('.swiper-slide');
1361
1362 if (swiperSlide) {
1363 let swiperInstance = swiper; // Assicurati di avere l'istanza di Swiper
1364 let slideIndex = Array.from(swiperSlide.parentNode.children).indexOf(swiperSlide);
1365
1366 // Calcola l'indice per centrare l'elemento
1367 let centerIndex = slideIndex - 1; // Poiché visualizzi 3 immagini, sottrai 1 per centrare
1368
1369 // Scorri fino all'elemento centrale
1370 swiperInstance.slideTo(centerIndex);
1371
1372 let previousSlide = swiperSlide.previousElementSibling;
1373 let nextSlide = swiperSlide.nextElementSibling;
1374
1375 if (previousSlide) {
1376 let label = document.createElement('div');
1377 label.className = 'etichettaCarosello';
1378 label.textContent = '${LanguageUtil.get(locale, "operaPrecedente")!}';
1379 previousSlide.appendChild(label);
1380 }
1381
1382 if (nextSlide) {
1383 let label = document.createElement('div');
1384 label.className = 'etichettaCarosello';
1385 label.textContent = '${LanguageUtil.get(locale, "operaSuccessiva")!}';
1386 nextSlide.appendChild(label);
1387 }
1388 }
1389 }
1390
1391let viewer = OpenSeadragon({
1392 id: "openseadragon",
1393 prefixUrl: "https://cdnjs.cloudflare.com/ajax/libs/openseadragon/3.0.0/images/",
1394 tileSources: {
1395 type: 'image',
1396 url: "<#if ImmaginePrincipaleOpera?is_hash && ImmaginePrincipaleOpera.getData??>${ImmaginePrincipaleOpera.getData()}<#else>${ImmaginePrincipaleOpera!}</#if>"
1397 },
1398 showNavigationControl: false,
1399 showNavigator: true,
1400 navigatorPosition: "TOP_RIGHT",
1401 navigatorSizeRatio: 0.3,
1402 defaultZoomLevel: 1,
1403 minZoomLevel: 1,
1404 maxZoomLevel: 10,
1405 visibilityRatio: 1,
1406 homeFillsViewer: true,
1407 constrainDuringPan: true,
1408 autoResize: true,
1409 wrapHorizontal: false,
1410 animationTime: 0.5,
1411 preserveViewport: true,
1412 preserveImageSizeOnResize: false
1413});
1414
1415// Controllo se il dispositivo è mobile per cambiare il comportamento dell'immagine
1416function isMobile() {
1417 return window.innerWidth <= 768;
1418}
1419
1420// Funzione di adattamento per mobile
1421function adjustImageForMobile() {
1422 if (isMobile()) {
1423 const container = document.getElementById('openseadragon');
1424 const viewport = viewer.viewport;
1425
1426 // Imposta l'altezza del container al 100% dell'altezza del viewport
1427 container.style.height = '100vh';
1428
1429 // Calcola il rapporto di aspetto dell'immagine
1430 const image = viewer.world.getItemAt(0);
1431 const imageAspect = image.getContentSize().x / image.getContentSize().y;
1432
1433 // Calcola il rapporto di aspetto del viewport
1434 const viewportAspect = container.clientWidth / container.clientHeight;
1435
1436 // Imposta lo zoom in base al rapporto di aspetto
1437 if (imageAspect > viewportAspect) {
1438 viewport.fitVertically();
1439 } else {
1440 viewport.fitHorizontally();
1441 }
1442 }
1443}
1444
1445// Esegui la funzione all'inizio e quando la finestra cambia dimensione
1446window.addEventListener('load', adjustImageForMobile);
1447window.addEventListener('resize', adjustImageForMobile);
1448
1449// Aggiorna il range dello slider in base al maxZoomLevel
1450document.getElementById('zoomSlider').setAttribute('max', viewer.maxZoomLevel);
1451document.getElementById('openseadragon').addEventListener('wheel', function(event) {
1452 // Se è un pinch (gesture di zoom), non interferire con l'evento
1453 if (event.ctrlKey || event.deltaMode !== WheelEvent.DOM_DELTA_PIXEL) {
1454 return;
1455 }
1456
1457 // Se è uno scroll normale con due dita, previeni il comportamento di default
1458 // e forza lo scroll della pagina solo se non siamo su mobile
1459 if (!isMobile()) {
1460 event.preventDefault();
1461 window.scrollBy({
1462 top: event.deltaY * 3,
1463 behavior: 'auto'
1464 });
1465 }
1466}, { passive: false });
1467// Funzione per lo scambio delle immagini
1468function swapImages(clickedImg) {
1469
1470 let mainImageUrl = viewer.world.getItemAt(0).source.url;
1471 let clickedImageUrl = clickedImg.src;
1472
1473 // Aggiorna OpenSeadragon con la nuova immagine
1474 viewer.open({
1475 type: 'image',
1476 url: clickedImageUrl
1477 });
1478
1479 // Aggiorna l'immagine secondaria con quella che era principale
1480 clickedImg.src = mainImageUrl;
1481
1482 // Aggiorna anche gli attributi alt e data-fileentryid se necessario
1483 let mainAlt = clickedImg.getAttribute('alt');
1484 let mainFileEntryId = clickedImg.getAttribute('data-fileentryid');
1485
1486 // Forza il refresh del viewer
1487 viewer.forceRedraw();
1488}
1489
1490viewer.addHandler('open', function() {
1491 // Adatta l'immagine in base al dispositivo - versione semplificata
1492 setTimeout(function() {
1493 viewer.viewport.goHome(true);
1494 }, 100);
1495
1496 var viewport = viewer.viewport;
1497 var imageSize = viewer.world.getItemAt(0).getContentSize();
1498
1499 // Calcola la nuova posizione centrale
1500 var newCenter = new OpenSeadragon.Point(
1501 0.5, // Mantieni il centro orizzontale
1502 1 / 3 // Sposta il centro verticale a 1/3 dell'altezza
1503 );
1504
1505 // Converti la posizione in coordinate di visualizzazione
1506 var newCenterViewport = viewport.imageToViewportCoordinates(newCenter.x * imageSize.x, newCenter.y * imageSize.y);
1507
1508 // Imposta il nuovo centro
1509 viewport.panTo(newCenterViewport);
1510});
1511
1512// Rimuoviamo tutto il codice DOMContentLoaded precedente
1513document.addEventListener("DOMContentLoaded", function() {
1514 // Implementazione autoplay del primo video quando è visibile
1515 const videoContainer = document.querySelector('.video-container');
1516 if (videoContainer) {
1517 const firstVideoWrapper = videoContainer.querySelector('.video-wrapper');
1518 if (firstVideoWrapper) {
1519 const firstVideo = firstVideoWrapper.querySelector('video');
1520 if (firstVideo) {
1521 // Aggiungiamo attributo muted per consentire l'autoplay nella maggior parte dei browser
1522 firstVideo.muted = true;
1523
1524 // Creiamo un observer per rilevare quando il video diventa visibile
1525 const observer = new IntersectionObserver((entries) => {
1526 entries.forEach(entry => {
1527 if (entry.isIntersecting) {
1528 // Il video è visibile, avvia la riproduzione
1529 firstVideo.play().catch(e => console.log("Autoplay non riuscito:", e));
1530 // Smettiamo di osservare dopo il primo avvio
1531 observer.unobserve(firstVideo);
1532 }
1533 });
1534 }, { threshold: 0.5 }); // Il video deve essere visibile almeno al 50%
1535
1536 // Inizia ad osservare il video
1537 observer.observe(firstVideo);
1538 }
1539 }
1540 }
1541});
1542
1543// Funzione semplificata per toggleAudio
1544function toggleAudio() {
1545 var audio = document.getElementById('myAudio');
1546 var audioButton = document.getElementById('audioGuideToggle');
1547 var audioStatus = document.getElementById('audioStatus');
1548
1549 if (!audio) {
1550 console.error("Elemento audio non trovato");
1551 audioStatus.style.display = 'block';
1552 audioStatus.textContent = 'Audio non disponibile';
1553 setTimeout(function() {
1554 audioStatus.style.display = 'none';
1555 }, 3000);
1556 return;
1557 }
1558
1559 console.log("Toggle audio. Stato attuale:", audio.paused ? "In pausa" : "In riproduzione");
1560
1561 if (audio.paused) {
1562 audioButton.classList.add('play');
1563 audioStatus.style.display = 'block';
1564 audioStatus.textContent = 'in riproduzione';
1565
1566 // Tentiamo di riprodurre l'audio
1567 var playPromise = audio.play();
1568
1569 if (playPromise !== undefined) {
1570 playPromise.then(_ => {
1571 console.log("Riproduzione avviata con successo");
1572 })
1573 .catch(error => {
1574 console.error("Errore nella riproduzione:", error);
1575 audioButton.classList.remove('play');
1576 audioStatus.textContent = 'Errore riproduzione';
1577 });
1578 }
1579 } else {
1580 audioButton.classList.remove('play');
1581 audioStatus.style.display = 'block';
1582 audioStatus.textContent = 'in pausa';
1583 audio.pause();
1584 }
1585}
1586
1587// Assicuriamoci che il pulsante audioGuideToggle abbia l'evento click
1588document.addEventListener('DOMContentLoaded', function() {
1589 var audioGuideToggle = document.getElementById('audioGuideToggle');
1590 if (audioGuideToggle) {
1591 // Rimuoviamo tutti gli event listener precedenti
1592 var newAudioGuideToggle = audioGuideToggle.cloneNode(true);
1593 audioGuideToggle.parentNode.replaceChild(newAudioGuideToggle, audioGuideToggle);
1594
1595 // Aggiungiamo l'onclick direttamente
1596 newAudioGuideToggle.onclick = toggleAudio;
1597 console.log("Event listener aggiunto al pulsante audioGuideToggle");
1598 } else {
1599 console.error("Pulsante audioGuideToggle non trovato");
1600 }
1601});
1602
1603document.getElementById('scrollDownLinkDescrizione').addEventListener('click', function(event) {
1604 event.preventDefault();
1605 let informazioniOpera = document.getElementById('informazioniOpera');
1606 if (informazioniOpera) {
1607 const yOffset = -100; // Offset negativo per scrollare più in basso
1608 const y = informazioniOpera.getBoundingClientRect().top + window.pageYOffset + yOffset;
1609 window.scrollTo({top: y, behavior: 'smooth'});
1610 }
1611});
1612
1613document.getElementById('scrollDownLinkMultimedia')?.addEventListener('click', function(event) {
1614 event.preventDefault();
1615 let multimedia = document.getElementById('multimedia');
1616 if (multimedia) {
1617 const yOffset = -60;
1618 const y = multimedia.getBoundingClientRect().top + window.pageYOffset + yOffset;
1619 window.scrollTo({top: y, behavior: 'smooth'});
1620 }
1621});
1622
1623document.getElementById('scrollDownLinkSchedaTecnica').addEventListener('click', function(event) {
1624 event.preventDefault();
1625 let schedaTecnica = document.getElementById('schedaTecnica');
1626 if (schedaTecnica) {
1627 const yOffset = -40;
1628 const y = schedaTecnica.getBoundingClientRect().top + window.pageYOffset + yOffset;
1629 window.scrollTo({top: y, behavior: 'smooth'});
1630 }
1631});
1632
1633document.getElementById('scrollDownLinkAltreOperePercorso').addEventListener('click', function(event) {
1634 event.preventDefault();
1635 let altreOperePercorso = document.getElementById('altreOperePercorso');
1636 if (altreOperePercorso) {
1637 const yOffset = -100;
1638 const y = altreOperePercorso.getBoundingClientRect().top + window.pageYOffset + yOffset;
1639 window.scrollTo({top: y, behavior: 'smooth'});
1640 }
1641});
1642
1643let isAdjusting = false; // Aggiungi questa variabile globale
1644
1645function checkZoomContain() {
1646 if (isAdjusting) return;
1647
1648 let scale = viewer.viewport.getZoom();
1649
1650 if (scale <= 1) {
1651 if (!isZoomingOut) {
1652 isAdjusting = true;
1653 isZoomingOut = true;
1654 viewer.viewport.goHome(true);
1655 setTimeout(() => {
1656 isAdjusting = false;
1657 }, 100);
1658 }
1659 } else {
1660 isZoomingOut = false;
1661 }
1662}
1663
1664viewer.addHandler('zoom', function(event) {
1665 let zoomLevel = viewer.viewport.getZoom();
1666 document.getElementById('zoomSlider').value = zoomLevel;
1667
1668 // Usa requestAnimationFrame per limitare la frequenza dei controlli
1669 requestAnimationFrame(() => {
1670 checkZoomContain();
1671 });
1672});
1673
1674 // Aggiungi eventi per i pulsanti di zoom
1675 document.getElementById('zoomInButton').addEventListener('click', function() {
1676 viewer.viewport.zoomBy(1.2);
1677 viewer.viewport.applyConstraints();
1678 });
1679
1680document.getElementById('zoomOutButton').addEventListener('click', function() {
1681 let currentZoom = viewer.viewport.getZoom();
1682 if (currentZoom > 1) {
1683 viewer.viewport.zoomBy(0.8);
1684 viewer.viewport.applyConstraints();
1685 }
1686});
1687
1688document.getElementById('zoomSlider').addEventListener('input', function() {
1689 let zoomValue = Math.max(1, parseFloat(this.value));
1690 viewer.viewport.zoomTo(zoomValue);
1691});
1692
1693}
1694
1695function goToVideoLIS() {
1696 // Scorri fino alla sezione multimedia
1697 let multimedia = document.getElementById('multimedia');
1698 if (multimedia) {
1699 const yOffset = -60;
1700 const y = multimedia.getBoundingClientRect().top + window.pageYOffset + yOffset;
1701 window.scrollTo({top: y, behavior: 'smooth'});
1702 }
1703}
1704
1705document.getElementById('openseadragon').addEventListener('click', function(event) {
1706 event.preventDefault();
1707 event.stopPropagation();
1708 return false;
1709});
1710
1711// Aggiungiamo un nuovo event listener per touchstart per prevenire lo scroll su mobile
1712document.getElementById('openseadragon').addEventListener('touchstart', function(event) {
1713 event.preventDefault();
1714 event.stopPropagation();
1715 return false;
1716}, { passive: false });
1717</script>
1718
1719<input type="hidden" id="pkOperaHidden" value="${articleResourcePrimaryKey!}">