Table with filtering to the content

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Romulo NF
    New Member
    • Nov 2006
    • 54

    Table with filtering to the content

    Greetings again everyone
    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:

    Code:
    <table>
     <thead>
      <tr>
       <th>Header</th>
      </tr>
     </thead>
     <tbody>
      <tr>
       <td>Content</td>
      </tr>
     </tbody>
    </table>
    And here comes the css/js, and after that a simple sample.

    JS: filter:js
    Code:
    ///////////////////////////////////////////////
    // 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"
    		}
    	}
    }
    CSS: filter.css
    Code:
    .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}
    Sample: filter.html
    Code:
    <!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>
    Thats basically it. Feel free to use the script anywhere.
    If you find something needing some fix, send me an email.

    Good luck!
Working...