Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 13 of 13
  1. #1
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Table row filtering

    Hey all

    Here's the setup. I've got a PHP page that delivers MySql data into an HTML table for a To Do list. Works peachy. Now, I wanted to add a filtering tool to the table, which I've also done, and it works fine. However, I'm dissatisfied with some of the methods I've used becuase they involve a bit of hard coding, and will make it difficult to expand on later down the road. I think you will see what I mean. There's a decent amount of code, but I want to include it all so that you may just copy>paste it and see the page as I do. Also, I thought I was using strictly DOM methods, but this isn't working in NS6

    Thanks to those who have the patience for this.
    Code:
    <!doctype html public "-//W3C//DTD HTML 3.2 Final//EN" />
    <html>
    <head>
    <title>Dynamic Table Test</title>
    <style>
    td	{
    	font-size: 12px;
    	}
    h2, h3	{
    	font-family: Verdana, Arial, Helvetica, sans-serif;
    	color: #696969;
    	}
    table.dispTable {
    	font-family: Verdana, sans-serif;
    	font-size: 10px;
    	border: 1px solid black;
    	width: 585px;
    	padding: 0px;
    	margin: 5px 0px;
    	}
    table.dispTable th {
    	color: white;
    	font-weight: bold;
    	font-size: 120%;
    	background-color: #999;
    	padding: 3px;
    	text-align: left;
    	}
    table.dispTable tr td {
    	padding: 3px;
    	}
    table.dispTable tr.odd {
    	background-color: #FFF;
    	}
    table.dispTable tr.even {
    	background-color: #EEE;
    	}
    </style>
    <script>
    function doFilter(t, val, cIndex) {
    	var cIndex2 = (cIndex == 1) ? 2 : 1;
    	var sel2 = t.childNodes[1].cells[cIndex2].firstChild;
    	var val2 = sel2.options[sel2.selectedIndex].value;
    
    	for (var i=2; i<t.childNodes.length; i++) {
    		var tr = t.childNodes[i]
    		var txtNode1 = tr.cells[cIndex].firstChild.data;
    		var txtNode2 = tr.cells[cIndex2].firstChild.data;
    		if ((txtNode1 == val || val == 'all') && (txtNode2 == val2 || val2 == 'all'))
    			tr.style.display = "";
    		else
    			tr.style.display = "none";
    		}
    	}
    </script>
    </head>
    
    <body>
    
    	<h3>Jon's To Do List</h3>
    	<table class="dispTable" cellspacing="0">
    		<tr id="1">
    			<th>Title</th>
    			<th>Priority</th>
    			<th>Status</th>
    			<th>Date</th>
    		</tr>
    		<tr id="2">
    			<td style="text-align:right">Filter:</td>
    			<td>
    				<select id="fil_priority" onChange="doFilter(this.parentNode.parentNode.parentNode,this.options[this.selectedIndex].value, this.parentNode.cellIndex);">
    				<option value="all">All</option>
    				<option value="Low">Low</option>
    				<option value="Medium">Medium</option>
    				<option value="High">High</option>
    				<option value="Critical">Critical</option>
    				<option value="N/A">N/A</option>
    				</select>
    			</td>
    			<td>
    				<select id="fil_status" onChange="doFilter(this.parentNode.parentNode.parentNode,this.options[this.selectedIndex].value, this.parentNode.cellIndex);">
    				<option value="all">All</option>
    				<option value="Open">Open</option>
    				<option value="Deferred">Deferred</option>
    				<option value="Complete">Complete</option>
    				<option value="Archived">Archived</option>
    				<option value="Prepaid">Prepaid</option>
    				</select>
    			</td>
    			<td>Date</td>
    		</tr>
    		<tr id="3" class="odd">
    			<td>Test #1</td>
    			<td>Medium</td>
    			<td>Open</td>
    			<td>8/12/02</td>
    
    		</tr>
    		<tr id="4" class="even">
    			<td>Test #2</td>
    			<td>High</td>
    			<td>Complete</td>
    			<td>8/12/02</td>
    
    		</tr>
    		<tr id="5" class="odd">
    			<td>Fix Servers</td>
    			<td>High</td>
    			<td>Complete</td>
    			<td>8/13/02</td>
    		</tr>
    		<tr id="6" class="even">
    			<td>Clean House</td>
    			<td>Critical</td>
    			<td>Complete</td>
    			<td>8/16/02</td>
    
    		</tr>
    		<tr id="7" class="odd">
    			<td>another test</td>
    			<td>Critical</td>
    			<td>Open</td>
    			<td>8/16/02</td>
    
    		</tr>
    		<tr id="8" class="even">
    			<td>Test Again!!!</td>
    			<td>Medium</td>
    			<td>Open</td>
    			<td>8/16/02</td>
    		</tr>
    	</table>
    </body>
    </html>

  • #2
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    if you do this:

    ...
    <tr>
    <td>stuff</td>
    </tr>
    ...

    Gecko browsers will interpret it like this:
    RowElement
    -text Node
    -TD Element
    -text Node

    So you your TD is no longer first child....
    You have 3 options:
    1. have table constructed without any new lines and spaces between tags.
    2. have a function that will parse your document and remove all the empty text nodes on load
    3. construct the table on the client side (see my page for example)
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"

  • #3
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Just going a little further on the concept of "spurious" text nodes:

    Whitespace in Mozilla's XML parser is interpretted as a TextNode to preserve formatting. It is perfectly legal to interpret indentation as text nodes, and in some cases is very useful. When IE parses your code, its internal representation is an ugly, unreadable mess. Just look at document.documentElement.outerHTML, and you'll see what I mean. Mozilla will leave formatting more or less the way it is.

    The negative aspect though is that all of a sudden, you have text nodes where you don't want them.

    An excellent way around this is the DOM2 Traversal specs, in which you can specify "filters" that only iterate through nodes that match the filter, i.e. node.nodeType == Node.ELEMENT_NODE

  • #4
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Well, I coded up this function to remove all the empty textNodes, but IT doesn't work in NS
    Code:
    function detn(oNode) {
    	for (var j=0; j<oNode.childNodes.length; j++) {
    		var currNode = oNode.childNodes[j];
    		if (currNode.nodeType == 3 && (currNode.data == '' || currNode.data == ' ')) {
    			alert('Empty Text Node Found');
    			currNode.removeNode();
    			}
    		if (currNode.childNodes.length>0)
    			detn(currNode);
    		}
    	}
    jkd
    An excellent way around this is the DOM2 Traversal specs
    Perhaps, but not so excellent when over 90% of my demographic on this projects uses IE.
    Last edited by beetle; 08-30-2002 at 06:06 PM.

  • #5
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I think it should be
    node.nodeValue (as defined in W3C specs) not
    node.data
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"

  • #6
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks Vladdy, I changed it to nodeValue, but I still don't get even a single alert in NS

  • #7
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    OK,
    I took another look at your function...

    First, you can not use for loop when you remove nodes you are looping through,
    use this:
    Code:
    var j=0;
      while( j<oNode.childNodes.length)
       { var currNode = oNode.childNodes[j];
          //do things
          j++;
       }
    Second, you are using the removeNode method incorrectly. Do this:
    Code:
    oNode.removeNode(currNode);
    And third, you are testing for empty strings and space when your nodes have new lines and such. Try this:
    Code:
    if (currNode.nodeType == 3 && escape(currNode.nodeValue).substring(0,1) == '%')
    Now, your DoFilter still does not work in Gecko....
    I think the problem is that Gecko interprets the table structure differently (especially since you do not have <tbody> and <thead> defined) and your
    this.parentNode.parentNode.parentNode
    ends up referencing different node.
    Put the rows that you are working with in
    <tbody id="tablebody'>
    and try this:
    DoFilter(document.getElementById('tablebody', ...)
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"

  • #8
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ok, I've got this now, but it doesn't loop in NS (or remove the child, I suspect. Why does my highlighted line work in NS?
    Code:
    function detn(oNode) {
    	for (var i=0; i<oNode.childNodes.length;i++) {
    		var currNode = oNode.childNodes[i];
    		if (currNode.childNodes.length>0)
    			detn(currNode);
    		if (currNode.nodeType == 3 && !currNode.nodeValue.search(/^\s+$/)) {
    			alert('Empty Text Node Found');
    			oNode.removeChild(currNode);
    			}
    		}
    	}

  • #9
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ok, I'll try that stuff and let you know....

  • #10
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Well, through some various tests, I've discovered that my recursive function isn't recurring properly in NS, and at the moment I'm not sure why. calling detn() the first time on the TBODY node yeilds the removal of 9 empty text nodes. If I force run detn() again (on the TBODY) it removes an additional 40 empty text nodes. One more iteration that removes 4 emtpy text nodes is required before no more are found, and all my doFilter() functions work properly.

    Any clues? I'm gonna keep messing with it.

    Here is how my detn() function looks at the moment
    Code:
    function detn(oNode) {
    	var j=0;
    	while( j<oNode.childNodes.length) {
    		var currNode = oNode.childNodes[j];
    		if (currNode.childNodes.length>0)
    			detn(currNode);
    		if (currNode.nodeType == 3 && !currNode.nodeValue.search(/^\s+$/)) {
    //			alert('Empty Text Node Found');
    			oNode.removeChild(currNode);
    			}
    		j++;
    		}
    	}
    Last edited by beetle; 08-30-2002 at 08:43 PM.

  • #11
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Code:
    function removeAllTextNodes(pNode) {
      var tree = document.createTreeWalker(pNode, NodeFilter.SHOW_TEXT, { acceptNode: function(node) { return /\S/.test(node.nodeValue) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT } }, false);
      while (tree.nextNode())
        tree.currentNode.parentNode.removeChild(tree.currentNode);
    }
    I create a TreeWalker with the root node set to the argument. I then tell it that only TextNodes will be visible in iterating, I then create a filter which rejects all text nodes that /\S/.test returns true for (i.e. non-whitespace), and accept any node which only has whitespace (i.e. indentation).
    I then iterate through all the nodes matching my criteria, and remove them from their parent node.

    This should take care of your spurious text node problem in Mozilla.

  • #12
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by jkd
    This should take care of your spurious text node problem in Mozilla.
    *Should* being the operative word I appreciate your time jkd, but it's not working.

    After much deliberation, I've ended with this, which works.
    Code:
    function initTNparse() {
    	window.TNcount = 1;
    	while (window.TNcount != 0) {
    		window.TNcount = 0;
    		TNparse(document.getElementById('tablebody'));
    		}
    	}
    
    function TNparse(oNode) {
    	var j=0;
    	while( j<oNode.childNodes.length) {
    		var currNode = oNode.childNodes[j];
    		if (currNode.childNodes.length>0)
    			TNparse(currNode);
    		if (currNode.nodeType == 3 && !currNode.nodeValue.search(/^\s+$/)) {
    			oNode.removeChild(currNode);
    			window.TNcount++;
    			}
    		j++;
    		}
    	}
    
    </script>
    </head>
    
    <body onLoad="initTNparse();">
    Whew, what a day! Now, I'm still curious if I can get my doFilter() function to be any more flexible. Right now it's hard coded to work with only two of the columns. There may be occaisions where I need more. Any ideas?

  • #13
    Senior Coder
    Join Date
    Jun 2002
    Location
    Nashua, NH
    Posts
    1,724
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Building table dynamically would be my answer not only to the differencies in the way Gecko and IE parse HTML but to flexibility as well.
    Vladdy | KL
    "Working web site is not the one that looks the same on common graphical browsers running on desktop computers, but the one that adequately delivers information regardless of device accessing it"


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •