Partage
  • Partager sur Facebook
  • Partager sur Twitter

Sélectionner un élément

problème avec addEventListener

Sujet résolu
    30 juillet 2011 à 1:53:46

    Bonjour à tous !
    Je me lance à la découverte de HTML5 et CSS3 en faisant une petite webapp (enfin l'interface pour commencer, je sais pas jusqu'où j'irais ^^ ).
    Et là, ben j'ai un soucis pour gérer la sélection d'un outil.
    J'ai une série de <div> représentant les boutons des différents outils. Ces div peuvent avoir une classe .on lorsque l'outil est actif.
    Je veux donc que lorsqu'on clique sur un des boutons, il s'active en faisant un tool.classList.add("on"). (Pour la désactivation de l'autre, je verrais après).
    Donc en théorie c'est plutôt simple, je fais ceci :
    function init(){
    	var tools = document.querySelectorAll("#toolbox > div");
    	for(var i = 0 ; i < tools.length ; i++){
    		tools[i].addEventListener('click', function(event){
    			self.classList.add('on');
    		});
    	}
    }
    


    Sauf que bien évidemment, le self porte sur window et non sur le parent du addEventListener(). >_<
    Et là mystère : comment récupérer mon tools[i] dans le callback ? Peut-on ajouter un paramètre ?
    Merci d'avance pour les réponse ! :)
    • Partager sur Facebook
    • Partager sur Twitter
      31 juillet 2011 à 1:39:15

      Bonsoir,

      je pense que le mot-clé let pourrait t'aider :
      function init(){
           var tools = document.querySelectorAll("#toolbox > div");
           for(var i = 0, tln = tools.length; i < tln; i++) {
                let j = i;     // la magie du let opère, j contiendra la valeur de i et pourra être utilisé dans les callback (contrairement à i qui aura toujours sa "valeur finale")
                tools[i].addEventListener('click',
                     function(event) {
                      tools[j].classList.add('on');
                     },
                     false);
           }
      }
      


      (pour des raisons de compatibilité, j'ai rajouté false à addEventListener)
      • Partager sur Facebook
      • Partager sur Twitter
        31 juillet 2011 à 2:08:12

        Ça a l'air magique ! :)
        Mais Chrome ne le supporte pas. :(
        Et pour le moment, vu que c'est juste un petit test pour moi, je fais un truc en Chrome only... Zut.

        Ah puis je m'attaque à plus compliqué maintenant aussi : un système de fenêtres.
        Voilà ce que j'ai (sous Chrome donc) :
        Image utilisateur

        Et voilà le code :
        index.html
        <!DOCTYPE html>
        <html lang = "fr">
        	<head>
        		<title>Nouveau document - Tangente</title>
        		<meta charset = "utf-8" />
        		<link rel = "stylesheet" href="tangente.css" />
        		<script>
        			// <!--
        			// Que des tests qui marchent pas pour le moment...
        			// -->
        		</script>
        	</head>
        	<body onload="init();">
        		<header>
        			<svg>
        				<circle id="cercle" cx="4.1607143" cy="9.058609" r="3.5" style="fill:none;stroke:#000000;stroke-width:1.5;" />
        				<path id="tangente" d="M 2.34955418,19.482359 10.3931975,5.3579092" style="fill:none;stroke:#000000;stroke-width:1.5;" />
        			</svg>
        			Nouveau document - Tangente<br/>
        			<nav>
        				<div>
        					Fichier
        					<ul>
        						<li>Nouveau document</li>
        						<li>Ouvrir...</li>
        						<li class = "plus">
        							Documents récents
        							<ul>
        								<li>Tangente.svg</li>
        								<li>Test_3.svg</li>
        								<li>logo.svg</li>
        								<li class = "separateur"></li>
        								<li onclick = "historique();">Historique...</li>
        							</ul>
        						</li>
        						<li class = "separateur"></li>
        						<li>Enregistrer</li>
        						<li>Enregistrer sous...</li>
        						<li class = "separateur"></li>
        						<li>Quitter</li>
        					</ul>
        				</div>
        				<div>
        					Edition
        					<ul>
        						<li>Annuler</li>
        						<li>Rétablir</li>
        						<li class = "separateur"></li>
        						<li>Couper</li>
        						<li>Copier</li>
        						<li>Coller</li>
        						<li class = "separateur"></li>
        						<li>Supprimer</li>
        					</ul>
        				</div>
        				<div>
        					Affichage
        					<ul>
        						<li class = "plus">
        							Zoom
        							<ul>
        								<li>Zoom +</li>
        								<li>Zoom -</li>
        								<li class = "separateur"></li>
        								<li>Tout afficher</li>
        								<li>Ajuster à la sélection</li>
        							</ul>
        						</li>
        						<li>Grille</li>
        						<li>Palette</li>
        						<li>Timeline</li>
        					</ul>
        				</div>
        			</nav>
        		</header>
        		
        		<nav id = "options">
        		</nav>
        		
        		<nav id = "toolbox">
        			<div class = "on">
        				<svg>
        					<path id="Souris" d="m 27.023803,22.459602 -16.00489,-12.246863 2.60362,19.984077 5.027028,-4.711809 2.844295,7.692847 4.175928,-2.410988 -5.240043,-6.309672 z" style = "fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;"/>
        				</svg>
        			</div>
        			<div>
        				<svg>
        					<circle id="Cercle" cx="20" cy="20" r="10" style="fill:none;stroke:#000000;stroke-width:2;" />
        				</svg>
        			</div>
        			<div>
        				<svg>
        					<rect id="Rectangle" x="10" y="10" width="20" height="20" rx="3" ry="3" style="fill:none;stroke:#000000;stroke-width:2;" />
        				</svg>
        			</div>
        			<div>
        				<svg>
        					<rect id="chemin_poignee" x="10" y="25" width="5" height="5" rx="0" ry="0" style="fill:none;stroke:#000000;stroke-width:1;" />
        					<path id="chemin_tangente" d="m 15,27.5 15,0" style="fill:none;stroke:#000000;stroke-width:1;" />
        					<circle id="chemin_cercle" cx="32" cy="27.5" r="2" style="fill:none;stroke:#000000;stroke-width:1;" />
        					<path id="chemin_tangente" d="m 15,26 c 16.696429,-0.58036 10,-17.5 10,-17.5" style="fill:none;stroke:#000000;stroke-width:2;" />
        				</svg>
        			</div>
        			<div>
        				<svg>
        					<defs>
        						<linearGradient id="gradient">
        							<stop offset="0" style="stop-color:#000000;stop-opacity:1;" />
        							<stop offset="1" style="stop-color:#000000;stop-opacity:0;" />
        						</linearGradient>
        					</defs>
        					<rect id="Degrade" x="10" y="10" width="20" height="20" rx="3" ry="3" style="fill:url(#gradient);fill-opacity:1;stroke:none;" />
        				</svg>
        			</div>
        			<div>
        				<svg>
        					<text id="Texte" x="12" y="30" style="font-size:26px;fill:#000000;fill-opacity:1;">
        						<tspan>A</tspan>
        					</text>
        				</svg>
        			</div>
        		</nav>
        		
        		<div class = "fenetre">
        			<header>
        				<nav class = "quitter"></nav>
        				Historique...
        			</header>
        			<div class = "corps">
        				<ul>
        					<li>Tangente.svg</li>
        					<li>Test_3.svg</li>
        					<li>logo.svg</li>
        				</ul>
        			</div>
        		</div>
        		
        		<div id = "canvas">
        			<svg> <!--viewBox="0 0 100 100"-->
        				<g id="dessin">
        					<circle cx="50" cy="100" r="10" style="fill:#00ff00;" />
        				</g>
        				<g id="auxiliaires">
        					<circle id="_curseur" cx="0" cy="0" r="5" style="fill:#000000;" />
        				</g>
        			</svg>
        		</div>
        		
        	</body>
        </html>
        


        tangente.css
        body{
        	margin : 0px;
        	
        	background : #ececec;
        	
        	font-family : "Loma", sans-serif;
        	color : black;
        }
        
        /* HEADER */
        
        header{
        	height : 60px;
        	padding : 0px;
        	padding-left : 10px;
        	
        	border-top-left-radius : 10px;
        	border-top-right-radius : 10px;
        	
        	font-weight : bold;
        	
        	background : -webkit-gradient(linear, left top, left bottom,
        		from(#c1b59f), to(#ececec),
        		color-stop(0.05, #7c6a4e), color-stop(0.1, #837258), color-stop(0.99, #5c4f39));
        }
        
        header svg{
        	height : 20px;
        	width : 12px;
        	display : inline;
        }
        
        header nav{
        	height : 25px;
        	margin-top : 8px;
        	font-weight : normal;
        }
        
        header nav div{
        	padding-right : 8px;
        	padding-left : 8px;
        	display : inline-block;
        }
        
        header nav div:hover{
        	height : 24px;
        	margin-top : -1px;
        	padding-right : 7px;	
        	padding-left : 7px;
        	
        	border-top-left-radius : 10px;
        	border-top-right-radius : 10px;
        	
        	color : #e8e8e8;
        	
        	cursor : pointer;
        	border : 1px solid #7d6d53;
        	background : -webkit-gradient(linear, left top, left bottom,
        		from(#5c4f39), to(#837258));
        }
        
        header nav div ul{
        	width : 200px;
        	
        	display : none;
        	margin : 0px;
        	margin-left : -10px;
        	padding : 0px;
        	
        	list-style-type : none;
        	
        	border-bottom-left-radius : 5px;
        	border-bottom-right-radius : 5px;
        	background : -webkit-gradient(linear, left top, left bottom,
        		from(#d9d9d9), to(#bbbbbb));
        }
        
        header nav div ul li{
        	padding : 0px 10px 0px 10px;
        }
        
        header nav div ul li.separateur{
        	height : 1px;
        	margin : auto;
        	width : 80%;
        	background : #e8e8e8;
        }
        
        header nav div ul li.plus{
        	background : url(design/fleche.png) 190px center no-repeat;
        }
        
        header nav div ul li:not(.separateur):hover{
        	border-radius : 10px;
        	background : -webkit-gradient(linear, left top, left bottom,
        		from(#938268), to(#6a5b44));
        }
        
        header nav div ul li.plus:hover{
        	background : url(design/fleche.png) 190px center no-repeat,
        	-webkit-gradient(linear, left top, left bottom,
        		from(#938268), to(#6a5b44));
        }
        
        header nav div:hover ul{
        	color : black;
        	display : block;
        	position : absolute;
        	
        	box-shadow : #aaaaaa -2px 0px 5px;
        }
        
        header nav div ul li.plus ul{
        	display : none;
        	border-top : 3px solid #938268;
        }
        
        header nav div ul li.plus:hover ul{
        	display : block;
        	position : absolute;
        	margin-left : 190px;
        	margin-top : -25px;
        }
        
        
        /* OPTIONS */
        
        #options{
        	height : 40px;
        	padding : 0px;
        	padding-left : 10px;
        	
        	background : -webkit-gradient(linear, left top, left bottom,
        		from(#f4f4f4), to(#e0e0e0), color-stop(0.9, #ececec));
        }
        
        
        /* TOOLBOX */
        
        #toolbox{
        	width : 40px;
        	float : left;
        }
        
        #toolbox div{
        	height : 40px;
        	border-top-left-radius : 50px;
        	border-bottom-left-radius : 50px;
        }
        
        #toolbox div:hover, #toolbox div.on{
        	width : 38px;
        	border-right : 2px solid #ececec;
        	background : -webkit-gradient(linear, left top, right top,
        		from(#c0c0c0), to(#d0d0d0));
        	cursor : pointer;
        }
        
        /* CANVAS */
        
        #canvas{
        	margin : 0px 40px 0px 40px;
        	background : white;
        }
        
        #canvas:hover{
        	cursor : cross;
        }
        
        /* FENETRE */
        
        .fenetre{
        	width : 300px;
        	position : absolute;
        	top : 50px;
        	left : 500px;
        	z-index : 90;
        	
        	border-radius : 10px;
        	box-shadow : #ececec -2px 2px 5px;
        }
        
        .fenetre header{
        	height : 27px;
        	
        	margin : 0px;
        	padding-top : 3px;
        	
        	background : -webkit-gradient(linear, left top, left bottom,
        		from(#c1b59f), to(#ececec),
        		color-stop(0.1, #7c6a4e), color-stop(0.2, #837258), color-stop(0.98, #5c4f39));
        }
        
        .fenetre header .quitter{
        	float : right;
        	
        	height : 8px;
        	width : 8px;
        	
        	margin-top : 7px;
        	margin-right : 5px;
        	
        	border : 2px solid #5c4f39;
        	border-radius : 10px;
        	
        	background : #837258;
        }
        
        .fenetre header .quitter:hover{
        	cursor : pointer;
        	background : #706149;
        }
        
        .fenetre .corps{
        	margin : 0px;
        	padding : 10px;
        	background : #ececec;
        	
        	border : 1px solid #e0e0e0;
        	border-top : none;
        	
        	border-bottom-left-radius : 10px;
        	border-bottom-right-radius : 10px;
        }
        
        .fenetre .corps ul{
        	margin : 0px;
        	padding : 0px;
        	list-style : none;
        }
        


        L'utilisation du svg pour les boutons est peut-être un peu lourde mais je voulais faire une app sans images pour que le design puisse être changé le plus facilement possible (et parce que IloveSVG ^^ ).
        J'utilise cependant une image pour la flèche : Image utilisateur

        Donc voilà : Mon soucis est que le peu de JavaScript que j'ai fait, c'était essentiellement un conglomérat de bouts de jQuery et de JavaScript mélangés et maintenant j'aimerais dans la mesure du possible éviter l'utilisation de frameworks (j'aime pas ça du tout).
        J'aurais bien imaginer quelque chose du genre au moment du clic, on retient l'offset entre le coin de la fenêtre et la souris puis tant qu'on clique les déplacements de la souris sont répercutés sur la fenêtre. Mais pour cela il faut pouvoir stocker l'offset. C'est là que je bloque car je veux que mon système fonctionne pour un nombre indéterminé de fenêtre donc je peux pas utiliser une variable en vrac... Il faut qu'elle soit liée à la fenêtre, et là je trouve pas comment.
        Ensuite, il y aura le problème de l'ajout de fenêtre, parce que je veux que ce soit propre et pas trop lourd, afin de pouvoir ajouter facilement une fenêtre.
        Bref, je vise peut-être un peu haut mais je pense que j'ai quand même un bon bagage de prog, même si c'est pas dans le javascript. ^^
        • Partager sur Facebook
        • Partager sur Twitter
          31 juillet 2011 à 10:33:34

          C'est un problème de portée assez courant. Et il peut se résoudre avec une closure
          function init(){
               var tools = document.querySelectorAll("#toolbox > div");
               for(var i = 0, tln = tools.length; i < tln; i++) {
                    let j = i;     // la magie du let opère, j contiendra la valeur de i et pourra être utilisé dans les callback (contrairement à i qui aura toujours sa "valeur finale")
                    tools[i].addEventListener('click',
                         function(objet) {
                              return function(){objet.classList.add('on');};
                         }(tools[i]),
                         false);
               }
          }
          


          Pour le reste, j'ai du mal à comprendre ton problème. Tu veux attacher des actions de la souris à tes fenêtres, c'est ça ? madiv.onlick ? Un truc du genre ?
          • Partager sur Facebook
          • Partager sur Twitter
          Directeur technique, créateur de jeux HTML5 et fan de JavaScript | La suite de OnHack est sur les rails !
            31 juillet 2011 à 12:02:59

            Merci, je savais pas qu'on pouvait passer des arguments à une fonction anonyme. Ça me semble plus propre que le let aussi.
            Par contre, ça marche curieusement, parce que l'évènement semble ne pas être pris en compte : la classe est ajoutée au chargement. :(
            Voilà mon code :
            function init(){
            	var tools = document.querySelectorAll('#toolbox > div');
            	for(var i = 0 ; i < tools.length ; i++){
            		tools[i].addEventListener('click', function(obj){
            			obj.classList.toggle('on');
            		}(tools[i]), false);
            	}
            }
            


            Pour mon autre problème, je reconnais que je me suis mal exprimé. Je vais avancer un peu plus le travail pour avoir une question plus spécifique, quitte à partir un peu dans la mauvaise direction.
            Merci à toi donc. :)
            • Partager sur Facebook
            • Partager sur Twitter
              31 juillet 2011 à 14:21:16

              Ca marche curieusement parce que tu n'as pas bien repris mon code ;)
              • Partager sur Facebook
              • Partager sur Twitter
              Directeur technique, créateur de jeux HTML5 et fan de JavaScript | La suite de OnHack est sur les rails !
                1 août 2011 à 19:08:19

                Bah j'ai pas repris le let parce que Chrome n'en veut pas et la boucle fait la même chose... Enfin en tous cas dans la pratique ça marche pas mieux avec la tienne. :(
                • Partager sur Facebook
                • Partager sur Twitter
                  2 août 2011 à 21:16:08

                  N'y a-t-il donc aucune solution avec Chrome ?
                  Je crois que je vais devoir ajouter un onclick à chaque bouton alors...

                  edit : J'ai fini par trouver :
                  var tools = document.querySelectorAll('#toolbox > div');
                  for(var i = 0, tln = tools.length; i < tln; i++){
                  	tools[i].setAttribute("onclick", "this.classList.toggle('on');");
                  }
                  
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Sélectionner un élément

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown