在contenteditable元素中插入链接

Pee*_*Haa 18 javascript jquery hyperlink contenteditable

我正在开发一个简单的博客系统,我正在使用contenteditable,以便用户可以格式化文本.

到目前为止,一切都像魅力一样.

我想要的下一件事是用户可以在文本中添加超链接.

用户必须选择(部分)文本并单击链接按钮.之后会打开一个弹出窗口,用户应该输入链接地址.

当用户点击接受按钮时,我想将链接添加到他们在contenteditable中选择的文本.

我怎么能实现这个功能,因为我不知道如何做到这一点?

我的网站:http://82.170.147.49/blog/3/alpha-release

我的网站jsFiddle:http://jsfiddle.net/qhN9j/

Tim*_*own 58

document.execCommand() 在所有主流浏览器中为您做到这一点:

document.execCommand("CreateLink", false, "http://stackoverflow.com/");
Run Code Online (Sandbox Code Playgroud)

要在显示链接对话框时保留选择,可以使用以下功能:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

jsFiddle示例:http://jsfiddle.net/JRKwH/1/

UPDATE

要掌握创建的链接(如果有的话),这很棘手.你可以使用我自己的Rangy库:

var sel = rangy.getSelection();
if (sel.rangeCount) {
    var links = sel.getRangeAt(0).getNodes([1], function(el) {
        return el.nodeName.toLowerCase() == "a";
    });
    alert(links.length);
}
Run Code Online (Sandbox Code Playgroud)

...或类似以下内容:

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;
}
Run Code Online (Sandbox Code Playgroud)

jsFiddle:http://jsfiddle.net/JRKwH/3/

  • 唐先生.你是我一直以来的英雄!最后我可以摆脱丑陋的javascript提示窗口;)虽然我认为clmarquart有一个有效的观点.我要做的下一件事是创建一个与目标(_blank)的链接,我想我将需要insertHTML(或其他东西).是否可以通过向`a`标记添加目标来使代码工作?如果你能成为我的英雄,我会把你的地位升级为上帝!:) (3认同)
  • @PeeHaa:好问题.这将是棘手的,因为该命令处理多个案例.有时根本不会创建任何链接(如果所选内容已经在具有相同URL的链接中),或者只链接了另一个链接中未包含的内容.我会在答案中加一点. (2认同)
  • @PeeHaa:更新了. (2认同)

clm*_*art 7

正如alfred所说,已经有很好的编辑器,尤其是基本功能.您可以将其限制为使用尽可能少的功能或许多功能.

从头开始开发它的困难之处在于,所有浏览器的行为略有不同.除了IE之外,以下内容应该让您在大多数浏览器中朝着正确的方向前进:

var selected = document.getSelection();
document.execCommand("insertHTML",false,"<a href='"+href+"'>"+selected+"</a>");
Run Code Online (Sandbox Code Playgroud)


Ali*_*Ali 6

更好看的答案:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)
select some of text then click link button!
<button onclick='link()'>link text to google</button>
Run Code Online (Sandbox Code Playgroud)

此方法可以应用于任何地方,并且不需要元素contenteidtable.

您可以像其他元素一样向新的A元素添加任何事件或属性.

window.getSelection().toString()检查一些文字,在实际选择.它在chrome中工作得很好,我没有IE测试,反正有其他方法可以检查它.但是surroundContents(),正如MDN所建议的那样,IE9中的关键部分是可用的.

最后我建议使用iFrame而不是contenteditable div,这样就不用担心保留选择了.