SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    ALT.NET - because we need it silver trophybronze trophy dhtmlgod's Avatar
    Join Date
    Jul 2001
    Location
    Scotland
    Posts
    4,836
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Search a page with javascript

    Is there anyway to search text on a page with Javascript, kinda the same way if you search a page with the browser?

  2. #2
    SitePoint Enthusiast kgish's Avatar
    Join Date
    Dec 2001
    Location
    Gouda, The Netherlands
    Posts
    64
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you are only doing a search through the regular visibile text (not any hidden HTML tag stuff like attributes, etc), then the best thing to do is traverse the document node-tree and filter through all the text nodes.

    Any of the text nodes containing text which matches can be handled appropriately.

    Here's some sample code using DOM:
    Code:
    // Call top-level search, starting with document.
    searchString(document, the_string);
     
    // searchString is a recursively called function which traverses all
    // the nodes and child-nodes for text elements matching the given
    // search string.
    function searchString(n, s)
    {
    	if (n.nodeType == 3 /*Node.TEXT_NODE*/)
    	{
    		if (n.nodeValue.indexOf(s) >= 0)
    		{
    			// String matches, so do something here.
    		}
    	}
    	if (n.hasChildNodes())
    	{
    		for (var m = n.firstChild; m != null; m = m.nextSibling)
    		{
    			searchString(m, s);
    		}
    	}
    }
    For example, you might want to make the found substrings bold reverse color with reverse background so that they stand out.

    You could also popup a search results window with the phrases linked back to the original document.

    Give me a little time and I will create the example for you.

    Hope this helps.
    Kiffin
    Your average future-famous kind of guy...

  3. #3
    SitePoint Enthusiast kgish's Avatar
    Join Date
    Dec 2001
    Location
    Gouda, The Netherlands
    Posts
    64
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Alright, sorry about the slight delay, but here is my complete solution.

    This is what it does. Enter the string to search in the form text field and hit the submit button.

    Each and every occurrence of the given search string (here is 'this' the default word) is highlighted in the browser windown by making the text bold and putting it in a boxed window.

    This is just an example of how it might be done. Have fun.

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <title>Search test page</title>
    <script language="javascript" type="text/javascript">
    <!--
    // Count of strings found:
    var jsrc_cnt = 0;
    // searchString() is a recursively called function which traverses
    // all the nodes and child-nodes for text elements matching the
    // given search string.
    function searchString(n, s) {
    var cnt = 0;
     
    // Sanity check, just in case.
    if (s.length == 0) return 0;
     
    if (n.nodeType == 3 /*Node.TEXT_NODE*/) {
    	var indices = new Array();
    	var ind = n.nodeValue.indexOf(s);
    	while (ind >= 0) {
    	 // String matches, so do something here.
    	 indices[cnt++] = ind;
     
    	 // Any more matches?
    	 ind += s.length;
    	 if (ind < n.nodeValue.length) {
    		// Get next index, if possible.
    		ind = n.nodeValue.indexOf(s,ind);	 
    	 } else {
    		// Past the end of the string, so stop.
    		ind = -1;
    	 }
    	}
    	if (cnt > 0) {
    	 var parent = n.parentNode;
    	 var text = n.nodeValue;
     
    	 var newnodes = new Array();
     
    	 // Slice out substrings.
    	 for (var i = 0, j = 0, ptr = 0; i < indices.length; i++) {
    		if (indices[i] > ptr) {
    		 // Text before.
    		 newnodes[j++] = document.createTextNode(text.substr(ptr,indices[i]-ptr));
    		}
     
    		// Take care of the found string.
    		var bnode = document.createElement("span");
    		bnode.setAttribute("id", "jsrch_"+jsrc_cnt++);
    		bnode.appendChild(document.createTextNode(s));
    		newnodes[j++] = bnode;
    		ptr = indices[i] + s.length;
     
    		if (ptr < text.length) {
    		 if (i < indices.length - 1) {
    			// Still more matches to come.
    			if (indices[i+1] > ptr) {
    			 // Text after, until next match.
    			 newnodes[j++] = document.createTextNode(text.substr(ptr,indices[i+1]-ptr));
    			 ptr = indices[i+1];
    			}
    		 } else {
    			// Text after, until end of line.
    			newnodes[j++] = document.createTextNode(text.substr(ptr,text.length-ptr));
    			ptr = text.length;
    		 }
    		}
    	 }
    	 parent.removeChild(n);
    	 for (var i = 0; i < newnodes.length; i++) {
    		parent.appendChild(newnodes[i]);
    	 }	 
    	}
    }
    else if (n.hasChildNodes()) {
    	// Run through all the child nodes and call
    	// this routine recursively.
    	for (var m = n.firstChild; m != null; m = m.nextSibling) {
    	 cnt += searchString(m, s);
    	}
    }
    return cnt;
    }
    //
    // handleSearch() is a wrapper function for calling searchString()
    // and then hiliting the strings found.
    function handleSearch(s) {
    var tot = searchString(document, s);
     
    if (tot == 0) {
    	alert('No matches found for the string "'+s+'"');
    } else {
    	 for (var j = 0; j < tot; j++) {
    		var obj = document.getElementById('jsrch_'+j);
    	 if (obj) {
    		obj.style.color = "#FFF";
    		obj.style.border ="1px solid #000";
    		obj.style.padding ="3px";
    		obj.style.fontWeight ="bold";
    		obj.style.backgroundColor ="#F00";
    	 }
    	}
    	alert('The string "'+s+'" was found '+tot+' times.');
    }
    }
    //-->
    </script>
    </head>
    <body>
    <h2>This is the search test page.</h2>
    <form action="java_script_:handleSearch(document.forms['frm_search'].txt_search.value)" name="frm_search">
    <input type="text" name="txt_search" value="this" size="30" cols="50">
    <input type="submit" name="btn_search" value="Search">
    </form>
    <p>Alright so this is just a simply test to see of this really works like this should (try this test by searching for the word this)</p>
    </body>
    </html>
    Last edited by kgish; Dec 7, 2003 at 07:30.
    Kiffin
    Your average future-famous kind of guy...

  4. #4
    SitePoint Enthusiast kgish's Avatar
    Join Date
    Dec 2001
    Location
    Gouda, The Netherlands
    Posts
    64
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So dhtmlgod, is this the correct answer?
    Kiffin
    Your average future-famous kind of guy...

  5. #5
    He's No Good To Me Dead silver trophybronze trophy stymiee's Avatar
    Join Date
    Feb 2003
    Location
    Slave I
    Posts
    23,449
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    That's pretty darn cool! But it is a little buggy in case you were wondering.

  6. #6
    SitePoint Enthusiast kgish's Avatar
    Join Date
    Dec 2001
    Location
    Gouda, The Netherlands
    Posts
    64
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Buggy? Please tell me why...
    Kiffin
    Your average future-famous kind of guy...

  7. #7
    He's No Good To Me Dead silver trophybronze trophy stymiee's Avatar
    Join Date
    Feb 2003
    Location
    Slave I
    Posts
    23,449
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    The first search for this worked perfectly. But if I did a search for any other word on the page it gave an incorrect count and wouln not hightlight the terms.

  8. #8
    SitePoint Enthusiast kgish's Avatar
    Join Date
    Dec 2001
    Location
    Gouda, The Netherlands
    Posts
    64
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes you are absolutely right on that one. However, the example was meant only as illustrating a basic algorithm for searching and hilighting is all.

    Thanks for casting the critical eye anyway, always appreciated.
    Kiffin
    Your average future-famous kind of guy...

  9. #9
    He's No Good To Me Dead silver trophybronze trophy stymiee's Avatar
    Join Date
    Feb 2003
    Location
    Slave I
    Posts
    23,449
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    No prob! I did think that was pretty cool and never thought of using javascript in that way.


Bookmarks

Posting Permissions

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