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!