【发布时间】:2012-01-18 08:31:31
【问题描述】:
我希望能够双击以选择 div 中的一些文本,然后触发一个 JavaScript 函数,该函数在所选文本之后插入一些 HTML,很像 Google Wave 中的“编辑/回复”功能。
我已经确定了如何在双击时触发功能,它正在定位选择并随后在其后插入 HTML,这就是问题所在。
【问题讨论】:
标签: javascript dom
我希望能够双击以选择 div 中的一些文本,然后触发一个 JavaScript 函数,该函数在所选文本之后插入一些 HTML,很像 Google Wave 中的“编辑/回复”功能。
我已经确定了如何在双击时触发功能,它正在定位选择并随后在其后插入 HTML,这就是问题所在。
【问题讨论】:
标签: javascript dom
以下函数将在所有主流浏览器的选择末尾插入一个 DOM 节点(元素或文本节点)(请注意,Firefox 现在默认允许多选;以下仅使用第一个选择):
function insertNodeAfterSelection(node) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.collapse(false);
range.insertNode(node);
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.collapse(false);
html = (node.nodeType == 3) ? node.data : node.outerHTML;
range.pasteHTML(html);
}
}
如果您更愿意插入 HTML 字符串:
function insertHtmlAfterSelection(html) {
var sel, range, node;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = window.getSelection().getRangeAt(0);
range.collapse(false);
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.collapse(false);
range.pasteHTML(html);
}
}
2012 年 1 月 18 日更新
最后,这是一个插入 HTML 并保留选择的版本(即扩展选择以包括最初选择的内容和插入的内容)。
现场演示:http://jsfiddle.net/timdown/JPb75/1/
代码:
function insertHtmlAfterSelection(html) {
var sel, range, expandedSelRange, node;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = window.getSelection().getRangeAt(0);
expandedSelRange = range.cloneRange();
range.collapse(false);
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
expandedSelRange.setEndAfter(lastNode);
sel.removeAllRanges();
sel.addRange(expandedSelRange);
}
}
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
expandedSelRange = range.duplicate();
range.collapse(false);
range.pasteHTML(html);
expandedSelRange.setEndPoint("EndToEnd", range);
expandedSelRange.select();
}
}
【讨论】:
window.getSelection() 将为您获取选定的文本 (Documentation)。 您可以使用 jQuery.after() (Documentation) 在元素后插入新的 html。
在您选择的文本函数调用中,您必须遍历所有 DOM 元素,检查它们的 x&y 位置到当前光标位置 - 获取最近的元素并在之后插入或使用函数 .elementFromPoint(x,y) (@987654323 @)
这是我目前能想到的最好方法。它并不完美,但它是一个开始的地方。
【讨论】:
window.getSelection() 不返回任何 x,y 坐标
我不知道这是否可能,但我认为是部分解决方案。
在您的双击事件中,您可以获得event object and access the property target。
拥有目标元素you can get the selected text。
现在获取目标元素 html 并找到所选文本的索引及其长度,将您的 html 注入到 index + length 位置。
我想你已经看到了这个问题,它可以匹配多个地方的文本。要解决它,您可能必须找到光标的位置并与元素进行比较,我不知道该怎么做...
希望我能帮上点忙。
【讨论】: