The rows of the three tables below each have onclick, onmouseover and onmouseout event handlers set by the Javascript after page load. On every event, a classname is added or removed from the corresponding rows in each table.
The html for the tables is free of script, but to keep the document tree compatible across browsers, there should be no whitespace between <tr> tags. A carriage return between one </tr> and the next <tr> creates a textnode in Mozilla browsers, but is ignored by ie.
Move your mouse over a table to see the current row highlighted in all three tables. Click a row to highlight it even more!
| JULI | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | |
| Row 1 | n | N | N | e | e | e | f | f | f | f | f | n | n | n | n | F | |||||||||||||||
| Row 2 | F | F | e | e | n | N | N | e | e | e | f | f | f | f | f | n | n | n | n | ||||||||||||
| Row 3 | n | F | F | e | e | n | N | N | e | e | e | f | f | f | f | f | |||||||||||||||
| Row 4 | f | f | n | n | n | n | F | F | e | e | n | N | N | e | e | e | |||||||||||||||
| Row 5 | e | e | f | f | f | f | f | n | n | n | n | F | F | e | e | n | N | ||||||||||||||
| AUG | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | |
| Row 1 | F | e | e | n | N | N | e | e | e | f | f | f | f | f | n | n | n | n | |||||||||||||
| Row 2 | F | F | e | e | n | N | N | e | e | e | f | f | f | f | f | n | n | ||||||||||||||
| Row 3 | n | n | n | n | U | F | F | e | e | n | N | N | e | e | e | f | f | ||||||||||||||
| Row 4 | f | f | f | f | f | n | n | n | n | F | F | e | e | n | N | N | |||||||||||||||
| Row 5 | N | e | e | e | f | f | f | f | f | n | n | n | n | F | F | e | e |
| SEP | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T | F | L | S | M | T | O | T |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | |
| Row 1 | F | F | e | e | n | N | N | e | e | e | f | f | f | f | f | n | n | n | n | |||||||||||
| Row 2 | n | n | U | F | F | e | e | n | N | N | e | e | e | f | f | f | f | |||||||||||||
| Row 3 | f | f | f | n | n | n | n | N | N | U | F | F | e | e | n | N | N | e | e | |||||||||||
| Row 4 | e | e | e | F | f | e | f | f | e | n | n | n | n | U | U | F | F | e | e | |||||||||||
| Row 5 | n | N | N | e | e | e | f | f | f | f | f | n | n | n | n | U |
The initialization is done by the anonymous function at the end (if all necesary tags and elements are placed before it in the source, the code can run without waiting for the window.onload event to fire). It loops through all the tables the document has to offer, and attaches three anonymous functions to the three events firing on each of the rows, except the first, which is a header row.
The function called onmouseout checks for the className before toggling, as the user may well be holding his mouse over one of the tables during the initialization!
function toggleclass( el, name ) {
name = ' ' + name;
var s = el.className;
el.className = s.indexOf( name )<0 ? s + name : s.replace( name, '' );
}
function multiplerows( el, name ) {
var t = document.getElementsByTagName( 'table' ), i = t.length, r = 0;
while( ( el = el.previousSibling ) ) { r++; }
while(i--) { toggleclass( t[i].rows[r], name ); }
}
(function() {
var t = document.getElementsByTagName( 'table' ), i = t.length, j, k;
while( i-- ) {
j = t[i].rows.length;
while( --j > 1 ) {
k = t[i].rows[j];
k.onclick = function() { multiplerows( this, 'clicked' ); };
k.onmouseover = function() { multiplerows( this, 'hovered' ); };
k.onmouseout = function() {
if( this.className.indexOf( 'hovered' )>-1 ) { multiplerows( this, 'hovered' ); } };
}
}
})();
As a click occurs only when the mouse is already over an element, it is important to place the class definition for the clicked state after the one for the mouseover state in the cascade of styles.
.neutral { background: none; }
.hovered { background: yellow; }
.clicked { background: gold; }