Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set anchor name with execCommand

I know how to set an <a /> tag with the href attribute in a contenteditable like this:

execCommand("CreateLink", false, "#jumpmark");

which will result in

<a href="#jumpmark">selection</a>

However I cannot figure out how to set an anchor name instead of the href.
This is my desired result:

<a name="jumpmark">selection</a>

Can anyone help me?

Side notes: I am using jQuery and Rangy as libraries, however I would prefer a solution that works directly with execCommand.

Update: Here's a jsfiddle: http://jsfiddle.net/fjYHr/ Select some text and click the button. All I want is that with the button click a link is inserted with a name attribute set instead of the href.

like image 568
Horen Avatar asked Dec 19 '12 09:12

Horen


3 Answers

You could use something like the following, which is adapted from the pasteHtmlAtCaret() function from this answer of mine:

Demo: http://jsfiddle.net/F8Zny/

Code:

function surroundSelectedText(element) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            element.appendChild( document.createTextNode(range.toString()) );
            range.deleteContents();
            range.insertNode(element);

            // Preserve the selection
            range = range.cloneRange();
            range.setStartAfter(element);
            range.collapse(true);
            sel.removeAllRanges();
            sel.addRange(range);
        }
    } else if (document.selection && document.selection.type != "Control") {
        // IE < 9
        var selRange = document.selection.createRange();
        element.appendChild( document.createTextNode(selRange.text) );
        selRange.pasteHTML(element.outerHTML);
    }
}

If you must use document.execCommand() then you could use the InsertHTML command in non-IE browsers. However, IE does not support it.

document.execCommand("InsertHTML", false, '<a name="jumpmark">selection</a>');
like image 179
Tim Down Avatar answered Sep 21 '22 17:09

Tim Down


I see you're using Rangy, but I don't how to use it at all. Before I realized what Rangy was, I looked up how to get the current selection. I found a function that gets it and replaces it with a passed in value. I ended up modfiying it, but here it is:

http://jsfiddle.net/fjYHr/1/

$(document).ready(function () {
    $("#setlink").click(function () {
        replaceSelectedText("jumplink");
    });
});

function replaceSelectedText(nameValue) {
    var sel, sel2, range;
    if (window.getSelection) {
        sel = window.getSelection();
        sel2 = ""+sel;  // Copy selection value
        if (sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            var newA = document.createElement("a");
            newA.name = nameValue;
            newA.innerHTML = sel2;
            range.insertNode(newA);
        }
    } else if (document.selection && document.selection.createRange) {
        // Not sure what to do here
        range = document.selection.createRange();
        var newA = "<a name='" + nameValue.replace(/'/g, "") + "'>" + range.text + "</a>";
        range.text = newA;
    }
}

Notice how I store the original current selection, then replace it with an <a> element that gets its name set with the passed-in value.

As for the document.selection part (which seems to be used by IE < 9), I'm not 100% sure that the code I provided will work (actually allow HTML in the selection, and not escaping it). But it's my attempt :)

like image 39
Ian Avatar answered Sep 22 '22 17:09

Ian


As you've seen execCommand is rather limited in the attributes you can set, as such you cannot set the name attribute using it - only the href.

As you have jQuery set as a tag, you can use that as an alternative:

var $a = $('<a></a>').attr('name', 'jumpmark').appendTo('body');

Update

I need to work on the current selection. Specifically I don't have a jQuery object that I can append to, meaning I don't have a DOM node that I can work on

In this case use a plugin such as Rangy to get the selection which you can then amend with jQuery as required.

like image 43
Rory McCrossan Avatar answered Sep 22 '22 17:09

Rory McCrossan