[ACCEPTED]-Insert link in contenteditable element-contenteditable
document.execCommand()
does this for you in all major browsers:
document.execCommand("CreateLink", false, "http://stackoverflow.com/");
To 6 preserve the selection while your link dialog 5 is displayed, you can use the following 4 functions:
function saveSelection() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
var ranges = [];
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
ranges.push(sel.getRangeAt(i));
}
return ranges;
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
}
function restoreSelection(savedSel) {
if (savedSel) {
if (window.getSelection) {
sel = window.getSelection();
sel.removeAllRanges();
for (var i = 0, len = savedSel.length; i < len; ++i) {
sel.addRange(savedSel[i]);
}
} else if (document.selection && savedSel.select) {
savedSel.select();
}
}
}
jsFiddle example: http://jsfiddle.net/JRKwH/1/
UPDATE
To get hold 3 of the link(s) created (if any were created 2 at all) is tricky. You could use my own 1 Rangy library:
var sel = rangy.getSelection();
if (sel.rangeCount) {
var links = sel.getRangeAt(0).getNodes([1], function(el) {
return el.nodeName.toLowerCase() == "a";
});
alert(links.length);
}
... or something like the following:
function getLinksInSelection() {
var selectedLinks = [];
var range, containerEl, links, linkRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
linkRange = 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() == "a") {
selectedLinks.push(containerEl);
} else {
links = containerEl.getElementsByTagName("a");
for (var i = 0; i < links.length; ++i) {
linkRange.selectNodeContents(links[i]);
if (linkRange.compareBoundaryPoints(range.END_TO_START, range) < 1 && linkRange.compareBoundaryPoints(range.START_TO_END, range) > -1) {
selectedLinks.push(links[i]);
}
}
}
}
linkRange.detach();
}
} else if (document.selection && document.selection.type != "Control") {
range = document.selection.createRange();
containerEl = range.parentElement();
if (containerEl.nodeName.toLowerCase() == "a") {
selectedLinks.push(containerEl);
} else {
links = containerEl.getElementsByTagName("a");
linkRange = document.body.createTextRange();
for (var i = 0; i < links.length; ++i) {
linkRange.moveToElementText(links[i]);
if (linkRange.compareEndPoints("StartToEnd", range) > -1 && linkRange.compareEndPoints("EndToStart", range) < 1) {
selectedLinks.push(links[i]);
}
}
}
}
return selectedLinks;
}
jsFiddle: http://jsfiddle.net/JRKwH/3/
Better looking answer:
function link() {
if (window.getSelection().toString()) {
var a = document.createElement('a');
a.href = 'http://www.google.com';
a.title = 'GOOGLE';
window.getSelection().getRangeAt(0).surroundContents(a);
}
}
select some of text then click link button!
<button onclick='link()'>link text to google</button>
This method can be 11 applied anywhere and does not require the 10 element to be contenteidtable
.
you can add any event or 9 attributes to the new A element like other 8 elements.
The window.getSelection().toString()
checks if some text is actually 7 selected. It works well in chrome, I don't 6 have IE to test, anyway there are other 5 methods to check it. But surroundContents()
which is the key 4 part is available in IE9 as suggested by 3 MDN.
Finally I suggest to use an iFrame instead 2 of contenteditable div so there will be 1 no worry about preserving the selection.
As alfred said there are already well-developed 7 editors, especially for the basic features. You 6 can restrict it to use as few, or as many 5 features, as you would like.
The difficult 4 part in developing it from scratch, is that 3 all browsers act slightly differently. The 2 following should get you moving in the right direction 1 in most browsers, other than IE:
var selected = document.getSelection();
document.execCommand("insertHTML",false,"<a href='"+href+"'>"+selected+"</a>");
EDIT It is not possible in IE in Execcommand, because 3 we cannot insert quotes in 'href', we must 2 do it in pure javascript with range :
// IN 1 DIV IN ONE IFRAME
// Get the frame
var iframe = document.getElementById('myframe');
// Selection object in the frame
theSelection = iframe.contentWindow.getSelection();
// position of the selection to insert
theRange = theSelection.getRangeAt(0);
// get content inside the original selection (and delete content in)
var fragment = theRange.extractContents();
// Create a new link in frame
var newLink = iframe.contentWindow.document.createElement('a');
// Create a text element with the fragment to put in the link
var theText = document.createTextNode(fragment.textContent);
// URL
theLink.href = '#';
// Title
theLink.title = 'title';
// Attribute 'onclick'
theLink.setAttribute('onclick', thelink);
// Target
theLink.target = '_blank';
// Add the text in the link
theLink.appendChild(theText);
// Insert the link at the range
theRange.insertNode(newLink);
// DIV WITHOUT FRAMES
// Selection object in the window
theSelection = window.getSelection();
// begin of the selection to insert
theRange = theSelection.getRangeAt(0);
// get content inside the original selection (and delete content in)
var fragment = theRange.extractContents();
// Create a new link in the document
var newLink = document.createElement('a');
// Create a text element with the fragment to put in the link
var theText = document.createTextNode(fragment.textContent);
// URL
theLink.href = '#';
// Title
theLink.title = 'title';
// Attribute 'onclick'
theLink.setAttribute('onclick', thelink);
// Target
theLink.target = '_blank';
// Add the text in the link
theLink.appendChild(theText);
// Insert the link at the range
theRange.insertNode(newLink);
I would do it this way:
- Create a link with a (possibly unique) initial bogus
href
attribute to identify it by. - Fetch that element using
document.querySelector('a[href=<unique-href>]')
. - You now have a reference to the created element and can do with it as you please.
The benefit of this 2 is that you don't have to work with Selection
at 1 all.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.