alex
alex

Reputation: 493

get HTML of selected text in firefox extension

I'm developing a firefox extension. So, when the user selects a text and then right-clicks in order for some context menus to appear, i should be able to retrieve from that selection a list with all the links contained in it. How am i able to do that? i see that currentDocument.getSelection() only retrieves simple text not the whole HTML data.

Thank you TIM . I have one more problem though! This is how i use your function . Where i call it the text is bolded.

The problem is that when i select a text and right the text that activates your function, if the cursor is over normal text i get the links allright; if the cursor is over LINK TEXT (the actual link) i get and undefined response. Why might this happen?

window.addEventListener("contextmenu", function(e) { 
    getSelectionLink();
}, false);


function getSelectionLink() {
var SelectionText = "";
var trywindow = false;

var start = 0;
var stop = 0;

var focusedElement = document.commandDispatcher.focusedElement;

if(focusedElement && null != focusedElement)
{
    try
    {   
        alert(focusedElement.value);
    }
    catch(e)
    {
        trywindow = true;
    }
}
else
{
    trywindow = true;
}

if(trywindow)
{
    var focusedWindow = document.commandDispatcher.focusedWindow;
    var winWrapper = new XPCNativeWrapper(focusedWindow, 'document');
    var Selection = winWrapper.getSelection();

    alert(getSelectedElements(winWrapper, "a"));
    //parseSelection(Selection);
}
}

Upvotes: 2

Views: 2560

Answers (2)

Tim Down
Tim Down

Reputation: 324507

Here's a function that will get you a list of all elements with a particular tag name that are wholly or partially selected. It works in all major browsers except IE < 9:

function getSelectedElements(win, tagName) {
    var sel = win.getSelection(), selectedElements = [];
    var range, elementRange, elements;
    if (sel.getRangeAt && sel.rangeCount) {
        elementRange = win.document.createRange();
        for (var r = 0; r < sel.rangeCount; ++r) {
            range = sel.getRangeAt(r);
            containerEl = range.commonAncestorContainer;
            if (containerEl.nodeType != 1) {
                containerEl = containerEl.parentNode;
            }
            if (containerEl.nodeName.toLowerCase() == tagName) {
                selectedElements.push(containerEl);
            } else {
                elements = containerEl.getElementsByTagName(tagName);
                for (var i = 0; i < elements.length; ++i) {
                    elementRange.selectNodeContents(elements[i]);
                    if (elementRange.compareBoundaryPoints(range.END_TO_START, range) < 1
                            && elementRange.compareBoundaryPoints(range.START_TO_END, range) > -1) {
                        selectedElements.push(elements[i]);
                    }
                }
            }
        }
        elementRange.detach();
    }
    return selectedElements;
}

console.log( getSelectedElements(currentWindow, "a") );

Upvotes: 3

Wladimir Palant
Wladimir Palant

Reputation: 57651

You should be using currentWindow.getSelection(), it returns a Selection object (see https://developer.mozilla.org/en/DOM/Selection). Given that only one part of a node might be selected it isn't quite clear what kind of HTML data you expect. Here is an approach that will give you too much in this scenario (much like "View Selection Source" feature does):

var selection = currentWindow.getSelection();
var range = selection.getRangeAt(0);
var container = range.commonAncestorContainer;
if (container instanceof Element)
    alert(container.innerHTML);  // Container element
else
    alert(container.nodeValue);  // A single text node

Upvotes: 0

Related Questions