Create JavaScript custom event

后端 未结 4 413
予麋鹿
予麋鹿 2020-12-02 09:56

I would like to create a custom event in JavaScript.

I have a WPF application with a WebBrowser inside, and a HTML page with JavaScript.

I work with a printe

相关标签:
4条回答
  • 2020-12-02 10:05

    I like using this EventDispatcher constructor method, which, using a dummy element, isolates the events so they will not be fired on any existing DOM element, nor the window or document.

    I am using CustomEvent and not createEvent because it's the newer approach. Read more here.

    I like to wrap each native method with these names:

    on, off, trigger

    function eventDispatcher(){
      // Create a dummy DOM element, which is a local variable 
      var dummy = document.createTextNode('')
    
      // Create custom wrappers with nicer names
      return {
        off(...args){ 
          dummy.removeEventListener(...args) 
          return this
        },
        on(...args){ 
          dummy.addEventListener(...args) 
          return this
        },
        trigger(eventName, data){
          if( !eventName ) return
          
          // if the event should be allowed to bubble, 
          // then "dummy" must be in the DOM
          var e = new CustomEvent(eventName, {detail:data})
          dummy.dispatchEvent(e)
          return this
        }
      }
    }
    
    ////////////////////////////////////
    // initialize the event dispatcher by creating an instance in an isolated way
    var myEventDispatcher = eventDispatcher();
    
    ////////////////////////////////////
    // listen to a "foo" event
    myEventDispatcher
      .on('foo', e => console.log(e.type, e.detail) )
      .on('bar', e => console.log(e.type, e.detail) )
    
    ////////////////////////////////////
    // trigger a "foo" event with some data
    myEventDispatcher
      .trigger('foo', 123)
      .trigger('bar', 987);


    The above eventDispatcher could be integrated into another code, for example, a Constructor: (for example some component)

    function eventDispatcher(){
      var dummy = document.createTextNode('')
    
      return {
        off(...args){ 
          dummy.removeEventListener(...args) 
          return this
        },
        on(...args){ 
          dummy.addEventListener(...args) 
          return this
        },
        trigger(eventName, data){
          if( !eventName ) return
          var e = new CustomEvent(eventName, {detail:data})
          dummy.dispatchEvent(e)
          return this
        }
      }
    }
    
    /////////////////////////////
    // Some component: 
    
    var MyComponent = function(){
      // merge `EventDispatcher` instance into "this" instance
      Object.assign(this, eventDispatcher())
      
      // set some default value
      this.value = 1
    }
    
    MyComponent.prototype = {
      set 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("Type:", e.type,", Value:", e.detail) )
    
    // set some value
    comp.value = 3;


    See related answer to the question "Event Handler Namespace in Vanilla JavaScript"

    0 讨论(0)
  • 2020-12-02 10:19

    Requirement: 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();

    0 讨论(0)
  • 2020-12-02 10:22

    Perhaps something like this?

    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);
    });
    

    An alternative solution would be to use function composition, but then it would be hard to remove specific listeners.

    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');
    });
    

    EDIT:

    Here's how you can do it with 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);
    });
    
    0 讨论(0)
  • 2020-12-02 10:23

    Ok I found a solution.

    I had to change the WebBrowser IE Version to Internet Explorer 11: http://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version

    And then :

    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
    });
    
    0 讨论(0)
提交回复
热议问题