Jump to content

Highlighting Text Using Ranges


awitt

Recommended Posts

So, I need some help with ranges using javascript. I am creating an HTML table field with school closings for the state. the ranges come into play because I'm trying to implement search functionality. I want users to type their search criteria into a text input box and then have any matches on the page get highlighted. Here's the code I'm working with - the problem is the search() function:

<?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   <xsl:template match="/">	   <html>		   <head>		   				<meta name="description"					content="List of Closings / Delays / Emergencies in the State of Ohio" />				<meta name="keywords"					content="closed, closings, school, cancel, cancelled, cancellation, delay, snow, emergency" />		   			   		<style type = "text/css">		   			.matched_word		   			{color: green}		   		</style>					   		   		<script type="text/javascript">		   				   			var table = new Array();					var tabletext = "";						   					   			function closing(id, co, lo, st)		   			{		   				this.ID = id		   				this.County = co;		   				this.Location = lo;		   				this.Status = st;		   			}		   					   			function create_array()		   			{   			   				var i = 0;			   						   				<xsl:for-each select = "closings/county/announcement">		   						   					var closing1 = new closing("<xsl:value-of select = "./@id" />", "<xsl:value-of select = "../@name" />", 		   						"<xsl:value-of select = "location" />", "<xsl:value-of select = "status" />");		   					table[i] = closing1;		   					i++;		   							   				</xsl:for-each>		   			}		   					   			function all()		   			{   						for (x in table)						{							var current_id = "row_" + table[x].ID;							document.getElementById(current_id).style.display = "table-row";						}					}		   			function search()		   			{						var searchthis = document.getElementById("search_text").value;												for (x in table)						{							var row_coll = document.getElementById("test").rows;							var cell_coll = row_coll[x].cells;													for (i = 2; i >= 0; i--)							{								var text_to_search = cell_coll[i].innerHTML;																if(text_to_search.indexOf(searchthis) != -1)								{									var node_sel = cell_coll[i];									var start_node = node_sel.firstChild;									var end_node = node_sel.firstChild;																		var range_sel = document.createRange();																		var eSpan = document.createElement("span");									eSpan.style.backgroundColor = "yellow";																		range_sel.setStart(start_node, text_to_search.indexOf(searchthis));									range_sel.setEnd(end_node, searchthis.length);									range_sel.surroundContents(eSpan);								}							}						}		   			}		   					   			function filter()		   			{			   			if (sort_by.value != 0)			   			{					   		if (sort_by.value == 1)					   		{					   			all();					   								   			for (x in table)					   			{					   				if ( !(table[x].Status.match("closed")) && !(table[x].Status.match("Closed")) )					   				{					   					var current_id = "row_" + table[x].ID;					   					document.getElementById(current_id).style.display = "none";					   				}					   			}					   		}				   							   			else if (sort_by.value == 2)				   			{				   				all();				   								   			for (x in table)					   			{					   				if ( !(table[x].Status.match("emergency")) && !(table[x].Status.match("Emergency")) )					   				{					   					var current_id = "row_" + table[x].ID;					   					document.getElementById(current_id).style.display = "none";					   				}					   			}				   			}				   							   			else if (sort_by.value == 3)				   			{				   				all();				   								   			for (x in table)					   			{					   				if ( !(table[x].Status.match("delay")) && !(table[x].Status.match("Delay")) )					   				{					   					var current_id = "row_" + table[x].ID;					   					document.getElementById(current_id).style.display = "none";					   				}					   			}				   			}				   							   			else if (sort_by.value == 4)				   			{				   				all();				   								   			for (x in table)					   			{					   				if ( (table[x].Status.match("close"))     || 					   					 (table[x].Status.match("delay"))     || 					   					 (table[x].Status.match("emergency")) || 					   					 (table[x].Status.match("Close"))     ||					   					 (table[x].Status.match("Delay"))     || 					   					 (table[x].Status.match("Emergency"))  )					   				{					   					var current_id = "row_" + table[x].ID;					   					document.getElementById(current_id).style.display = "none";					   				}					   			}				   			}				   							   			else if (sort_by.value == 5)				   			{all();}				   							   			else if (sort_by.value == 6)				   			{				   				all();				   							   				for (x in table)				   				{				   					if ( !(table[x].County == "Franklin") && !(table[x].County == "franklin") )				   					{				   						var current_id = "row_" + table[x].ID;					   					document.getElementById(current_id).style.display = "none";				   					}				   				}				   			}						}		   			}		   						</script>		   					   	<title>State of Ohio Closings / Delays / Emergencies</title>	            <h1>School Closings</h1>	            	            <p>	               <b>Search Criteria:  </b>	               <input type="text" id="search_text" onkeyup="search()" />	            </p>		            <p>	               <b>Choose a Filter:  </b>		               <SELECT id="sort_by" onchange="filter()">	                  <option value="0">- Choose a Filter -</option>	                  <option value="0">---------------------</option>	                  <option value="1">Closed Schools</option>	                  <option value="2">Snow Emergencies</option>	                  <option value="3">Delays</option>	                  <option value="0">---------------------</option>	               	  <option value="6">Franklin County</option>	                  <option value="4">Any Other</option>	                  <option value="5">ALL</option>	               </SELECT>	            </p><p />	            		   </head>		   		   <body>		   				   		<script type="text/javascript">create_array();</script>		   				   		<table border = "4" id="test">		   			<tr bgcolor = "#9acd32">		   				<th align = "center"><b><b>COUNTY</b></b></th>		   				<th align = "center"><b><b>LOCATION</b></b></th>		   				<th align = "center"><b><b>STATUS</b></b></th>		   			</tr>		   			<xsl:for-each select = "closings/county/announcement">			   				<tr>			   					<xsl:attribute name="id">row_<xsl:value-of select="./@id" /></xsl:attribute>			   					<td>			   						<xsl:value-of select = "../@name" />			   					</td>			   					<td>			   						<xsl:value-of select = "location" />			   					</td>			   					<td>			   						<xsl:value-of select = "status" />			   					</td>			   				</tr>		   			</xsl:for-each>		   		</table>		   </body>	   </html>	</xsl:template></xsl:stylesheet>

