views:

34

answers:

3

I'm trying to use jQuery Button to build a button bar for each item on my page; however following the examples I get poor performance when the number of items goes over 100. I've added context to my calls which helped a little but it bugs me that I'm revisting the same context for each button built.

Below is an example of the code used to add a two button button bar to each item in my page. The context is the same, but it gets iterated over for each button in the button bar. Is there a way to iterate over this context once and apply the code to setup each button?

function initLater()
{
    $(function () {

        $('input.ItemSelect', $('#container fieldset div.controls div.controlsToolbar')).button({
            text: false,
            icons: {
                primary: 'ui-icon-check'
            }
        });
        $('a.btnPrint', $('#container fieldset div.controls div.controlsToolbar')).button({
            text: false,
            icons: {
                primary: 'ui-icon-print'
            }
        });
    });
}
A: 

Yes.

var toolbar = $('#container fieldset div.controls div.controlsToolbar');

toolbar.find('input.ItemSelect').button(...);
SLaks
+2  A: 

You can store and re-use the reference using .find(), like this:

function initLater()
{
    $(function () {
        var ctx = $('#container fieldset div.controls div.controlsToolbar');
        ctx.find('input.ItemSelect').button({
            text: false,
            icons: {
                primary: 'ui-icon-check'
            }
        });
        ctx.find('a.btnPrint').button({
            text: false,
            icons: {
                primary: 'ui-icon-print'
            }
        });
    });
}

A $(selector, context) call is really just a context.find(selector) internally anyway, you can see how it's handled here :)

Alternatively, you can chain it using .end(), like this:

$('#container fieldset div.controls div.controlsToolbar')
  .find('input.ItemSelect').button({
    text: false,
    icons: { primary: 'ui-icon-check' }
}).end().find('a.btnPrint').button({
    text: false,
    icons: { primary: 'ui-icon-print' }
});
Nick Craver
+1 for showing relevant jQuery source code. It's always useful to know how things are actually done.
Ken Redler
I like these but I was hoping to find a way to not have to reiterate over the context for each button. What I'd really like is a way to apply all of my button setup within each hit of the context so that I'd only traverse the context once.
William Jens
@William - This evaluates the `#container fieldset div.controls div.controlsToolbar` selector once, stores the results as DOM elements in an array (a jQuery object is a wrapped array of DOM elements), you're not fetching it twice, within those elements you're searching for `input.ItemSelect` and `a.btnPrint`, but you're not crawling the tree to get to the `.controlsToolbar` again, is that your concern?
Nick Craver
I guess that's a little better than what I thought. I had hoped there was maybe a 'sibblings' like solution so the array wouldn't need to be traversed more than once.
William Jens
@William - This part of things should be very fast, if they are siblings/direct children then `.children()` is faster than `.find()`, but that's about as good as it gets...the plugin code takes much more time to run than the selector though.
Nick Craver
@Nick - You're right - it's the plugin code that crawls. I replaced the button calls with a .css call to update the background color and it's fast. I might have to drop the button calls and roll my own button bar on the server. Thanks for pointing me in the right direction.
William Jens
+1  A: 

I don't see why not. $('#container fieldset div.controls div.controlsToolbar') is just an instance of the jQuery object, so it can be stored:

function initLater()
{
    $(function () {
         var cntxt = $('#container fieldset div.controls div.controlsToolbar');
        $('input.ItemSelect', cntext).button({
            text: false,
            icons: {
                primary: 'ui-icon-check'
            }
        });
        $('a.btnPrint', cntext).button({
            text: false,
            icons: {
                primary: 'ui-icon-print'
            }
        });
    });
}
JacobM