toy toy - 3 months ago 12
Javascript Question

How to make sure that the event is only added once?

I want to check if every time the URL has changed, I'd fire an event. Since, there's no pushstate event I'm following this advice How to get notified about changes of the history via history.pushState?

(function(history) {
var pushState = history.pushState;
history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({
state: state
});
}
return pushState.apply(history, arguments);
}

function e(event) {
console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
}
window.addEventListener('popstate', e);
history.onpushstate = e;
})(window.history)


However, my lib allows mutliple instances. If I initialize my library multiple times, I'd get messages according to how many times the the library has been initialized. Is there anyway I can make sure that only one event is attached even though I run that snippet multiple times?

Answer

One way to accomplish this might be through the use of an intermediary object. This approach would allow you control over the event in the instance that you want to remove it and can be extended easily for other similar use cases. I've added a public isBound boolean incase of an instance where you would want to verify that the event has been subscribed to.

(function(history) {
  var pushState = history.pushState;

  function e(event) {
    console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
  }

  function proxyPopstateEvent (evt) {
    history.pushState = function(state) {
      if (typeof history.onpushstate == "function") {
        history.onpushstate({
          state: state
        });
      }
      return pushState.apply(history, arguments);
    }

    var proxy = function (e) {
      this.event = e;
      this.isBound = false;

      this.bindPopstateEvent = function() {
        window.addEventListener('popstate', this.event);
        history.onpushstate = this.event;
        this.isBound = true;
      }

      this.removePopstateEvent = function() {
        window.removeEventListener('popstate', this.event);
        history.onpushstate = {};
      }
    };
    window.popstateEventProxy = new proxy(evt);
    window.popstateEventProxy.bindPopstateEvent();
  }

  if (!window.popstateEventProxy) {
    proxyPopstateEvent(e);
  }
})(window.history)
Comments