Javascript dynamic table filtering

Discussion in 'Web Design and Development' started by drsoong, Mar 24, 2008.

  1. drsoong macrumors member

    Joined:
    Mar 24, 2008
    Location:
    Munich
    #1
    Hi,

    I just joined Macrumors after having purchased my first Mac :)apple: Macbook 2.2GHz) on Christmas. :)

    My first post on Macrumors, however, is related to some hobby-horse web development I am doing at the moment:

    I want to dynamically filter a HTML table on a page according to the user inputs in search fields and drop-down-menus. On the site www.vonloesch.de I found some very useful code that does that either for a complete row or for individual columns:

    For the whole row:

    Code:
    function filter (phrase, _id){
     	var words = phrase.value.toLowerCase().split(" ");
     	var table = document.getElementById(_id);
     	var ele;
     	for (var r = 1; r < table.rows.length; r++){
     		ele = table.rows[r].innerHTML.replace(/<[^>]+>/g,"");
     	        var displayStyle = 'none';
     	        for (var i = 0; i < words.length; i++) {
     		    	if (ele.toLowerCase().indexOf(words[i])>=0)
     					displayStyle = '';
     		    	else {
     					displayStyle = 'none';
     					break;
     		    	}
     	        }
     		table.rows[r].style.display = displayStyle;
     	}
    }
    
    or for only one column:

    Code:
    function filter_column (term, _id, cellNr){
    	var suche = term.value.toLowerCase();
    	var table = document.getElementById(_id);
    	var ele;
    	for (var r = 1; r < table.rows.length; r++){
    		ele = table.rows[r].cells[cellNr].innerHTML.replace(/<[^>]+>/g,"");
    		if (ele.toLowerCase().indexOf(suche)>=0 )
    			table.rows[r].style.display = '';
    		else table.rows[r].style.display = 'none';
    	}
    }
    
    Being familar with C/C++, I am not entirely new to the concepts of programming, but Web Development and Javascript in particular are new to me. My problem is that my initial idea to simply modify the code to check for the entries of multiple text fields to allow for logically "AND" combined search criteria seems not so easy to achieve. The problem with the above the code is that, when having multiple search fields on a page, switching from one to another destroys the filter criteria of the first and I cannot, say, filter for "name" and "type" in a boolean "AND" manner.

    My idea was to lose some of the flexibility of the above functions, by tayloring it to the specific tables I am using, and fetching the individual entries from multiple search fields and combine them into one "if"-statement that decides if a row should be displayed or not. The code I use is the following:

    Code:
    /* Filter object_table	*/
    function filter_object(){
    	
    	table = document.getElementById("object_table");
    	
    	/* Get all form fields in this division */
    	var name = document.object_form.object_name.value.toLowerCase();
    	var constellation = document.object_form.object_constellation.value.toLowerCase();
    	var type = document.object_form.object_type.value.toLowerCase();
    	var astronomer = document.object_form.object_astronomer.value.toLowerCase();
    
    	//alert(name);
    
    	/* Convert all search terms to lower case */
    	// name=name.toLowerCase();
    	// constellation=constellation.toLowerCase();
    	// type=type.toLowerCase();
    	// astronomer=astronomer.toLowerCase();
    
    	// Loop over table rows and cells, and search for combined term
    	for (var r = 1; r < table.rows.length; r++){
    		// get content of cell and remove tags
    		
    		//element = table.rows[r].cells[c].innerHTML.replace(/<[^>]+>/g,"");
    		//element.toLowerCase();		// convert to lower case
    			
    		var table_name = table.rows[r].cells[0].innerHTML.replace(/<[^>]+>/g,"").toLowerCase();	
    		var table_constellation = table.rows[r].cells[3].innerHTML.replace(/<[^>]+>/g,"").toLowerCase();			
    		var table_type = table.rows[r].cells[4].innerHTML.replace(/<[^>]+>/g,"").toLowerCase();
    		var table_astronomer = table.rows[r].cells[5].innerHTML.replace(/<[^>]+>/g,"").toLowerCase();
    
    		if ( table_name.indexOf(name)>=0 || table_constellation.indexOf(constellation)>=0 
    			|| table_type.indexOf(type)>=0 || table_astronomer.indexOf(astronomer)>=0 ) {
    			table.rows[r].style.display = '';
    		}
    		else{
    			table.rows[r].style.display = 'none';
    		}
    
    	}
    }
    
    
    I taylor the function to specifically work for the table that displays information about (astronomical) objects. I fetch the the entries in the search fields and those of the columns of the row I am currently in. Simply comparing the two should yield the desired result.

    NB: The functions are called on the "onkeyup"-Events of several HTML-form fields on my page, to provide the user with an instant update of his search:

    Code:
    echo "<form name=\"object_form\">";
    echo "<table class=\"wide-table\">\n";
    echo "<thead>\n";
    echo "<td>Object name</td><td>Constellation</td><td>Type</td><td>Astronomer</td>";
    echo "</thead>\n";
    echo "<tbody>\n";
    echo "<tr>\n";
    echo "<td>";
    echo "<input name=\"object_name\" onkeyup=\"filter_object()\" type=\"text\">";
    echo "</td>";
    echo "<td>\n";
    echo "<input name=\"object_constellation\" onkeyup=\"filter_object()\" type=\"text\">";
    echo "</td>\n";
    echo "<td>\n";
    echo "<input name=\"object_type\" onkeyup=\"filter_column(this, 'object_table', 4)\" type=\"text\">";
    echo "</td>\n";
    echo "<td>\n";
    echo "<input name=\"object_astronomer\" onkeyup=\"filter_column(this, 'object_table', 5)\" type=\"text\">";
    echo "</td>\n";
    echo "</tr>\n";
    echo "</tbody>\n";
    echo "</table>\n";
    echo "</form>\n";
    
    ... the problem is that the filtering does not work at all anymore with my code (filter_column() still works, but the combined search with filter_object() not). The table is not filtered, rows that do not contain the search criteria, are not left out. Considering I am using the same line as in the previous versions I suppose that changing the display.style property should still work, but the logical consequence of that would be that my if-clause has some stupid logical error?

    I tried debugging it with Firefox' Javascript debugger and as far as I could see, the variables contain the expected values (search fields and table column entries), but the if-logic fails.

    I must have some really stupid error and I would be very happy if someone could point me to it. :rolleyes:

    Thanks for your help.
     
  2. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #2
    You mention logical AND, but your code is using logical or operators:

    Code:
    		if ( table_name.indexOf(name)>=0 || table_constellation.indexOf(constellation)>=0 
    			|| table_type.indexOf(type)>=0 || table_astronomer.indexOf(astronomer)>=0 ) {
    			table.rows[r].style.display = '';
    		}
    		else{
    			table.rows[r].style.display = 'none';
    		}
    
    I'm not 100% sure what you intend, but you could try using the logical and operator:

    Code:
    		if ( table_name.indexOf(name)>=0 && table_constellation.indexOf(constellation)>=0 
    			&& table_type.indexOf(type)>=0 && table_astronomer.indexOf(astronomer)>=0 ) {
    			table.rows[r].style.display = '';
    		}
    		else{
    			table.rows[r].style.display = 'none';
    		}
    
     
  3. drsoong thread starter macrumors member

    Joined:
    Mar 24, 2008
    Location:
    Munich
    #3
    Thanks - logical error

    What I am trying to achieve was this:

    If there is some tabulated information given on a page, I want the user to enter say "3C" (as a wildcard for the name) and "AGN" for the type so that the table gets filtered to those rows only fulfilling all criteria.

    HTML:
    <table>
    <tr>
    <td>Object name	</td><td>Rightascension</td><td>Declination</td><td>Constellation</td><td>Type</td><td>Astronomer</td>
    </tr>
    <tr>
    <td>3C273</td><td>12:29:06.70</td><td>+12:13:08.6</td><td>Virgo</td><td>AGN</td><td>unknown</td>
    <td>3C279</td><td>12:56:11.17</td><td>-5:47:21.5</td><td>Virgo</td><td>AGN</td><td>unknown</td>
    </tr>
    <tr>
    <td>3C454.3</td><td>22:53:57.70</td><td>+16:08:53.0</td><td>Pegasus</td><td>Blazar</td><td>unknown</td>
    </tr>
    </table>
    

    That actually solves my problem! Thanks a million, I knew I must have made a stupid mistake. Of course, from logical stand-point this means all criteria must be fulfilled, therefore "AND". :)

    I really messed it up there with my if-clause. :eek:


    I am glad I received so quick help here on Macrumors. I still have a few other issues on my Web development to solve and good Javascript-Tutorials, at least those that go beyond the basics, are hard to find.
     

Share This Page