1
\$\begingroup\$

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?

\$\endgroup\$

migrated from stackoverflow.com Jul 21 '13 at 21:32

This question came from our site for professional and enthusiast programmers.

  • 12
    \$\begingroup\$ Well, you're using jQuery, but that looks nothing like jQuery. \$\endgroup\$ – elclanrs Jul 21 '13 at 10:01
  • 4
    \$\begingroup\$ This question appears to be off-topic because it is just a rant, not a constructive programming question. \$\endgroup\$ – Barmar Jul 21 '13 at 10:02
  • 2
    \$\begingroup\$ Just because you throw in one $ somewhere does not mean you're using jQuery to its full potential. I don't see an answerable question here. \$\endgroup\$ – deceze Jul 21 '13 at 10:03
  • 2
    \$\begingroup\$ @ user1422845: The code can be a lot shorter whether you use the DOM or jQuery: pastie.org/8160759 (I also fixed a couple of bugs, like the missing declaration for r, which mean you were falling prey to The Horror of Implicit Globals, and the fact you were trying to use appendChild on the value held by #placeholder, rather than on #placeholder). \$\endgroup\$ – T.J. Crowder Jul 21 '13 at 10:09
  • 5
    \$\begingroup\$ There's a clear and constructive question in there: how to achieve this using jQuery to its full potential. Not sure why this post is getting so much criticism. \$\endgroup\$ – Stuart Jul 21 '13 at 10:11
4
\$\begingroup\$

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.

\$\endgroup\$
  • \$\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 Aug 1 '14 at 10:31
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\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 Jul 21 '13 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy