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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.