Now, I'm decent with my knowledge of javascript and XML technology, but, just in case you couldn't tell by my code, I don't really know what I'm doing with ranges. Anyways, any help on this would be awesome, thanks.

<closings> 	<county name="Adams"> 		<announcement id="1" onn="1" wbns="0"> 			<location>Ohio Valley Local Schools</location> 			<status>Closed</status> 			<source>172.19.16.33</source> 			<creationtime>Jan 28 2009 05:02AM</creationtime> 			<expiretime>Jan 28 2009 01:00PM</expiretime> 		</announcement> 		<announcement id="2443" onn="1" wbns="0"> 			<location>Snow Emergency</location> 			<status>Level 3 Snow Emergency</status> 			<source>172.19.16.33</source> 			<creationtime>Jan 28 2009 09:19AM</creationtime> 			<expiretime>Jan 28 2009 07:00PM</expiretime> 		</announcement> 	</county> 	<county name="Allen"> 		<announcement id="6" onn="1" wbns="0"> 			<location>Elida Local Schools</location> 			<status>Closed</status> 			<source>4193314115</source> 			<creationtime>Jan 28 2009 05:40AM</creationtime> 			<expiretime>Jan 28 2009 01:00PM</expiretime> 		</announcement> 		<announcement id="3538" onn="1" wbns="0"> 			<location>Snow Emergency</location> 			<status>Level 1 Snow Emergency</status> 			<source>172.19.16.8</source> 			<creationtime>Jan 28 2009 09:15AM</creationtime> 			<expiretime>Jan 28 2009 07:00PM</expiretime> 		</announcement> 	</county></closings>

And here's a lil sample of the XML file I am transforming against.

Link to comment
Share on other sites

What behavior are you seeing when you search? It would probably be useful to get Firebug set up with Firefox and use it to help debug. You can use console.log to send output to the Firebug console. Add some log statements to the search function to make sure you're selecting what you think you are (e.g., write out the node_sel, start_node, text_to_search etc to make sure they are what you expect them to be).Other than that, you might want to look into some of the other methods of the range object, like selectNodeContents.https://developer.mozilla.org/en/DOM/range

