Visualizzazione risultati 1 fino 18 di 18
Like Tree3Likes
  • 2 Post By
  • 1 Post By

Discussione: Chiudere tendina su click esterno

  1. #1
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito Chiudere tendina su click esterno

    Ciao a tutti,

    sto creando una tendina su una pagina html per la selezione della lingua.

    Questo è il codice che uso:
    Codice HTML:
    <html>
    <head>
    <style>
    :root {
      font: 8pt Arial;
      }
        
    #tendina {
      display: inline-block;
      width: 10em;
      height: 2em;
      background-color: yellow;
      }
    </style>
    <script>
    window.onload = function() {
        document.getElementById('tendina').addEventListener('click', aprit());
        window.addEventListener('click', chiudit());
        
        }
        
    function aprit() {
        document.getElementById('scelte').style.display = 'block';
        }
        
    function chiudit() {
        document.getElementById('scelte').style.display = 'none';
        }
        
    function sellingua(quale) {
        console.log('Lingua selezionata: ' + quale);
        }
    </script>
    </head>
    <body>
    <div id="tendina">Lingua: it</div>
    
    <ul id="scelte">
    <li onclick="sellingua('it')">it</li>
    <li onclick="sellingua('en')">en</li>
    </ul>
    </body>
    </html>
    L'ho pubblicato anche su jsfiddle a questo indirizzo: https://jsfiddle.net/5pdyu655/

    Ciò che voglio fare è che se l'utente clicca sul div giallo, si apre il menu lingue, altrimenti se clicco fuori dal menu e sta aperto, deve chiudersi.

    Ovviamente il codice è molto rudimentale e non intendo usare jQuery.

    Cos'è che non va?


    Grazie
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  2. #2
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    22,744

    Predefinito

    Inserisci un console.log() sia in aprit() che in chiudit(). Vedrai subito dove sta il problema.

    Ciao!

  3. #3
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Ho seguito il tuo suggerimento, facendo così le nuove funzioni:

    Codice HTML:
    function aprit() {
        console.log('apri');
        document.getElementById('scelte').style.display = 'block';
        }
        
    function chiudit() {
        console.log('chiudi');
        document.getElementById('scelte').style.display = 'none';
        }
    E anche aggiornato il codice su jsfiddle così: https://jsfiddle.net/5pdyu655/1/
    Su jsfiddle c'è qualcosa che non va, ma tanto l'ho messo il codice solo per farlo vedere.

    Ho provato in locale una semplice pagina html, e ho visto che al caricamento della pagina mi esegue aprit() e chiudit() insieme, e poi ai miei click non succede niente. Penso di aver fatto una bella frittata!

    Come posso risolvere?


    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  4. #4
    L'avatar di alemoppo
    alemoppo non è connesso Staff AV
    Data registrazione
    24-08-2008
    Residenza
    PU / BO
    Messaggi
    22,744

    Predefinito

    Soluzione un po' brutta:

    Codice HTML:
    <html>
    <head>
    <style>
    :root {
      font: 8pt Arial;
      }
        
    #tendina {
      display: inline-block;
      width: 10em;
      height: 2em;
      background-color: yellow;
      }
    </style>
    <script>
    var lastOpen = new Date();
    window.onload = function() {
    	window.addEventListener('click', chiudit, false);
    	document.getElementById('tendina').addEventListener('click', aprit, false);
    }
    
    function aprit() {
    	document.getElementById('scelte').style.display = 'block';
    	lastOpen = new Date();
    }
    
    function chiudit() {
    	now = new Date();
    	if(lastOpen.getTime()  < (now.getTime()-10))	//se è stato aperto prima di 10ms fa, chiudo:
    		document.getElementById('scelte').style.display = 'none';
    }
    
    function sellingua(quale) {
    	console.log('Lingua selezionata: ' + quale);
    }
    </script>
    </head>
    <body>
    <div id="tendina">Lingua: it</div>
    
    <ul id="scelte">
    <li onclick="sellingua('it')">it</li>
    <li onclick="sellingua('en')">en</li>
    </ul>
    </body>
    </html>
    Forse sarebbe meglio disabilitare gli eventi e abilitarli quando servono, lavorando con la removeEventListener().

    Ciao!

  5. #5
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Citazione Originalmente inviato da alemoppo Visualizza messaggio
    Forse sarebbe meglio disabilitare gli eventi e abilitarli quando servono, lavorando con la removeEventListener().
    Infatti, come posso fare?

    Vorrei fare più o meno come fanno tutti i siti, cliccando su una voce si apre la tendina, cliccando fuori si chiude.



    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  6. #6
    Guest

    Predefinito

    Il problema principale è che il click su window cattura anche quello sul div per cui vale sempre il chiudi.
    Ultima modifica di vplaza : 05-02-2017 alle ore 19.13.45

  7. #7
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Sì c'avevo pensato, ma vorrei sapere come fanno tutti i siti a fare questo giochetto, e io non ci riesco.


    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  8. #8
    Guest

    Predefinito

    Imposti l'evento sull'elemento più esterno (document o window) e stabilisci poi su quale elemento specifico si è cliccato diversificando l'azione.

    Più tardi, spero di fornirti un esempio.

  9. #9
    Guest

    Predefinito

    dunque eccomi

    come promesso eccoti un esempio funzionante (lo vedi all'opera qui)

    Basta porre il listener sul documento e poi muoversi in base a quale elemento si è cliccato.

    Ho spostato il codice JS in basso dopo tutto il codice per avere la certezza che sia caricato dopo tutti gli elementi.

    Codice HTML:
    <!doctype html>
    <html>
    <head>
    	<meta charset="UTF-8">
    	
    	<style>
    		:root {
    			font: 8pt Arial;
    		}
        
    		#tendina {
    			display: inline-block;
    			width: 10em;
    			height: 2em;
    			background-color: yellow;
    			cursor: pointer;
    		}
    		
    		#lingue {
    			display: none;
    			cursor: pointer;
    		}
    	</style>
    
    </head>
    
    <body>
    	<div id="tendina">Lingua: <span id="lingua">it</span></div>
    
    	<div id="lingue">
    		<ul id="scelte">
    			<li>it</li>
    			<li>en</li>
    		</ul>
    	</div>
    
    	<script>
    		var div_tendina = document.getElementById('tendina');
    		var div_lingue = document.getElementById('lingue');
    		var span_lingua = document.getElementById('lingua');
    	 
    		function azione(e) {
    			if(e.target.getAttribute('id') == 'tendina'){
    				div_lingue.style.display = 'block';
    			}else{
    				div_lingue.style.display = 'none';
    			}
    		}
        
    		function sellingua(e) {
    			var lingua = (e.target.innerHTML);
    			alert('Lingua selezionata: ' + lingua);
    			span_lingua.innerHTML = lingua;
    		}
    	
    		window.onload = function() {
    			div_lingue.style.display = 'none';
    			document.addEventListener('click', azione);
    			div_lingue.addEventListener('click', sellingua);
    		}
    	</script>
    
    </body>
    </html>
    Oppure si potrebbe anche gestire il tutto con la sola funzione "azione" e con un solo listener, gestendo l'oggetto che riceve l'azione (il click), come da pagina visibile qui e che riporto
    Naturalmente megli si individua l'elemento più si ha la certezza che non si verifichino interferenze.

    Codice HTML:
    <!doctype html>
    <html>
    <head>
    	<meta charset="UTF-8">
    	
    	<style>
    		:root {
    			font: 8pt Arial;
    		}
        
    		#tendina {
    			display: inline-block;
    			width: 10em;
    			height: 2em;
    			background-color: yellow;
    			cursor: pointer;
    		}
    		
    		#lingue {
    			display: none;
    			cursor: pointer;
    		}
    	</style>
    
    </head>
    
    <body>
    	<div id="tendina">Lingua: <span id="lingua">it</span></div>
    
    	<div id="lingue">
    		<ul id="scelte">
    			<li>it</li>
    			<li>en</li>
    		</ul>
    	</div>
    
    	<script>
    		var div_tendina = document.getElementById('tendina');
    		var div_lingue = document.getElementById('lingue');
    		var span_lingua = document.getElementById('lingua');
    	 
    		function azione(e) {
    			if(e.target.getAttribute('id') == 'tendina'){
    				div_lingue.style.display = 'block';
    			}else if(e.target.tagName == 'LI') {
    				var lingua = (e.target.innerHTML);
    				alert('Lingua selezionata: ' + lingua);
    				span_lingua.innerHTML = lingua;
    				div_lingue.style.display = 'none';
    			}else{
    				div_lingue.style.display = 'none';
    			}
    		}
    	
    		window.onload = function() {
    			div_lingue.style.display = 'none';
    			document.addEventListener('click', azione);
    		}
    	</script>
    
    </body>
    </html>
    Ultima modifica di vplaza : 05-02-2017 alle ore 23.29.18
    alemoppo and foreach like this.

  10. #10
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Inanzitutto grazie per la risposta esauriente e il tempo che mi hai dedicato.

    Ovviamente, soffro di pignoleria e quindi ho fatto delle modifiche per semplificare ancora di più, questo è il codice che ho provato e funziona (preso dal tuo secondo esempio):
    Codice HTML:
    <!DOCTYPE html>
    <html>
    <head>
    <style>
    :root {
    font: 8pt Arial;
    }
    
    #tendina {
    display: inline-block;
    width: 10em;
    height: 2em;
    background-color: yellow;
    }
    
    #scelte {
    display: none;
    }
    </style>
    <script>
    function azione(e) {
    if(e.target.getAttribute('id') == 'tendina') {
    console.log('apri');
    scelte.style.display = 'block';
    } else if(e.target.tagName == 'LI' && e.target.hasAttribute('sigla') == true) {
    console.log('scegli ' + e.target.getAttribute('sigla'));
    tendina.innerHTML = 'Lingua: ' + e.target.getAttribute('sigla');
    scelte.style.display = 'none';
    } else {
    console.log('chiudi');
    scelte.style.display = 'none';
    }
    }
    
    window.onload = function() {
    var tendina = document.getElementById('tendina');
    var scelte = document.getElementById('scelte');
    document.addEventListener('click', azione);
    };
    </script>
    </head>
    
    <body>
    <div id="tendina">Lingua: it</div>
    <ul id="scelte">
    <li sigla="it">it</li>
    <li sigla="en">en</li>
    </ul>
    </body>
    </html>
    Ho messo il codice JS nella testa (head) del file html, come si dovrebbe fare, e poi le dichiarazioni delle variabili al caricamento della pagina

    In più ho aggiunto la condizione e.target.hasAttribute('sigla') == true per accertarmi che il clic venga fatto in quella tendina, in quanto nella pagina saranno presenti anche altri elementi <li>.

    Questa ovviamente è solo una prova che funziona (e grazie ancora ), ma sulla pagina finale ci saranno le bandierine al posto di "it" o "en", e poi le chiamate XMLHttpRequest() per recuperare dal server le frasi nella lingua desiderata. Ovviamente dovrò togliere anche tutti i console.log() che ho messo per provare. Poi sistemerò la grafica, ci vorranno i posizionamenti relativi e assoluti.


    Ancora grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  11. #11
    Guest

    Predefinito

    Citazione Originalmente inviato da foreach Visualizza messaggio
    Ho messo il codice JS nella testa (head) del file html, come si dovrebbe fare, e poi le dichiarazioni delle variabili al caricamento della pagina
    Sicuro? E in base a quale standard?
    Gli elementi del DOM sono manipolabili solo DOPO il loro caricamento per cui gli script che li gestiscono andrebbero messi dopo gli stessi.
    karl94 likes this.

  12. #12
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Citazione Originalmente inviato da vplaza Visualizza messaggio
    Sicuro? E in base a quale standard?
    Gli elementi del DOM sono manipolabili solo DOPO il loro caricamento per cui gli script che li gestiscono andrebbero messi dopo gli stessi.
    Lo so, infatti ho usato una piccola correzione: document.onload, e esegue la funzione.

    Piccola svista: ora ho inserito il codice nella pagina a dovere, però negli elementi della lista (<li>) e nella descrizione di "tendina" ho inserito dei tag html per le bandierine delle lingue.

    Il problema è che cliccando su una bandierina, non prende il codice mio, invece sul testo sì.

    Come posso ovviare a questo problema?


    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  13. #13
    Guest

    Predefinito

    Beh, senza vedere è abbastanza difficile dire qualcosa.

  14. #14
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Scusa il ritardo, causa lavoro.

    Allora il codice con le bandierine è questo:

    Codice HTML:
    <!DOCTYPE html>
    <html>
    <head>
    <style>
    :root {
    font: 8pt Arial;
    }
    
    #tendina {
    display: inline-block;
    width: 10em;
    height: 2em;
    background-color: yellow;
    }
    
    #scelte {
    display: none;
    }
    
    band {
    width: 34px;
    height: 21px;
    display: inline-block;
    border: 0;
    background-repeat: no-repeat;
    background-image: url('bandiere21.png');
    vertical-align: middle;
    border: 1px solid #999999;
    margin: 0em 0.5em;
    }
    </style>
    <script>
    function azione(e) {
    if(e.target.getAttribute('id') == 'tendina') {
    console.log('apri');
    scelte.style.display = 'block';
    } else if(e.target.tagName == 'LI' && e.target.hasAttribute('sigla') == true) {
    console.log('scegli ' + e.target.getAttribute('sigla'));
    tendina.innerHTML = 'Lingua: ' + e.target.getAttribute('sigla');
    scelte.style.display = 'none';
    } else {
    console.log('chiudi');
    scelte.style.display = 'none';
    }
    }
    
    window.onload = function() {
    var tendina = document.getElementById('tendina');
    var scelte = document.getElementById('scelte');
    document.addEventListener('click', azione);
    };
    </script>
    </head>
    
    <body>
    <div id="tendina">Lingua: it<band class="it" /></div>
    <ul id="scelte">
    <li sigla="it"><band class="it" />it</li>
    <li sigla="en"><band class="en" />en</li>
    </ul>
    </body>
    </html>
    Ovviamente l'attributo class delle bandierine definisce la proprietà background-position.

    Cliccando su una bandierina non richiama l'apertura/chiusura della tendina.

    In più ho notato che cliccando sul div tendina si apre la lista, ma ricliccando non si chiude.

    Come posso rimediare?


    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  15. #15
    Guest

    Predefinito

    TAG band? Cos'è?
    Usa il tag LI e ci metti dentro l'immagine (anche come sfondo CSS).

  16. #16
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Prima di tutto scusa il ritardo di una settimana, ma gli altri giorni non ho tempo.

    Citazione Originalmente inviato da vplaza Visualizza messaggio
    TAG band? Cos'è?
    Usa il tag LI e ci metti dentro l'immagine (anche come sfondo CSS).
    Il tag <band> sta per bandierina, e gli ho definito questa grafica:
    Codice HTML:
    band {
    width: 32px;
    height: 21px;
    border: 0;
    background-repeat: no-repeat;
    background-image: url('bandiere32.png');
    display: inline-block;
    vertical-align: middle;
    }
    
    band.it {
    background-position: 0px 0px;
    }
    
    band.en {
    background-position: 0px -21px;
    }
    
    band.fr {
    background-position: 0px -42px;
    }
    
    band.es {
    background-position: 0px -63px;
    }
    
    band.de {
    background-position: 0px -84px;
    }
    Si deduce che l'immagine delle bandierine è solo una, che ne contiene tutte e 5 una sotto l'altra. Ora mi sembra difficile impostare una singola bandierina come sfondo al <li>, anche se funzionerebbe il gioco dei click.

    Citazione Originalmente inviato da foreach Visualizza messaggio
    In più ho notato che cliccando sul div tendina si apre la lista, ma ricliccando non si chiude.
    In più ho quest'altro problema.


    Come posso fare?


    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


  17. #17
    darbula non è connesso AlterGuru 2500
    Data registrazione
    24-04-2011
    Messaggi
    2,896

    Predefinito

    Stai utilizzando XHTML giusto?.. Cmq. Ecco la correzione del secondo esempio
    Codice:
    <script>
    var div_tendina = document.getElementById('tendina');
    var div_lingue = document.getElementById('lingue');
    var span_lingua = document.getElementById('lingua');
    var n = 0;
    function azione(e) {
    if(e.target.getAttribute('id') == 'tendina'){
    n = ++n;
    if(n == 2){
    n = 0;
    a = 'none';
    }else{
    a = 'block';
    }
    div_lingue.style.display = a;
    }else if(e.target.tagName == 'LI') {
    var lingua = (e.target.innerHTML);
    alert('Lingua selezionata: ' + lingua);
    span_lingua.innerHTML = lingua;
    div_lingue.style.display = 'none';
    }
    }
    window.onload = function() {
    document.addEventListener('click', azione);
    }
    </script>
    Quando clicchi esattamente dove ci sta scritto sigla dopo il tag li (appana il classico puntino) allora sarà vera e si chiude... Uhm ma tu invece vuoi che si chiuda al click della bandierina.
    Ultima modifica di darbula : 21-02-2017 alle ore 01.03.39

  18. #18
    L'avatar di foreach
    foreach non è connesso Altervistiano Junior
    Data registrazione
    11-06-2008
    Residenza
    3 metri sotto terra
    Messaggi
    501

    Predefinito

    Grazie per il suggerimento, mi hai fatto venire un'idea migliore

    Citazione Originalmente inviato da darbula Visualizza messaggio
    Uhm ma tu invece vuoi che si chiuda al click della bandierina.
    Questo è il codice del pulsante che apre la tendina sotto di esso per scegliere la lingua:
    Codice HTML:
    <div id="tendina">Lingua: it<band class="it" /></div>
    Ma soltanto che funziona solo se clicco sul testo o sul margine interno (padding di css), ma se clicco sulla bandierina che si trova qui, non apre la tendina.

    Come posso fare?

    Grazie,
    foreach
    Codice PHP:
    foreach($vettore as $chiave => $valore) {
    echo 
    "Ciao";


Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •