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 9 of 9
  1. #1
    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

    Gecko Find/Highlight Text in page

    People have complained that window.find() doesn't work, and everyone knows Gecko doesn't support IE's proprietary TextRange object, some have assumed you can't do this in Gecko.

    On the contrary though:

    Code:
    Node.prototype.findTextMatches = [];
    
    Node.prototype.findText = function(query, ignoreCase) {
    	this.findTextMatches.length = 0;
    	if (ignoreCase)
    		query = query.toLowerCase();
    
    	var tw = this.ownerDocument.createTreeWalker(this, NodeFilter.SHOW_TEXT, { acceptNode: function(node) {	return NodeFilter['FILTER_' + (RegExp(query, (ignoreCase ? 'i' : '')).test(node.nodeValue) ? 'ACCEPT' : 'REJECT')] } }, true);
    	var offsets = [];
    	offsets[-1] = query.length * -1;
    	var totalMatches, trueOffsetDiff;
    	var range = this.ownerDocument.createRange();
    
    	while (tw.nextNode()) {
    		totalMatches = tw.currentNode.nodeValue.split(RegExp(query, (ignoreCase ? 'i' : ''))).length - 1;
    		for (var i = 0; i < totalMatches; i++) {
    			trueOffsetDiff = offsets[offsets.length - 1] + query.length;
    			offsets[offsets.length] = tw.currentNode.nodeValue.substr(trueOffsetDiff)[ignoreCase ? 'toLowerCase' : 'toString']().indexOf(query) + trueOffsetDiff;
    
    			range.selectNode(tw.currentNode);
    			range.setStart(tw.currentNode, offsets[offsets.length - 1]);
    			range.setEnd(tw.currentNode, range.startOffset + query.length);
    			this.findTextMatches[this.findTextMatches.length] = range.cloneRange();
    		}
    		offsets.length = 0;
    	}
    	return (tw.currentNode != this);
    }
    
    Node.prototype.highlightText = function() {
    	if (this.findTextMatches.length > 0) {
    		with (window.getSelection()) {
    			removeAllRanges();
    			addRange(this.findTextMatches.shift());
    		}
    		return true;
    	}
    	else
    		return false;
    }
    To search all text in the body, ignoring case, you'd go like:

    document.body.findText('search query', true);

    That loads up an array full of ranges selecting the text into document.body.findTextMatches.

    To selectively highlight next occurences after executing findText:

    document.body.highlightText();
    // highlights first occurence

    document.body.highlightText();
    // removes previous selection, highlights second occurrence

    // etc

    Just calling that method over and over will successfully highlight instances. It returns true if it highlighted something, false otherwise,

    Also, since I prototyped Node, it works not just in HTML documents, but can work in XML documents too.

    Calling document.findText in an HTMLDocument may cause interesting results, as it searches through all the nodes, including <head>...

  • #2
    Regular Coder
    Join Date
    Jun 2002
    Location
    The Netherlands
    Posts
    217
    Thanks
    0
    Thanked 0 Times in 0 Posts

    wow

    This is really cool!But I never thougth that it was impossible (being a big Mozilla fan).

  • #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
    Bah, much to my embarassment, I discovered on an IDL rampage I was having at lxr.mozilla.org this:
    http://lxr.mozilla.org/seamonkey/sou...SWindow.idl#95

    The reason window.find() never seemed to work was that we never supplied it enough arguments.

    window.find('search query', caseSensitive, searchBackwards, wrapAround, wholeWord, searchInFrames, showDialog)

    A string, followed by 6 booleans.

    An equivalent statement to all that code above is:

    window.find('search string', caseSensitive, false, false, false, false, false)

    But that searches the entire window... my code can selectively search the text od certain nodes.
    Last edited by jkd; 07-10-2002 at 07:10 AM.

  • #4
    Regular Coder
    Join Date
    Jun 2002
    Location
    The Netherlands
    Posts
    217
    Thanks
    0
    Thanked 0 Times in 0 Posts
    So,the find() function of Mozilla is way more powerfull than the find() function of IE
    I find it very handy that I can open the find dialog too.

  • #5
    New Coder
    Join Date
    Jun 2002
    Posts
    70
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi. I've neen trying to run your findText script in Netscape 6. If I try:

    win = parent.frames[1]
    win.document.body.findText(str, true)

    ...I get findText() function not found. Isn't there a way to define findText for a parent.frames[1]? If I try just:

    document.body.findText(str, true)

    ...I get NodeFilter not found. Where is NodeFilter defined?

    I've tried win.find(str,true), which comes back find() function not found. I don't believe NS6 has find().

  • #6
    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
    *sigh* No need to both email me and post a reply here. This is definitely the more important area, as others can see it.

    From the email I replied with so others can see it:

    It doesn't work in early versions of NS6. I use the recently implemented TreeWalker interface and NodeFilter to iterate through possible text nodes. I know for sure NS7 PR and above supports it, and the latest NS6 build *might*. I always write my scripts in a version of Mozilla (what NS6+ is based on) never outdated by a week, so a lot of stuff will not work in NS6.

  • #7
    vrt
    vrt is offline
    New to the CF scene
    Join Date
    Jul 2005
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Exclamation match whole word doesn't seem to work

    hi all
    ever faced this problem guys ? searching works with optional args but matching whole word doesn't seem to work... sos!
    vrt

  • #8
    Senior Coder
    Join Date
    Feb 2004
    Location
    Edinburgh
    Posts
    1,352
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by Bosko
    I find it very handy that I can open the find dialog too.
    you'll be able to do that in IE, too, no doubt. a quick search on MSDN should be able to confirm or refute that.
    *keep it simple (TM)

  • #9
    New to the CF scene
    Join Date
    Nov 2005
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by jkd
    window.find('search query', caseSensitive, searchBackwards, wrapAround,
    wholeWord, searchInFrames, showDialog)
    In case there is no search result I want to inform the user with
    an appropriate message, but the above mentionend window.find(...)
    never returns false because one search result is the text in the input field.

    Anyone noticed that behaviour? Is there a workaround except not
    using this method?

    BTW: Using your script I wondered if it is possible to jump to the selection
    the same way the standard find() is doing this.

    Regards
    lufa
    Last edited by lufa; 11-25-2005 at 04:44 PM.


  •  

    Posting Permissions

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