Visita

  • Orari e prezzi
  • Pianifica la tua visita
  • Visita di gruppo
  • Visita accessibile
  • Raccomandazioni
  • Come arrivare

Collezione

  • Esplora la collezione. ( Tutto il museo )
  • ES. Pittura del Bailo nel 1900
  • Stampe, disegni e fotografie
  • Scultura e arti decorative
  • Cornici
  • Museo esterno
  • La prospettiva femminile

Cosa c'è

  • Mostre
  • Video
  • Audio
  • Notizie

Imparare

  • Istruzione nel Museo
  • Bollettino del Museo
  • Storia e architettura del museo
enit [beta]

Pisana ( English )

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("&quot;", "\"", "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!}">