Problem Statement
Write JavaScript code hideOddRows.js that attaches to the button click event and hides the odd rows of the table when clicked.
Expected Output
When you click on "Hide Odd Rows":
Solution
/* hideOddRows.js */
document.querySelector('[name=HideRows]').onclick = hideRows;
function hideRows(){
var elements = document.getElementsByClassName('hide');
Array.prototype.forEach.call(elements, function(element){
element.style.display = "none";
});
return true;
}
<!DOCTYPE html>
<html>
<head>
<title>Hide odd rows</title>
<meta charset="UTF-8">
</head>
<body>
<div style="background-color:#8F9779;width:200px;height:30px;">
</div>
<hr style="width:200px" align="left">
<table border="1" >
<tr class="hide" >
<td width="40" height="20">row 1</td>
</tr>
<tr>
<td width="40" height="20">row 2</td>
</tr>
<tr class="hide">
<td width="40" height="20">row 3</td>
</tr>
<tr>
<td width="40" height="20">row 4</td>
</tr>
<tr class="hide">
<td width="40" height="20">row 5</td>
</tr>
</table><br>
<button type="button" name="HideRows">Hide Odd Rows</button>
<script type="text/javascript" src="hideOddRows.js"></script>
</body>
</html>
Questions
I could not manage to place
script
tag inhead
due to DOM loading issue. How do I improve this solution to placescript
tag inhead
?Can I improve the HTML code?
Note: I've yet to learn jQuery.
2 Answers 2
Your JavaScript is OK, but beware of writing code where you can get away without it. In this case, there is a CSS3 :nth-child()
selector 1 that lets you select odd rows without tagging them manually with class="hide"
.
You just have to trigger the CSS rule when the button is pressed. Note that if you want to select one specific element in a document, it's better to mark it using id="..."
and select it using document.getElementById(...)
— that's exactly what it is designed to do, and browsers will optimize ID lookups to be as fast as possible.
/* hideOddRows.js */
document.getElementById('HideRows').onclick = function hideRows() {
document.getElementsByTagName('table').item(0).className = 'odd-rows-hidden';
}
table.odd-rows-hidden tr:nth-child(odd) {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<title>Hide odd rows</title>
<meta charset="UTF-8">
</head>
<body>
<div style="background-color:#8F9779;width:200px;height:30px;">
</div>
<hr style="width:200px" align="left">
<table border="1" >
<tr>
<td width="40" height="20">row 1</td>
</tr>
<tr>
<td width="40" height="20">row 2</td>
</tr>
<tr>
<td width="40" height="20">row 3</td>
</tr>
<tr>
<td width="40" height="20">row 4</td>
</tr>
<tr>
<td width="40" height="20">row 5</td>
</tr>
</table><br>
<button type="button" id="HideRows">Hide Odd Rows</button>
<script type="text/javascript" src="hideOddRows.js"></script>
</body>
</html>
1 Caveat: requires Internet Explorer ≥ 9. If you need to support older versions of IE, you'll probably want jQuery.
- I could not manage to place script tag in head due to DOM loading issue. How do I improve this solution to place script tag in head?
Placing the script
tag in the header is not a necessity of HTML, in fact, I often put my script
s at the bottom of my body
tag.
- Can we improve html code?
Yeah, we can.
<tr class="hide" > <td width="40" height="20">row 1</td> </tr> <tr> <td width="40" height="20">row 2</td> </tr> <tr class="hide"> <td width="40" height="20">row 3</td> </tr> <tr> <td width="40" height="20">row 4</td> </tr> <tr class="hide"> <td width="40" height="20">row 5</td> </tr>
Instead of using class="hide"
, you can iterate over the elements and count the index.
return true;
is unnecessary because you don't do anything with the result.
Instead of Array.prototype.forEach.call(elements
, you can evoke forEach
directly on the nodelist, as long as you attach the additional call to Array.prototype.slice.call
.
I would suggest to remember that for cases where you make frequent document retrieval calls, simplifying document calls comes in very handy:
For example, one of my simplifications for jQuery-like selection:
function $$(selector, el) {
if (!el) { el = document; }
return Array.prototype.slice.call(el.querySelectorAll(selector));
}
Which would let you make a call like:
$$('.postTitle')
and iterate over it like an array.
All together:
All together, it would look like:
document.querySelector('[name=HideRows]').onclick = function(){
Array.prototype.slice.call(document.getElementsByTagName('td')).forEach(function(element, index){
if (index % 2 !== 0){
element.style.display = "none";
}
});
}
Additionally, you should call things like in .onclick = hideRows
before it's defined, if the function was anonymous, that would cause a bug. It's a good habit to get into.
-
\$\begingroup\$ In your final code, you use the class
hide
which is given only to the odd rows, and then check for(index % 2 !== 0)
. That will only return every second odd row instead of every odd row. \$\endgroup\$bIgBoY– bIgBoY2015年12月16日 06:35:12 +00:00Commented Dec 16, 2015 at 6:35 -
\$\begingroup\$ It is a JavaScript solution, a polyfill is when you replace an unwritten function with its implementation in a different solution/library, for example jQuery has a simpler document retrieval system, which I tend to replace with polyfills to discourage jQuery use \$\endgroup\$Quill– Quill2015年12月16日 12:44:30 +00:00Commented Dec 16, 2015 at 12:44