Wrapping a DOM Element Inside a JavaScript Object

I noticed a common template in JavaScript that I wrote, and wondered if there was already a template that defined something similar to best practice? Essentially, this is how to get the DOM element and wrap it inside / bind to a JavaScript object. Take this example where you need a filter in your web application. Your page looks like this:

<html> <head></head> <body> <div id="filter"></div> </body> </html> 

Then you wrap the element as follows:

 var myFilter = new Filter({ elem: document.getElementById('filter'), prop: 'stacks-test', someCallback: function() { // specify a callback } }); 

And JavaScript (where spec is the object passed to the constructor):

 var Filter = function(spec) { this.elem = spec.elem; this.prop = spec.prop; this.callback = spec.someCallback; this.bindEvents(); }; Filter.prototype.bindEvents = function() { var self = this; $(this.elem).click(function(e) { self.updateFeed(); }; }; Filter.prototype.updateFeed = function() { this.prop; // 'stacks-test' this.callback(); // ... // code to interact with other JavaScript objects // who in turn, update the document }; 

What is this approach called, and what are the best practices and warnings?

+7
source share
2 answers

You may be interested in the Dojo, Dijit widget library - if I understand your question correctly, it essentially does what you ask and much more.

In Dijit, a widget essentially encapsulates a DOM node, its contents, any JavaScript that defines its behavior, and (imported separately) CSS to style its appearance.

A widget has its own life cycle, registry, and events (including many that simply map to DOM events in the node inside the widget, for example myWidget.onClick can effectively call myWidget.domNode.onclick ).

Widgets can (but not necessarily) have their original content defined in a separate HTML template file, with which you can also bind events to nodes in the template to widget methods, as well as set widget properties that refer to specific nodes in the template.

I barely scratch the surface here. If you want to know more about this, you can start with these help pages:

Everyone said, I don’t know what you ultimately wanted, and maybe this is a little for your purposes (given that I am throwing you the whole other library), but I thought that this could cause interest at least.

+2
source

Continuing my comment on the question, jQuery is a potential tool to work with, as it already provides some basics for what you need. However, having said this, he introduces his own difficulties, and, moreover, not all jQuery paths are equal. I suggest one way to use jQuery as an "object model", but it may or may not suit your needs.


First of all. The philosophy of jQuery is that you start everything by first selecting an element using $() or equivalent to jQuery() . All operations conceptually begin with this. This is a slightly different mindset than creating an object that wraps the element and maintains a reference to that wrapper, but essentially this is what jQuery does for you. Calling $('#some-id') calls the element with the identifier "some-id" and transfers it to the jQuery object.


One way: Record Filter plugins.

Replace the constructor with the initFilter() jQuery method. You can do this by modifying the jQuery prototype and using the jQuery object as your wrapper. The jQuery prototype refers to jQuery.fn , therefore:

 jQuery.fn.initFilter = function (prop, callback) { // Save prop and callback this.data('filter-prop', prop); this.data('filter-callback', callback); // Bind events (makes sense to do this during init) this.click(function () { $(this).updateFeed(); }); }; 

Then do a similar thing for updateFeed() :

 jQuery.fn.updateFeed = function () { this.data('filter-prop'); this.data('filter-callback')(); }); 

And use it as follows:

 $('#filter').initFilter(prop, callback); 

Note that updateFeed can simply be inserted into the click handler to prevent unnecessary pollution of the jQuery namespace. However, one of the advantages of using jQuery like this is that you do not need to keep a reference to the object if you need to call some function on it later, since jQuery associates all the links with the actual elements. If you want to call the updateFeed program, then:

 $('#filter').updateFeed(); 

then will be called on the correct object.


Some things to consider

Of course, there are drawbacks to this method. First, all the properties that we saved against an element using .data() are shared by all jQuery functions that act on that element. I tried to make this easier by pre-assigning the filter names to the property names, but depending on the complexity of your object (s), this may not be acceptable.

Moreover, this exact method may not be so suitable for objects that require a lot of manipulation (i.e. objects with many functions), since all these functions become common to all jQuery objects. There are ways to encapsulate all this, which I will not go into, but jQuery-ui does this with its widgets, and I am experimenting with another alternative in the library being created.

However, backtracking a bit, the only reason I suggested using jQuery is primarily because your Filter object is heavily attached to the DOM. It binds events to the DOM, it modifies the DOM based on user interaction, it mainly lives in the DOM, so use something based on the DOM, i.e. jQuery.

+1
source

All Articles