I'm on the road to prepare for the 70-480 Microsoft exam and I'm learning the basics of jQuery.
Now I wrote the following JavaScript function to create a table dynamically:
function MakeTableJavascript() {
var rows = document.getElementById("rows").value;
var cols = document.getElementById("cols").value;
var placeholder = document.getElementById("placeholder");
var table = document.createElement("table");
table.setAttribute("border", "1");
for (var r = 0; r <= rows; r++) {
var row = document.createElement("tr");
for (var c = 0; c < cols; c++) {
if (r == 0) {
var head = document.createElement("th");
var texthead = document.createTextNode("Column " + c);
head.appendChild(texthead);
row.appendChild(head);
}
else {
var col = document.createElement("td");
var textrow = document.createTextNode(c.toString() + r.toString());
col.appendChild(textrow);
row.appendChild(col);
}
}
table.appendChild(row);
}
placeholder.appendChild(table);
}
Then I re-wrote the same function with jQuery:
function MakeTablejQuery() {
var rows = $('#rows').val();
var cols = $('#cols').val();
var placeholder = $('#placeholder').val();
var table = document.createElement("table");
$('table').attr("border", 1);
for (r = 0; r <= rows; rows++) {
var row = document.createElement("tr");
for (var c = 0; c < cols; c++) {
if (r == 0) {
var head = document.createElement("th");
var texthead = document.createTextNode("Column " + c);
head.appendChild(texthead);
row.appendChild(head);
}
else {
var col = document.createElement("td");
var textrow = document.createTextNode(c.toString() + r.toString());
col.appendChild(textrow);
row.appendChild(col);
}
}
table.appendChild(row);
}
placeholder.appendChild(table);
}
The result in term of lines of written code is practically the same.
Surely I can use jQuery in a better way to write less code, but at the actual state I have no idea on how to do so.
Can anyone more experienced in jQuery give me a suggestion to narrow the above code?
2 Answers 2
Well, how about
function MakeTablejQuery(rows, cols) {
var table = $("<table/>").attr("border", 1);
for (r = 0; r < rows; r++) {
var row = $("<tr/>");
for (var c = 0; c < cols; c++) {
if (r == 0) {
row.append($("<th/>").text("Column " + c))
} else {
row.append($("<td/>").text(c.toString() + r.toString()))
}
}
table.append(row);
}
$("#placeholder").append(table);
}
MakeTablejQuery(5, 3);
And here's a more elegant version in a functional style:
Number.prototype.times = function(fn) {
for(var r = [], i = 0; i < this; i++)
r.push(fn(i));
return r;
}
function MakeTablejQuery(numRows, numCols) {
var header = numCols.times(function(c) {
return $("<th/>").text("Column " + c);
});
var row = function(r) {
return $("<tr/>").append(numCols.times(function(c) {
return $("<td/>").text([c, r].join(""));
}));
};
return $("<table/>")
.append(header)
.append(numRows.times(row))
.attr("border", 1);
}
$("#placeholder").append(MakeTablejQuery(5, 3));
Also, jQuery is not about "less" code, it's about more readable code - note how the last "return" statement reads almost like an english sentence.
-
\$\begingroup\$ Just a quick FYI you can append strings with HTML in, and jQuery will automatically handle the conversion, there's no need to call:
row.append($("<th/>").text("Column " + c))
when jquery will happily accept:row.append("<th>Column " + c)
(the tag will close itself if left open as well, which can make things a little easier to work with). \$\endgroup\$scragar– scragar2014年08月01日 10:31:00 +00:00Commented Aug 1, 2014 at 10:31
There are many ways to approach this, but since you complained (at least clearly in your original question) your code not seeming "less", here's something that illustrate why jQuery says "write less":
function MakeTablejQuery() {
var rows = $('#rows').val(), row;
var cols = $('#cols').val();
var table = $("<table>").attr("border", "1");
$('#placeholder').append(table);
for (var r = 0; r <= rows; r++) {
table.append(row = $("<tr>"));
for (var c = 0; c < cols; c++) {
row.append($(r ? "<td>" : "<th>").text(r ? c+""+r : "Column " + c));
}
}
}
Check a fiddle with both (plain JavaScript and jQuery) implementations.
Kinda nice, eh? When using jQuery to create elements, we have $('<tr>')
[1], which is an alternative to document.createElement('tr')
.
But that's not the biggest advantage here. The main difference is that, when you use append()
and text()
, jQuery returns the element in where you called those functions, whereas JavaScript's .appendChild()
returns the appended element (used as parameter). jQuery's approach allows a more fluent programming. (Also, just calling .text()
instead of having to call .createTextNode()
and .appendChild()
is so much sweeter.)
And, yeah, ok, I may have gone too far using the ternary operator, but, hey, isn't it great that even with it you can still read the code? If you only had .createTextNode()
, it wouldn't even be possible. But your question asks for less lines of code to show the power of jQuery not a plugin for table creation, right?
[1] You don't have to close the tag: $('<tr>')
works just as well as $('<tr/>')
or $('<tr></tr>')
. But don't take my word for it: check the docs.
-
\$\begingroup\$ Hm. It seems the question was a bit misleading. You are aware that creating functions and extending prototypes is not a jQuery-specific, just plain JavaScript, feature and your question asked for a jQuery demonstration, right? I guess that if that was on the table, then asking for jQuery in here was kinda pointless, as you could just have created substitutes for
.appendChild()
(and others) that behaved just like.append()
, making jQuery simply unecessary in this scenario. \$\endgroup\$acdcjunior– acdcjunior2013年07月21日 20:02:02 +00:00Commented Jul 21, 2013 at 20:02
$
somewhere does not mean you're using jQuery to its full potential. I don't see an answerable question here. \$\endgroup\$r
, which mean you were falling prey to The Horror of Implicit Globals, and the fact you were trying to useappendChild
on the value held by#placeholder
, rather than on#placeholder
). \$\endgroup\$