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]

Venus of the Ports

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: 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!}">