1<!DOCTYPE html> 2<html lang="it"> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>Area Metropolitana di Milano â Scheda Uccelli</title> 7 <link rel="stylesheet" href="styles.css?v=3"> 8
8<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/heic2any.min.js"></script>
8 9</head> 10<body> 11 <div class="page"> 12 13<div class="card"> 14 <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;"> 15 <button type="button" onclick="if(confirm('Vuoi davvero uscire? I dati inseriti andranno persi.')) window.location.href='../index.html'" style="background: transparent; border: none; cursor: pointer; padding: 0;" aria-label="Torna indietro"> 16 <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#12458c" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 17 <line x1="19" y1="12" x2="5" y2="12"></line> 18 <polyline points="12 19 5 12 12 5"></polyline> 19 </svg> 20 </button> 21 <h1 style="margin: 0; font-size: 24px; text-align: center; flex-grow: 1;">Area Metropolitana di Milano</h1> 22 <div style="width: 28px;"></div> 23 </div> 24 <div class="sub">Scheda di identificazione Uccelli</div> 25 26 <form id="bird-form" 27 action="https://eu-submit.jotform.com/submit/260210470291344" 28 method="POST" 29 enctype="multipart/form-data" 30 accept-charset="utf-8"> 31 <!-- FIX UID INJECTION --> 32 <input type="hidden" name="uid" id="uid_field"> 33
33<script> 34 try { 35 const params = new URLSearchParams(window.location.search); 36 const uid = params.get('uid'); 37 if (uid) { 38 const uidF = document.getElementById('uid_field'); 39 if(uidF) uidF.value = uid; 40 const webF = document.querySelector('input[name="website"]'); 41 if(webF) webF.value = uid; 42 } 43 } catch(e) {} 44 </script>
44 45 46 <input type="hidden" name="formID" value="260210470291344"> 47 <input type="hidden" name="simple_spc" value="260210470291344"> 48 <input type="text" name="website" value="" style="display:none"> 49 <!-- ISTRUZIONI --> 50 <hr> 51 <div class="row"><strong>Dati del rilevatore</strong></div> 52 53 <div class="row"> 54 <label for="nomeRilevatore">Iniziale Nome e Cognome <span style="color:#dc2626">*</span></label> 55 <input type="text" id="nomeRilevatore" name="q168_nomeCognome" placeholder="Es. M.Rossi" required pattern="^[A-Za-zÃ-ÃÃ-öø-ÿ]\.\s?[A-Za-zÃ-ÃÃ-öø-ÿ][A-Za-zÃ-ÃÃ-öø-ÿ\' -]*$" title="Usa il formato M.Rossi"> 56 <div class="help">Campo obbligatorio per la certificazione del progetto didattico. Per tutelare la privacy, inserire esclusivamente l'iniziale del nome seguita dal cognome, nel formato M.Rossi (non utilizzare nomi completi).</div> 57 </div> 58 59 <div class="row"> 60 <label for="email">E-mail di riferimento <span style="color:#dc2626">*</span></label> 61 <input type="email" id="email" name="q128_email" placeholder="Inserisci e-mail" required> 62 <div class="help">Usa unâe-mail scolastica o privata. Verrà utilizzata solo per comunicazioni scientifiche.</div> 63 </div> 64 65 <div class="row"> 66 <label for="istitutoScolastico">Istituto scolastico <span style="font-weight: normal; color: #666;">(facoltativo)</span></label> 67 <input type="text" id="istitutoScolastico" name="q_istituto_scolastico" placeholder="Es. Liceo Scientifico Leonardo da Vinci..." list="scuoleList"> 68 <datalist id="scuoleList"></datalist> 69 <div class="help">Inizia a digitare per cercare la tua scuola nella Città Metropolitana di Milano.</div> 70 </div> 71 72 <div class="row"> 73 <label style="font-weight:700;">Dichiarazione età </label> 74 <label style="font-weight:400; display:flex; align-items:flex-start; gap:8px;"> 75 <input type="checkbox" id="ageGate14"> 76 <span>Dichiaro di avere almeno 14 anni oppure di avere lâautorizzazione di un genitore/tutore.</span> 77 </label> 78 <div class="help">La scelta viene salvata solo su questo dispositivo.</div> 79 </div> 80 81 <div class="row"> 82 <button type="button" class="btn" style="background:#1d4ed8" id="clearSavedUserData">Dimentica dati salvati su questo dispositivo</button> 83 <div class="help">Nome ed e-mail vengono salvati solo su questo dispositivo. Puoi cancellarli in qualsiasi momento.</div> 84 </div> 85 86 <div class="row"> 87 <div class="help">ð¦ <strong style="font-size:16px">Come compilare:</strong> Carica una o due foto nitide dell'uccello.</div> 88 </div> 89 90 <!-- FILE UPLOAD --> 91 <div class="row"> 92 <label for="birdImage"> 93 Carica Foto <span style="color:#dc2626">*</span> 94 <button type="button" class="info-btn" onclick="toggleInfo('info-foto')" aria-label="Informazioni caricamento">i</button> 95 </label> 96 97 <div id="info-foto" class="info-box"> 98 ð¸ <strong>Suggerimento:</strong> Se carichi la foto originale scattata con lo smartphone (non inoltrata da WhatsApp), l'app leggerà automaticamente la <strong>data</strong> e la <strong>posizione GPS</strong>, compilando i campi per te! 99 </div> 100 101 <input type="file" id="birdImage" name="q999_upload[]" accept="image/*" multiple required> 102 <div class="help">Carica fino a <strong>2 foto</strong> in formato <strong>JPG</strong> o <strong>PNG</strong>.</div> 103 104 <div id="exifWarningBox" style="display:none; background:#eff6ff; border-left:4px solid #1d4ed8; padding:12px; margin-top:8px; margin-bottom:8px; border-radius:4px; font-size:13px; line-height:1.5; color:#12458c; box-shadow:0 2px 5px rgba(0,0,0,0.05);"> 105 â ï¸ <strong>Metadati EXIF non disponibili</strong><br/><br/> 106 La foto non contiene <strong>ð data</strong> o <strong>ð posizione GPS</strong>: <strong>controlla data e posizione</strong>.<br/><br/> 107 Per ottenere foto con geotag:<br/> 108 ð± <strong>iPhone</strong>: Impostazioni â Privacy â Localizzazione â Fotocamera â <strong>Attiva âDurante lâuso dellâappâ</strong><br/> 109 ð¤ <strong>Android</strong>: Fotocamera â Impostazioni â <strong>Attiva âLocalizzazione / Tag GPSâ</strong> 110 </div> 111 112<!-- A2 IMAGE PREVIEW BOX --> 113<div id="imagePreviewBox" class="image-preview-box" style="display:none;"> 114<h3>ð¸ Anteprima Immagini Caricate</h3> 115<div id="previewContainer"></div> 116</div> 117 </div> 118 119 <!-- DATA AVVISTAMENTO --> 120 <div class="row"> 121 <label for="dataAvvistamento">Data avvistamento</label> 122 <input type="date" id="dataAvvistamento" name="q14_dataAvvistamento"> 123 <div class="help">*Se la foto contiene la data di scatto, questo campo può compilarsi automaticamente.</div> 124 </div> 125 126 <!-- Cosa hai osservato? --> 127 <div class="row"> 128 <label>Cosa hai osservato? <span style="color:#dc2626">*</span></label> 129 <div class="inline"> 130 <label><input type="radio" name="q167_cosaHai" value="Uccello vivo" required> Uccello vivo</label> 131 <label><input type="radio" name="q167_cosaHai" value="Uccello morto" required> Uccello morto</label> 132 </div> 133 </div> 134 135 <!-- Conosci la specie? --> 136 <div class="row"> 137 <label>Conosci la specie? <span style="color:#dc2626">*</span></label> 138 <div class="inline"> 139 <label><input type="radio" name="conosciSpecieLocal" value="si" required> Sì</label> 140 <label><input type="radio" name="conosciSpecieLocal" value="no" required> No</label> 141 </div> 142 </div> 143 144 <!-- Dimensione --> 145 <div class="row" id="dimensionePanel" style="display:none"> 146 <label>Scegli la dimensione aiutandoti con l'osservazione delle sagome:</label> 147 <div style="display:flex; flex-direction:column; gap:8px; margin-top:8px;"> 148 <label style="font-weight:400; display:flex; align-items:center; gap:8px;"> 149 <input type="radio" name="dimensione" value="PICCOLO (< 15 cm)"> PICCOLO (< 15 cm) 150 </label> 151 <label style="font-weight:400; display:flex; align-items:center; gap:8px;"> 152 <input type="radio" name="dimensione" value="MEDIO (15-30 cm)"> MEDIO (15-30 cm) 153 </label> 154 <label style="font-weight:400; display:flex; align-items:center; gap:8px;"> 155 <input type="radio" name="dimensione" value="GRANDE (30-50 cm)"> GRANDE (30-50 cm) 156 </label> 157 <label style="font-weight:400; display:flex; align-items:center; gap:8px;"> 158 <input type="radio" name="dimensione" value="MOLTO GRANDE (>50 cm)"> MOLTO GRANDE (> 50 cm) 159 </label> 160 161 <!-- Immagine Mano (mostrata via JS se PICCOLO) --> 162 <div id="sizeRefImage" style="display:none; text-align:center; margin-top:10px;"> 163 <img src="grafica/mano_pettirosso.png" alt="Dimensione piccolo" style="max-width:200
163px; border-radius:8px;"> 164 </div> 165 </div> 166 </div> 167 168 <!-- CAMPI SPECIE (solo se Sì) --> 169 <div id="speciesFields" style="display:none"> 170 <div id="speciesFieldsContainer"> 171 <div> 172 <div class="row"> 173 <label for="nomeSpecie">Nome specie</label> 174 <div class="autocomplete"> 175 <input type="text" id="nomeSpecie" name="q17_nomeSpecie" placeholder="Inizia a digitare..." autocomplete="off" class="species-input"> 176 </div> 177 178 </div> 179 180 <!-- Cavità fields --> 181 <div class="row cavita-row" style="display:none;"> 182 <label>Hai avvistato cavità (nidi)?</label> 183 <div class="inline"> 184 <label><input type="radio" name="q78_haiOsservato[]" value="No"> No</label> 185 <label><input type="radio" name="q78_haiOsservato[]" value="Si"> Sì</label> 186 </div> 187
188 <div class="cavita-details-row" style="display:none; margin-top:10px;"> 189 <label for="numeroCavita">Numero di cavità avvistate:</label> 190 <input type="number" id="numeroCavita" name="q79_numeroCavita" placeholder="Es. 3" style="margin-bottom:10px;"> 191 192 <label for="numeroCivico">Numero civico edificio (se visibile):</label> 193 <input type="text" id="numeroCivico" name="q77_numeroCivico" placeholder="Es. 12A"> 194 </div> 195 </div> 196 197 </div> 198 </div> 199 200 <div id="otherSpeciesField" class="row" style="display:none"> 201 <label for="otherSpecies">Di che specie si tratta?</label> 202 <input type="text" id="otherSpecies" name="otherSpecies" placeholder="Specificare la specie"> 203 </div> 204 205 <div class="row"> 206 <label for="numeroIndividui">Numero individui? <span style="color:#dc2626">*</span></label> 207 <input type="number" id="numeroIndividui" name="q19_numeroIndividui" class="numero-individui-input" placeholder="Inserisci numero (es. 1, 10, 100...)" min="1" required> 208 </div> 209 210 <div class="row"> 211 <label>Sesso: <span style="color:#dc2626">*</span></label> 212 <div style="display:flex; flex-direction:column; gap:3px; margin-top:8px;"> 213 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 214 <input type="checkbox" name="q20_sesso[]" value="Maschio"> Maschio 215 </label> 216 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 217 <input type="checkbox" name="q20_sesso[]" value="Femmina"> Femmina 218 </label> 219 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 220 <input type="checkbox" name="q20_sesso[]" value="Non riconosciuto"> Non riconosciuto 221 </label> 222 </div> 223 </div> 224 225 <div class="row"> 226 <p style="font-weight:600; color:#003366; margin-bottom:10px; margin-top:0;">Sei nel periodo marzo-luglio? Compila i Codici Altante!</p> 227 <button type="button" class="btn btn-outline" onclick="openAtlanteModal()">CODICI ATLANTE</button> 228 <div id="codiciAtlanteDisplay" class="codici-display" style="display:none"></div> 229 <input type="hidden" id="codiciAtlanteInput" name="q21_codiciAtlante"> 230 <input type="hidden" id="altreOsservazioniAtlante" name="q22_ulterioriOsservazioniAtlante"> 231 </div> 232 233 <div class="row"> 234 <label>Ambiente circostante</label> 235 <div style="display:flex; flex-direction:column; gap:3px; margin-top:8px;"> 236 <p style="font-size:14px; color:#555; margin:0 0 8px 0;">Puoi selezionare uno o più ambienti.</p> 237 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 238 <input type="checkbox" name="q13_ambienteCircostante[]" value="Verde urbano"> ð³ Verde urbano 239 </label> 240 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 241 <input type="checkbox" name="q13_ambienteCircostante[]" value="Area edificata"> ð Area edificata 242 </label> 243 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 244 <input type="checkbox" name="q13_ambienteCircostante[]" value="Presenza d'acqua"> ð§ Presenza d'acqua 245 </label> 246 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 247 <input type="checkbox" name="q13_ambienteCircostante[]" value="Area industriale"> ð Area industriale 248 </label> 249 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 250 <input type="checkbox" name="q13_ambienteCircostante[]" value="Area agricola"> ð¾ Area agricola 251 </label> 252 <label style="font-weight:400; display:flex; align-items:center; gap:6px;"> 253 <input type="checkbox" name="q13_ambienteCircostante[]" value="Terrazza/balcone"> ð¡ Terrazza/balcone 254 </label> 255 </div> 256 </div> 257 258 <div class="row"> 259 <label for="ulterioriOsservazioni">Ulteriori osservazioni</label> 260 <textarea id="ulterioriOsservazioni" name="q7_ulterioriInformazioni" placeholder="Aggiungi ulteriori osservazioni..."></textarea> 261 </div> 262 </div> 263
264 <!-- COLORI (solo se No) --> 265 <div id="colorPanel" style="display:none"> 266 <div class="color-section-title"> 267 Identifica la specie tramite il colore predominante del piumaggio 268 <button type="button" class="info-btn" onclick="toggleInfo('info-colori')" aria-label="Informazioni colori">i</button> 269 </div> 270 271 <div id="info-colori" class="info-box"> 272 ð¨ <strong>Come fare:</strong> Clicca sul riquadro che meglio rappresenta il colore dominante del piumaggio. Ti mostreremo una lista di uccelli con quei colori per aiutarti a trovare quello giusto. 273 </div> 274 275 <div class="color-grid" id="colorGrid"> 276 <!-- Each button has no caption; use aria-labels --> 277 <button class="color-btn" type="button" aria-label="NERO" data-color="NERO"> 278 <div class="swatch"><div class="part c-nero" style="flex:1"></div></div> 279 </button> 280 <button class="color-btn" type="button" aria-label="BIANCO" data-color="BIANCO"> 281 <div class="swatch"><div class="part c-bianco" style="flex:1"></div></div> 282 </button> 283 <button class="color-btn" type="button" aria-label="BIANCO/NERO" data-color="BIANCO/NERO"> 284 <div class="swatch"><div class="part c-bianco" style="flex:1"></div><div class="part c-nero" style="flex:1"></div></div> 285 </button> 286 287 <button class="color-btn" type="button" aria-label="NERO/GRIGIO" data-color="NERO/GRIGIO"> 288 <div class="swatch"><div class="part c-nero" style="flex:1"></div><div class="part c-grigio" style="flex:1"></div></div> 289 </button> 290 <button class="color-btn" type="button" aria-label="GRIGIO" data-color="GRIGIO"> 291 <div class="swatch"><div class="part c-grigio" style="flex:1"></div></div> 292 </button> 293 <button class="color-btn" type="button" aria-label="ROSSO" data-color="ROSSO"> 294 <div class="swatch"><div class="part c-rosso" style="flex:1"></div></div> 295 </button> 296 <button class="color-btn" type="button" aria-label="GIALLO" data-color="GIALLO"> 297 <div class="swatch"><div class="part c-giallo" style="flex:1"></div></div> 298 </button> 299 <button class="color-btn" type="button" aria-label="GIALLO/BLU" data-color="GIALLO/BLU"> 300 <div class="swatch"><div class="part c-giallo" style="flex:1"></div><div class="part c-blu" style="flex:1"></div></div> 301 </button> 302 <button class="color-btn" type="button" aria-label="GIALLO/NERO" data-color="GIALLO/NERO"> 303 <div class="swatch"><div class="part c-giallo" style="flex:1"></div><div class="part c-nero" style="flex:1"></div></div> 304 </button> 305 <button class="color-btn" type="button" aria-label="ROSSO/GIALLO" data-color="ROSSO/GIALLO"> 306 <div class="swatch"><div class="part c-rosso" style="flex:1"></div><div class="part c-giallo" style="flex:1"></div></div> 307 </button> 308 <button class="color-btn" type="button" aria-label="MARRONE/ROSSO" data-color="MARRONE/ROSSO"> 309 <div class="swatch"><div class="part c-marrone" style="flex:1"></div><div class="part c-rosso" style="flex:1"></div></div> 310 </button> 311 <button class="color-btn" type="button" aria-label="MARRONE" data-color="MARRONE"> 312 <div class="swatch"><div class="part c-marrone" style="flex:1"></div></div> 313 </button> 314 <button class="color-btn" type="button" aria-label="MARRONE/BIANCO" data-color="MARRONE/BIANCO"> 315 <div class="swatch"><div class="part c-marrone" style="flex:1"></div><div class="part c-bianco" style="flex:1"></div></div> 316 </button> 317 <button class="color-btn" type="button" aria-label="MARRONE/NERO" data-color="MARRONE/NERO"> 318 <div class="swatch"> 319 <div class="part" style="flex:1; background:#7a4c31;"></div> 320 <div class="part" style="flex:1; background:#000000;"></div> 321 </div> 322 </button> 323 <button class="color-btn" type="button" aria-label="VERDE" data-color="VERDE"> 324 <div class="swatch"><div class="part c-verde" style="flex:1"></div></div> 325 </button> 326 <button class="color-btn" type="button" aria-label="BEIGE" data-color="BEIGE"> 327 <div class="swatch"><div class="part c-beige" style="flex:1"></div></div> 328 </button> 329 <button class="color-btn" type="button" aria-label="ARANCIO/NERO" data-color="ARANCIO/NERO"> 330 <div class="swatch"><div class="part c-arancio" style="flex:1"></div><div class="part c-nero" style="flex:1"></div></div> 331 </button> 332 <button class="color-btn" type="button" aria-label="ARANCIONE/MARRONE" data-color="ARANCIONE/MARRONE"> 333 <div class="swatch"><div class="part c-arancio" style="flex:1"></div><div class="part c-marrone" style="flex:1"></div></div> 334 </button> 335 <button class="color-btn" type="button" aria-label="GRIGIO/ARANCIO" data-color="GRIGIO/ARANCIO"> 336 <div class="swatch"><div class="part c-arancio" style="flex:1"></div><div class="part c-grigio" style="flex:1"></div></div> 337 </button> 338 339 <button class="color-btn" type="button" aria-label="BLU" data-color="BLU"> 340 <div class="swatch"><div class="part c-blu" style="flex:1"></div></div> 341 </button> 342 </div> 343 <input type="hidden" id="colorePredominante" name="colorePredominante"> 344 345 <!-- Container per le schede specie filtrate --> 346 <div id="speciesCardsContainer" class="species-cards-container" style="display:none; margin-top:20px;"></div> 347 348 <div class="row" id="schedaSpecieRow" style="display:none;margin-top:12px"> 349 <div class="species-card"> 350 <div class="help"> 351 <strong id="nomeComuneSpecie"></strong> 352 <span id="nomeScientificoSpecie" style="font-style:italic"></span> 353 </div> 354 <div class="species-body"> 355 <div class="species-images"> 356 <div class="img-block">
357 <img id="fotoSpecieAperta" 358 src="" 359 alt="Ali aperte"> 360 <div class="caption">Ali aperte</div> 361 </div> 362 363 <div class="img-block"> 364 <img id="fotoSpecieChiusa" 365 src="" 366 alt="Ali chiuse"> 367 <div class="caption">Ali chiuse</div> 368 </div> 369 </div> 370 <div class="species-text"> 371 <p id="testoAmbienteSpecie" class="help"></p> 372 <button type="button" class="btn species-select-btn">Seleziona specie</button> 373 </div> 374 </div> 375 </div> 376 </div> 377 </div> 378 379 <hr> 380 <div class="row"> 381 <strong>Geolocalizzazione 382 <button type="button" class="info-btn" onclick="toggleInfo('info-mappa')" aria-label="Informazioni mappa">i</button> 383 </strong> 384 </div> 385 386 <div id="info-mappa" class="info-box"> 387 ð <strong>Correggi la posizione:</strong> Il segnaposto rosso indica dove è stata scattata la foto. Se la posizione non è precisa, <strong>tieni premuto sul segnaposto rosso e trascinalo</strong> esattamente dove hai visto la specie. 388 </div> 389 390 <div class="row"> 391 <input 392 type="text" 393 id="mapSearch" 394 placeholder="Cerca indirizzo o luogo" 395 autocomplete="off" 396 /> 397 </div> 398 <div class="row"> 399 <div id="map"></div> 400 </div> 401 402 <!-- Campi nascosti per coordinate --> 403 <input type="hidden" id="jotformGeoloc" name="q16_mappa" value=""> 404 <input type="hidden" id="latitudine" name="latitudine"> 405 <input type="hidden" id="longitudine" name="longitudine"> 406 407 <hr> 408 <div class="row"><strong>Consenso al trattamento dati</strong></div> 409 <div class="row"> 410 <div class="inline"> 411 <label><input type="radio" name="q266_ilSottoscritto" value="Acconsento"> Acconsento</label> 412 <label><input type="radio" name="q266_ilSottoscritto" value="Non Acconsento"> Non acconsento</label> 413 </div> 414 <div id="consentWarning" class="warning">Per inviare il modulo è necessario selezionare âAcconsentoâ.</div> 415 <div class="help" style="margin-top:6px"> 416 Autorizzo il trattamento dei dati personali ai sensi del Regolamento (UE) 2016/679 (GDPR).<br> 417 Le informazioni inserite nel modulo e i metadati delle immagini (es. data di scatto e coordinate GPS) sono utilizzati solo per lâidentificazione della specie vegetale e per registrare la segnalazione.<br> 418 Nessun dato viene utilizzato per finalità diverse da quelle indicate.<br> 419 <a href='/privacy' rel='noopener noreferrer' target='_blank'>Leggi la Privacy Policy</a> 420 </div> 421 </div> 422 423 <div class="row"> 424 <button class="btn btn-full" id="submitButton" type="submit">Invia</button> 425 </div> 426 </form> 427 </div> 428 </div> 429
429<script src="https://unpkg.com/exifr/dist/full.umd.js"></script>
429 430 <div id="outOfBoundsModal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.6); z-index:10002; align-items:center; justify-content:center;"> 431 <div style="background:#222; color:#fff; padding:24px; border-radius:14px; max-width:320px; text-align:center; box-shadow:0 10px 25px rgba(0,0,0,0.5);"> 432 <p style="font-size:16px; line-height:1.5; margin:0 0 20px; color:#fff;"> 433 La segnalazione sembra provenire da fuori la Città Metropolitana di Milano. Il sistema accetta solo segnalazioni interne a quest'area. 434 </p> 435 <button id="closeOutOfBoundsBtn" type="button" style="background:transparent; color:#3b82f6; border:none; font-size:17px; font-weight:600; cursor:pointer; padding:8px 16px;"> 436 Chiudi 437 </button> 438 </div> 439 </div> 440 441
441<script src="species_db.js?v=2"></script>
441 442
442<script src="../scuole_milano.js"></script>
442 443
443<script src="script.js?v=2026-04-24_1"></script>
vendor: 1 bytes, line 443
443
444<script type="module"> 445 import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js"; 446 import { getAuth, onAuthStateChanged, setPersistence, browserLocalPersistence } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js"; 447 import { getFirestore, doc, setDoc, getDoc, collection, getDocs, writeBatch, updateDoc, increment } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; 448 449 const firebaseConfig = { 450 apiKey: "AIzaSyDLwAgTCyoRXIWTyWPWgjUqD_9qfObAE0k", 451 authDomain: "guardamiwebapp.firebaseapp.com", 452 projectId: "guardamiwebapp", 453 storageBucket: "guardamiwebapp.firebasestorage.app", 454 messagingSenderId: "105692008925", 455 appId: "1:105692008925:web:fc61d601f308b28e0c6634", 456 measurementId: "G-N3S20SDTWV" 457 }; 458 459 try { 460 const app = initializeApp(firebaseConfig); 461 const auth = getAuth(app); 462 const db = getFirestore(app); 463 464 window.firebaseAuth = auth; 465 window.firebaseDb = db; 466 window.fs = { collection, getDocs, doc, setDoc, writeBatch, getDoc, updateDoc, increment }; 467 468 setPersistence(auth, browserLocalPersistence).catch(console.error); 469 console.log("Firebase initialized in Citizen Module"); 470 471 onAuthStateChanged(auth, (user) => { 472 if (user) { 473 console.log("User logged in:", user.uid); 474 if (window.syncHistoryFromFirestore) { 475 window.syncHistoryFromFirestore(); 476 } 477 } 478 }); 479 480 } catch (e) { 481 console.error("Firebase init error:", e); 482 } 483</script>
483 484 485<!-- Google Maps API: sostituisci LA_TUA_API_KEY con la tua chiave --> 486
486<script 487 src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBBOUfEisnrZ-u5DExX0RiRZmsY7A87BFE&libraries=places&callback=initMap" 488 async 489 defer 490 ></script>
490 491 492<!-- Lightbox for image enlargement --> 493 <div id="lightbox"> 494 <span class="close-button" onclick="closeLightbox()">Ã</span> 495 <button class="lightbox-delete" onclick="deleteCurrentLightboxImage()" type="button">Ã</button> 496 <button class="lightbox-arrow lightbox-prev" onclick="prevImage()" type="button">â¹</button> 497 <img id="lightboxImage" src="" alt="Enlarged image"> 498 <button class="lightbox-arrow lightbox-next" onclick="nextImage()" type="button">âº</button> 499 </div> 500 501 502 503<!-- Codici Atlante Modal --> 504<div id="atlanteModal" class="modal-backdrop" style="display:none;"> 505 <div class="modal-content"> 506 <span class="close-modal" onclick="closeAtlanteModal()">X</span> 507 <h2 style="color:#003366; margin-top:0;">Codici Atlante</h2> 508 <p style="color:#cc0000; font-size:14px; margin-bottom:15px;">Seleziona uno o più codici per questa specie, poi chiudi con la X.</p> 509 510 <div class="modal-scroll-area"> 511 <h3 style="color:#003366; font-size:16px; margin-top:10px;">Possibile sito di nidificazione</h3> 512 <label class="modal-option"><input type="checkbox" value="1"> 1 â Osservazione della specie nel suo periodo riproduttivo</label> 513 <label class="modal-option"><input type="checkbox" value="2"> 2 â Specie osservata durante il periodo riproduttivo nel suo habitat</label> 514 <label class="modal-option"><input type="checkbox" value="3a"> 3a â Udito richiami nuziali o tambureggiamento</label> 515 <label class="modal-option"><input type="checkbox" value="3b"> 3b â Visto maschio in parata</label> 516 <label class="modal-option"><input type="checkbox" value="3c"> 3c â Maschio in canto presente in periodo di nidificazione</label> 517 518 <h3 style="color:#003366; font-size:16px; margin-top:20px;">Probabile sito di nidificazione</h3> 519 <label class="modal-option"><input type="checkbox" value="4"> 4 â Coppia presente nel suo habitat nel suo periodo di nidificazione</label> 520 <label class="modal-option"><input type="checkbox" value="5"> 5 â Comportamento territoriale (canto, comportamento aggressivo, ecc.)</label> 521 <label class="modal-option"><input type="checkbox" value="6"> 6 â Comportamento nuziale: parata, accoppiamento o scambio di nutrimento tra adulti</label> 522 <label class="modal-option"><input type="checkbox" value="7"> 7 â Visita di un probabile sito di nidificazione</label> 523 <label class="modal-option"><input type="checkbox" value="8"> 8 â Gridì dâallarme o altri comportamenti che indicano la presenza di un nido o di giovani nelle vicinanze</label> 524 <label class="modal-option"><input type="checkbox" value="10"> 10 â Trasporto di materiale o costruzione di un nido, scavo di una cavità </label> 525 526 <h3 style="color:#003366; font-size:16px; margin-top:20px;">Nidificazione certa</h3> 527 <label class="modal-option"><input type="checkbox" value="12"> 12 â Nido vuoto utilizzato di recente o gusci dâuovo della stagione in corso</label> 528 <label class="modal-option"><input type="checkbox" value="13"> 13 â Giovani involati di recente o incapaci di volare</label> 529 <label class="modal-option"><input type="checkbox" value="14"> 14 â Adulto che arriva a un nido il cui contenuto non può essere verificato (troppo alto o in cavità )</label> 530 <label class="modal-option"><input type="checkbox" value="16"> 16 â Adulto che trasporta cibo durante il periodo di nidificazione</label> 531 <label class="modal-option"><input type="checkbox" value="17"> 17 â Gusci dâuovo schiusi o predati</label> 532 <label class="modal-option"><input type="checkbox" value="18"> 18 â Nido con un adulto in cova</label> 533 <label class="modal-option"><input type="checkbox" value="19"> 19 â Nido contenente uova o piccoli</label> 534 535 <h3 style="color:#003366; font-size:16px; margin-top:20px;">Altre osservazioni</h3> 536 <textarea id="atlanteNotes" placeholder="Scrivi qui eventuali osservazioni aggiuntive per questa specie..." style="width:100%; height:80px;"></textarea> 537 </div> 538 </div> 539</div> 540 541<!-- Success Modal removed (legacy) --> 542 543<style> 544@keyframes popIn { 545 0% { transform: scale(0.8); opacity: 0; } 546 100% { transform: scale(1); opacity: 1; } 547} 548</style> 549 550<div id="geo-permission-modal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.8); z-index:99999; align-items:center; justify-content:center; font-family:sans-serif;"> 551 <div style="background:white; padding:24px; border-radius:16px; text-align:center; max-width:320px; width:90%; box-shadow:0 10px 25px rgba(0,0,0,0.2);"> 552 <img src="logo.png" alt="GuardaMI Logo" style="width:80px; height:80px; border-radius:16px; margin-bottom:16px; box-shadow:0 4px 12px rgba(0,0,0,0.1); object-fit: cover;"> 553 <h3 style="margin:0 0 12px; font-size:18px; color:#111827; font-weight:700;">GuardaMI ® WebApp</h3> 554 <p style="margin:0 0 24px; font-size:15px;
554 color:#4b5563; line-height:1.5;">vorrebbe utilizzare la tua posizione attuale per localizzare le tue segnalazioni.</p> 555 <button id="geo-allow-btn" style="background:#1d4ed8; color:white; border:none; padding:12px 24px; border-radius:8px; font-weight:600; font-size:16px; width:100%; cursor:pointer; box-shadow:0 4px 6px rgba(29, 78, 216, 0.2);">Consenti</button> 556 <button id="geo-deny-btn" style="background:transparent; color:#6b7280; border:none; padding:12px; margin-top:8px; font-size:14px; cursor:pointer;">Non ora</button> 557 </div> 558</div> 559
560<script> 561document.addEventListener('DOMContentLoaded', function() { 562 try { 563 const qp = new URLSearchParams(window.location.search); 564 if (qp.get('screenshot') === '1') { 565 const milano = { lat: 45.4642, lng: 9.19 }; 566 try { sessionStorage.setItem('geoPromptShown', 'true'); } catch(e) {} 567 try { sessionStorage.setItem('geoConsentSession', 'denied'); } catch(e) {} 568 try { sessionStorage.setItem('geoLast', JSON.stringify(milano)); } catch(e) {} 569 } 570 } catch(e) {} 571 const modal = document.getElementById('geo-permission-modal'); 572 const consentSession = sessionStorage.getItem('geoConsentSession'); 573 574 // Pre-centra su ultima posizione della SESSIONE, se presente 575 try { 576 const last = sessionStorage.getItem('geoLast'); 577 if (last) { 578 const obj = JSON.parse(last); 579 if (window.map && window.marker && obj && obj.lat && obj.lng) { 580 const p = { lat: obj.lat, lng: obj.lng }; 581 window.map.setCenter(p); 582 window.map.setZoom(15); 583 window.marker.setPosition(p); 584 const latInput = document.getElementById('latitudine'); 585 const lngInput = document.getElementById('longitudine'); 586 if (latInput && lngInput) { 587 latInput.value = obj.lat.toFixed(6); 588 lngInput.value = obj.lng.toFixed(6); 589 } 590 } 591 } 592 } catch(e) {} 593 594 // Se già concesso in QUESTA sessione, geolocalizza subito senza mostrare modale 595 if (consentSession === 'granted') { 596 if (modal) modal.style.display = 'none'; 597 if (window.chiediGeolocalizzazione) { window.chiediGeolocalizzazione(); } 598 return; 599 } 600 601 // Altrimenti mostra modale una sola volta per sessione 602 if (!sessionStorage.getItem('geoPromptShown') && modal) { 603 setTimeout(function(){ modal.style.display = 'flex'; }, 500); 604 } 605 606 // Pulsanti modale 607 const allowBtn = document.getElementById('geo-allow-btn'); 608 const denyBtn = document.getElementById('geo-deny-btn'); 609 if (allowBtn) { 610 allowBtn.addEventListener('click', function() { 611 if (modal) modal.style.display = 'none'; 612 sessionStorage.setItem('geoPromptShown', 'true'); 613 if (window.chiediGeolocalizzazione) { window.chiediGeolocalizzazione(); } 614 }); 615 } 616 if (denyBtn) { 617 denyBtn.addEventListener('click', function() { 618 if (modal) modal.style.display = 'none'; 619 sessionStorage.setItem('geoPromptShown', 'true'); 620 sessionStorage.setItem('geoConsentSession', 'denied'); 621 }); 622 } 623 624 try { 625 const qp = new URLSearchParams(window.location.search); 626 if (qp.get('screenshot') === '1') { 627 const shot = String(qp.get('shot') || '').trim().toLowerCase(); 628 const click = (sel) => { 629 const el = document.querySelector(sel); 630 if (el && el.click) el.click(); 631 }; 632 const hideMap = () => { 633 try { 634 const map = document.getElementById('map'); 635 if (map) map.style.display = 'none'; 636 const mapSearch = document.getElementById('mapSearch'); 637 if (mapSearch) mapSearch.style.display = 'none'; 638 const rowSearch = mapSearch && mapSearch.closest ? mapSearch.closest('.row') : null; 639 if (rowSearch) { 640 rowSearch.style.display = 'none'; 641 const prev = rowSearch.previousElementSibling; 642 if (prev && prev.classList && prev.classList.contains('row')) prev.style.display = 'none'; 643 } 644 const geoStrong = Array.from(document.querySelectorAll('strong')).find((x) => 645 String(x.textContent || '').trim().toLowerCase().startsWith('geolocalizzazione') 646 ); 647 const geoRow = geoStrong && geoStrong.closest ? geoStrong.closest('.row') : null; 648 if (geoRow) geoRow.style.display = 'none'; 649 const info = document.getElementById('info-mappa'); 650 if (info) info.style.display = 'none'; 651 } catch(e) {} 652 }; 653 if (shot === 'carousel-form') { 654 setTimeout(() => { 655 try { 656 hideMap(); 657 click('input[name="conosciSpecieLocal"][value="no"]'); 658 click('input[name="dimensione"][value^="MEDIO"]'); 659 const colorPanel = document.getElementById('colorPanel'); 660 if (colorPanel) colorPanel.style.display = 'none'; 661 const panel = document.getElementById('dimensionePanel'); 662 if (panel && panel.scrollIntoView) panel.scrollIntoView({ block: 'start' }); 663 } catch(e) {} 664 }, 650); 665 } 666 if (shot === 'carousel-guide') { 667 setTimeout(() => { 668 try { 669 hideMap(); 670 click('input[name="conosciSpecieLocal"][value="no"]'); 671 click('input[name="dimensione"][value^="MEDIO"]'); 672 click('button.color-btn[data-color="BIANCO/NERO"]'); 673 const cards = document.getElementById('speciesCardsContainer') || document.getElementById('colorPanel'); 674 if (cards && cards.scrollIntoView) cards.scrollIntoView({ block: 'start' }); 675 } catch(e) {} 676 }, 900); 677 } 678 } 679 } catch(e) {} 680}); 681</script>
681 682 683 <div id="successOverlay"> 684 <div id="successModal"> 685 <div id="successCheck">â</div> 686 <h2>Grazie per la segnalazione!</h2> 687 <p>Il file è stato correttamente trasmesso.<br/>Il Team di GuardaMI</p> 688 </div> 689 </div> 690</body>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.