Last Updated: February 25, 2016
·
1.104K
· ultimatedelman

Wiring Up Events With Dynamic Singletons

In some webapps, it's possible to have singleton objects that get instantiated once but initialized often. For instance (assume jQuery):

(function(window){
 window.MyNamespace = window.MyNamespace || {};
 var MySingleton = MyNamespace.MySingleton = {
 init: function() {
 //init code
 }
 }
 MySingleton.init(); //init on load
})(window);

The above code adds a singleton to your global namespace (which can be referenced by MyNamespace.MySingleton elsewhere in your code). A lot of times, in the init() function, event binding takes place:

init: function() {
 this.elem = $('#myelem');

 //wire events to this specific element
 this.elem
 .on('click', '.myclass1', this.handleClick)
 .on('change', '.myclass2', this.handleChange)
 //etc
 ;

 //wire events to doc, like triggered custom events
 $(document)
 .on('customevent', this.handleCustomEvent)
 //etc
 ;
}

This is fine if your objects main element sticks around in the DOM and your singleton is not re-init-ed. But what if you have a webapp that dynamically loads your HTML, replacing whatever was there before? Your DOM elements will successfully rebind (assuming you have fresh DOM elements), but your document events will get re-bound, meaning they will react an increasing number of times as users flip through your app.

Handling this is simple: create a hasBound property on your singleton (simplified example):

var MySingleton = {
 hasBound: false
 , init: function() {
 // [ DOM wireup ]

 if (!this.hasBound) {
 // [ document wireup ]
 this.hasBound = true;
 }
 }
 }

Now you can safely re-init your singleton without worrying about multi-binding your events!