Mike Henke
Mike Henke

Reputation: 864

how to make this jquery more reusable?

I would like to be able to pass in "rider" or something else and have add/remove do the same thing but for other items beside rider like subaccounts.

$(function(){
    var template = $('#riders-div .rider-new:first').clone(),
        ridersCount = 0;

    var addRider = function(){
        ridersCount++;
        var rider = template.clone().removeClass("dontshow").find(':input').each(function(){
            var newId = this.id.replace('-', 's['+ ridersCount + '][') + ']';
            $(this).prev().attr('for', newId); // update label for (assume prev sib is label)
            this.name = this.id = newId; // update id and name (assume the same)
        }).end() // back to .rider
        .appendTo('#rider-exist'); // add to container
        $('#rider-message').html('').removeClass("ui-state-highlight").removeClass("ui-state-error");
    };

    $('#addButton').click(addRider()); // attach event

$("#removeButton").click(function () {
  $('#riders-div .rider-new:last').remove();
$('#rider-message').html('').removeClass("ui-state-highlight").removeClass("ui-state-error");
     });
});

https://gist.github.com/1081078

Upvotes: 1

Views: 266

Answers (2)

Cameron
Cameron

Reputation: 179

It seems like you are defining some sort of management system for this "Rider" module (I dunno, just what I'm seeing). The way I would improve this code to begin with would be to use some OO js. From there when there is the need to make it more generic (such as changeable class names), you make those selectors parameters to the constructor. It'll also have the benefit of making the code much more unit testable!

If you want some specific code examples I'll post something, just let me know.

Upvotes: 0

Josiah Ruddell
Josiah Ruddell

Reputation: 29831

You will want to create a plugin out of this code. The approach is as you need more features, add options to the plugin. I started the plugin below. Also code replacing element IDs (etc) needs to be more generic. Below I added a regex to replace the number in the element id.

Add callbacks where necessary to perform implementation specific actions/UI tweaks. So in your example above add the code to reset the message html ($('#rider-message').html('')) in the after callback.

after: function(i){
    $('#rider-message').html(''); //...
}

And so on

$.fn.cloneForm = function(options){
    var self = this, count = 0, 
        opts = $.extend({}, {
            after: function(){}, 
            template:'', 
            prependTo: '', 
            on: 'click'
        }, options),
        template = $(opts.template).clone(); // unmodified clone

    self.bind(opts.on + '.cloneForm', function(){
        count++;
        template.clone().find(':input').each(function(){
            var newId = this.id.replace(/[0-9]/i, count) // replace number
            $(this).prev().attr('for', newId);           // update label for
            this.name = this.id = newId;                 // update id and name (assume the same)
        }).end().prependTo(opts.prependTo);
        opts.after.call(self, count);                    // run callback
    });
}

Usage:

$('#addButton').cloneForm({ 
    template: '#riders-div .rider-new:first',
    prependTo: '#riders-div',
    after: function(){ console.log('im done'); }
});

Upvotes: 1

Related Questions