views:

90

answers:

3

I want to write a Chrome extension that looks at the HTML of the page its on, and if it finds eg <div id="hello"> then it will output, as a HTML list in the popup, 'This page has a friendly div' and if it finds eg <a href="http://bananas.com"&gt;I am married to a banana</a> then it will output 'This guy is weird.'

So in other words, searching for specific stuff in the DOM and outputting messages in the popup depending on what it finds.

I had a look at http://stackoverflow.com/questions/2063015/google-chrome-extension-accessing-the-dom for accessing the dom but I'm afraid I don't really understand it. Then of course there will be traversing the dom and presumably using regex and then conditional statements.

+1  A: 

Hi Sean,

Well that stackoverflow question asked how to let your extension talk to the DOM. There are numerous ways, one way is through chrome.tabs.executeScript, and another way is through Message Passing as I explained in that question.

Back to your question, you could use XPath to search within the DOM. It is pretty powerful. For example you said you want to search for <div id="hello">, you can do it like this:

var nodes = document.evaluate("//div[@id='hello']", document, null, 
                               XPathResult.ANY_TYPE, null)
var resultNode = nodes.iterateNext()
if (resultNode) {
  // Found the first node. Output its contents.
  alert(resultNode.innerHTML);
}

Now for your second example, same thing .. <a href="http://bananas.com"&gt;I am married to a banana</a>

var nodes = document.evaluate("//a[@href='http://bananas.com']/text()[contains(.,'married')]",
                               document, null, 
                               XPathResult.ANY_TYPE, null)
var resultNode = nodes.iterateNext()
if (resultNode) {
  // Found the first node. Output its contents.
  alert('This guy is weird');
}

Well you could use XPath which does work perfectly in Chrome, and you can make your query simple such as finding nodes that you want or even complex with detail. You can query any node, and then do post processing if you wish as well.

Hope that helped. Remember all this should be within a content script in the Chrome Extension. And if you want your extension to communicate to that, you can use Message Passing as I explained in the other post. So basically, within your popup.html, you send a request to the content script to find you text. Your content script will send back a response from its callback. To send the request, you should use chrome.tabs.sendRequest and within the content script.You listen for that request and handle it. As I explained in the other stackoverflow question.

Mohamed Mansour
A: 

Unless the problem is more complex than I think, why not just use jQuery or other convenient js api for this? This is what they were made for - to traverse the dom easily. You can inject jquery and your script that will be using it into required pages in manifest:

"content_scripts": [ {
    "js": [ "jquery.js", "script.js" ],
    "matches": [ "http://*/*", "https://*/*" ]
}]
serg
right, but how would I ensure that the jQuery code I run affects the page rendered in the tab, and not `popup.html`?
Sean McRaghty
@Sean Mohamed Mansour explained that in his last paragraph pretty well. I just suggested easier alternative than xpath (in my opinion).
serg
A: 

Do NOT use regular expressions to parse HTML. The <center> cannot hold.

With that out of the way... although you can use XPath, I think querySelector is similar in power while being somewhat simpler as well.

You simply pass a CSS selector as a string, and it returns the elements that match the selector. Kinda like using jQuery without needing to load the jQuery library.

Here's how you would use it:

var query = document.querySelector("div#hello");
if (query) {
    alert("This page has a friendly div");
}

var query = document.querySelectorAll("a[href='http://bananas.com']");
for (var i = 0; i < query.length; i += 1) {
    if (query[i].textContent === "I am married to a banana") {
        alert("This guy is weird.");
        return;
    }
}

document.querySelector finds only a single element, and returns null if that element is not found.

document.querySelectorAll returns a fake-array of elements, or an empty fake-array if none are found.

...however, it sounds like you're wanting to update the browser action popup when something is detected in a webpage, correct? If so, that is possible but immensely more difficult.

Mohamed Mansour's post will get you to the point where you can communicate between content scripts and the background page/popup, but there are other bits that need to be done as well.

Pauan

related questions