Stas Bichenko
Stas Bichenko

Reputation: 13263

What is the preferred way to assign a jQuery object to a JavaScript object for event binding?

Example:

I want to create a multi-window webapp. Each window is a jQuery object (with a DOM element attached to it), but it should also have specific properties and methods (such as close() or minimize()). It seems then, that I should create a class MyWindow with a property DOMElement which would contain the jQuery object.

But how will I bind DOM events to the MyWindow objects?

I could do something like MyWindow.DOMElement.on('click', function(){...}. But the DOMElement doesn't know which MyWindow it's attached to and won't be able to manipulate it's properties if needed. For example, it wouldn't be able to invoke it's MyWindow's close() method.

I currently see two ways of solving this problem.

First. Extend the jQuery object in MyWindow.DOMElement property with a single property myWindow which would point to the object's parent MyWindow object.

Second. Extend the jQuery object with the MyWindow's properties and make it an instanceof MyWindow as well (through parasitic inheritance, perhaps?). This way event handlers will have access to all properties and methods of MyWindow through the use of this.

Both ways seem somewhat weird.

What is the preferred way to assign a DOM object to a Javascript object for event binding?

Upvotes: 1

Views: 108

Answers (1)

Rob Johnstone
Rob Johnstone

Reputation: 1734

I would essentially do as you say in your first solution:

MyWindow objects containing the relevant jquery object for the dom element as one of its properties:

var MyWindow = function(params) {
  this.close = function() {/*close window*/};
  this.minimise = function() {/*minimise window*/};
  this.$elm = $('#'+params.id);
  // do all the other stuff you have to do to initialise the window

  this.$elm.myWindow = this;
}

Then to bind a click:

window1 = new MyWindow({id: 'window'});
window1.$elm.on('click', function() {
  this.close();
});

EDIT: An alternative that I recently used is to have a separate event handler that routes events to the correct method of the correct object however this requires you to keep track of which ids correspond to which objects as the following code illustrates:

var myWindows = [];

var MyWindow = function(params) {
  // initialise object

  myWindows[params.id] = this;
};

$(function() {
  $(document).on({
    click: function(e) {
      var myWindow = myWindows[$(this).attr('id')];
      if (typeof myWindow.click === 'function') {
        myWindow.click(e);
      }
    }
  }, '.myWindow');
};

You then bind events by simply adding the appropriate method to the object

var myWindow = new MyWindow({'id': window});

myWindow.click = function(event) {
  this.close();
};

However, the danger with this approach is that you have to be very careful about keeping the myWindows array up to date or you get all sorts of memory leaks (clearly the difficulty/importance of this will depend on the context of your app).

Upvotes: 1

Related Questions