Go Back   CodingForums.com > :: Client side development > JavaScript programming > Post a JavaScript

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 07-09-2002, 07:34 PM   PM User | #1
jkd
Senior Coder

 
jkd's Avatar
 
Join Date: May 2002
Location: metro DC
Posts: 3,163
Thanks: 1
Thanked 18 Times in 18 Posts
jkd will become famous soon enough
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>...
__________________
jasonkarldavis.com
jkd is offline   Reply With Quote
Old 07-09-2002, 08:23 PM   PM User | #2
Bosko
Regular Coder

 
Join Date: Jun 2002
Location: The Netherlands
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
Bosko is an unknown quantity at this point
wow

This is really cool!But I never thougth that it was impossible (being a big Mozilla fan).
Bosko is offline   Reply With Quote
Old 07-10-2002, 06:05 AM   PM User | #3
jkd
Senior Coder

 
jkd's Avatar
 
Join Date: May 2002
Location: metro DC
Posts: 3,163
Thanks: 1
Thanked 18 Times in 18 Posts
jkd will become famous soon enough
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.
__________________
jasonkarldavis.com

Last edited by jkd; 07-10-2002 at 06:10 AM..
jkd is offline   Reply With Quote
Old 07-10-2002, 03:41 PM   PM User | #4
Bosko
Regular Coder

 
Join Date: Jun 2002
Location: The Netherlands
Posts: 217
Thanks: 0
Thanked 0 Times in 0 Posts
Bosko is an unknown quantity at this point
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.
Bosko is offline   Reply With Quote
Old 07-12-2002, 07:27 PM   PM User | #5
dallen24
New Coder

 
Join Date: Jun 2002
Posts: 70
Thanks: 0
Thanked 0 Times in 0 Posts
dallen24 is an unknown quantity at this point
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().
dallen24 is offline   Reply With Quote
Old 07-12-2002, 11:22 PM   PM User | #6
jkd
Senior Coder

 
jkd's Avatar
 
Join Date: May 2002
Location: metro DC
Posts: 3,163
Thanks: 1
Thanked 18 Times in 18 Posts
jkd will become famous soon enough
*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:

Quote:
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.
__________________
jasonkarldavis.com
jkd is offline   Reply With Quote
Old 07-20-2005, 05:39 AM   PM User | #7
vrt
New to the CF scene

 
Join Date: Jul 2005
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
vrt is an unknown quantity at this point
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
vrt is offline   Reply With Quote
Old 07-22-2005, 09:50 AM   PM User | #8
jbot
Senior Coder

 
Join Date: Feb 2004
Location: Edinburgh
Posts: 1,352
Thanks: 0
Thanked 0 Times in 0 Posts
jbot is an unknown quantity at this point
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)
jbot is offline   Reply With Quote
Old 11-25-2005, 12:52 PM   PM User | #9
lufa
New to the CF scene

 
Join Date: Nov 2005
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
lufa is an unknown quantity at this point
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 03:44 PM..
lufa is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 02:30 PM.


Advertisement
Log in to turn off these ads.