IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Obligé de cliquer deux fois pour changer l'image background


Sujet :

JavaScript

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 37
    Par défaut Obligé de cliquer deux fois pour changer l'image background
    Bonjour, j'ai un petit site sur un Arduino via le shield ethernet avec des images boutons qui sont chargés par le CSS en background d'un div

    Mais seulement je voudrais pouvoir changer l'image (rouge ou vert) selon l'état du bouton.

    J'ai trouvé un exemple sur internet qui fonctionne très bien:

    https://codepen.io/mikacontact/pen/ZXxgGY

    mais que je n'arrive pas à le faire fonctionner:

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    <!DOCTYPE html>
    <html>
        <head>
            <title>Arduino Ajax I/O</title>
     
    		<link rel="stylesheet" href="test3css.css" type="text/css" />
     
    		<link rel="shortcut icon" href="cloud.ico" /><!-- icône à choisir-->
     
     
            <script>
                    
     
    (function() {
      var tabLinks = document.querySelectorAll(".link"),
          i = 0,
          maxLoop = tabLinks.length;
            for (i; i < maxLoop; i++) {
        tabLinks[i].addEventListener("click", function(event) {
        //ternaire 
        event.target.parentNode.className === "styleOne" ?
          event.target.parentNode.className = "styleTwo" :
          event.target.parentNode.className = "styleOne" ;
        })
      }
    })()
     
     
                    function GetButton2()
                    {
                            if (LED4_state === 1) {
                                    LED4_state = 0;
                                    strLED4 = "&LED4=0";
                            }
                            else {
                                    LED4_state = 1;
                                    strLED4 = "&LED4=1";
                            }
                    }
     
                    
                    </script>
     
        </head>
     
        <body onload="GetArduinoIO()">
            <h1>Arduino Ajax I/O</h1>
     
    		<div class="red">
    			<div id="slatenav">
    			<ul>
    			<li><a href="index.htm" title="Page d'accueil" >Accueil</a></li>
    			<li><a href="ajax_io.htm" title="Ajax Inputs/Outputs" class="current">Interrupteurs/Relais</a></li>
    			<li><a href="gauges.htm" title="Cadrans">Cadrans</a></li>
    			<li><a href="http://www.13styles.com/css-menus/slate/" title="css menus">Our Work</a></li>
    			<li><a href="http://www.13styles.com/css-menus/slate/" title="css menus">Contact Us</a></li>
    			</ul>
    			</div>
    		</div>
     
     
     
    		<div class="styleOne"><a class="link" href="#">Click me1</a></div>
    		<div class="styleOne"><a class="link" href="#">Click me2</a></div>
    		<div class="styleOne"><a class="link" href="#">Click me3</a></div>
    		<div class="styleOne"><a class="link" href="#">Click me4</a></div>
     
        </body>
    </html>

    et le
    Code CSS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    body {
     
    	background:#aaa url(grid.png) center top repeat;
     
    	margin: auto;
    	padding: auto;
    }
     
    img.image{
    	display: block;
        margin-left: auto;
        margin-right: auto
    }
     
    h1
    {
       font-size: 20px;
       /*font-style: italic;*/
       font-family: "Arial Black", Arial, Verdana, serif;
       text-align: center;
       color: black;
    }
     
     
    /* ---------------------- Redslate nav ---------------------- */
    .red #slatenav{position:relative;display:block;height:42px;font-size:12px;font-weight:bold;background:transparent url(rd.gif) repeat-x top left;font-family:Arial,Verdana,Helvitica,sans-serif;text-transform:uppercase;}
    .red #slatenav ul{margin:0px;padding:0;list-style-type:none;width:auto;}
    .red #slatenav ul li{display:block;float:left;margin:0 1px 0 0;}
    .red #slatenav ul li a{display:block;float:left;color:#FECCC3;text-decoration:none;padding:14px 22px 0 22px;height:28px;}
    .red #slatenav ul li a:hover,.red #slatenav ul li a.current{color:#fff;background:transparent url(rd2.gif) no-repeat top center;}
    /* ---------------------- END Redslate nav ---------------------- */
     
     
     
    		.IO_box {
    			float: left;
    			margin: 0 20px 20px 0;
    			border: 1px solid blue;
    			padding: 0 5px 0 5px;
    			width: 120px;
    		}
     
    		.bouton_box {
    			float: left;
    			margin: 0 20px 20px 0;
    			border: 2px solid yellow;
    			padding: 0 5px 0 5px;
    			width: 200px;
    		}
     
     
    		h2 {
    			font-size: 85%;
    			color: #5734E6;
    			margin: 5px 0 5px 0;
    		}
    		p, form, button {
    			font-size: 80%;
    			color: #252525;
    		}
    		.small_text {
    			font-size: 70%;
    			color: #737373;
    		}
     
    		.IO_box2 a {
     
    		float:left;
    		margin: 0 20px 20px 0;
     
     
    		display:block;
    		width:200px;
    		line-height:50px;
    		text-align:center;
    		vertical-align:middle;
    		background:url(bouton1.png) no-repeat;
    		color:white;
    		text-decoration:none;
    		/*float:left;
    		/*margin:2px;*/
    		}
     
     
    				.styleOne {
      background-image: url('http://www.lasantedemonchat.fr/www.lasantedemonchat.fr/uploads/2016/07/ArriveChaton-300x200.jpg');
      background-repeat: no-repeat;
      background-position: left center;
      width: 250px;
      height: 150px;
    }
    .link{text-decoration:none; color: #00F;}
    .link:hover{text-decoration:underline; color: #F00;}
    .styleTwo {
      background-image: url('http://www.biofan.com/blog/wp-content/uploads/2016/07/462-FR-Chaton-a-donner_comment-re%CC%81ussir-une-adoption-4-300x200.jpg');
      background-repeat: no-repeat;
      background-position: left center;
      width: 250px;
      height: 150px;

    ça marche pas donc j'ai fait comme çà
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    		<div class="styleOne"><a class="link" href="#" onClick="change3()">Click me3</a></div>

    et comme ceci en javascript:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    	function change3() {
    		var tabLinks = document.querySelectorAll(".link"),
    		//var test = event.target.parentNode.className;
    		i = 0,
    		maxLoop = tabLinks.length;
    		//alert(maxLoop);
    		//alert("je suis dans function change3");
    		for (i; i < maxLoop; i++) {
    			//alert("je suis dans function et dans le for 3");
    			//alert(test);
    			tabLinks[i].addEventListener("click", function(event) {
    			//ternaire 
    			event.target.parentNode.className === "styleOne" ?
    			  event.target.parentNode.className = "styleTwo" :
    			  event.target.parentNode.className = "styleOne" ;
    			})
    		}
    	}
    Et là ça fonctionne mais je suis obligé de cliquer deux fois pour que l'image soit changée: à chaque fois à la deuxième exécution de la fonction change3()

    Je ne pense pas être très loin du résultat escompté mais je bloque, d'autant plus que ce ne sont pas mes langages préférés...

  2. #2
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    Il y a en gros deux problèmes :
    1. change3 ajoute des gestionnaires d’évènements (avec addEventListener) ;
    2. change3 est elle-même dans un gestionnaire onclick.


    Dans l’idéal, il faut que tu attaches les gestionnaires de clics dès que les éléments existent. Pour ça il y a le <body onload="..."> que tu as utilisé, ou mieux : l’évènement DOMContentLoaded. Cet évènement est émis quand le DOM de la page est entièrement construit, mais sans attendre la fin du chargement des ressources externes (typiquement, les images).

    Quand à l’opérateur ternaire, personnellement je m’en méfie car ce n’est pas toujours clair au niveau des priorités. Un bon vieux if/else fait aussi bien le travail.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    document.addEventListener("DOMContentLoaded", function () {
      "use strict";
     
      const tabLinks = document.querySelectorAll(".link");
      for (const link of tabLinks) {
        // F12 pour voir la console
        console.log("dans la boucle for, link = ", link);
     
        const parent = event.target.parentNode;
        link.addEventListener("click", function (event) {
          console.log("clic sur link");
          if ("styleOne" === parent.className) { // Yoda condition
            parent.className = "styleTwo";
          }
          else {
            parent.className = "styleOne";
          }
        });
      }
    });
    Documentation :
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 37
    Par défaut autre solution
    Merci pour ces infos mais j'ai essayé de faire au plus simple et j'ai trouvé un exemple que je comprends et c'est le principal:

    Le code html concerné:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <a class="link" href="javascript:changebackground3()" 
    						style="background-image: url(green.png);" id="LED3" onclick="GetButton1()"/>LED 3 is OFF au d&eacutebut (D8)</a>
    et le javascript correspondant pour l'action matérielle à l'appui sur le bouton:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    		// fonction exécutée si appuie sur le bouton 1
    		function GetButton1()
    		{
    			console.log("et j'envoie l'état du bouton au serveur");
    			if (LED3_state === 1) {
    				LED3_state = 0;
    				strLED3 = "&LED3=0";
    			}
    			else {
    				LED3_state = 1;
    				strLED3 = "&LED3=1";
    			}
    		}
    et la fonction qui change le background du lien a sur lequel est le bouton:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    		// fonction qui change l'image de fond (background) selon si on a appuyé sur l'élément "LED3"
    		function changebackground3()
    			{
    			console.log("je change le background");
    			console.log(document.getElementById("LED3").getAttribute("style"));
    			if (document.getElementById("LED3").getAttribute("style") == 'background-image: url("green.png");' ||
    			document.getElementById("LED3").getAttribute("style") == 'background-image: url(green.png);') {
    				document.getElementById("LED3").style='background-image: url("red.png");';
    				}
    			else {
    				document.getElementById("LED3").style='background-image: url("green.png");';
    				}
    			}
    Ce code fonctionne très bien sur PC; firefox ou Chrome mais pas très bien sur tablette galaxy samsung tab 2 sur le laquelle le javascript est bien activé.

    Il allume ou éteint bien ma LED mais ne change pas le background du bouton comme le fait mes PC:

    (impossible de uploader une image !!!)



    Le problème, je pense, vient du fait que le navigateur de la tablette n'exécute pas "très" bien la fonction demandée, que faire...?

  4. #4
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    L’important à propos de la tablette aurait été de savoir avec quel navigateur tu as testé.
    Quoiqu’il en soit, je soupçonne trois causes de problème :
    1. un HTML mal formé
    2. un usage inadapté des styles avec setAttribute
    3. un problème de « forme canonique » de background-image


    On va commencer par répertorier les problèmes de HTML. Selon le navigateur, ils peuvent mener à une mauvaise interprétation, et donc un arbre DOM ne ressemblant pas à ce que tu attendais.

    • Le &eacute n’a pas son ; (point-virgule)
    • Il y a un / (slash) parasite dans la partie ouvrante du <a>


    Moins important, mais source de confusion : on ne met plus de JavaScript dans l’attribut href depuis 1841.

    Voici un HTML déjà un peu plus propre :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <a id="LED3" class="link" href="#"
       style="background-image: url(green.png);"
       onclick="GetButton1(); changebackground3(); return false">LED 3 is OFF au d&eacute;but (D8)</a>

    Pour faire encore mieux, il faudrait retirer l’attribut style et utiliser uniquement des classes. Dans l’idéal, le JS ne manipule jamais directement les styles, car ça rend le script trop dépendant de la mise en page (couplage entre la couche présentation et la couche comportement). Au moindre changement de mise en page, le script pourrait ne plus fonctionner.

    Tu utilisais des classes dans ton code précédent, pourquoi n’as-tu pas continué ?

    Bon, mais si c’est plus simple pour toi, on va continuer à manipuler les styles directement. Le problème de setAttribute c’est qu’il modifie l’attribut HTML style. C’est un problème parce qu’il y a une petite différence entre un attribut HTML et la représentation DOM de ce sur quoi l’attribut est censé agir. Je ne sais pas si je suis clair.

    Concrètement, la propriété DOM style est un peu magiquement reliée à la présentation de l’élément. Modifie cette propriété et, si c’est nécessaire, le moteur d’affichage du navigateur sera notifié qu’il y a des choses à mettre à jour.
    En changeant l’attribut style, ce n’est pas aussi immédiat. Je ne dis pas que le problème est forcément ici, mais en tout cas mon attention est attirée par ce genre de choses.

    Je vais expliquer cette histoire de « forme canonique ». Quand tu accèdes à la déclaration CSS background-image, tu peux remarquer que la syntaxe n’est pas forcément telle que tu l’avais écrite : le navigateur peut avoir rajouté des guillemets url("green.png"), ou au contraire les avoir retirés url(green.png). Et il peut aussi utiliser des guillemets simples. On peut également se poser des questions sur le point-virgule à la fin. Je ne sais pas si tout ça est standardisé quelque part, mais peut-être que le navigateur de ta tablette ne fait pas comme les autres.
    Bref, le mieux pour tester tout ça c’est d’utiliser une expression rationnelle (regexp).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /url\(["']?green\.png["']?\);?/
    Et là tu commences à comprendre pourquoi c’est plus facile d’utiliser des classes

    Sans setAttribute, et avec une regexp, ton code ressemblerait à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // fonction qui change l'image de fond (background) selon si on a appuyé sur l'élément "LED3"
    function changebackground3() {
      const LED3element = document.getElementById("LED3");
      console.log("je change le background");
      console.log(LED3element.style);
      console.log(LED3element.style.backgroundImage);
      if (/url\(["']?green\.png["']?\);?/.test(LED3element.style.backgroundImage)) {
        LED3element.style.backgroundImage = 'url("red.png")';
      }
      else {
        LED3element.style.backgroundImage = 'url("green.png")';
      }
    }
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 37
    Par défaut ne fonctionne toujours pas sur la tablette
    Merci de prendre du temps à la résolution de mon problème.
    Mais même avec les corrections apportées, la tablette ne veut rien savoir et ne change pas d'image de fond de mon "bouton".

    Je pensais que ça devait être assez simple de mettre du vert dans un lien/bouton et d'y mettre du rouge quand celui-ci a été cliqué/activé
    Tout simplement le même principe que le décroché/raccroché des smartphones...

    Soit-dit en passant, j'ai toujours cru que Victor Hugo utilisait du javascript dans son roman "Notre Dame des cendres" de 1841...

    Ou autrement alors en utilisant des class, on pourrait selon le getElementById, choisir une class plutôt qu'une autre avec un background différent l'une de l'autre.

    C'est l'esprit du premier exemple cité plus haut mais qui ne fonctionne pas au copié/collé.

    Quelle serait la solution la plus simple ?

    p.s : pourquoi je n'arrive plus à uploader des fichiers sur ce forum (Error#2038)

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 37
    Par défaut résolvaide
    Le problème venait du navigateur de la tablette, c'est celui par défaut et impossible de savoir qu'est-ce que c'est, ce n'est pas chrome...

    Du coups j'ai installé opéra et ça fonctionne au niveau des chargements des background image par le javascript mais c'est d'une lenteur !

  7. #7
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Par défaut
    Pense à optimiser tes images si elles sont trop lourdes
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 05/04/2017, 12h01
  2. cliquer deux fois pour ouvrir dans un nouvel onglet
    Par rosert dans le forum ASP.NET
    Réponses: 0
    Dernier message: 07/12/2012, 15h57
  3. Obligation de cliquer deux fois
    Par Juju54350 dans le forum ASP.NET
    Réponses: 4
    Dernier message: 01/02/2011, 14h22
  4. Réponses: 4
    Dernier message: 29/01/2008, 14h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo