Partage
  • Partager sur Facebook
  • Partager sur Twitter

Lightbox maison

petit exercice

Sujet résolu
    9 avril 2010 à 20:31:57

    Salut les ZérOs,

    J'essaie de me faire un petit script genre lightbox avec mes propres connaissances.
    ça a l'air de marcher mais j'aimerais bien avoir une "correction", savoir si ça peut être optimisé, ce qu'il ne faut pas faire etc.

    Pour l'instant, ce que fait le script c'est de, au clic sur une image de class "attached", créer un div noir occupant 100% de la page avec une copie de image, centrée, à l'intérieur. Cliquer sur cette image détruit le div. Et tout ça avec des effets de fondus.

    J'ai utilisé des conditions, une boucle, une closure, du DOM, innerHTML et setInterval.

    <script type="text/javascript">
    <!--
    var body = document.getElementsByTagName('body')[0];
    var image = document.getElementsByTagName('img');
    var opac_fond = opac_image = 0;
    var timer="";
    
    function opacity(opac, obj) 
    {
        var object = obj.style;
        object.opacity = (opac / 100);
        object.MozOpacity = (opac / 100);
        object.KhtmlOpacity = (opac / 100);
        object.filter= "progid:DXImageTransform.Microsoft.Alpha(opacity=" + opac + ")";
    }
    
    function show(bg, pic)
    {
    if(opac_fond <= 100)
    	{
    	opacity(opac_fond, bg);
    	opac_fond = opac_fond + 10;
    	}
    else{
    	opac_fond = 100;
    	if(opac_image <= 100)
    	{
    		opacity(opac_image, pic);
    		opac_image = opac_image + 5;
    	}
    	else{
    		opac_image = 100;
    		clearInterval(timer);
    		}
    	}
    }
    
    function clear_fond(bg, pic)
    {
    if(opac_image >= 0)
    	{
    	opacity(opac_image, pic);
    	opac_image = opac_image - 5;
    	}
    else{
    	opac_image = 0;
    	if(opac_fond >= 0)
    	{
    		opacity(opac_fond, bg);
    		opac_fond = opac_fond - 10;
    	}
    	else{
    		opac_fond = 0;
    		clearInterval(timer);
    		body.style.overflow="auto";
    		var parent = bg.parentNode;
    		parent.removeChild(bg);
    		}
    	}
    }
    
    for(var i=0; i<image.length; i++)
    {
    	if(image[i].className=="attached")
    	{
    		image[i].style.cursor="pointer";
    		( function (image) 
    		{
    			return function()
    			{
    				image.onclick = function() 
    				{
    					var fond = document.createElement("div");
    					body.appendChild(fond);
    					fond.id="fond";
    					fond = document.getElementById("fond");
    					var style = fond.style;
    					style.opacity=style.MozOpacity=style.KhtmlOpacity=0; 
    					style.filter= "progid:DXImageTransform.Microsoft.Alpha(opacity=0)";
    					style.background="black";	style.position="absolute";	
    					style.zIndex=100;			body.style.overflow="hidden";
    					style.left=0;				style.top=0;
    					style.height="100%";		style.width="100%";
    					fond.innerHTML='<img id="imageshown" style="opacity:0; -moz-opacity:0; -khtml-opacity:0; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0); cursor:pointer; position: absolute; left: 50%; top: 50%; margin-top: -'+image.height/2+'px; ;margin-left: -'+image.width/2+'px;" src="'+image.src+'" alt="'+image.alt+'" />';
    					var imageshown = document.getElementById("imageshown");
    					imageshown.onclick=function(){timer = setInterval(function(){clear_fond(fond, imageshown)}, 10);}
    					timer = setInterval(function(){show(fond, imageshown)}, 10);
    				};
    			}
    		}
    		)(image[i])();
    	}
    }
    //-->
    </script>
    


    Merci à ceux qui voudront bien jeter un oeil :)
    • Partager sur Facebook
    • Partager sur Twitter
      9 avril 2010 à 20:40:08

      Bon, déjà je remarque qu'il est très facile de le faire bugguer. Par exemple en ouvrant puis refermant trop vite la box, le voile noir reste ^^

      Ensuite, il serait bon de lancer le code (et l'initialisation des variables) au chargement de la page... avec un petit addEventListener/attachEvent ;)
      • Partager sur Facebook
      • Partager sur Twitter
        9 avril 2010 à 21:23:44

        Merci pour ta réponse !

        Qu'est-ce qui plante en fait concrètement quand on clique trop vite ? Est-ce que c'est parce qu'il n'y a pas de clearInterval avant le nouveau timer ? Si non, je peux toujours attribuer le onclick à l'image à la fin de l'animation (mais c'est de la triche :p ).

        Pour le addEventListener, j'ai entendu dire que si je mets mon script à la fin du body, il est lu avant l'évènement onload, ce qui me semble pas mal sur le principe. Tu penses quoi de ça ?

        Si non, est-ce qu'il y a un moyen d'améliorer les performances de ce script ?

        Merci bien :)
        • Partager sur Facebook
        • Partager sur Twitter
          9 avril 2010 à 22:44:35

          Bah moi quand je parlais du onload, c'est parce que je pense au cas où tu le distribuerais... et où il devrait donc être propre et surtout utilisable de manière très simple... (pas de contrainte de placement, etc. :-° )

          Placer le script à la fin, ça fonctionne... normalement. Mais pas toujours.

          Et le jour où ça fonctionne pas, bah t'as l'air d'un con... :-°

          Pour ce qui est du bug, oui, je crois qu'il faut que tu fasses un clearInterval avant le nouveau timer.


          Ah aussi, je crois bien que ta closure n'est pas obligatoire...
          Si tu t'en passes, tu peux accéder à image avec le mot clé this dans la fonction attribuée au onclick.
          Une closure serait nécessaire pour récupérer la valeur de i par exemple. ;)
          • Partager sur Facebook
          • Partager sur Twitter
            9 avril 2010 à 23:43:45

            Le truc c'est que je ne comprends pas trop quand je peux utiliser this : en AS2, quand j'écris mc.onRelease ou mc.onEnterFrame ça a l'air de se faire en partant d'un objet : je sais que this réfèrera à mc, alors que si j'écris

            bouton.onclick = function()
            {
              if(image[2].className=="attached")
              {
                this.style.display="none";
              }
            }
            

            qu'est-ce qui me dit si this correspond à bouton ou à image[2] ? pour moi il correspond à bouton parce que c'est de lui que la fonction est partie, mais je me trompe peut-être, et dans le cas de mon script on ne part apriori de rien, on n'est même pas dans une fonction.
            • Partager sur Facebook
            • Partager sur Twitter
              10 avril 2010 à 0:26:36

              Allons, il y a une différence entre attribuer une méthode et donner une classe ^^

              Ici, this c'est le bouton.


              Retiens simplement ça :

              quand tu affectes un événement (que ce soit onclick, onload, onmouseover, onkeyup, que sais-je...) this représente toujours l'objet sur lequel tu appliques l'événement. Facile ! :p
              • Partager sur Facebook
              • Partager sur Twitter
                10 avril 2010 à 1:15:55

                ça je comprends bien, c'est même le seul cas où j'ose utiliser this. Dans le cas présent je n'ai pas osé écrire this.onclick (ce qui aurait évité des closures) parce que je ne sais pas à quoi renvoie this quand on n'est pas dans un évènement.

                Maintenant, je pense que je dois faire bêtement des tests avec alert() et je serai fixé...

                Merci pour ta patience !
                • Partager sur Facebook
                • Partager sur Twitter
                  10 avril 2010 à 8:28:26

                  Non t'écris pas this.onclick.

                  T'écris image[i].onclick = function(), et dans la fonction, tu peux utilisé this pour référer au image[i] cliqué.
                  C'est ça qui fait que la closure n'est pas utile ici ^^
                  • Partager sur Facebook
                  • Partager sur Twitter
                    10 avril 2010 à 10:12:12

                    Merde, t'as raison...

                    Bon, faut que je potasse un peu, parce que là je ne comprends plus pourquoi j'étais si souvent bloqué sur des créations d'évènements avec une boucle (c'est pas souvent qu'on utilise un array[i] sur autre chose que l'élément qui lance le onclick j'ai l'impression)

                    Merci encore :D
                    • Partager sur Facebook
                    • Partager sur Twitter
                      10 avril 2010 à 10:36:45

                      Mais par contre, pour récupérer le i dans la fonction... là il te faut une closure ! ^^
                      • Partager sur Facebook
                      • Partager sur Twitter
                        10 avril 2010 à 10:56:50

                        Si j'essaie de schématiser :

                        Quand on crée un évènement dans une boucle sur un élément ciblé dans un array, le i est automatiquement "clôturé" pour élément[i].onevent parce que l'évènement est défini au moment où i a une valeur bien définie.

                        Par contre tout ce qui est contenu à l'intérieur de la fonction appelée par l'évènement est une variable, qui du coup change avec i et prend sa valeur finale a la fin de la boucle ?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          10 avril 2010 à 11:43:31

                          Hm... mouais ça doit être ça... plus ou moins ^^

                          C'est la formulation qui me dérange un peu.

                          Quand tu crées un événement sur un élément, cette propriété est créée immédiatement. (Donc on est sûr et certain de l'avoir créé sur le bon élément quoi).

                          Par contre, la fonction qui est affectée à cet événement n'est pas exécutée tout de suite. Elle ne le sera que lorsque l'événement sera déclenché.


                          Quand l'événement sera déclenché, la fonction sera exécutée. Et la fonction aura toujours accès à i, vu que sa portée dépend de son emplacement de définition.

                          Mais entre temps, i aura changé de valeur ^^


                          C'est pas facile de poser des mots là-dessus en fait huhu ^^

                          Je conçois que c'est pas évident à comprendre tout ça... Fais des tests, des bidouilles, etc. et tu concevras ça nickel ;)
                          • Partager sur Facebook
                          • Partager sur Twitter
                            10 avril 2010 à 16:23:24

                            Je pense que expliqué comme ça c'est très clair :)
                            Bon, je passe ne "résolu".
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Lightbox maison

                            × 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