I've done a few hours of additional research but I still can't find a good pattern to what I would think is a common problem.
I'm working on a .Net MVC2 app. Our app is made up of a main page then a number of partial views (included pages) each one of the partial views corresponds to a widget consisting of an HTML structure and JS-jQuery guts
Some of our widgets have rich interactions with each other so of course we are using the jQuery's event binding something to the effect of this:
Data Summary Widget
$(document).bind("DataUpdated", summaryobject.updateTotals());
Data Manipulation Widget
$(document).trigger("DataUpdated");
The problem we are having is that as a user navigates to parts of the applications these widgets (HTML/DOM) are removed from the page and replace with the new set of partial views. When a user navigates back the HTML (visual representation) is reloaded along with the jQuery binding which creates a double binding.
So far my solutions seem lame to me.
(1) bind to the DOM object the binding is for:
$("#summaryobject").bind("DataUpdated", summaryobject.updateTotals());
The problem with this is that then my triggering widget needs to know what DOM bject to trigger on: $("#summaryobject")
which kind of defeats the purpose.
(2) Create a EventBus object to tract who bound which events and only allow events to be bound once. The problem I am having is when storing/binding the events I can't track who created it so I can't unregister it if I need to....perhaps unregistered events isn't event necessary.
What patterns are others using to manage custom events?
I ended up doing this for now:
under my pagemanager object I wrote this method
function PageManager() {
this.eventBusRegistry = [];
///<summary>Registers Event if not already bound</summary>
this.registerForEvent = function (eventName, eventOwner, functionToBind) {
if (this.eventBusRegistry[eventName + eventOwner] == null) {
this.eventBusRegistry[eventName + eventOwner] = "BOUND";
$(document).bind(eventName, functionToBind);
}
}
}
For my widgets class I did this.
///<summary>Widget</summary>
function Widget(inWidgetName) {
//the data you wish to update.
this.data = {};
//name of widget
this.widgetName = inWidgetName;
}
Widget.prototype.registerForEvent = function (eventName, functiontoBind) {
//Session is the instance of PageManager
Session.registerForEvent(eventName, this.widgetName, functiontoBind);
};
For any instance of a widget you call registerForEvent to bind events.
This is far from a perfect solution. Our design will still have memory leaks in that we don't unregister our JS objects. However, our objects are overwritten each time they are loaded so worse case is that every object in the application can be registered once, even if they are not used.
However, binding a method to an event binds to the document object which is not overwritten or course. So this code will stop us from rebinding. We still have a bit of a sloppy setup however it's ramifications should be minimized.