Link to comment
Share on other sites

What behavior are you seeing when you search? It would probably be useful to get Firebug set up with Firefox and use it to help debug. You can use console.log to send output to the Firebug console. Add some log statements to the search function to make sure you're selecting what you think you are (e.g., write out the node_sel, start_node, text_to_search etc to make sure they are what you expect them to be).Other than that, you might want to look into some of the other methods of the range object, like selectNodeContents.https://developer.mozilla.org/en/DOM/range
Man, I've been tryin to understand this HTML DOM, but I'm having trouble grasping it. For example, can I select all "td" tagged items (i.e. every cell of data in my table) and iterate through them? If I could do that, then I could just test each "td" block of data against then search term. Then I'm thinkin' I could surround the pertinent characters with some <span background-color="yellow"></span> tags. Would something like that work?
Link to comment
Share on other sites

Would something like that work?
Yes, you can iterate through all the tds, but, depending on how many tds are on your page, that could be a pretty heavy operation.
// get all the tds in the document.var tds = document.getElementsByTagName("td");

If you only want to search for the tds in a particular table, you can do something like this:

var t = document.getElementById("theTableID");var tds = t.getElementsByTagName("td");

Link to comment
Share on other sites

Sure:var td_list = document.getElementsByTagName('td');for (i = 0; i < td_list.length; i++)...The actual element will be td_list, so you can test td_list.innerHTML and use range.selectNodeContents(td_list) to select the text and wrap your span around it, or you can set td_list.style to apply a background color.

Link to comment
Share on other sites

function search()		   			{						var searchthis = document.getElementById("search_text").value;												var html_table = document.getElementById("test");						var td_coll = html_table.getElementsByTagName("td");						for (i = td_coll.length; i >= 0; i--)						{							if ((td_coll[i] != null) || (td_coll[i] != ""))							{								var x = td_coll[i].indexOf(searchthis);																if (x != -1)								{									var part1 = "";									var part2 = "";									var part3 = "";																		part1 = td_coll[i].innerHTML.substr(0, x);									part2 = '<span background = "yellow">' + td_coll[i].innerHTML.substr(x, searchthis.length);									part2 += '</span>';		   							part3 = td_coll[i].innerHTML.substr(x + searchthis.length);		   									   							td_coll[i].innerHTML = part1 + part2 + part3;								}							}						}		   			}

So here's my modified search function, but when i run the html in mozilla, it gives me an error: td_coll is undefined. Am I still doing something wrong?

Link to comment
Share on other sites

for (i = td_coll.length - 1; i >= 0; i--)That's going to search from the bottom to the top though. If you want to search from top to bottom do this:for (i = 0; i < td_coll.length; i++)
enh, it doesn't matter which direction i search - the whole table's gotta be iterated through. plus, my Oxygen editor doesn't like '<' symbols, so i just make it easier on myself and go backwards with my loops. anyways, why is it saying that td_coll is undefined when it obviously is?
Link to comment
Share on other sites

Here's another implementation of my search() function:

function search()		   			{						var searchthis = document.getElementById("search_text").value;												var html_table = document.getElementById("test");						var td_coll = html_table.getElementsByTagName("td");						for (i = td_coll.length - 1; i >= 0; i--)						{							if ((td_coll[i] != null) || (td_coll[i] != ""))							{								var x = td_coll[i].innerHTML.indexOf(searchthis);																if (x != -1)								{		   							var rRange = document.createRange();		   							rRange.selectNodeContents(td_coll[i], x);		   									   							var sSpan = document.createElement("span");		   							sSpan.style.backgroundColor = "yellow";		   							rRange.surroundContents(sSpan);								}							}						}		   			}

[/i]Now, this works pretty well; it's gettin' close. What this does is select the whole word if there's a match. I only want to select the character. Anyone know how to modify to achieve this? I've tried using the setStart and setEnd methods, but apparently, I don't know how to use them correctly. Oh, and thank you JustSomeGuy - that was a dumb thing on my part not to notice the length-1.

