Recently i´ve been asked to develop a script to allow filtering in the content of the table, with dinamic options based on the own content. Example: a table with the name of some students and their respective numbers, and then you wanna show only studentes called "Joao", or students with number "5", or even only students called "joao" with number "5".
The structure we are going to use is a basic html table, like:
Expand|Select|Wrap|Line Numbers
- <table>
- <thead>
- <tr>
- <th>Header</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>Content</td>
- </tr>
- </tbody>
- </table>
JS: filter:js
Expand|Select|Wrap|Line Numbers
- ///////////////////////////////////////////////
- // Created by: Romulo do Nascimento Ferreira //
- // Email: romulo.nf@gmail.com //
- ///////////////////////////////////////////////
- //
- // Parameters
- // tableID = id of the table to allow the filtering
- // numRows = max number of rows to show (more will create a scrollbar)
- //
- function createFilter(tableID,numRows) {
- this.table = document.getElementById(tableID)
- this.table.className = "filter"
- this.header = this.table.tHead
- this.mainBody = this.table.tBodies[0]
- this.numCol = this.header.rows[0].cells.length
- this.maxRows = numRows
- this.selectArray = new Array(this.numCol)
- this.optionArray = new Array(this.numCol)
- // create an extra tr beneath the header
- this.newTr = document.createElement("tr")
- this.header.appendChild(this.newTr)
- for (x=0; x<this.numCol; x++) {
- // loop to create the th's
- tempTh = document.createElement("th")
- this.newTr.appendChild(tempTh)
- // create one select box to each th
- tempSelect = document.createElement("select")
- tempSelect.style.width = this.header.rows[0].cells[x].offsetWidth - 10 + "px"
- tempSelect.ativado = false
- tempSelect.filtro = this
- tempSelect.onchange = function() { this.filtro.applyFilter(this) }
- this.selectArray[x] = tempSelect
- tempTh.appendChild(tempSelect)
- }
- for (x=0; x<this.header.rows.length; x++) {
- // create an extra th to allow the scrolling
- tempTh = document.createElement("th")
- tempTh.className = "scrollBar"
- this.header.rows[x].appendChild(tempTh)
- }
- // change the table normal structure to allow the scroll
- tempTr = document.createElement("tr")
- tempTd = document.createElement("td")
- divHolder = document.createElement("div")
- tempTable = document.createElement("table")
- this.newBody = document.createElement("tbody")
- for (x=this.mainBody.rows.length-1; x>=0; x--) {
- this.newBody.appendChild(this.mainBody.rows[x])
- }
- tempTd.colSpan = this.numCol + 1
- divHolder.className = "holder"
- this.mainBody.appendChild(tempTr)
- tempTr.appendChild(tempTd)
- tempTd.appendChild(divHolder)
- divHolder.appendChild(tempTable)
- tempTable.appendChild(this.newBody)
- divHolder.style.height = numRows * this.newBody.rows[0].cells[0].offsetHeight + "px"
- this.populateFilters()
- }
- createFilter.prototype.populateFilters = function() {
- for (x=0; x<this.numCol; x++) {
- tempOptionArray = new Array()
- count = 0
- // clear all the options from the selects
- if (this.selectArray[x].options.length > 0) {
- for (y=this.selectArray[x].options.length-1; y>=0; y--) {
- this.selectArray[x].remove(y)
- }
- }
- // search through all visible rows and populate an array with all the possibilities
- for (y=0; y<this.newBody.rows.length; y++) {
- if (this.newBody.rows[y].style.display !="none") {
- tempOptionArray[count] = this.newBody.rows[y].cells[x].innerHTML
- count = count + 1
- }
- }
- // sort this array
- tempOptionArray.sort()
- // remove all repeated entries
- for (y=tempOptionArray.length-1; y>=1; y--) {
- if (tempOptionArray[y] == tempOptionArray[y-1]) {
- tempOptionArray.splice(y,1)
- }
- }
- // create a blank option to remove the filter
- blankOption = document.createElement("option")
- blankOption.innerHTML = ""
- blankOption.value = ""
- this.selectArray[x].appendChild(blankOption)
- // loop the array and populate the select box
- for (y=0; y<tempOptionArray.length; y++) {
- newOption = document.createElement("option")
- newOption.innerHTML = tempOptionArray[y]
- newOption.value = tempOptionArray[y]
- this.selectArray[x].appendChild(newOption)
- if (this.selectArray[x].ativado) {
- this.selectArray[x].options[1].selected = "selected"
- }
- }
- }
- this.zebraRows()
- }
- createFilter.prototype.applyFilter = function(filtro) {
- cellIndex = filtro.parentNode.cellIndex
- appliedFilter = filtro.value
- appliedFilter != "" ? filtro.ativado = true : filtro.ativado = false
- // loop all rows and compare the innerHTML from the tds with the filter
- // hide the tds that dont match the filter
- for (x=0; x<this.newBody.rows.length; x++) {
- this.newBody.rows[x].flag = false
- for (y=0; y<this.numCol; y++) {
- if (this.newBody.rows[x].cells[y].innerHTML != this.selectArray[y].value && this.selectArray[y].value !="") {
- this.newBody.rows[x].flag = true
- }
- }
- this.newBody.rows[x].flag ? this.newBody.rows[x].style.display = "none" : this.newBody.rows[x].style.display = ""
- }
- this.populateFilters()
- }
- createFilter.prototype.zebraRows = function() {
- this.nextClass = "odd"
- for (x=0; x<this.newBody.rows.length; x++) {
- if (this.newBody.rows[x].style.display != "none") {
- this.newBody.rows[x].className = this.nextClass
- this.nextClass == "odd" ? this.nextClass = "even" : this.nextClass = "odd"
- }
- }
- }
Expand|Select|Wrap|Line Numbers
- .filter {border-collapse:collapse; table-layout:fixed; width:500px}
- .filter th {text-align:center; background:#eee; border:1px dotted #777; font:bold 11px verdana; line-height:16px; padding:1px}
- .filter td {text-indent:5px; overflow:hidden; white-space:nowrap; font:normal 11px verdana}
- .filter th select {overflow:hidden; font:normal 11px verdana}
- .even td {background:#fff}
- .odd td {background:#eee}
- .filter table {width:480px; table-layout:fixed; border-collapse:collapse}
- .filter .holder {width:499px; overflow:auto;}
- .filter .scrollBar {border:0; background:transparent; width:13px;}
- * html .filter .scrollBar {width:16px}
Expand|Select|Wrap|Line Numbers
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
- <html>
- <head>
- <title>Filter</title>
- </head>
- <script src="filter.js"></script>
- <link rel="stylesheet" href="filter.css" type="text/css">
- <script>
- window.onload = function() {
- new createFilter("tabelaUm",10)
- }
- </script>
- <body>
- <h2>Filter</h2>
- <script>
- arrayNomes = ['Ricardo','Paulo','Maria','Joana','Rita','Fabiano']
- arrayNumeros = ['1','2','3','4','5','6','7','8','9']
- arrayTipo = ['Excellent','OK','Bad']
- tabela = document.createElement("table")
- tabela.id = "tabelaUm"
- thead = document.createElement("thead")
- tabela.appendChild(thead)
- tr = document.createElement("tr")
- for (x=0; x<4; x++) {
- th = document.createElement("th")
- th.innerHTML = "Header " + (x+1)
- tr.appendChild(th)
- }
- thead.appendChild(tr)
- tbody = document.createElement("tbody")
- for (x=0; x<250; x++) {
- tr = document.createElement("tr")
- td = document.createElement("td")
- td.innerHTML = arrayNomes[Math.floor(Math.random()*6)]
- tr.appendChild(td)
- td = document.createElement("td")
- td.innerHTML = arrayNumeros[Math.floor(Math.random()*9)]
- tr.appendChild(td)
- td = document.createElement("td")
- td.innerHTML = arrayNumeros[Math.floor(Math.random()*9)]
- tr.appendChild(td)
- td = document.createElement("td")
- td.innerHTML = arrayTipo[Math.floor(Math.random()*3)]
- tr.appendChild(td)
- tbody.appendChild(tr)
- }
- tabela.appendChild(tbody)
- document.getElementsByTagName("body")[0].appendChild(tabela)
- </script>
- </body>
- </html>
If you find something needing some fix, send me an email.
Good luck!