1
\$\begingroup\$

I know there are many great plugins on the Net nowadays. But due to safety issues, external plugin are restricted. Thus, I wrote some JavaScript for an interactively searchable HTML table. The main features I need are a vertically scrollable table and interactive filtering. Since the window size is not fixed, I also added width adjustments.

The fiddle

  1. Can someone please check if there are any parts I can refine OR that should be fixed? (i.e. I should define this as a var, etc.)

  2. I have replaced $("table#table-body tr:gt(0)").each() to $(row + ":gt(0)").each(), is the code still correct (note: var bodyTr = $(row + ":visible:eq(0) td");)?

JavaScript

//Perparing table
/*
*comment
*/
$("<div>", {class: "tablewrapper"}).insertBefore("table#table-body");
$("<table>", {class: "header"}).appendTo($("<div>", {class: "headerwrapper"}).appendTo("div.tablewrapper"));
$("table#table-body").appendTo($("<div>", {class: "bodywrapper"}).appendTo("div.tablewrapper"));
$("table#table-body>thead").clone().val("").appendTo("table.header");
$("table.header>tr").removeClass("header_hidden");
$("table#table-body").find("thead tr").addClass("header_hidden");
$("table#table-body").find("tbody td:nth-child(2)").addClass("lefty");
$("<input>", {type: "text"}).attr("id","search-criteria").appendTo($("<div>", {class:"s_box"}).insertAfter("div.headerwrapper"));
$("<div>").attr("id","count").insertAfter("div.s_box");


resizeTable();
var bodyTd = $("table#table-body tr td");

$(window).resize(resizeTable);

//search function
$("#search-criteria").on("keyup", function () {
var keyword = $(this).val().replace(/[A-Za-z0-9]/g, function (td_word) {
    return String.fromCharCode(td_word.charCodeAt(0) - 0xFEE0);
}).toLowerCase();
var row = "table#table-body tbody>tr";

if (keyword !== "") {
    $(row).each(function () {
        var td_word = $(this).text().toLowerCase();
        //shorthand if function
        $(this).closest(row)[td_word.indexOf(keyword) !== -1 ? 'show' : 'hide']();
    });
    var srowCount = $(row).filter(":visible").length;
    document.getElementById('count').innerHTML = srowCount;
    if (srowCount === 0) {
        if(!$(row).last().hasClass('s_empty'))
        {
            $("table#table-body tbody").last().append('<tr class="s_empty"><td colspan="5" style="text-align:center">Search not found</td></tr>');
        }
        $("tr.s_empty").show();
    } else {
        $("tr.s_empty").remove();
    }
} else {
    $("tr.s_empty").remove();
    $(row).show();
    document.getElementById('count').innerHTML = $(row).length;
}

});

    var row = "table#table-body tbody>tr";
    var srowCount = $(row).filter(":visible").length;
    document.getElementById('count').innerHTML = srowCount;

function resizeTable() {
    //width adjustments
    $("table.header").width($("#table-body").width());
    $("div.s_box").width(($("div.headerwrapper").width()-10)).height(($("table.header").height()-9));
    $("input#search-criteria").width(($("div.headerwrapper").width()-30)).height(($("div.s_box").height()-0.05));
    var counter_h = ($("table.header").height()/2+$("table.header").height()-1);
    $("div#count").css({"top":counter_h});

    var bodyTr = $("table#table-body tbody>tr:visible:eq(0) td");
    console.log(bodyTr);
    $("table.header tr:first th").each(function (index, value) {
        $(this).width(bodyTr.eq(index).width());
    });

    //apply widths to every TD
    $("table#table-body tr:gt(0)").each(function () {
        $(this).children().each(function (index) {
            $(this).width(bodyTr.eq(index).width());
        });
    });
}

CSS

div.tablewrapper, div.headerwrapper, div.bodywrapper {
    border:0px;
}

div.headerwrapper {
    background-color:#1BA7F5;    
}

div.bodywrapper {
    height:100px;
    overflow-y:scroll;
    border-bottom:solid 2px #1BA7F5;
}

table.header, table#table-body {
    border:0px;
    border-collapse:collapse;
    border-spacing:0px;
    text-align:center;
}

table.header {
    line-height:32px;
    background-color:#1BA7F5; 
    color:#FFF;
}

table.header th {
    padding-left:10px;
    text-align:left;
    font-weight: normal;
}

table#table-body {
    width:100%;
}

table#table-body tr {
    line-height:30px;
    border-top:1px solid #C4C4C4;
}

table#table-body tr.header_hidden {
    display:none;
}

table#table-body tr:hover {
    background-color:#FFFF99;
}

div.s_box {
padding: 5px 5px;
background: #c4c4c4;
box-sizing: border-box;
}

input#search-criteria {
-webkit-appearance: none;
padding: 0 10px;
border: none;
border-radius: 6px;
font-size: 13px;
line-height: 23px;
background: #fff;
}

input#search-criteria:focus{
    outline:none;
}

div#count {
position: absolute;
right: 17px;
color: #FFF;
background-color: #9EB4C2;
line-height: 19px;
font-size: 15px;
padding: 0 5px;
border-radius: 3px;
}

table#table-body tbody td.lefty {
    text-align:left;
}
\$\endgroup\$
2
\$\begingroup\$

Code like this should be encapsulated and written in a way, so that it can be applied to any table, possibly even multiple tables on the same page. Currently you are putting everything in the global namespace and limiting yourself to a specific table by hard coding the id table-body (and using more IDs in the code).

You should instead consider implementing it as a jQuery plugin.


$(this).closest(row)[td_word.indexOf(keyword) !== -1 ? 'show' : 'hide']();

Can be simplified to

$(this).closest(row).toggle(td_word.indexOf(keyword) !== -1);
\$\endgroup\$
  • \$\begingroup\$ Thank you RoToRa. I understand what you are saying, although I am not skilled and knowledge enough yet to do that yet. 1 month ago, I knew pretty much nothing about JavaScript. Hope you can understand and that is also why I am trying to ask people to review it. ... thanks for the if > toggle. this is the use of .toggle( display ) right? (just read it on JQuery API now.) PS. if it is not too much, can you explain how I can encapsulate it? Perhaps I can try it myself from your example/explanation. Unless you are super kind and decide to review it. \$\endgroup\$ – Maki Mar 3 '15 at 15:15
  • \$\begingroup\$ RoToRa, I have tried to create a few new lines (1-21) if i didn't misunderstand what you are saying about encapsulating. 1) Is that the right idea, 2) how would I place the original parts into function (a) now? \$\endgroup\$ – Maki Mar 4 '15 at 2:03

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.