web-dev-qa-db-fra.com

Événements personnalisés dans jQuery?

Je cherche des idées sur la meilleure façon d'implémenter la gestion d'événements personnalisée dans jQuery. Je sais comment raccorder des événements à partir des éléments dom tels que 'click', etc., mais je construis une minuscule bibliothèque/plug-in javascript pour gérer certaines fonctionnalités de prévisualisation.

J'ai un script en cours d'exécution pour mettre à jour du texte dans un élément dom à partir d'un ensemble de règles et de données/entrées utilisateur que j'ai obtenues, mais maintenant, j'ai besoin de ce même texte affiché dans d'autres éléments que ce script ne peut pas connaître. Ce dont j'ai besoin, c'est d'un bon modèle pour observer en quelque sorte ce script produisant le texte nécessaire.

Alors, comment je fais ça? Ai-je oublié certaines fonctionnalités intégrées de jquery pour déclencher/gérer des événements utilisateur ou ai-je besoin d'un plugin jquery pour le faire? Selon vous, quel est le meilleur moyen/plugin de gérer cela?

172

Regarde ça:

(reproduit à partir de la page de blog expirée http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/ basé sur la version archivée de http://web.archive.org/web/20130120010146/http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/ )


Publier/S'abonner avec jQuery

17 juin 2008

Dans le but d’écrire une interface utilisateur jQuery intégrée à la fonctionnalité hors ligne de Google Gears, j’ai utilisé un code pour rechercher l’état de la connexion réseau à l’aide de jQuery.

L'objet de détection de réseau

Le principe de base est très simple. Nous créons une instance d'un objet de détection de réseau qui interrogera une URL à intervalles réguliers. Si ces demandes HTTP échouent, nous pouvons supposer que la connectivité réseau a été perdue ou que le serveur est tout simplement inaccessible à l'heure actuelle.

$.networkDetection = function(url,interval){
    var url = url;
    var interval = interval;
    online = false;
    this.StartPolling = function(){
        this.StopPolling();
        this.timer = setInterval(poll, interval);
    };
    this.StopPolling = function(){
        clearInterval(this.timer);
    };
    this.setPollInterval= function(i) {
        interval = i;
    };
    this.getOnlineStatus = function(){
        return online;
    };
    function poll() {
        $.ajax({
            type: "POST",
            url: url,
            dataType: "text",
            error: function(){
                online = false;
                $(document).trigger('status.networkDetection',[false]);
            },
            success: function(){
                online = true;
                $(document).trigger('status.networkDetection',[true]);
            }
        });
    };
};

Vous pouvez voir la démo ici. Configurez votre navigateur pour qu'il fonctionne hors ligne et voyez ce qui se passe…. non, ce n’est pas très excitant.

Déclenchement et liaison

Ce qui est passionnant cependant (ou du moins ce qui me passionne) est la méthode par laquelle le statut est relayé par l’application. J’ai trébuché sur une méthode peu discutée d’implémentation d’un système pub/sub en utilisant les méthodes de déclenchement et de liaison de jQuery.

Le code de la démo est plus obtus que nécessaire. L’objet de détection de réseau publie les événements d’état "Statut" dans le document, qui les écoute activement et, à son tour, publie les événements "Alerter" à tous les abonnés (pour plus d’informations plus tard). Le raisonnement derrière cela est que, dans une application du monde réel, il y aurait probablement plus de logique pour contrôler quand et comment les événements "notify" sont publiés.

$(document).bind("status.networkDetection", function(e, status){
    // subscribers can be namespaced with multiple classes
    subscribers = $('.subscriber.networkDetection');
    // publish notify.networkDetection even to subscribers
    subscribers.trigger("notify.networkDetection", [status])
    /*
    other logic based on network connectivity could go here
    use google gears offline storage etc
    maybe trigger some other events
    */
});

En raison de l’approche centrée DOM de jQuery, les événements sont publiés sur (déclenchés) sur des éléments DOM. Cela peut être la fenêtre ou l'objet de document pour les événements généraux ou vous pouvez générer un objet jQuery à l'aide d'un sélecteur. L’approche que j’ai adoptée avec la démo consiste à créer une approche presque identique pour la définition des abonnés.

Les éléments DOM qui doivent être abonnés sont classés simplement avec "abonné" et "networkDetection". Nous pouvons alors publier des événements uniquement sur ces éléments (dont il n'y en a qu'un dans la démo) en déclenchant un événement de notification sur $(“.subscriber.networkDetection”)

Le div #notifier qui fait partie du groupe d'abonnés .subscriber.networkDetection A alors une fonction anonyme liée à celui-ci, effectivement agissant en tant qu'auditeur.

$('#notifier').bind("notify.networkDetection",function(e, online){
    // the following simply demonstrates
    notifier = $(this);
    if(online){
        if (!notifier.hasClass("online")){
            $(this)
                .addClass("online")
                .removeClass("offline")
                .text("ONLINE");
        }
    }else{
        if (!notifier.hasClass("offline")){
            $(this)
                .addClass("offline")
                .removeClass("online")
                .text("OFFLINE");
        }
    };
});

Alors voilà. C’est très joli et mon exemple n’est pas du tout excitant. Cela ne présente pas non plus quoi que ce soit d’intéressant que vous puissiez faire avec ces méthodes, mais si quelqu'un est intéressé à creuser par le biais de la source, n'hésitez pas. Tout le code est inséré dans l'en-tête de la page de démonstration

103
Vitor Silva

Le lien fourni dans la réponse acceptée montre une manière simple d’implémenter le système de publication/sous à l’aide de jQuery, mais j’ai trouvé le code un peu difficile à lire. voici ma version simplifiée du code:

http://jsfiddle.net/tFw89/5/

$(document).on('testEvent', function(e, eventInfo) { 
  subscribers = $('.subscribers-testEvent');
  subscribers.trigger('testEventHandler', [eventInfo]);
});

$('#myButton').on('click', function() {
  $(document).trigger('testEvent', [1011]);
});

$('#notifier1').on('testEventHandler', function(e, eventInfo) { 
  alert('(notifier1)The value of eventInfo is: ' + eventInfo);
});

$('#notifier2').on('testEventHandler', function(e, eventInfo) { 
  alert('(notifier2)The value of eventInfo is: ' + eventInfo);
});
119
Manuel Navarro

Je pense que oui ... il est possible de "lier" des événements personnalisés, comme (de: http://docs.jquery.com/Events/bind#typedatafn ):

 $("p").bind("myCustomEvent", function(e, myName, myValue){
      $(this).text(myName + ", hi there!");
      $("span").stop().css("opacity", 1)
               .text("myName = " + myName)
               .fadeIn(30).fadeOut(1000);
    });
    $("button").click(function () {
      $("p").trigger("myCustomEvent", [ "John" ]);
    });
21
Tuxified

J'avais une question similaire, mais je cherchais une réponse différente. Je cherche à créer un événement personnalisé. Par exemple, au lieu de toujours dire ceci:

$('#myInput').keydown(function(ev) {
    if (ev.which == 13) {
        ev.preventDefault();
        // Do some stuff that handles the enter key
    }
});

Je veux l'abréger à ceci:

$('#myInput').enterKey(function() {
    // Do some stuff that handles the enter key
});

déclencher et lier ne raconte pas toute l’histoire, c’est un plugin JQuery. http://docs.jquery.com/Plugins/Authoring

La fonction "enterKey" est attachée en tant que propriété à jQuery.fn - c'est le code requis:

(function($){
    $('body').on('keydown', 'input', function(ev) {
        if (ev.which == 13) {
            var enterEv = $.extend({}, ev, { type: 'enterKey' });
            return $(ev.target).trigger(enterEv);
        }
    });

    $.fn.enterKey = function(selector, data, fn) {
        return this.on('enterKey', selector, data, fn);
    };
})(jQuery);

http://jsfiddle.net/b9chris/CkvuJ/4/

Une des merveilles de ce qui précède est que vous pouvez gérer les entrées au clavier avec élégance sur des écouteurs de liens tels que:

$('a.button').on('click enterKey', function(ev) {
    ev.preventDefault();
    ...
});

Modifications: mise à jour pour transmettre correctement le contexte this correct au gestionnaire et pour renvoyer toute valeur renvoyée par le gestionnaire à jQuery (par exemple, dans le cas où vous souhaitiez annuler l'événement et le bouillonnement). Mise à jour pour transmettre un objet événement jQuery approprié aux gestionnaires, y compris le code de clé et la possibilité d'annuler un événement.

Old jsfiddle: http://jsfiddle.net/b9chris/VwEb9/24/

15
Chris Moschini

C'est un ancien post, mais je vais essayer de le mettre à jour avec une nouvelle information.

Pour utiliser des événements personnalisés, vous devez le lier à un élément DOM et le déclencher. Donc vous devez utiliser

La méthode .on () prend un type d'événement et une fonction de gestion d'événement comme arguments. En option, il peut également recevoir des données liées à un événement en tant que deuxième argument, poussant la fonction de gestion des événements vers le troisième argument. Toutes les données transmises seront disponibles pour la fonction de gestion des événements dans la propriété data de l'objet événement. La fonction de gestion des événements reçoit toujours l'objet événement comme premier argument.

et

La méthode .trigger () prend un type d'événement comme argument. Facultativement, cela peut aussi prendre un tableau de valeurs. Ces valeurs seront transmises à la fonction de gestion des événements en tant qu'arguments après l'objet événement.

Le code ressemble à ceci:

$(document).on("getMsg", {
    msg: "Hello to everyone",
    time: new Date()
}, function(e, param) {
    console.log( e.data.msg );
    console.log( e.data.time );
    console.log( param );
});

$( document ).trigger("getMsg", [ "Hello guys"] );

On peut trouver une bonne explication ici et ici . Pourquoi cela peut-il être utile? J'ai trouvé comment l'utiliser dans cette excellente explication de ingénieur Twitter .

PS En clair, vous pouvez le faire avec new CustomEvent , mais méfiez-vous de IE et problèmes de Safari.

8
Salvador Dali

Voici comment je crée des événements personnalisés:

var event = jQuery.Event('customEventName);
$(element).trigger(event);

Certes, vous pourriez simplement faire

$(element).trigger('eventname');

Mais la façon dont je vous ai écrit vous permet de détecter si l’utilisateur a empêché par défaut ou non de le faire.

var prevented = event.isDefaultPrevented();

Cela vous permet d'écouter la demande de votre utilisateur final d'interrompre le traitement d'un événement particulier, par exemple si vous cliquez sur un élément de bouton dans un formulaire, mais que vous ne souhaitez pas que le formulaire soit publié en cas d'erreur.


J'écoute alors habituellement des événements comme ça

$(element).off('eventname.namespace').on('eventname.namespace', function () {
    ...
});

Encore une fois, vous pourriez juste faire

$(element).on('eventname', function () {
    ...
});

Mais j'ai toujours trouvé cela un peu dangereux, surtout si vous travaillez en équipe.

Il n'y a rien de mal à ce qui suit:

$(element).on('eventname', function () {});

Cependant, supposons que je doive dissocier cet événement pour une raison quelconque (imaginez un bouton désactivé). Je devrais alors faire

$(element).off('eventname', function () {});

Cela supprimera tous les événements eventname de $(element). Vous ne pouvez pas savoir si, à l'avenir, quelqu'un liera également un événement à cet élément et vous annuleriez également par inadvertance cet événement.

Le moyen le plus sûr d’éviter cela est d’espacer les espaces de noms en faisant

$(element).on('eventname.namespace', function () {});

Enfin, vous avez peut-être remarqué que la première ligne était

$(element).off('eventname.namespace').on('eventname.namespace', ...)

I personally always unbind an event before binding it just to make sure that the same event handler never gets called multiple times (imagine this was the submit button on a payment form and the event had been bound 5 times)

3
Luke Madhanga