Link to comment
Share on other sites

It looks like selectNodeContents doesn't use an index, it just selects the entire contents. If you want to select just part of it you'll probably need to use setStart and setEnd like you were.
Yea, I ended up taking that index (x) out. I saw that after the posting. But I cannot figure out how to define the setStart and setEnd. What I have figured out is this:Apparently, the setEnd/Start methods will accept an integer value for the offset. Here's what makes it tricky:
If the startNode is a Node of type Text, Comment, or CDATASection, then startOffset is the number of characters from the start of startNode. For other Node types, startOffset is the number of child nodes between the start of the startNode.Setting the start point below (further down in the document) than the end point will throw an NS_ERROR_ILLEGAL_VALUE exception.
So, it looks like the selectNodeContents has selected a node of some non-text type. That doesn't make sense to me, it's filled with text. And, I do not know how to find and/or set the type of node that I've selected. So, when I try to define some integer value that I want to be the offset, it thinks I'm talking about a number of nodes to offset, instead of the number of characters to offset. So it seems to me, that if someone out there knew ranges well, all they'd have to do is explain to me how to further define a range using the setStart and setEnd methods provided to me.
Link to comment
Share on other sites

You can check the node type using node.nodeType.http://www.javascriptkit.com/domref/nodetype.shtmlYou can also use Firebug's console.log to write the node to the console and then browse through the childNodes property to see what the structure of the node looks like. The td itself is not a text node, it's an element node. In a structure like this:<td>some text</td>The td is an element node that contains 1 child. The child is an unnamed text node with the content "some text". To access the text node from the td, you would need to use td.firstChild or td.childNodes[0].

Link to comment
Share on other sites

You can check the node type using node.nodeType.http://www.javascriptkit.com/domref/nodetype.shtmlYou can also use Firebug's console.log to write the node to the console and then browse through the childNodes property to see what the structure of the node looks like. The td itself is not a text node, it's an element node. In a structure like this:<td>some text</td>The td is an element node that contains 1 child. The child is an unnamed text node with the content "some text". To access the text node from the td, you would need to use td.firstChild or td.childNodes[0].
Dude, you are awesome! That last bit was exactly what I needed for the past couple of hours. Thank you so much man.
Link to comment
Share on other sites

Alrighty fellas (well, mainly you, JustSomeGuy), one more part of this problem to figure out. So, the search text is coming from an input box on the page of type text - makes sense, huh? Well, the functionality I just implemented with the whole search and highlight thing needs to be reversed. I have two problems whenever the user types more than one character:1) Firstly, I must remove the span tags that allowed me to change the background color so that the highlighting goes back to nonexistent and the process can start all over again.2) I get an error:

uncaught exception: Index or size is negative or greater than the allowed amount (NS_ERROR_DOM_INDEX_SIZE_ERR)file:///C:/Documents%20and%20Settings/...Line 8168
Here's the code for the search() method:
function search()		   			{		   				remove_span_tags();		   						   				var searchthis = null;		   				var html_table = null;		   				var td_coll = null;		   									searchthis = document.getElementById("search_text").value;						html_table = document.getElementById("test");						td_coll = html_table.getElementsByTagName("td");						for (i = td_coll.length - 1; i >= 0; i--)						{							if ((td_coll[i] != null) || (td_coll[i] != ""))							{								var x = td_coll[i].innerHTML.indexOf(searchthis);																if (x != -1)								{		   							var rRange = document.createRange();		   							rRange.selectNodeContents(td_coll[i].firstChild);		   									   							var sSpan = document.createElement("span");		   							sSpan.style.backgroundColor = "yellow";																		var start_node = rRange.startContainer;									var end_node = rRange.endContainer;																		rRange.setStart(start_node, x);									rRange.setEnd(end_node, (x + searchthis.length));		   							rRange.surroundContents(sSpan);								}							}						}rRange.detach();}

This method works well and does what I want it to, finally. Now, I'm setting the variables to null at the top so that when another character is entered, everything in the method gets reset basically. That doesn't work, though. Oh, and here's the code for removing tags:

