3

Imagine I have a table of data in HTML and each of the rows have, say, one of three possible classes: RowA, RowB, and RowC; which represent the information in the rows. (For example, Small, Medium, and Large cars).

Above the table, I have 3 checkboxes: "Show Small Cars", "Show Medium Cars", "Show Large Cars".

If the user deselects "Show Small Cars", then the rows containing small cars should disappear.

This is how I would do it:

function showHideRows(classToShowOrHide, checkBoxSender)
{
  var tableObj = document.getElementById("myDataTable");

  for (i = 0; i < tableObj.childNodes.length; i++)
    if (tableObj.childNodes[i].className == classToShowOrHide)
      tableObj.childNodes[i].style.display = checkBoxSender.checked ? "visible" : "none";
}

Is there a better way? For example, can I modify the css class using javascript to include/exclude a display: none?

I'm not using jQuery.

Ozzah
  • 10,631
  • 16
  • 77
  • 116
  • Even though you're not using jQuery, you might want to look into how jQuery would do it, and see if you can just lift those few functions out of it. – DevinB Sep 09 '11 at 00:06
  • I believe this will fail if the cell has more than one class. – James Montagne Sep 09 '11 at 00:09
  • http://stackoverflow.com/questions/1933602/how-to-getelementbyclass-instead-of-getelementbyid-with-javascript Specifically the post by CMS should help you. – Corbin Sep 09 '11 at 00:14
  • @kingjiv The `` will only have one class, and this function will be used on only one page, ever :) – Ozzah Sep 09 '11 at 00:14

4 Answers4

10

If you define your markup/styles as this:

<table class="showSmallCars showMediumCars">
  <tr class="smallCar">...<tr>
  <tr class="mediumCar">...<tr>
</table>

CSS:
table tr { display:none; }
table.showSmallCars tr.smallCar { display:table-row; }
table.showMediumCars tr.mediumCar { display:table-row; }

then it is enough for you to modify class attribute on table to present records of groups you need: Thus <table class="showSmallCars showMediumCars"> will show smalls an mediums and <table class="showSmallCars showMediumCars showLargeCars"> will show all of them.

And no need to scan all rows in script.

c-smile
  • 26,734
  • 7
  • 59
  • 86
  • Beat me by 53 seconds! We've pretty much posted the same technique - one difference is that my version shows all rows by default, while this version shows none. This has nicer handling of multiple options, though. Nice job! – Ben Hull Sep 09 '11 at 00:24
  • Oh hey, that's pretty clever! Thanks for that! – Ozzah Sep 09 '11 at 00:25
  • A nice tweak would be to use compound selectors: `table.showSmallCars tr.smallCar, table.showMediumCars tr.mediumCar, table.showLargeCars tr.largeCar { display:table-row; }` – Ben Hull Sep 09 '11 at 01:06
  • Yes, that's how I implemented it ;) – Ozzah Sep 09 '11 at 04:46
3

jQuery is a cleaner way to do it; go to http://www.jquery.com and follow the instructions there to start using it, then your function becaomse

function showHideRows(classToShowOrHide, checkBoxSender)
{
    $('.' + classToShowOrHide, '#myDataTable').each(function(){
        $(this).css('display', ((checkBoxSender.checked) ? 'visible' : 'none'));
    });
}

If you want to do it in vanilla JS, something like this should be about right. Probably a gremlin in the following code somewhere, I don't do much vanilla JS any more :) jQuery is that good.

window.onload=function(){
    if (document.getElementsByClassName == undefined) {
        document.getElementsByClassName = function(className)
        {
            var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
            var allElements = document.getElementsByTagName("*");
            var results = [];

            var element;
            for (var i = 0; (element = allElements[i]) != null; i++) {
                var elementClass = element.className;
                if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
                    results.push(element);
            }

            return results;
        }
    }
}

function showHideRows(classToShowOrHide, checkBoxSender)
{
      for (i = 0; i < document.getElementsByClassName(classToShowOrHide); i++)
          document.getElementsByClassName(classToShowOrHide)[i].style.display = checkBoxSender.checked ? "visible" : "none";
}
Joe
  • 15,669
  • 4
  • 48
  • 83
3

Really, the basics of showing and hiding rows can be done very cleanly in CSS. Javascript is only required to tell the surrounding table what type it should show - and that's just a matter of setting a class name.

If this is your HTML:

<table>
    <thead>
        <tr>
            <td>Name</td>
            <td>Type</td>
            <td>Price</td>
        </tr>
        <tbody>
            <tr class="rowA">
                <td>Falcon</td>
                <td>Large</td>
                <td>$160.00</td>
            </tr>
            <tr class="rowA">
                <td>Commodore</td>
                <td>Large</td>
                <td>$160.00</td>
            </tr>
            <tr class="rowB">
                <td>Camry</td>
                <td>Medium</td>
                <td>$110.00</td>
            </tr>
            <tr class="rowB">
                <td>Lancer</td>
                <td>Medium</td>
                <td>$105.00</td>
            </tr>
            <tr class="rowC">
                <td>Prius</td>
                <td>Small</td>
                <td>$75.00</td>
            </tr>
            <tr class="rowC">
                <td>Civic</td>
                <td>Small</td>
                <td>$80.00</td>
            </tr>
        </tbody>
    </thead>
</table>

Use this CSS:

/* The rows to show */

table.showTypeA .rowA,
table.showTypeB .rowB,
table.showTypeC .rowC {
  display: table-row;  
} 

/* Then, hide the other types */

table.showTypeA .rowB,
table.showTypeA .rowC,
table.showTypeB .rowA,
table.showTypeB .rowC,
table.showTypeC .rowA,
table.showTypeC .rowB {
    display: none; 
} 

All you need to do with javascript is set a class on the table of 'showTypeA', 'showTypeB', 'showTypeC', and the browser will take care of the rest.

Ben Hull
  • 7,524
  • 3
  • 36
  • 56
1

I know you asked for JavaScript, but you could do it failry easy with jQuery.

Like: http://jsfiddle.net/XJRVt/17/

You would proberbly also need to do a check on page load :)

Marco Johannesen
  • 13,084
  • 6
  • 31
  • 36
  • Thanks, I have done this in jQuery in the past and I know it's very simple, but this project has to be jQuery-free unfortunately. – Ozzah Sep 09 '11 at 00:42