Just jQuery The Core UI - Easy Plugins
Written by Ian Elliot   
Sunday, 21 May 2023
Article Index
Just jQuery The Core UI - Easy Plugins
The Table Plugin
Option

The Table Plugin

So now we can create our table plugin, which is easy:

$.fn.table=table;

That's all we have to do. Of course, in most cases you would define the function as an anonymous function:

$.fn.table=function(n,m){....};

but you don't have to.

Now you can create a table just by writing:

var myTable=$().table(2,3);

and then add it to a node in the DOM using

$("body").append(myTable);

jQuery Integration

This is easy, but surely the table function should append the element it creates to any elements selected by the jQuery call?

That is, it would be better if you could write:

$("body").table(2,3);

and have the new element automatically append to the body element as the last child.

The key to doing this is to know that when the table function is called the context, i.e. this, is set to the jQuery results object returned by $("body"). Thus you can work with the jQuery results object within your function quite easily.

To append the table to the DOM objects selected by "body" all you need to do is change the end of the function to read: 

 this.append(table);
 return table;
}

This works perfectly but it has some consequences. You can now write:

$("body").table(3, 2);

and the table will be appended as the last child element of the body. 
However, you can now no longer call your function outside of the context of jQuery. In other words, it can only be run as a plugin. To stop its direct use you need to either define it as an anonymous function or in an immediately invoked function expression IIFE, more of which later.

The next problem is that the append will add your table object to each of the selected elements in the jQuery object. That is, if you do:

$("div").table(3, 2);

a 3 by 2 table will be added as the last child of each matching div.

This might be exactly what you want to do, but if you want to take the alternative standard jQuery action of only affecting the first selected element you have to code this in your plugin.

So, for example, if you want to change the behavior to adding a table to the first element of the selection you might use: 

 this.first().append(table); 
 return table;
}

However, you have to be careful how to work with the selection – it has repercussions as we will see.

Chaining

When you write a plugin you have to take great care what you decide to return. It can make your plugin very usable or very irritating. In most cases jQuery methods return a jQuery object, usually the one they were passed in the context, this, or a modified version of it.

The reason they return the jQuery object is because this allows the chaining of methods that makes jQuery so easy and powerful.

Of course you can't always fit in with this pattern. If your plugin needs to return some information, such as the maximum height of an element say, then it has to return a numeric result and chaining has to stop.

However, the situation is usually not as clear cut as this. For example, in our case the table plugin is currently returning a table object.

Is this sensible?

Well as the table object is currently appended to the first element in the jQuery object returning it doesn't make much sense. It seems more reasonable to return the jQuery object and allow chaining to continue. 

To do this the end of the function has to be written as: 

 this.first().append(table); 
 return this; 
}

Now you can write:

$("div").table(3, 2).append("some text");

and the table object will be added to the first div and the text will then be added to the elements in the jQuery object in the usual way.

Does the final append add to all of the divs or just the first one in the selection?

The point is that the first() method reduces the selection to the first element so you might make the mistake of thinking that this is all the jQuery object you return contains. A moment’s thought should convince you that, as we return this, what append works on is the original jQuery object with all of the divs selected. Hence the text is added to all the div elements.

What if you want the table method to modify the selection? That is, after using table only the first element is in the selection to be passed on to subsequent chained methods. Once again the answer should be obvious - simply save the jQuery object you want to pass on and use it in the return.

For example: 

 var newjQuery=this.first().append(table); 
 return newjQuery;
}

Now when you try: 

$("div").table(3, 2).append("some text");

the text is added only to the first div.

The rule is that when your plugin is called this is a jQuery object of all the elements that have been selected. If you want to allow chaining you have to return a jQuery object – either the original or a modified one as appropriate.

In general, if your plugin's name doesn't sound as though it should change the selection, you are safer returning the unmodified selection.

If you want to be really clever you can opt to return something different if there are no selected elements.

For example:

if(this.length===0){ 
 return table; 
}else{ 
 this.first().append(table); 
 return this; 
}

which returns the jQuery object that contains the table element if nothing is selected and the original jQuery object if there are selected elements. It lets you write:

var myTable=$().table(3, 2).append("some text");
$("#div2").append(myTable);

which appends the text to the table element and then lets you do what you want with the resulting DOM object.

If you plan to make your plugin vary what it returns make sure that it seems natural. In this case returning the table object seems to make sense as this is like appending it to nothing.

Even if it is obvious and natural, make sure you document it.



Last Updated ( Sunday, 21 May 2023 )