Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get page selection including HTML?

I'm writing a Chrome Extension, and I was wondering if it was possible to get the selected text of a particular tab, including the underlying HTML? So if I select a link, it should also return the <a> tag.

I tried looking at the context menu event objects (yes, I'm using a context menu for this), and this is all that comes with the callback:

editable : false
menuItemId : 1
pageUrl : <the URL>
selectionText : <the selected text in plaintext formatting, not HTML>

It also returns a Tab object, but nothing in there was very useful, either.

So I'm kind of at a loss here. Is this even possible? If so, any ideas you might have would be great. Thanks! :)

like image 889
qJake Avatar asked Aug 11 '10 19:08

qJake


2 Answers

Getting the selected text of a page is fairly easy, you can do something like

var text = window.getSelection().toString();

and you'll get a text representation of the currently selected text that you can pass from a content script to a background page or a popup.

Getting HTML content is a lot more difficult, mostly because the selection isn't always at a clean HTML boundary in the document (what if you only select a small part of a long link, or a few cells of a table for example). The most direct way to get all of the html associated with a selection is to reference commonAncestorContainer, which is a property on a selection range that corresponds with the deepest node which contains both the start and end of the selection. To get this, you'd do something like:

var selection = window.getSelection();
// Only works with a single range - add extra logic to 
// iterate over more ranges if needed
var range = selection.getRangeAt(0);
var container = range.commonAncestorContainer;
var html = container.innerHTML

Of course, this will likely contain a lot of HTML that wasn't actually selected. It's possible that you could iterate through the children of the common ancestor and prune out anything that wasn't in the selection, but that's going to be a bit more involved and may not be necessary depending on what you're trying to do.

To show how to wrap this all up into an extension, I've written a short sample which you can reference: http://github.com/kurrik/chrome-extensions/tree/master/contentscript-selection/

like image 133
Arne Roomann-Kurrik Avatar answered Oct 07 '22 23:10

Arne Roomann-Kurrik


If you don't want all of the siblings, just the selected HTML, use range's other methods like .cloneContents() (to copy) or .extractContents() (to cut).

Here I use .cloneContents():

function getSelectedHTML() {
    var range = window.getSelection().getRangeAt(0); // Get the selected range
    var div = document.createElement("div");
    div.appendChild(range.cloneContents()); // Get the document fragment from selected range
    return div.innerHTML; // Return the actual HTML
}
like image 36
Zach Saucier Avatar answered Oct 08 '22 00:10

Zach Saucier