user45678
user45678

Reputation: 341

How to dynamically convert html table rows to columns?

To modify the database format SQL uses two functions called PIVOT and UNPIVOT. I was wondering, is there a way of achieving the same thing using a script on the client side?

Let's take this table for example:

Rowa. pro_img#1|${product.name}|${product.price}|${product.description}
Rowb. prod_img#2|${product.name}|${product.price}|${product.description}
Rowc. prod_img#3|${product.name}|${product.price}|${product.description}
Rowd. pro_img#4|${product.name}|${product.price}|${product.description}

As you already know, every html table with dynamic data will print rows. What i'm trying to do is having an html table with dynamic data printing columns so I can display a nice product listing like in this example:

Product_img#1|             Product_img#2|            Product_img#3|
Product_name|              Product_name|             Product_name|
Product_price|             Product_price|            Product_price|
Product_description|       Product_description|      Product_description|

I'm trying to display 3 objects per row. Is there a way of doing this with a simple javascript?

I'm trying to achieve exactly the same thing as Vans (example here)!

Edited New code

<div id="product_container">
                <c:forEach var="product" items="${categoryProducts}" varStatus="iter">
                
                    <div id="product_image"><a href="viewProduct?${product.id}">
                                    <img class="img" alt="" src="${initParam.productImagePath}${product.id} (1).jpg" /></a></div>
                    <div id="product_name">${product.name}</div>
                    <div id="product_price">${product.price}</div>
                    <div id="add_toList"><form id="wishlistForm" action="addToWishlist" method="post">
              <input name="productId" value="${product.id}" type="hidden">

              <input class="submit" value="<fmt:message key='AddToWishlist'/>" type="submit">
            </form></div>
            
                    <div id="add_toCart"><form id="cartForm" action="addToCart" method="post">
              <br>
              <br>

              <input name="productId" value="${product.id}" type="hidden">
              <input class="submit" value="<fmt:message key='AddToCart'/>" type="submit">


            </form></div>
                    
                    
                    
                    
            </c:forEach>
                </div>

Upvotes: 2

Views: 3832

Answers (3)

Samurai
Samurai

Reputation: 3729

jsfiddle DEMO

This function takes an HTML table and returns a table which has the given table's rows and columns swapped.

Example input:

----------------
A1  |  A2  |  A3
----------------
B1  |  B2  |  B3
----------------

Output:

---------
A1  |  B1
---------
A2  |  B2
---------
A3  |  B3
---------

Javascript:

function convertTable(tbl) {
    var rows = tbl.rows.length;
    var cols = tbl.rows[0].cells.length;
    var tbl2 = document.createElement('table');

    for (var i = 0; i < cols; i++) {
        var tr = document.createElement('tr');
        for (var j = 0; j < rows; j++) {
            var td = document.createElement('td');
            var tdih = tbl.rows[j].cells[i].innerHTML;
            td.innerHTML = tdih;
            tr.appendChild(td);
        }
        tbl2.appendChild(tr);
    }
    return tbl2;
}

Upvotes: 3

maraca
maraca

Reputation: 8743

You could create custom divs for each object:

function generateProductDiv(product) {
   return
     '<div class="product">' +
         '<img src="' + product.image + '">' +
         '...' +
     '</div>';
}

Create a div for each product put them in a parent divs and style them with css (the CSS property display: table; and table-* might be of interest to you if you want to do it this way, another possibility is to use libraries).

The easier solution is just to put those divs inside the cells of a table although you should only use tables if you really want to display tabular data.

You seem to have JSP code, not Javascript, here is how to generate the forms in JSP (btw. JSP is the same as Java Servlets, just another way of writing it, simply put: JSP = html with Java, Servlet = Java with html). Using forms instead of divs because that seems to be what you want:

<c:forEach var="product" items="${categoryProducts}" varStatus="iter">
    <form id="wishlistForm" action="addToWishlist" method="post">
        ...
        <a href="viewProduct?${product.id}">
            <img class="img" alt="" src="${initParam.productImagePath}${product.id} (1).jpg" />
        </a>
        ...
    </form>
</c:forEach>

Upvotes: 2

cutmancometh
cutmancometh

Reputation: 1727

The best (easiest, most maintainable, most semantic) way to do this is pure CSS. You shouldn't have to change the markup at all.

And it's actually pretty easy.

You just have to get the browser to stop treating it like table data. The key is the display: CSS property.

display defaults to table-row for <tr> elements and table-cell for <td> elements, which makes sense. You have to "break" that property.

tr, td {
    display: block;
}

In other words, you're telling the browser to "display table row and table data elements just like any other block-level element (like a div, for example)".

This gets you almost all the way there. Now you have to get the table "rows" (which are now being laid out like divs) to stack next to each other, instead of on top of each other.

tr {
    float: left;
}

Now, you end up with the possibility of the new "rows" not being the same height. If, for example, your product images are not all the same height, or if your descriptions are different lengths, you'd end up with the table being way out of alignment.

So, you need to give your <td>s all the same height.

td{
    height: 150px; /*or whatever height you want*/
}

So, the full CSS code looks like this:

tr {
    display: block;
    float: left;
}
td {
    display: block;
    height: 150px;
}

Obviously, this is only the most basic code to get your foot in the door. In the real world, you'd give each type of <td> its own height, something like:

td.product-image {
    height: 150px;
}
td.product-description {
    height: 70px;
}
td.product-price {
    height: 40px;
}

Here's a codepen that puts it all together: table data pivoted

Also, here's some more info on the CSS display property if you're interested.

Best of luck. Feel free to ask in comments if you have any further questions.

Upvotes: 0

Related Questions