Search code examples
javascriptjqueryinline-editing

Javascript inline edit, how to cancel edit to have original data?


I have data

<tr id="row_1">
  <td id="td_1_1">Text 1</td>
  <td id="td_2_1">Text 2</td>
  <td><a href="#" onclick="editRow(1)">Edit row</a></td> 
</tr>

then in javascript

function editRow(row_id) {
   //some ajax to retrieve html in the format
   //<td><input type="text" name="td_1" value="Text 1"></td>
   //<td><input type="text" name="td_2" value="Text 2"></td>
   //<td><input type="submit" name="submit" value="submit"></td>
}

in editRow function I do some ajax and retrieve TDs and replace [$(row_id).html(html)] the row's TDs. All this works fine. But I need to have one cancel button, clicking which brings the original TDs back (that is .. no input boxes). Any ideas, how to achieve this functionality? Do I need to copy the before edit row html to a variable, and then later on cancel replace input boxes html? Thank you for your help.

EDIT

Also, if user clicks somewhere else on the page, it should consider it as cancel and bring the original data back. How to bind this action?


Solution

  • First of all - look into Javascript frameworks. The kind of functionality you are talking about is advanced enough that if you really want your code to work in all browsers correctly you shouldn't do this on your own. It would also let you keep your HTML free of ugly inline Javascript and such, which is considered bad practice.That being said, here's a thought:

    Have you considered having two rows per item, one of the row in "edit mode" and one of the row in "normal mode"? You could style the "edit mode" rows to be hidden by default, and when someone clicks on the edit link you can hide that row and bring the edit one into view. This would really be easier than doing an AJAX call to get the edit form.

    EDIT

    Here's some code to get you started:

    function editRow(row_id, callback) {
       // you would get this dynamically through ajax, thus why we need the callback
       var html = '<tr id="edit_' + row_id + '" class="edit"><td><input type="text" name="td_1" value="Text 1"></td><td><input type="text" name="td_2" value="Text 2"></td><td><input type="submit" name="submit" value="submit"></td></tr>';
       callback(html);
    }
    
    $('a.edit', '#data').click(function() {
        var $tr = $(this).closest('tr');
        var id = $tr.attr('id').split('_').pop();
        var edit_row = '#edit_' + id;
        if($(edit_row).length == 1) { // edit row already exists
            $tr.hide();
            $(edit_row).show();
        } else { // doesn't exist, fetch it
            editRow(id, function(html) {
                $tr.hide();
                $tr.after(html);
            });
        }
        return false;
    });
    
    $(window).click(function(e) {
        $('tr.edit:visible').each(function() {
            var $tr = $(e.target).closest('tr');
            var id = $(this).attr('id').split('_').pop();
            console.log(e.target, $tr, this);
            if($tr.attr('id') != this.id) {
                $(this).hide();
                $('#row_' + id).show();
            }
        });
    });
    

    I should probably note that there are a lot of jQuery plugins that do a lot of this for you, and depending on the needs of your application you might be better off just fetching the row every time, not fetching them at all, etc. This is just a rough idea of what you might have to do to achieve what you want, and the rest is up to you. :)