Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery, A search for a smarter way to Initialize

I'm looking for a better way to manage global component/plugin/widget initialization in a large project. It has many jQuery-powered components that I would like to initialize quickly & efficiently and after scouring the internet, I've only really found short-sighted examples that are only realistic/performant in smaller sites.

The Problem

I Want to find a smart & elegant way of getting rid of this:

$(function() { $('.widget-one').widgetOne(); });
$(function() { $('.widget-two').widgetTwo(); });
$(function() { $('.widget-three').widgetThree(); });
$(function() { $('.widget-four').widgetFour(); });

Now before you smack me for it, let me state that I know that in most cases (but not all) .widget-one is a bad selector as it will on older browsers get all elements in the dom and check for the class.

The issue is, these widgets are not one-off's, and I may not know about thier existance ahead of time (generated in a web app view, maybe 2-3 times based on logic or a loop of products or something).

So the following solutions are out:

$(function() { $('#WidgetOne').widgetOne(); });

and

<span id="WidgetOne_12345">...</span>
<script type="javascript">
   $(function() { $('#WidgetOne_12345').widgetOne(); });
</script>

Thoughts

This is not a new problem, It's been around since day one. It still baffles me how this is so difficult to solve with jQuery even at this level of maturity. Either that or I'm missing something blatantly obvious.

Unfortunately google-fu turns out badly on this subject as everyone suggests one of two things:

  • jQuery's .live() or .delegate() catch-all event handlers. This is just scary on a fundamental level. .delegate() wouldn't be so bad, but this requires that the plugin/widget/control/whatever be entirely event driven. This would work in a lot of cases for sure, but not in others. It also makes following & organizing the code very complex. I won't even go into .live(), for large complex sites, the event bubbling is slow & when you get enough components together, the list of queries to match becomes large making each click/focus/whatever event incrementally slower on the whole for the entire page.
  • Work arounds that involve plugins like liveQuery, which is a very cool plugin for sure but it primarily seems to have been designed to solve a different issue (the issue of new items being brought in by ajax/dom creation), and still will get incrementally slower the more queries that stack up that need to be checked against.

Conclusion

There has to be a better way, I know there has to be one. I've exhausted my google fu on the subject, and still cannot find ideas/concepts/examples/discussion that is newer than jQuery 1.3.2 or with a grand picture in mind. In a perfect world this wouldn't be a problem because everyone would use intelligent browsers with modern standards & a decent javascript engine, and .class queries wouldn't take eons and eons, but unfortunately this is not the case.

I'm looking for ideas on how to tackle this, after going through many SO questions similar to this, and many articles on various jquery techniques I feel that if the information is out there it's buried underneath the many false positives & "101 best jquery plugin" results that turn up in any search with jQuery. I know someone out there has ran into this predicament.

Ideas, links, examples, anything is welcome, there just has to be a better way.

like image 909
Aren Avatar asked Dec 01 '11 19:12

Aren


1 Answers

just brainstorming off the top of my head I can think of one thing that would decrease your "select and initialize" time, but may be a trade off in pain during development. furthermore, you can't really use params with this method, but if you have a situation exactly like the one you describe above, this may be worth doing.

if you maintain that each of your initializing elements all have the same class (like widget for example), you can create a single selector system of initializing your widgets.

structure the classes instead like this in your HTML:

<div class="widget" widgetFunc="widgetOne"></div>
<div class="widget" widgetFunc="widgetTwo"></div>

etc.

and your jquery init function will look like:

var $widgetInitializerElements = $('.widget');

$.each($widgetInitializerElements,function(){ 
    var initialize = window[$(this).attr('widgetFunc')];

    if(typeof initialize === 'function'){
        $(this).initialize(); 
    }
});

so this would reduce your selection to one time, and keep your jquery pretty clean. you just have to worry about all those HTML elements which may not be feasible and you will have trouble if you need to add params to initialize calls :/

like image 174
Evan Avatar answered Sep 29 '22 16:09

Evan