Get parent node from selection (range) in Gecko and Webkit

I am trying to add an attribute when using the wysiwyg editor, which uses the createLink command. I thought it would be trivial to return the node that is created after the scan executes this command.

Turns out I can grab the newly created node in IE. Any ideas?

The following code demonstrates the problem (the debug logs below show different output in each browser):

var getSelectedHTML = function() { if ($.browser.msie) { return this.getRange().htmlText; } else { var elem = this.getRange().cloneContents(); return $("<p/>").append($(elem)).html(); } }; var getSelection = function() { if ($.browser.msie) { return this.editor.selection; } else { return this.iframe[0].contentDocument.defaultView.getSelection(); } }; var getRange = function() { var s = this.getSelection(); return (s.getRangeAt) ? s.getRangeAt(0) : s.createRange(); }; var getSelectedNode = function() { var range = this.getRange(); var parent = range.commonAncestorContainer ? range.commonAncestorContainer : range.parentElement ? range.parentElement(): range.item(0); return parent; }; // **** INSIDE SOME EVENT HANDLER **** if ($.browser.msie) { this.ec("createLink", true); } else { this.ec("createLink", false, prompt("Link URL:", "http://")); } var linkNode = $(this.getSelectedNode()); linkNode.attr("rel", "external"); $.log(linkNode.get(0).tagName); // Gecko: "body" // IE: "a" // Webkit: "undefined" $.log(this.getSelectedHTML()); // Gecko: "<a href="http://site.com">foo</a>" // IE: "<A href="http://site.com" rel=external>foo</A>" // Webkit: "foo" $.log(this.getSelection()); // Gecko: "foo" // IE: [object Selection] // Webkit: "foo" 

Thanks for any help on this, I looked through related SO questions without success!

+6
javascript gecko webkit
source share
3 answers

This is the code I used to get the "parentNode" of the text cursor:

 var getSelectedNode = function() { var node,selection; if (window.getSelection) { selection = getSelection(); node = selection.anchorNode; } if (!node && document.selection) { selection = document.selection var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange(); node = range.commonAncestorContainer ? range.commonAncestorContainer : range.parentElement ? range.parentElement() : range.item(0); } if (node) { return (node.nodeName == "#text" ? node.parentNode : node); } }; 

I changed my IE method to get closer to yours. Tested and works IE8, FF3.6, Safari4, Chrome5. I installed jsbin preview with which you can test.

+13
source share

I found that the choice can get complicated and work with errors in browsers. Throw the magic of editing documents in a browser and it will get worse!

I looked at how TinyMCE implements what I am trying to do, and used the same approach to modify jHtmlArea.

Basically, a link is created with fake href. He then finds the dom element, looking for links with this particular href. Then you can add any attributes you need and update href using the actual URL.

The solution above provided by gnarf is a great example of getting the selected node and will work for most scenarios.

Below is the code of my work:

 var url = prompt("Link URL:", "http://"); if (!url) { return; } // Create a link, with a magic temp href this.ec("createLink", false, "#temp_url#"); // Find the link in the editor using the magic temp href var linkNode = $(this.editor.body).find("a[href='#temp_url#']"); linkNode.attr("rel", "external"); // Apply the actual desired url linkNode.attr("href", url); 
+1
source share

This is a hacky workaround, but should work if someone does not make two identical links.

this.getSelection() seems to be the same in both required browsers, therefore:

 var link=prompt('gimme link'); //add the thing var text=this.getSelection(); var whatYouNeed=$('a:contains("'+text+'")[href="'+link+'"'); 
0
source share

All Articles