views:

27

answers:

2

I'm getting a text node (node.nodeType == 3) returned from the getSelection range, eg.:

var selectionRange = selection.getRangeAt(0);
var startContainer = selectionRange.startContainer;

This startContainer usually is a text node, eg the following html:

<p>Paragraph in <u>parag</u>raph.</p>

Would result in the text node with text "raph." if | denotes the selection:

<p>Paragraph in <u>parag</u>r|aph|.</p>

That's right, the selected text is aph and the text node is raph., because before raph there is a new text node inside the u node.

Now, when calling $(startContainer).prevAll().each(function(index, node) ... I expected this to return U (which contains a text node with parag) and another text node (which contains Paragraph in ).

However, it returns only U and not the text node to the left of it.

Why is this? How do I get all same-level nodes before my startContainer, including text nodes with jQuery?

+2  A: 

In general, jQuery is about manipulating the elements of the DOM. It goes out of its way (most of the time, the .text() function being an obvious exception) to ignore text nodes, especially in the family of "DOM Navigation" functions.

Here is an older Stackoverflow question that might help you put together some code to find text nodes. As you see in that question, the jQuery .contents() function does include text nodes. Thus, you can do something like go up to the parent of your text node and get its contents that way, then from that set of children you can "find yourself" and determine immediate neighbors, etc.

Pointy
Is it considered bad practice to work with text nodes, even if getSelection range containers return text nodes, as defined by mozilla documentation?
Tom
I accepted your answer and also answered myself with the code I came up with thanks to you. Any improvements are welcome.
Tom
No, it's not bad practice, it's just not what jQuery is designed to facilitate.
Pointy
@Tom: Absolutely not. Working with text nodes and elements is vastly preferable to working with strings of HTML, which is what jQuery seems to encourage.
Tim Down
+1  A: 

Thanks to Pointy, who's answer I accepted, I came up with the following:

var left = true;
                        var leftNodes = [];
                        var rightNodes = [];
                        $(startContainer).parent().contents().each(function(index, node) {
                            if (!left) { //right
                                rightNodes.push(node);
                            }
                            else if ((node.isSameNode(startContainer)) && (left)) {
                                left = false;
                            }
                            else { //left
                                leftNodes.push(node);
                            }
                        });
Tom