Introduction
The jQuery library is a very powerful client-side framework. One of its strengths is that jQuery is very good at DOM (Document Object Model) manipulation. This can be demonstrated by implementing HTML table inline editing by jQuery. The code in this article presents a simple implementation of Gridview
style inline editing by jQuery. Gridview
is an ASP.NET server control with inline editing function. In part two of this article, I am going to show an editor style HTML table inline editing by jQuery.
Using the Code
First, add the following HTML markup to a web page.
<div>
<div class="errorSummary"></div>
<table id="tblCats" class="simpleTable">
<tr>
<th>Category Id</th>
<th>Category Name</th>
<th>Short Description</th>
<th>Action</th>
</tr>
</table>
</div>
Second, add a JavaScript global object to serve as table data source.
var catObj = (function () {
var cat = [];
var maxCatId = 0;
return {
GetCats: function () {
return cat;
},
AddCat: function (cat_name, short_desc) {
var cat_id = ++maxCatId;
cat.push({ cat_id: cat_id, cat_name: cat_name, short_desc: short_desc });
},
UpdateCat: function (cat_id, cat_name, short_desc) {
for (var i = 0; i < cat.length; i++) {
if (cat[i].cat_id == cat_id) {
cat[i].cat_name = cat_name;
cat[i].short_desc = short_desc;
break;
}
}
},
DeleteCat: function (cat_id) {
var j = undefined;
for (var i = 0; i < cat.length; i++) {
if (cat[i].cat_id == cat_id) {
j = i;
break;
}
}
if (j != undefined) {
cat.splice(j, 1);
}
}
};
})();
The construction of this global object uses JavaScript module pattern. The object created by this pattern behaves like an object created by a classic object-oriented language such as C#. This object exposes public
methods to manipulate a private
array variable. The private
variables of this object are protected
and cannot be accessed outside of the object itself. A detailed explanation of module pattern can be found in the following link.
Last, add some jQuery code to do inline editing.
$(document).ready(function () {
catObj.AddCat('cat name 1', 'short desc 1');
catObj.AddCat('cat name 2', 'short desc 2');
catObj.AddCat('cat name 3', 'short desc 3');
catObj.AddCat('cat name 4', 'short desc 4');
catObj.AddCat('cat name 5', 'short desc 5');
catObj.AddCat('cat name 6', 'short desc 6');
PopulateTable(catObj.GetCats());
});
function DoEdit(thisLink) {
if ($(thisLink).text() == 'Add') {
var catName = $(thisLink).parent().parent().find('td:eq(1) > input').val();
var shortDesc = $(thisLink).parent().parent().find('td:eq(2) > input').val();
if (catName == '' || shortDesc == '') {
$('div.errorSummary').html('Both Category Name and Short Description cannot be empty!');
$('div.errorSummary').show();
}
else {
catObj.AddCat(catName, shortDesc);
PopulateTable(catObj.GetCats());
}
}
else if ($(thisLink).text() == 'Delete') {
var catId = parseInt($(thisLink).parent().parent().find('td:first').html());
catObj.DeleteCat(catId);
PopulateTable(catObj.GetCats());
}
else if ($(thisLink).text() == "Edit") {
var elTr = $(thisLink).parent().parent();
var catName = elTr.find('td:eq(1)').html();
var shortDesc = elTr.find('td:eq(2)').html();
elTr.find('td:eq(1)').html('<input type="text"
data-oldvalue="' + catName + '" />');
elTr.find('td:eq(1) > input').val(catName);
elTr.find('td:eq(2)').html('<input type="text"
data-oldvalue="' + shortDesc + '" />');
elTr.find('td:eq(2) > input').val(shortDesc);
elTr.find('td:eq(3)').html('<a href="#">Update</a>
<a href="#">Cancel</a>');
elTr.find('td:eq(3) a').click(function (e) {
e.preventDefault();
DoEdit(this);
});
}
else if ($(thisLink).text() == 'Cancel') {
var elTr = $(thisLink).parent().parent();
var catName = elTr.find('td:eq(1) > input').attr('data-oldvalue');
var shortDesc = elTr.find('td:eq(2) > input').attr('data-oldvalue');
elTr.find('td:eq(1)').html(catName);
elTr.find('td:eq(2)').html(shortDesc);
elTr.find('td:eq(3)').html('<a href="#">Edit</a>
<a href="#">Delete</a>');
elTr.find('td:eq(3) a').click(function (e) {
e.preventDefault();
DoEdit(this);
});
}
else if ($(thisLink).text() == 'Update') {
var elTr = $(thisLink).parent().parent();
var catId = parseInt(elTr.find('td:first').html());
var catName = elTr.find('td:eq(1) > input').val();
var shortDesc = elTr.find('td:eq(2) > input').val();
if (catName == '' || shortDesc == '') {
$('div.errorSummary').html('Both Category Name and Short Description cannot be empty!');
$('div.errorSummary').show();
}
else {
catObj.UpdateCat(catId, catName, shortDesc);
PopulateTable(catObj.GetCats());
}
}
}
function PopulateTable(data) {
$('div.errorSummary').hide();
$('#tblCats tr:gt(0)').remove();
$(data).each(function () {
var row = '<tr><td>' + this.cat_id + '</td><td>' +
this.cat_name + '</td><td>' +
this.short_desc + '</td><td>' +
'<a href="#">Edit</a>
<a href="#">Delete</a></td></tr>'
$('#tblCats').append(row);
});
$('#tblCats').append('<tr><td></td>
<td><input type="text" />' +
'</td><td><input type="text" />
</td><td><a href="#">Add</a></td></tr>');
$('#tblCats a').click(function (e) {
e.preventDefault();
DoEdit(this);
});
}
The above code shows jQuery is very good at selecting and manipulating DOM elements. For example, look at this line of code.
var catName = $(thisLink).parent().parent().find('td:eq(1) > input').val();
This line of code can be explained as this:
- Wraps a link element inside a jQuery object.
- Gets the link's parent which is a
td
element. - Gets the
td
's parent which is a tr
element. - Finds the input element which is the immediate child of the second
td
element of this tr
. - Gets the value of the
input
element.
Since in many cases, a jQuery function returns a jQuery object, the above functions can be chained together to get a concise and clean programming style.
If the data source is on the server side, the code in this article can be modified to use Ajax calls or form post actions to manipulate server side data source.
Points of Interest
One of jQuery strengths is manipulating DOM.