function remove_span_tags()		   			{		   				var html_table2 = document.getElementById("test");						var span_coll = html_table2.getElementsByTagName("span");												if (span_coll.length > 0)						{							for (x in span_coll)							{span_coll[x].removeAttribute("backgroundColor");}						}		   			}

That also gives me an error:

span_coll[x].removeAttribute is not a functionfile:///C:/Documents%20and%20Settings/...Line 8186
That, I am assuming, is because I'm suing the function incorrectly.
Link to comment
Share on other sites

Try this for removing the spans, this should work:

function remove_span_tags(){  var html_table2 = document.getElementById("test");  var span_coll = html_table2.getElementsByTagName("span");  var span, par, sib, txt;  if (span_coll.length > 0)  {	for (var i = 0; i < span_coll.length; i++)	{	  span = span_coll[i];	  txt = span.innerHTML;	  par = span.parentNode;	  if (span.nextSibling == undefined)	  {		par.removeChild(span);		par.appendChild(document.createTextNode(txt));	  }	  else	  {		sib = span.nextSibling;		par.removeChild(span);		par.insertBefore(document.createTextNode(txt), sib);	  }	}  }}

That should remove all spans. That might actually not work very well if you reverse the order of the for loop, it counts on appending things in the order they show up in. I tested it with something like this (using document.getElementsByTagName):<html><body><div><span>text 1</span> text 2 <span>text 3</span></div><div><span>some more text</span></div></body></html>After running the code it gave this:<html><body><div>text 1 text 2 text 3</div><div>some more text</div></body></html>For the other error, which line of code is that indicating?Also, this site is a better reference, check the menu on the right for other sections:http://www.howtocreate.co.uk/tutorials/jav...pt/domstructure

Link to comment
Share on other sites

Yea, I had been working on removing the span tags last night. What you posted is pretty much what I had after I reworked my code and did some research on the HTML DOM. So, now that the span tags are being removed whenever the user types something, when it gets back to the search() function, it should (programmatically, that is) be in a fresh state, with rRange detached and nonexistent, as with all other variables and such. Anyways, every time the user types another character (more than one), it goes through remove_span_tags(), but when it gets back to the search() method, it raises this error:

uncaught exception: Index or size is negative or greater than the allowed amount (NS_ERROR_DOM_INDEX_SIZE_ERR) rRange.surroundContents(sSpan); Line 8176

Now, it says the problem is with the surroundContents method, but if my experience with this darn editor (oXygen) means anything, I'm gonna bet that it really has a problem with the setStart and setEnd methods that occur just before the call to surroundContents. Now, I've done some testing to try and pinpoint why this would be. Normally, someone just enters a character at a time, but often, they're trying to type more than that - usually a word. So, since my 'lil program here can't seem to get past one character quite yet, I just copied and pasted different various words into the search box. As long as it only has to go through the search() method once, there's no problem - it can find the word elephant if you want it to. But like I said, once it has to cycle back to search(), it breaks every time. Oh, and another question. You said that the for loop you had in your remove_span_tags() solution had to go in that direction (i.e. starting at zero and working up to length). Is that because in my search(), I went the opposite direction, so to remove and add nodes in the same exact spot, you have to come from the other direction? Did I get that right? Also, it looks to me like this error is because the nodes somehow got messed up compared to when the script is first loaded. For example, earlier yesterday when I was trying to use the setStart and setEnd methods, I was navigating nodes and not characters, like I thought. Is this the same reason for the NS_ERROR_DOM_INDEX_SIZE_ERR?

Link to comment
Share on other sites

