jQuery:将文本URL转换为链接作为输入

我正在取得进展但不太确定如何使这项工作正常……

我有一个令人满意的div,其function类似于textarea。

我还有一个正则表达式来识别输入的URL并自动链接它们。 我遇到了麻烦,但是当用户输入时,这项工作是“实时”的。

这是迄今为止我所拥有的jsFiddle 。 我遇到的另一个问题是在输入链接后光标跳转到div的开头(因为我正在替换div的.html() ?)

是否有创造性的解决方案在div中的单个文本字符串上使用.replace()而不必替换div的整个内容?

首先,IE会自动为您完成此操作。

对于其他浏览器,我建议在用户不活动一段时间后进行替换。 以下是我的答案,说明了如何进行替换:

https://stackoverflow.com/a/4045531/96100

这是一个与(坏)链接正则表达式和讨论类似的:

https://stackoverflow.com/a/4026684/96100

为了保存和恢复选择,我建议使用基于字符偏移的方法。 以下代码一般存在缺点,但对于在更改格式但保持文本不变的情况下保存和恢复选择的特定情况,这是理想的。 这是一个例子:

https://stackoverflow.com/a/13950376/96100

最后,这里有几个答案和讨论以及如何等待用户不活动的示例:

把它们放在一起:

 var saveSelection, restoreSelection; if (window.getSelection && document.createRange) { saveSelection = function(containerEl) { var range = window.getSelection().getRangeAt(0); var preSelectionRange = range.cloneRange(); preSelectionRange.selectNodeContents(containerEl); preSelectionRange.setEnd(range.startContainer, range.startOffset); var start = preSelectionRange.toString().length; return { start: start, end: start + range.toString().length } }; restoreSelection = function(containerEl, savedSel) { var charIndex = 0, range = document.createRange(); range.setStart(containerEl, 0); range.collapse(true); var nodeStack = [containerEl], node, foundStart = false, stop = false; while (!stop && (node = nodeStack.pop())) { if (node.nodeType == 3) { var nextCharIndex = charIndex + node.length; if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) { range.setStart(node, savedSel.start - charIndex); foundStart = true; } if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) { range.setEnd(node, savedSel.end - charIndex); stop = true; } charIndex = nextCharIndex; } else { var i = node.childNodes.length; while (i--) { nodeStack.push(node.childNodes[i]); } } } var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } } else if (document.selection) { saveSelection = function(containerEl) { var selectedTextRange = document.selection.createRange(); var preSelectionTextRange = document.body.createTextRange(); preSelectionTextRange.moveToElementText(containerEl); preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange); var start = preSelectionTextRange.text.length; return { start: start, end: start + selectedTextRange.text.length } }; restoreSelection = function(containerEl, savedSel) { var textRange = document.body.createTextRange(); textRange.moveToElementText(containerEl); textRange.collapse(true); textRange.moveEnd("character", savedSel.end); textRange.moveStart("character", savedSel.start); textRange.select(); }; } function createLink(matchedTextNode) { var el = document.createElement("a"); el.href = matchedTextNode.data; el.appendChild(matchedTextNode); return el; } function shouldLinkifyContents(el) { return el.tagName != "A"; } function surroundInElement(el, regex, surrounderCreateFunc, shouldSurroundFunc) { var child = el.lastChild; while (child) { if (child.nodeType == 1 && shouldSurroundFunc(el)) { surroundInElement(child, regex, createLink, shouldSurroundFunc); } else if (child.nodeType == 3) { surroundMatchingText(child, regex, surrounderCreateFunc); } child = child.previousSibling; } } function surroundMatchingText(textNode, regex, surrounderCreateFunc) { var parent = textNode.parentNode; var result, surroundingNode, matchedTextNode, matchLength, matchedText; while ( textNode && (result = regex.exec(textNode.data)) ) { matchedTextNode = textNode.splitText(result.index); matchedText = result[0]; matchLength = matchedText.length; textNode = (matchedTextNode.length > matchLength) ? matchedTextNode.splitText(matchLength) : null; surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true)); parent.insertBefore(surroundingNode, matchedTextNode); parent.removeChild(matchedTextNode); } } var textbox = document.getElementById("textbox"); var urlRegex = /http(s?):\/\/($|[^\s]+)/; function updateLinks() { var savedSelection = saveSelection(textbox); surroundInElement(textbox, urlRegex, createLink, shouldLinkifyContents); restoreSelection(textbox, savedSelection); } var $textbox = $(textbox); $(document).ready(function () { $textbox.focus(); var keyTimer = null, keyDelay = 1000; $textbox.keyup(function() { if (keyTimer) { window.clearTimeout(keyTimer); } keyTimer = window.setTimeout(function() { updateLinks(); keyTimer = null; }, keyDelay); }); }); 
 body { font:.8rem/1.5 sans-serif; margin:2rem; } div { border:thin solid gray; padding:1rem; height:10rem; margin:1rem 0; color:black; font-size:1rem; } a { color:blue; background:lightblue; } 
  Start typing a message with a link ie http://example.com...