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

Contribuez Discussion :

[jQuery] Construction et exemples d'utilisation de l'événement spécial clickOutside


Sujet :

Contribuez

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Billets dans le blog
    125
    Par défaut [jQuery] Construction et exemples d'utilisation de l'événement spécial clickOutside
    Construction et exemples d'utilisation de l'événement spécial clickOutside

    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
    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
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    <!DOCTYPE html>
    <html lang="fr">
    	<head>
    		<meta charset="utf-8" />
    		<meta name="author" content="Daniel Hagnoul">
    		<title>Forum jQuery</title>
    		<link href='http://fonts.googleapis.com/css?family=Sofia|Ubuntu:400|Kreon'>
    		<link rel="stylesheet" href="http://danielhagnoul.developpez.com/styles/dvjhRemBase.css">
    		<style>
    			.hyphens { -moz-hyphens:auto; -webkit-hyphens:auto; -ms-hyphens:auto; hyphens:auto; }
    			article { display:table-cell; text-align:justify; border:0.1rem dotted grey; }
    			.table1, .table2 { border-collapse:separate; border-spacing:3rem; }
    			.ligne { display:table-row; }
     
    			.table1 .ligne { height:25rem; }
    			.table1 article { width:40rem; vertical-align:top; }
     
    			/* TEST */
    			#example { margin: 1.2rem; padding: 0.6rem; width: 10rem; height: 10rem; border:0.1rem dotted red; }
    			#example span { color: blue; }
    		</style>
    	</head>
    	<body>
    		<h1>Forum jQuery</h1>
    		<h2>Titre 2</h2>
    		<section class="conteneur">
    			<section class="table1">
    				<section>
    					<article>
     
    						<div class="test" id="example">Le texte de la <span>division</span> incluse dans l'article.</div>
     
    					</article>
    					<article class="test">
     
    						<p>Un texte de contrôle.</p>
     
    					</article>
    				</section>
    			</section>
    		</section>
    		<footer itemscope itemtype="http://danielhagnoul.developpez.com/">
    			<time datetime="2012-12-09T20:25:46.702+01:00" pubdate>2012-12-09T20:25:46.702+01:00</time>
    			<span itemprop="name">Daniel Hagnoul</span>
    			<a href="http://www.developpez.net/forums/u285162/danielhagnoul/" itemprop="url">@danielhagnoul</a>
    			<a href="http://danielhagnoul.developpez.com/" itemprop="url">Mon cahier d’exercices</a>
    			<a href="http://javascript.developpez.com/faq/jquery/" itemprop="url">FAQ</a>
    			<a href="http://javascript.developpez.com/cours/?page=frameworks#jquery" itemprop="url">Tutoriels</a>
    		</footer>
    		<script src="http://danielhagnoul.developpez.com/lib/raphael-min.js"></script>
    		<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    		<script src="http://code.jquery.com/color/jquery.color-2.1.1.min.js"></script>
    		<script src="http://danielhagnoul.developpez.com/lib/dvjh/base.js"></script>
    		<script>
    			"use strict";
     
    			/*
    			 * Cliquez à l'extérieur !
    			 * Special event clickOutside
    			 * 
    			 * Daniel Hagnoul
    			 * Code v1.0.0 2012-12-09
    			 * 
    			 * L'événement requiert la transmission de l'attribut 
    			 * identity dans l'argument data du gestionnaire
    			 * d'événement.
    			 * 
    			 * L'attribut identity doit contenir un sélecteur 
    			 * jQuery valide correspondant à un ou des éléments 
    			 * du DOM.
    			 * 
    			 * Exemple : "article", ".test1" ou "#example".
    			 * 
    			 * L'événement ne se déclenche pas si
    			 * le clic se produit dans un élément du DOM qui 
    			 * possède ce sélecteur ou si l'un de ses ascendants
    			 * possèdent ce sélecteur.
    			 * 
    			 * Pour un sélecteur non spécifique, comme une 
    			 * classe ou un tag, cela peut être vu comme un 
    			 * inconvénient, mais c'est aussi un comportement 
    			 * souhaitable dans de nombreux cas.
    			 * 
    			 * Usage, exemple : $( document ).on( "clickOutside", 
    			 * { "identity" : "#monID" }, function( event ){...});
    			 */
    			( function( $ ){
     
    				var clickOutsideHandler = function( event ){
    	    				var identity = event.data.identity || "";
     
    	    				if ( $( event.target ).closest( identity )[ 0 ] === undefined ){
    	    					event.type = "clickOutside";
    	    					$.event.handle.apply( this, arguments );
    	    				}
    					};
     
    	   			$.event.special.clickOutside = {
    					setup : function( data, namespaces ){
    						jQuery( this ).on( "click", data, clickOutsideHandler );
    					},
    					teardown : function( namespaces ){
    						jQuery( this ).off( "click", clickOutsideHandler );
    					}
    	    		};
     
    			})( jQuery );
     
    			$(function(){
     
    				/*
    				 * Selon l'endroit où l'on clique, un à trois effets
    				 * peuvent se produiront.
    				 */
     
    				/*
    				 * Cas : $( "section.conteneur" ) et { "identity" : "div" }.
    				 * 
    				 * Comme il n'y a qu'une division dans le code de test, un clic
    				 * dans le sélecteur, mais à l'extérieur de la division agit sur 
    				 * la division.
    				 */
    				$( "section.conteneur" ).on( "clickOutside", { "identity" : "div" }, function( event ){
    					$( event.data.identity ).css( "background-color", "lightgrey" );
    				});
     
    				/*
    				 * Cas : $( document ) et { "identity" : ".test" }.
    				 * 
    				 * Comme il y a deux éléments du DOM qui ont cette classe
    				 * dans le code de test (la division et un tag article), seul 
    				 * un clic dans le sélecteur, mais à l'extérieur de ces 
    				 * éléments, agit sur la couleur du texte contenu dans ces 
    				 * éléments.
    				 */
    				$( document ).on( "clickOutside", { "identity" : ".test" }, function( event ){
    					$( event.data.identity ).css( "color", "green" );
    				});
     
    				/*
    				 * Cas : $( "body" ) et { "identity" : "#example" }.
    				 * 
    				 * Rappel : un ID doit être unique dans la page web.
    				 * 
    				 * Un clic dans le sélecteur, mais à l'extérieur de la 
    				 * division ayant cet ID, agit sur la division.
    				 */
    				$( "body" ).on( "clickOutside", { "identity" : "#example" }, function( event ){
    					$( event.data.identity ).css({ "width" : "20rem", "height" : "20rem" });
    				});
     
    			});
    		</script>
    	</body>
    </html>

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Ah c'est donc comme ça qu'on étend les Events jQuery. J'avais cherché mais n'avait point trouvé, merci pour le code.
    Sinon puis-je suggérer d'appeler l'évènement clickout pour rester en cohérence avec l'évènement mouseout ?
    Aussi concernant l'ordre des arguments, c'est un peu particulier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    /*
     * Cas : $( "section.conteneur" ) et { "identity" : "div" }.
    * 
    * Comme il n'y a qu'une division dans le code de test, un clic
     dans le sélecteur, mais à l'extérieur de la division agit sur 
    * la division.
    */
    $( "section.conteneur" ).on( "clickOutside", { "identity" : "div" }
    Ecrit comme ça, on pourrait croire que l'évènement survient lorsque l'on clique en dehors de section.conteneur. Je crois qu'il vaudrait mieux passer identity en sélecteur et définir le cadre en argument :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $( "#monDiv" ).on( "clickout", "section.conteneur", function(event){ ... });
    avec comme valeur par défaut document si le conteneur n'est pas indiqué.

    Inversement, on pourrait écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $( "section.conteneur" ).on( "click", ":not(#monDiv)", function(event){ ... });
    mais cela ne fonctionne pas si l'on clique sur un enfant de #monDiv.

    Donc ça se discute...
    Dans la mesure où le développeur veut identifier un clic en dehors d'un élément déterminé, ça me paraît plus logique de passer cet élément en premier. De plus, le cadre délimitant est facultatif, et pas l'élément exclus.

  3. #3
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Billets dans le blog
    125
    Par défaut
    Le choix du nom appartient à l'auteur. J'ai choisi "Cliquez à l'extérieur" qui se traduit par clickOutside.

    Je crois qu'un non-débutant en jQuery comprendra mes exemples d'utilisation et mes explications.

    Plutôt qu'une critique négative stérile, tu devrais écrire la version qui te convient et la posté à la suite et alors nous dire pourquoi tu penses qu'elle est supérieure à la proposition précédente.

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  4. #4
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Une critique négative stérile ?

    Permets-moi de repasser en revue mon post:

    Ah c'est donc comme ça qu'on étend les Events jQuery. J'avais cherché mais n'avait point trouvé, merci pour le code.
    Traduction: j'ai appris quelque-chose grâce à toi, je témoigne de ma reconnaissance. Déjà tu devrais être flatté au lieu de m'envoyer ballader

    Sinon puis-je suggérer d'appeler l'évènement clickout
    Ceci n'est pas une critique mais une suggestion, formulée de manière tout à fait aimable

    pour rester en cohérence avec l'évènement mouseout ?
    et argumentée de manière tout à fait valable il me semble

    Aussi concernant l'ordre des arguments, c'est un peu particulier :
    Ecrit comme ça, on pourrait croire que l'évènement survient lorsque l'on clique en dehors de section.conteneur. Je crois qu'il vaudrait mieux passer identity en sélecteur et définir le cadre en argument (...) avec comme valeur par défaut document si le conteneur n'est pas indiqué.
    Seconde suggestion, également argumentée, le clickOutside ne fait pas référence au sélecteur et peut donc être déroutant comparé aux autres évènements jQuery: $(objet).on("click") par rapport à $(cadre).on("clickOutside", {identity: objet})

    Inversement, on pourrait écrire :
    $( "section.conteneur" ).on( "click", ":not(#monDiv)", function(event){ ... });
    mais cela ne fonctionne pas si l'on clique sur un enfant de #monDiv.
    Là je me remets en question (et je repenche en ta faveur, dans l'ordre des arguments que tu as choisi !) en disant que cet ordre se rapproche plus de la logique initiale qu'aurait un dev jQuery voulant cette fonctionnalité, celle d'identifier la zone du clic puis d'exclure un event.target en paramètre à la manière du nouveau .live() en .on()

    Donc ça se discute...
    Appel au dialogue ! Visiblement avec toi faut pas compter là dessus...

    Dans la mesure où le développeur veut identifier un clic en dehors d'un élément déterminé, ça me paraît plus logique de passer cet élément en premier. De plus, le cadre délimitant est facultatif, et pas l'élément exclus
    Deux nouveaux arguments viennent appuyer ma suggestion, et me convainquent à te la formuler ici-même, pour le meilleur et pour le pire

    Donc il va falloir m'expliquer en quoi tout ceci est négatif et stérile. Je pense que tu devais être sacrément en pétard pour m'avoir répondu ça, j'espère sincérement qu'après une nuit de sommeil ou une douche froide tu sauras rejuger ça de manière plus posée.

    Maintenant, face à tes objections :
    Le choix du nom appartient à l'auteur. J'ai choisi "Cliquez à l'extérieur" qui se traduit par clickOutside.
    Okay très bien, mais là on parle d'une dizaine de lignes de code pour une fonctionnalité trouvable en une centaines de versions différentes sur le net. Pas de quoi vraiment déposer un brevet ! Surtout que ça vient à l'origine d'un topic où Bovino et moi avons posté le même code à quelques différences près ! D'ailleurs, c'est moi qui ai suggéré d'en faire un plug-in jQuery :
    http://www.developpez.net/forums/d12...v/#post7016660
    Donc le droit au baptême ça va cinq minutes... Si je te suggère de le renommer en clickout, c'est pas pour flatter mon égo mais pour des raisons bien valables :
    1) les évènements jQuery sont par convention intégralement en minuscules
    2) l'évènement standard le plus proche de celui-ci est mouseout, et pour des soucis de consistance dans le nommage il vaudrait mieux s'en inspirer. C'est pour la même raison qu'on a mousedown en parallèle à l'évènement keydown.

    Je crois qu'un non-débutant en jQuery comprendra mes exemples d'utilisation et mes explications.
    Tant qu'à faire, si un débutant pouvait comprendre aussi, ça serait utile sur ce forum Enfin ça confirme ce que je pensais, que tu as répondu ça en étant fatigué et sans avoir les idées claires

    tu devrais écrire la version qui te convient et la posté à la suite et alors nous dire pourquoi tu penses qu'elle est supérieure à la proposition précédente.
    Tu as déjà vu ma version dans le topic pré-cité et je pense avoir expliqué suffisamment en longueur pourquoi je pense que mes suggestions peuvent l'améliorer.

  5. #5
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Billets dans le blog
    125
    Par défaut
    Incompréhension mutuelle totale !

    Vous me prêtez des sentiments et des intentions que je n'éprouve pas.

    Pour moi, en programmation, les critiques sont stériles lorsqu'elles ne sont pas appuyées par un code meilleur que celui qui est critiqué.

    Si vous aviez pris le temps de "jouer" avec mon code (vous reconnaissez que ce type de code est nouveau pour vous) et essayez d'appliquer vos idées, je suis persuadé que vous n'auriez pas émis les mêmes commentaires.

    En ce qui me concerne, sauf apport d'un meilleur code que le mien, le sujet est clos.

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  6. #6
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Par défaut
    Citation Envoyé par danielhagnoul Voir le message
    Pour moi, en programmation, les critiques sont stériles lorsqu'elles ne sont pas appuyées par un code meilleur que celui qui est critiqué.
    Cela confirme mes craintes. J'espère que tu ne fais pas preuve du même zèle lorsque tu travailles en équipe ou échange avec un client...

    Pour moi, les idées valent mieux que les actes et avant de foncer tête baissée dans le code, je prends le temps de réfléchir à ce que je veux obtenir au final. C'est pourquoi mes suggestions ne concernaient pas ton code mais le plug-in obtenu au final. Si son utilisation s'avère peu intuitive voire déroutante, alors peu importe qu'il soit codé à merveille, il ne sera pas adopté.

    Lorsque je t'ai fait part de mes suggestions, je me suis placé en tant qu'utilisateur et non développeur. Puisqu'il s'agit là d'une contribution à destination de tous, je pense que tu devrais être un peu plus à l'écoute (et aimable, ça ne fait pas de mal non plus)

    Mais bon s'il n'y a que le code que tu daignes lire, voilà ce à quoi je suis arrivé:
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    (function($){
      var excluded = $([]);   
     
      $.event.special.clickout = {  
        setup: function(data){
          if(excluded.size()===0){
            $(document).on("click", $.event.special.clickout.handler);
          }
          $(this).data('outlimit', data && data.outlimit ? data.outlimit : document.body);        
          excluded = excluded.add(this);
        },
        teardown: function(data){
          $(this).removeData('outlimit');
          excluded = excluded.not(this);
          if(excluded.size()===0){
             $(document).off("click", $.event.special.clickout.handler);
          }
        },    
        add: function(handleObj){
          var old_handler = handleObj.handler;
          handleObj.handler = function(event,elm){
            event.target = elm; //redirect event
            old_handler.apply(this, arguments);
          };
        },
        handler: function(event){
          excluded.each(function(e,elm){
            var out = $(elm).data('outlimit') || document.body;
            if($(event.target).closest(elm).size() === 0 &&
               $(event.target).closest(out).size() !==0 ){
              //triggerHandler: stop event bubbling
              //extra parameters: click event target
              $(elm).triggerHandler( 'clickout', [ event.target ] );
            }
          });
        }      
      };
    })(jQuery);
    Démo : http://jsfiddle.net/wE529/

    Ce n'est certainement pas le "meilleur code", sûrement buggé et optimisable, mais ça aura le mérite de prouver qu'inverser les arguments est possible et que ça mérite de s'y intéresser...

Discussions similaires

  1. Besoin d'exemple d'utilisation d'un MouseListener
    Par hbzied dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 20/04/2006, 11h27
  2. [XML]Exemples d'utilisation
    Par le Daoud dans le forum XML/XSL et SOAP
    Réponses: 4
    Dernier message: 18/01/2006, 18h04
  3. Exemple d'utilisation de SOAP avec C++
    Par jlassira dans le forum Bibliothèques
    Réponses: 5
    Dernier message: 04/01/2006, 08h42
  4. Exemple d'utilisation de XMLDocument
    Par Mickey.jet dans le forum Langage
    Réponses: 4
    Dernier message: 20/06/2005, 19h51
  5. Recherche des exemple d'utilisation
    Par lemme dans le forum Merise
    Réponses: 2
    Dernier message: 26/02/2003, 13h00

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