Now, it says the problem is with the surroundContents method, but if my experience with this darn editor (oXygen) means anything, I'm gonna bet that it really has a problem with the setStart and setEnd methods that occur just before the call to surroundContents.
The best way to start troubleshooting that is to print everything you're sending to those functions. You can use Firebug's console.log to print all of the nodes and whatever else you're sending those functions and check the values manually to make sure they're all valid.
You said that the for loop you had in your remove_span_tags() solution had to go in that direction (i.e. starting at zero and working up to length).
That was a mistake, it actually doesn't need to go in a certain direction. Checking for the next sibling solved that problem, so matter which direction it goes, if it finds that an element has a next sibling then it will insert the new element before that sibling, or in the same place. If it doesn't have a sibling then it just appends to the parent.But that does raise an issue I wasn't thinking about. If you have a structure like this:<div>words words words</div>What you have there is a div element with 1 child text node that contains the text "words words words". If you highlight the first and last like so:<div><span>words</span> words <span>words</span></div>Then you have a div with 3 child nodes: a span, a text node, and a span. When the code removes the span tags, it will end up with 3 text nodes, instead of the original which had 1 text node. So the function to remove the spans might need to be modified so that after it removes all of the spans in a container (it can probably check each span's parent to see if they're in the same container), then it would need to get each text node and append the contents to a string, then remove all text nodes and add 1 text node with the contents of all the others, so that you're left with the original setup with 1 text node with all the text in it.I'm not sure if that's the reason you're getting errors, but to find that out you're going to need to use Firebug to help debug and inspect the elements.
Link to comment
Share on other sites

Well, that does help a lot; I'll try to implement some of those changes. And that last point brings up another issue about which I was thinning. Do you think that the remove_span_tags() method is quite right? Besides the reasons it may not be that you mentioned just a 'lil bit ago, shouldn't I be inserting the same type of node that I was extracting (i.e. a table-data element)?

Link to comment
Share on other sites

function search()		   			{		   				remove_span_tags();		   						   				var searchthis = null;  var td_coll = null;		   				var html_table = null;  var temp2 = null;						temp2 = document.getElementById("search_text").value;						searchthis = temp2.toLowerCase();						html_table = document.getElementById("test");						td_coll = html_table.getElementsByTagName("td");						for (i = td_coll.length - 1; i >= 0; i--)						{							if ((td_coll[i] != null) || (td_coll[i] != ""))							{								var temp = null;  var temp3 = null;  var x = null;								var starting_point = 0;								temp = td_coll[i].innerHTML;								temp3 = temp.toLowerCase();								x = temp3.indexOf(searchthis, starting_point);																while (x != -1)								{									var rRange = null;      var sSpan = null;									var start_node = null;  var end_node = null;										   							rRange = document.createRange();		   							rRange.selectNodeContents(td_coll[i].firstChild);		   									   							sSpan = document.createElement("span");		   							sSpan.style.backgroundColor = "yellow";																		start_node = rRange.startContainer;									end_node = rRange.endContainer;																		rRange.setStart(start_node, x + starting_point);									rRange.setEnd(end_node, (x + searchthis.length + starting_point));		   							rRange.surroundContents(sSpan);											   							{		   								console.log("Start Node: " + rRange.startContainer.innerHTML);										console.log("End Node: " + rRange.endContainer.innerHTML);										console.log("Start Position: " + rRange.startOffset);										console.log("End Position: " + rRange.endOffset);										console.log("--------------------------------------------------------------------------");									}																		starting_point = x + searchthis.length;		   							x = temp3.indexOf(searchthis, starting_point);								}							}						}		   			}

So, I found that my search() function didn't select all matches within a <td> element, only the first one, and then it moved on without a worry. I tried to mend this by looping through the element until there were no more matches. But, again, I get the error

uncaught exception: Index or size is negative or greater than the allowed amount (NS_ERROR_DOM_INDEX_SIZE_ERR) Line 8176
I don't know why - I traced my code and it all looks good. is there any reason that you can see that this wouldn't work? By the way, the error is pointing at the setStart() method. And on top of that, the error tracking I'm trying to do is not helping me - every starting and ending position is 1 (one) and 2 (two), respectively.
Link to comment
Share on other sites

I'm not sure which line that error is coming from, but it's talking about either an index or a size. So it could be referring to this:rRange.setStart(start_node, x + starting_point);rRange.setEnd(end_node, (x + searchthis.length + starting_point));rRange.surroundContents(sSpan);if the end point is the same as the start point then trying to select that might cause an error, so you might want to print those two expressions to make sure that the end point is after the start point. Also make sure the start and end points are both actually within the node being selected.

Link to comment
Share on other sites

