One Plugin to end all jQuery Plugins

Well, I could not resist this catchy title, could I? Perhaps I could. In any case I have this idea and implementation where one jQuery plugin is sort-of-a “socket” (not a network socket, but a socket in the wall) into which you can plug-in your “plugs” which will do standard jQuery related stuff.

Where “standard jQuery related stuff” is either changing the state of the DOM behind, or either using the information from the DOM to do something with it.

Meta Plugin
Meta Plugin

Example of the former is much loved “animation” stuff one can do with jQuery. Example of the latter, could be collecting some information from the DOM entities selected with the jQuery and doing something with that information. Sending it to some server or just displaying it would qualify as “doing something with the information”.

As it turns out it is easier to use jQuery for changing the state of the dom, then it is to use information that it can provide from the DOM, of the current page. This is because the latter involves your code which has nothing to do with the stuff that jQuery does. Strictly speaking this is not “difficult” , it is just not “naturally flowing” as jQuery chains of commands do.

Perhaps this looks a bit trivial, and you are perhaps wondering what am I going on about here, and why are you reading this post? You are demanding it,  and now I have to find an convincing use-case , to er… convince you. Ok, here we go. Consider writing a code that will “blanket” any user selected number of elements on the page, by placing one div “over” it. This div has to be just big enough to cover all the elements selected. We can make it transparent and/or write some text on it etc … Convincing enough for You? Good. So we have this clever algorithm which given set of overlapping squares, returns one square position and dimensions that “blankets” them all. Obviously we can imagine an plugin that does all of this. Walks through the current “stack” of selected elements, collects positions and dimensions of each , etc … And that is the point: plugin is required.

Each time you want to take something “out” form the jQuery object it is best to write a plugin that will take that “thing out” and then return it, or do something with it, and then return the jQuery instance (doing: return this;) so that Your beloved chaining is not broken.

If we could do the above we could have one (very) nice framework that would allow us to re use the plugin above for virtually “anything”. The actual solution will be in the callback given to the plugin. For example we could try solve the “blanketing” ?

Lovely … But. Will this work ? For starters, call to the callback() above may block the plugin or throw an exception. Fine. We can solve that.

Renamed it to “use”. This will execute the callback on a different call-path (not thread), and will also handle the exception thrown , if any. error_handler is either user defined or console or alert.

[nextpage title=”So far so good”]

Perhaps. What is this good for? Ok, for starters what we have here is an “meta thing”. “Meta concept”, overarching abstraction of a familly of abstractions. An “zigot” of meta-programming. In this case “plugin-of-plugins”. I shall call this “Meta Plugin”. Ok, but why is this a “good thing”?

For example , jQuery plugins are (badly?) missing name-spaces. There is no inbuilt classification of plugins, nor is there a valid way to do so. Which in the presence of hundreds of plugins is a problem. In the presence of thousands of plugins it will be (is already?) a nightmare. And to change jQuery plugin mechanism itself, is already a nightmare because of legacy plugins.

But, consider if everybody will be using “Meta Plugin” as an template? Simple but ubiquitous measure, which will give an single level hierarchy of namespacing for templates. Simply use this pattern, but in implementing it give it “your name”.

All the “Meta Plugin” implementations above are identical, but all are named differently. This guarantees (to some degree) re-usability of callbacks between different name-spaces. Like the callback c1() in the code above. This approach can be easily standardized by jQuery.

Name-spacing without name-spacing. Again if ubiquitously used this simple mechanism will do a lot of good for jQuery. It is indeed “yet another level of indirection” which makes code slower, but it seems it will be well worth it.

Now. There was/is a lot of discussion on how to develop re-usable architecture for jQuery patterns, how to “sneak in” namespaces, etc. All of this has proven that jQuery plugin namespaces can not be done properly without changing jQuery itself. And jQuery rightly team has not shown inclination to do so.

This “plugin meta architecture” is very unobtrusive and is not stopping anyone indulging in the above kind of plugin mental activity. The only requirement is to move all of that activity and solutions onto the callback object used here. So, one can fire away and do her favourite “ninja” scripting, but all in and around a callback object.

[nextpage title=”Conclusion”]
There is an small(ish) set of “official” jQuery plugins which are maintained by jQuery team. Consequently there is de-facto standard on what is a “good plugin”. And consequently to that there is a small list of “official” requirements for such a plugin. Each and every point in the list of “official” requirements for a good plugin one can be solve easily with the properly developed callback object, to be used by MetaPlugin.

This is one of the several possible valid callback object designs. Now let us see how is the callback object above solving the plugin requirements bellow.

  1. Claim only a single name in the jQuery namespace
    1. Solved, by using MetaPlugin
  2. Accept an options argument to control plugin behavior
    1. Using the callback as above this is easy (too).$("#toolbar").bbc( my_callback({ o1 : 1, o2: 2},":last") ;
  3. Provide public access to default plugin settings
    1. As made possible with the my_callback above. One just has to learn to use the callback object.// made here or somewhere else
      var callback = my_callback({ o1:1 })
      // just javascript
      var s1 = callback.default.s1
      //...
  4. Provide public access to secondary functions (as applicable)
    1. // just javascript
      callback.secondary() ;
      //...
  5. Keep private functions private
    1. As my_callback does…
  6. Support the Metadata Plugin
    1. As my_callback does, also

I thought it is better to have the solution for the “official” list of jQuery plugin requirements, here than in the comments bellow ;)
Of course one does not have to have all this “scafolding” to use MetaPlugin. Good old simple function will do, most of the time.

–DBJ