Ahmad
Ahmad

Reputation: 9658

Search within the text of an HTML Element

I want to search words within a specific web page element using webBrowser control API in C# (winforms) or using an injected java script.

I used the following java script and injected it into the loaded web page:

var TRange=null;

function findString (str) {

 var strFound;

  // EXPLORER-SPECIFIC CODE

  if (TRange!=null) {
   TRange.collapse(false);
   strFound=TRange.findText(str);
   if (strFound) TRange.select();
  }
  else if (TRange==null || strFound==0) {
   TRange=self.document.body.createTextRange();
   strFound=TRange.findText(str);
   if (strFound) TRange.select();
  }

 if (!strFound) alert ("String '"+str+"' not found!")
 return;
}

This code works for the entire page, but I want to search within the inner text of a specific element. How can I limit my search to such an element?

Upvotes: 1

Views: 630

Answers (3)

Reza Aghaei
Reza Aghaei

Reputation: 125197

You need to:

  1. Add a reference to Microsoft.mshtml.dll
  2. Then get IHTMLBodyElement from body using webBrowser1.Document.Body.DomElement
  3. Then find your tag and get IHTMLElement from your tag.
  4. Then get the IHtmlTextRange from body using createTextRange
  5. Then limit the search to your tag using moveToElementText
  6. Then find the string from the range using findText
  7. Then if the string found, you can select it.

Example

Here is a working example that we find "some" text in "div2" while we have 2 div elements, div1 and div2 and both of them contains "some" text.

Form

Create a Form and put a WebBrowser control on Form1 and write this code:

public Form1()
{
    InitializeComponent();
    this.Load += Form1_Load;
    this.webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
}

private void Form1_Load(object sender, EventArgs e)
{
    this.webBrowser1.Navigate(@"D:\file.html");
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    var searchText="some";
    var body = webBrowser1.Document.Body.DomElement as IHTMLBodyElement;
    var tag= webBrowser1.Document.GetElementById("div2").DomElement as IHTMLElement;

    var range = body.createTextRange();
    range.moveToElementText(tag);
    if (range.findText(searchText, searchText.Length, 0))
        range.select();
    else
        MessageBox.Show(string.Format("String '{0}' not found.", searchText));
}

Sample Html Content

Here is the content of file.html for test:

<html>
<head><title>Select content</title></head>
<body>
    <div id="div1">Here is some content</div>
    <div id="div2">Here is some other content</div>
</body>
</html>

Screenshot

And here is the screenshot:

enter image description here

Note

  • You may need to add some null checking to your code.
  • You can find the element using other attributes, for example using the name attribute:
  • For a javascript solution, you can take a look at Ahmad answer here
var tag = this.webBrowser1.Document.Body.All.GetElementsByName("somename")
              .Cast<HtmlElement>()
              .FirstOrDefault().DomElement as IHTMLElement;

Upvotes: 1

Ahmad
Ahmad

Reputation: 9658

The following java script which uses moveToElementText in the first call (when the TRange is null) works

var TRange=null;

function findString (str) {

 var strFound;

  // EXPLORER-SPECIFIC CODE

  if (TRange!=null) {
   TRange.collapse(false);
   strFound=TRange.findText(str);
   if (strFound) TRange.select();
  }
  else if (TRange==null || strFound==0) {
   TRange=self.document.body.createTextRange();
   var elem = document.getElementById('my_elem');
   // go to the element text
   TRange.moveToElementText(elem);
   strFound=TRange.findText(str);
   if (strFound) TRange.select();
  }

 if (!strFound) alert ("String '"+str+"' not found!")
 return;
}

Upvotes: 2

rgruenke
rgruenke

Reputation: 85

I assume you know how to get a DOM Reference of your Element. Following that, you could use JQuery to filter the textnodes in your Element like:

  $($element.contents()).filter(function(){
    return this.nodeType === 3; // filter textnodes only

  }).each(function(){

    findString(this.textContent);
  });

Upvotes: 0

Related Questions