Turns out, there was an error there where you mentioned. One of those 'numbers' was a long, so it treated my addition as concatenation. I changed all additions to be contained in a parseInt function so that I am always getting an integer back. Here's the trace:

Firebug's log limit has been reached. %S entries not shown. Preferences x: 7starting_point: 0searchthis.length: 1setStart: 7setEnd: 8Search Term's Length: 19Start Position: 1End Position: 2Start Node: Upper S<span style="background-color: yellow;">a</span>ndusky EVSDEnd Node: Upper S<span style="background-color: yellow;">a</span>ndusky EVSD--------------------------------------------------------------------------x: 2starting_point: 0searchthis.length: 1setStart: 2setEnd: 3Search Term's Length: 7Start Position: 1End Position: 2Start Node: Wy<span style="background-color: yellow;">a</span>ndotEnd Node: Wy<span style="background-color: yellow;">a</span>ndot--------------------------------------------------------------------------x: 2starting_point: 0searchthis.length: 1setStart: 2setEnd: 3Search Term's Length: 7Start Position: 1End Position: 2Start Node: Wy<span style="background-color: yellow;">a</span>ndotEnd Node: Wy<span style="background-color: yellow;">a</span>ndot--------------------------------------------------------------------------x: 3starting_point: 0searchthis.length: 1setStart: 3setEnd: 4Search Term's Length: 19Start Position: 1End Position: 2Start Node: Moh<span style="background-color: yellow;">a</span>wk Local SchoolEnd Node: Moh<span style="background-color: yellow;">a</span>wk Local School
So at this last entry here is where it throws that index-outta-bounds exception. Except, now that I can see if it is or not, it seems to be in bounds. Why the error? Another weird note: the error occurred in the exact same spot before and after the parseInt change.
Link to comment
Share on other sites

Those look fine, is the error in the function to remove the spans?Since this is an exception that's happening, one way to narrow it down would be to use try/catch blocks. If you wrap the line with an error in a try/catch block it won't show the error message.e.g.

try {rRange.surroundContents(sSpan);} catch (ex) { alert("error here"); }

Link to comment
Share on other sites

I cannot figure this out. Incredibly frustrating.

 ....loading....Firebug's log limit has been reached. %S entries not shown.		Preferences	 x: 7starting_point: 0searchthis.length: 1setStart: 7setEnd: 8Search Term's Length: 19Start Offset: 1End Offset: 2Start Container: Upper S<span style="background-color: yellow;">a</span>ndusky EVSDEnd Container: Upper S<span style="background-color: yellow;">a</span>ndusky EVSDStart Node: Upper SEnd Node: Upper S-----------------------------------------------------------------x: 2starting_point: 0searchthis.length: 1setStart: 2setEnd: 3Search Term's Length: 7Start Offset: 1End Offset: 2Start Container: Wy<span style="background-color: yellow;">a</span>ndotEnd Container: Wy<span style="background-color: yellow;">a</span>ndotStart Node: WyEnd Node: Wy-----------------------------------------------------------------x: 2starting_point: 0searchthis.length: 1setStart: 2setEnd: 3Search Term's Length: 7Start Offset: 1End Offset: 2Start Container: Wy<span style="background-color: yellow;">a</span>ndotEnd Container: Wy<span style="background-color: yellow;">a</span>ndotStart Node: WyEnd Node: Wy-----------------------------------------------------------------x: 3starting_point: 0searchthis.length: 1setStart: 3setEnd: 4Search Term's Length: 19Start Offset: 1End Offset: 2Start Container: Moh<span style="background-color: yellow;">a</span>wk Local SchoolEnd Container: Moh<span style="background-color: yellow;">a</span>wk Local SchoolStart Node: MohEnd Node: Moh-----------------------------------------------------------------uncaught exception: Index or size is negative or greater than the allowed amount (NS_ERROR_DOM_INDEX_SIZE_ERR)[break on this error] rRange.setEnd(end_node, (parseI...10) + parseInt(searchthis.length, 10)));result.html (line 8173)

