Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programming a callback function within a jQuery plugin

I'm writing a jQuery plug-in so I can reuse this code in many places as it is a very well used piece of code, the code itself adds a new line to a table which has been cloned from a hidden row, it continues to perform a load of manipulations on the new row.

I'm currently referencing it like this:

$(".abc .grid").grid();

But I want to include a callback so each area the plug-in is called from can do something a bit more unique when the row has been added. I've used the jQuery AJAX plug-in before, so have used the success callback function, but cannot understand how the code works in the background. Here's what I want to achieve:

$(".abc .grid").grid({
    row_added: function() {
        // do something a bit more specific here
    }
});

Here's my plug-in code

(function($){           

    $.fn.extend({ 

        //pass the options variable to the function
        grid: function() {

            return this.each(function() {

                grid_table=$(this).find('.grid-table > tbody');
                grid_hidden_row=$(this).find('.grid-hidden-row');
                //console.debug(grid_hidden_row);
                $(this).find('.grid-add-row').click(function(event) {
                /* 
                 * clone row takes a hidden dummy row, clones it and appends a unique row 
                 * identifier to the id. Clone maintains our jQuery binds
                 */

                    // get the last id
                    last_row=$(grid_table).find('tr:last').attr('id');
                    if(last_row===undefined) {
                        new_row=1;
                    } else {
                        new_row=parseInt(last_row.replace('row',''),10)+1;
                    }

                    // append element to target, changes it's id and shows it
                    $(grid_table).append($(grid_hidden_row).clone(true).attr('id','row'+new_row).removeClass('grid-hidden-row').show());

                    // append unique row identifier on id and name attribute of seledct, input and a
                    $('#row'+new_row).find('select, input, a').each(function(id) {
                        $(this).appendAttr('id','_row'+new_row);
                        $(this).replaceAttr('name','_REPLACE_',new_row);
                    });

                    // disable all the readonly_if_lines options if this is the first row
                    if(new_row==1) {
                        $('.readonly_if_lines :not(:selected)').attr('disabled','disabled');
                    }
                });

                $(this).find('.grid-remove-row').click(function(event) {
                /* 
                 * Remove row does what it says on the tin, as well as a few other house 
                 * keeping bits and pieces
                 */

                    // remove the parent tr
                    $(this).parents('tr').remove();

                    // recalculate the order value5
                    //calcTotal('.net_value ','#gridform','#gridform_total');

                    // if we've removed the last row remove readonly locks
                    row_count=grid_table.find('tr').size();
                    console.info(row_count);
                    if(row_count===0) {
                        $('.readonly_if_lines :disabled').removeAttr('disabled');
                    }

                });

            });

        }

    });

})(jQuery);

I've done the usually searching on elgooG... but I seem to be getting a lot of noise with little result, any help would be greatly appreciated.

Thanks!

like image 623
Ben Everard Avatar asked May 28 '10 10:05

Ben Everard


2 Answers

Maybe something like this?

$.fn.extend({ 

    //pass the options variable to the function
    grid: function(callbacks) {

        // The following can be used so you don't need
        // to test for callback existence in the rest 
        // of the plugin
        var defaults = {
            before: function() {},
            after: function() {},
            row_added: function() {}                
        }
        callbacks = $.extend({},defaults,callbacks);

        // perform callback
        if (callbacks.before)
            callbacks.before();

        return this.each(function() {
            // do stuff
            if (callbacks.row_added)
                callbacks.row_added();
            // do more stuff
        }

        // perform callback
        if (callbacks.after)
            callbacks.after();
   }
});

Call it with something like this:

$("#grid").grid({
    before: function() {},
    after: function() {},
    row_added: function() {}
});                                                              

EDIT: I just added default callbacks so that you don't need to test for the existence of the callbacks. Personally, I like to just test for existence before calling them, but you might prefer this route.

like image 104
Tauren Avatar answered Sep 28 '22 08:09

Tauren


Yuo can read this post:

http://www.learningjquery.com/2009/03/making-a-jquery-plugin-truly-customizable

which contains a paragraph on providing callback capabilities...

var defaults = {

    onImageShow : function(){}, // we define an empty anonymous function
                                // so that we don't need to check its
                                // existence before calling it.
    // ... rest of settings ...
};

// Later on in the plugin:     
$nextButton.bind('click', showNextImage);

function showNextImage() {
    // DO stuff to show the image here...
    // ...
    // Here's the callback:
    settings.onImageShow.call(this);
}
like image 31
mamoo Avatar answered Sep 28 '22 08:09

mamoo