1

I'm using document.execCommand("unlink", false, false); to remove hyperlinks and anchors in my own html editor. It works fine except in one case: it doesn't remove anchors in Firefox. Is this not supported in Firefox or is there another way to solve this?

Here's my example:

<div contenteditable="true">This is an <a name="anker">anchor</a>. And this is a <a href="#">normal hyperlink</a>. Please try to select them and then press the "Unlink" button.</div>

<input type="button" id="btn" value="Unlink">

$(document).ready(function() {    
    $('#btn').click(function() {
        document.execCommand("unlink", false, false);
    });
});

Check it out on Fiddle

vso
  • 199
  • 2
  • 17

1 Answers1

4

To answer your question about what alternatives there are, you could force the issue and set any a element's href attribute before calling unlink:

$(document).ready(function() {    
    var $editable = $('[contenteditable]');

    $('#btn').click(function() {
        $editable.find('a:not([href])').attr('href', '#');
        document.execCommand("unlink", false, false);
    });
});

http://jsfiddle.net/Bz7pR/7/

There are, of course, probably multiple ways to "solve" the problem. I figure $.unwrap() would probably work as well. I'm not that versed on document.execCommand and rich text editors, but I imagine you need to be careful, precise, and test test test.

Note, that is just a demonstration; you've really got to think about that and consider exactly how you're going to handle that problem. For instance, you could detect and only run that if Firefox is the browser, which would limit any unexpected damage or outcomes you might have.

EDIT

And here is a more complete version that only affects the selected text range:

$(document).ready(function() {    
    $('#btn').click(function unlink() {
        var holder,
            frag,
            range,
            child;

        if (window.getSelection && window.getSelection().getRangeAt) {
            holder = document.createElement('div');
            frag = document.createDocumentFragment();
            range = window.getSelection().getRangeAt(0);

            $(holder)
                .append(range.cloneContents())
                .find('a:not([href])')
                .attr('href', '#');

            while ((child = holder.firstChild)) {
                frag.appendChild(child);
            }

            range.deleteContents();
            range.insertNode(frag);
        }

        document.execCommand("unlink", false, false);
    });    
});

http://jsfiddle.net/Bz7pR/12/

I'm no genius when it comes to text ranges and selections, so I modified the code found in this answer:

https://stackoverflow.com/a/6252893/451969

To come up with what is above. If someone sees something that's either wrong or incoherent, leave me a comment below.

Community
  • 1
  • 1
Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
  • This is a nice idea! Now there's only one thing to think about. I'd like to remove only those anchors which are inside a user selection. Your suggested solution provides this but as a little side effect all anchors inside this div get the href attr. Would it be possible not to change the code of the unselected text? Unfortunately it's not so simple to handle the selected text (edit just the included elements) via jQuery. http://jsfiddle.net/Bz7pR/8/ – vso Dec 27 '12 at 10:33
  • @vso - See my edit. Not quite sure if it will work with multiple selections. What is above does work in IE, Firefox and Chrome, but not Opera for some reason. – Jared Farrish Dec 27 '12 at 11:59
  • Thank you very much! The last one works fine and is exactly what I needed - combined with a browser detection to be executed in Firefox only. – vso Dec 27 '12 at 13:24