3

I am trying to develop a plugin for jQuery. This is my first plugin, and I am stuck in the initial phase.

I need to do following things: I need to find the "add row" link from the table and bind to the click event. When the link is clicked, it should add a new row by cloning the existing template row. Initially the template row is hidden.

Following is the HTML.

<table id='grid1'>
    <tr>
        <td><a href='#' id='add_row'>Add New Row</a></td>
    </tr>
    <tr>
        <td>
            <table id='data_table'>
                <tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
                <tr><td>Data1</td><td>Data2</td><td>Col3</td></tr>
                <tr id='template_row'>
                   <td><input type='text' /></td>
                   <td><input type='text' /></td>
                   <td><input type='text' /></td>
                </tr>
            </table>
        </td>
    </tr>
</table>

And my jQuery so far:

(function($) {
  $.extend($.fn, {
    editableGrid: function() {
      function addRow() {
        //code to clone here but i need the instance of main table here ie grid1
      }
      this.find('#add_row').bind("click",addRow);
    }
  });   
})(jQuery);
3
  • 5
    Heh. Sounds like a case of "Please write my entire plugin for me." Commented May 20, 2011 at 5:21
  • no i have given a try but i stuck in passing the arguments.. Commented May 20, 2011 at 5:24
  • @Tomalak, never heard of jQuery homework lol Commented May 20, 2011 at 5:25

5 Answers 5

3

You need to .detach() the template from the table and put it on a factory variable, like:

var factory = $('#template_row').detach();
factory.removeAttr('id'); // Suggestion for Tomalak

It will hidden (not really) from the table. Next step is bind click on your link and specify here will go the new factory.clone item. Like:

$('button.new-link').click(function(){
  $('#data_table').append(factory.clone(true));
}); 

Take a look too in .clone() and plugin authoring

Sign up to request clarification or add additional context in comments.

1 Comment

+1 for suggesting detach(). You just need to remove the id attribute from the "factory variable"/template.
2

Going on from your current code:

(function($) {
  $.extend($.fn, {
    editableGrid: function() {
      this.find("a.add_row").click(function () {
        var $table  = $(this).parent("table").find("table.data_table");
        var $newRow = $table.find("tr.template_row").clone();

        $newRow.removeClass("template_row"); // !!!
        $table.append($newRow);
        return false;
      });
    }
  });   
})(jQuery);

Notes

  • work with CSS classes instead of IDs - only that way you can have multiple "editable grids" on one page
  • there is no benefit of using bind() over using click() here
  • you can pass functions directly as arguments - no need to define them separately
  • it can improve readability/clarity to use verbose selectors ("a.add_row" is better than just ".add_row")
  • in the outer function, this refers to a jQuery object containing all matched elements, so click() binds all of them in one step.
  • in the inner function, this refers to an individual DOM element (i.e. the clicked link) - it is not a jQuery object here!
  • don't forget to return false from the click function to prevent the browser default behavior
  • it's useful to prepend variables with a $ to denote that they contain a jQuery object

2 Comments

thanks for the description :) .. and it worked now i am extending it for my use ..
@Ujjwal Good to hear! Also look into @DavidRodrigues' answer, the detach() suggestion he makes is a good way to further improve this.
2

No need for a plugin just do this:

$('#add_row').click(function(){
     var clone = $('#template_row').clone();
     clone.removeAttr('id');
     clone.appendTo('#data_table');
})

Here is a demo: http://jsfiddle.net/Jw5TF/

3 Comments

One-liner: $('#data_table').append( $('#template_row').clone().removeAttr('id') );
@Tomalak, yea thats true too :-P
I'm not a code golfer, usually, but this was too tempting. ;)
1
$.fn.myTableTingPlugin = function() {
  var self = this;

  $(self).find(".template_row").hide(); // or use css class
  $(this).find(".add_row").click(function() { 
     // shuld probebly not use ids if its a plugin 
     // so i use a class here

     var newRow =  $(self).find(".template_row").clone();
     $(self).find(".data_table").append(newRow);
  });
}; 

Comments

1

First, don't use ids, classes are better. And double quotes are better too.

<table class="extendableTable">
    <tr>
        <td><a href="#" class="extendLink">Add New Row</a></td>
    </tr>
    <tr>
        <td>
            <table id="data_table">
                <tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
                <tr><td>Data1</td><td>Data2</td><td>Col3</td></tr>
                <tr id='template_row'>
                   <td><input type="text" /></td>
                   <td><input type="text" /></td>
                   <td><input type="text" /></td>
                </tr>
            </table>
        </td>
    </tr>
</table>

Source code of the plugin:

(function($) {
    $.fn.extendableTable = function(options){
        var table = this;
        this.find('.extendLink').click(function(){
            table.find('.dataTable .templateRow:first').clone().appendTo(table.find('.dataTable'));
            return false;
        });
    }
})(jQuery);

And then you can use plugin in such a way:

$('.extendableTable').extendableTable();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.