Here's the trace information that I'm getting. And I used the try/catch blocks and got similar responses; it did let me know that the actual errors are occurring during the setStart and setEnd methods, not during the surroundContents() method, which makes sense. I don't think there're any errors in the remove_span_tags() function, all that seems to be working well enough. The only thing there is that the extra text nodes are gonna still be there, but that shouldn't matter at this point, because that method isn't even getting processed since it's the first run through that i still cannot get past. There have been some changes in my search() function, so I'll re-post it here.

function search(){   	remove_span_tags();   	var searchthis = null;  var td_coll = null;	var html_table = null;  var temp2 = null;	temp2 = document.getElementById("search_text").value;	searchthis = temp2.toLowerCase();	html_table = document.getElementById("test");	td_coll = html_table.getElementsByTagName("td");	for (i = td_coll.length - 1; i >= 0; i--)	{		if ((td_coll[i] != null) || (td_coll[i] != ""))		{			var temp = null;  var temp3 = null;  var x = null;			var starting_point = 0;				temp = td_coll[i].innerHTML;			temp3 = temp.toLowerCase();			x = parseInt(temp3.indexOf(searchthis, starting_point), 10);						while (x != -1)			{				var rRange = null;      var sSpan = null;				var start_node = null;  var end_node = null;				   			rRange = document.createRange();	   			rRange.selectNodeContents(td_coll[i].firstChild);	   				   			sSpan = document.createElement("span");	   			sSpan.style.backgroundColor = "yellow";								start_node = rRange.startContainer;				end_node = rRange.endContainer;								rRange.setStart(start_node, (parseInt(x, 10) + parseInt(starting_point, 10)));				rRange.setEnd(end_node, (parseInt(x, 10) + parseInt(starting_point, 10) + parseInt(searchthis.length, 10)));				rRange.surroundContents(sSpan);								<!--				{					try					{rRange.setStart(start_node, (parseInt(x, 10) + parseInt(starting_point, 10)));}					catch (ex)					{alert ("rRange.setStart has encountered an error." + 						"\nStart Node: " + start_node.nodeValue + 						"\nsetStart: " + (parseInt(x, 10) + parseInt(starting_point, 10)));}										try					{rRange.setEnd(end_node, (parseInt(x, 10) + parseInt(starting_point, 10) + parseInt(searchthis.length, 10)));}					catch (ex)					{alert ("rRange.setEnd has encountered an error." + 						"\nEnd Node: " + end_node.nodeValue + 						"\nsetEnd: " + (parseInt(x, 10) + parseInt(starting_point, 10) + parseInt(searchthis.length, 10)));}	   					   				try	   				{rRange.surroundContents(sSpan);}	   				catch (ex)	   				{alert ("rRange.surroundContents(sSpan) has encountered an error.");}	   			}-->					   			{					console.log("x: " + x);					console.log("starting_point: " + starting_point);					console.log("searchthis.length: " + searchthis.length);					console.log("setStart: " + (parseInt(x, 10) + parseInt(starting_point, 10)));					console.log("setEnd: " + (parseInt(x, 10) + parseInt(starting_point, 10) + parseInt(searchthis.length, 10)));					console.log("Search Term's Length: " + temp3.length);					console.log("Start Offset: " + rRange.startOffset);					console.log("End Offset: " + rRange.endOffset);					console.log("Start Container: " + rRange.startContainer.innerHTML);					console.log("End Container: " + rRange.endContainer.innerHTML);					console.log("Start Node: " + start_node.nodeValue);					console.log("End Node: " + end_node.nodeValue);					console.log("-----------------------------------------------------------------");				}								starting_point = parseInt(x, 10) + parseInt(searchthis.length, 10);	   			x = temp3.indexOf(searchthis, starting_point);			}		}	}}

If anyone sees anything that may help, that'd be awesome. Thanks guys. Oh, if needed, there's an excerpt of the xml file I'm using in my very first post on this topic.

Link to comment
Share on other sites

parseInt might be running into trouble and not returning an integer.

a = parseInt(x, 10);b = parseInt(starting_point, 10);if (isNaN(a))  alert("not a number; x=" + x);if (isNaN(b))  alert("not a number; starting_point=" + starting_point);try{rRange.setStart(start_node, a + b);}catch (ex)...

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...