web-dev-qa-db-fra.com

Créer un événement personnalisé JavaScript

J'aimerais créer un événement personnalisé en JavaScript.

J'ai une application WPF avec un navigateur Web à l'intérieur et une page HTML avec JavaScript.

Je travaille avec une imprimante. Lorsque l'état de l'imprimante change, un événement est généré dans .NET.

Ensuite, j'appelle une méthode JavaScript OnPrinterStateChanged(state) avec la fonction InvokeScript du contrôle WebBrowser.

Le problème est que je dois implémenter la méthode OnPrinterStateChanged(state) dans ma page Web. Je ne peux pas changer le nom de la méthode ou m'abonner/me désabonner à l'événement ...

Je voudrais déplacer la méthode JavaScript OnPrinterStateChanged(state) dans un fichier JavaScript séparé.

Ce que je veux :

  • S'abonner/Se désabonner de l'événement dans ma page HTML et décider de ce que je veux faire lorsque l'événement est déclenché (ex.: "Function ChangeState")
  • Lorsque l'événement .NET est déclenché, il appelle la OnPrinterStateChanged(state) de mon fichier .js séparé, puis l'événement JavaScript est déclenché et la fonction ChangeState est appelée.

J'ai trouvé des solutions mais je n'ai pas réussi à le faire fonctionner ... Quel est le moyen le plus simple de le faire?

60
Gab

Peut-être quelque chose comme ça?

function OnPrinterStateChanged(state) {
    var evt = new CustomEvent('printerstatechanged', { detail: state });

    window.dispatchEvent(evt);
}


//Listen to your custom event
window.addEventListener('printerstatechanged', function (e) {
    console.log('printer state changed', e.detail);
});

Une solution alternative consisterait à utiliser la composition de fonction, mais il serait alors difficile de supprimer des écouteurs spécifiques.

function OnPrinterStateChanged(state) {}

function compose(fn1, fn2) {
    return function () {
        fn1.apply(this, arguments);
        fn2.apply(this, arguments);
    };
}

//Add a new listener
OnPrinterStateChanged = compose(OnPrinterStateChanged, function (state) {
    console.log('listener 1');
});

//Add another one
OnPrinterStateChanged = compose(OnPrinterStateChanged, function (state) {
     console.log('listener 2');
});

MODIFIER:

Voici comment vous pouvez le faire avec jQuery.

function OnPrinterStateChanged(state) {
    var evt = $.Event('printerstatechanged');
    evt.state = state;

    $(window).trigger(evt);
}


//Listen to your custom event
$(window).on('printerstatechanged', function (e) {
    console.log('printer state changed', e.state);
});
89
plalx

J'aime utiliser cette méthode de constructeur EventDispatcher qui, à l'aide d'un élément factice, isole les événements afin qu'ils ne soient déclenchés sur aucun élément DOM existant, ni le window ou document. .

J'utilise CustomEvent et non pas createEvent parce que c'est l'approche la plus récente. Lire la suite ici .

J'aime envelopper chaque méthode native avec ces noms:

on, off, trigger

function EventDispatcher(){
    // Create a dummy DOM element 
    var dummy = document.createTextNode('');

    // Create custom wrappers with nicer names
    this.off = dummy.removeEventListener.bind(dummy);
    this.on = dummy.addEventListener.bind(dummy);
    this.trigger = function(eventName, data){
        if( !eventName ) return;
        var e = new CustomEvent(eventName, {"detail":data});
        dummy.dispatchEvent(e);
    }
}

////////////////////////////////////
// initialize the event dispatcher by creating an instance in an isolated way
var myEventDispatcher = new EventDispatcher();

////////////////////////////////////
// listen to a "foo" event
myEventDispatcher.on('foo', e =>{
    console.log(e.type, e.detail);
});

////////////////////////////////////
// trigger a "foo" event with some data
myEventDispatcher.trigger('foo', 123);

Le EventDispatcher ci-dessus pourrait être utilisé dans un autre code

(par exemple un composant)

function EventDispatcher(){
    // Create a dummy DOM element 
    var dummy = document.createTextNode('');

    // Create custom wrappers with nicer names
    this.off = dummy.removeEventListener.bind(dummy);
    this.on = dummy.addEventListener.bind(dummy);
    this.trigger = function(eventName, data){
        if( !eventName ) return;
        var e = new CustomEvent(eventName, {"detail":data});
        dummy.dispatchEvent(e);
    }
}

/////////////////////
// Some component: //
/////////////////////

var MyComponent = function(){
    // set some default value
    this.value = 1;

    // merge `EventDispatcher` instance into "this" ('MyComponent' instance)
    Object.assign(this, new EventDispatcher()); 
}

MyComponent.prototype = {
    set : function(v){
        this.value = v;
        this.trigger('change', v);
    }
}

var comp = new MyComponent();

// bind a listener to "comp" (which itself is an instance of "MyComponent")
comp.on('change', e =>{
    console.log("event type:", e.type, "  |  event value:", e.detail);
});

// set some value
comp.set(3);

Voir la référence réponse à la question "Espace de noms du gestionnaire d'événements en JavaScript Vanilla"

6
vsync

Condition requise: ES6

let MyClass = (function () {
    let __sym = Symbol('MyClass');

    class MyClass {
        constructor() {
            this[__sym] = {};
        }
        on(event, callback) {
            this[__sym][event] = { callback: callback }
        }
        getError() {
            let event = this[__sym].error;

            if (event && event.callback) {
                event.callback('some parameter');
            }
        }
    }

    return MyClass;
}());

let myClass = new MyClass();

myClass.on('error', function (e) {
    console.log('error:', e);
});

console.log('before getting error:');

myClass.getError();
1
user9235753

Ok j'ai trouvé une solution.

Je devais changer le navigateur Web IE Version pour Internet Explorer 11: http://weblog.west-wind.com/posts/2011/May/21/Web-Browser- Control-Specifying-the-IE-Version

Puis :

function OnPrinterStateChanged(state) {

    var evt = document.createEvent("Event");
    evt.state = state;
    evt.initEvent("printerstatechanged", true, false);
    window.dispatchEvent(evt);

}


window.addEventListener('printerstatechanged', function (e) {
  // Do something
});
1
Gab