Some advice... rather than screwing around with readystatechange, just put the script before </body> and just run the attach then. By that point the DOM is always built, so you don't need to play around with events like onload, domdocumentready or readystatechange, just do it!
Likewise, try NOT to do lookups or nested references inside your events. They take up a good deal of time, processing power (therein battery life) which is why a lot of such scripting enhancements are unpopular with the mobile crowd. (which is why more and more mobile users are blocking JS)
If you were to store an array of the rows to be filtered in a data attribute (well, data_ since get/setAttribute are a PITA) you can do a lot of the heavy lifting at load time instead of on every keypress. The only reason to process every time is if you are adding/removing rows from the scripting -- and in that case I'd regenerate the list on add/remove/repopulate and not on keystroke.
Something like...
Code:
(function(d) {
'use strict';
function inputEvent(e) {
for (
var
value = e.target.value.toLowerCase(),
i = 0, iLen = e.target.data_targetRows.length;
i < iLen; i++
) e.target.data_targetRows[i].style.display =
e.target.data_targetRows[i].textContent.toLowerCase().indexOf(value) === -1 ?
'none' :
'table-row';
}
for (
var
inputs = d.getElementsByClassName('light-table-filter'),
i = 0, iLen = inputs.length;
i < iLen; i++
) {
inputs[i].data_targetRows = [];
inputs[i].addEventListener('input', inputEvent);
for (
var
tables = d.getElementsByClassName(inputs[i].getAttribute('data-table')),
j = 0, jLen = tables.length;
j < jLen; j++
) for (
var
table = tables[j],
k = 0, kLen = table.tBodies.length;
k < kLen; k++
) for (
var
rows = table.tBodies[k].rows,
l = 0, lLen = rows.length;
l < lLen; l++
) inputs[i].data_targetRows.push(rows[l])
}
})(document);
(untested, might be typo's but it should work)
In my version I create variable references to fixed values during the loop initializer, which prevents "long" array lookups on every loop. Amazingly declaring the new variable reference to an array index is faster inside the loop than looking it up every time -- same reason you'll see scripts (like mine) that store array lengths before looping too. I use "for" instead of "Array.forEach" as the overhead of the function calls (requring a good deal of stack dicking around) also slows down execution a LOT, even if it seems like less code/less typing.
I also reduced the number of functions -- that filter operation being in it's own function was cute, but it's just more overhead from another unnecessary function call. Unless you were calling that filter from multiple places, don't waste the overhead of a function on it!
I also prefer to keep things in call order; I realize JavaScript has "lifting" but I don't trust it.
I was going to go ahead and polyfill for legacy, but given the trigger event is "input", something that doesn't even exist in IE8/earlier there's really no reason to bother. STILL I'd consider trapping "keypress" and "onchange" instead (yes, both) with a timeout event for two reasons:
1) If someone is typing as fast as I do, you're not hammering the scripting for nothing. A 200 to 300ms delay before filtering can make an amazing drop in the amount of CPU chewed up by the scripting.
2) legacy browsers can trap onchange and keypress, and by the time a timeout() passes the event will have been processed. When a new event occurs you check if there's already a timeout counting down, if so you delete it... then either way create a new one. The trick would be passing the event to that timeout, which is why I'd put the timeout's handler and the element it is for into an object indexed by your data-table attribute.
Oh, and are you REALLY sure you'd have more than one table being filtered by this script? If you're only indexing one table axing the outer loop and using an ID instead would make more sense and use less overhead.
-------------
edit -- PS, i realize this is just a demo, but in production try to remember that a placeholder is not a label!