简体   繁体   English

动态突出显示符合特定标准的单词

[英]Dynamically Highlight Words That Fit a Specific Criteria

I have posted a similar question before , but it was too static.之前也发过类似的问题,不过太static了。 Now I want to make changes such that the code is dynamic.现在我想进行更改,使代码是动态的。

OBJECTIVE客观的

I want words that begin with "t" to be highlighted as a user types.我希望以“t”开头的单词在用户键入时突出显示。 If the word does not begin with "t" then do nothing.如果单词不以“t”开头,则什么也不做。 Basically, the user would have a normal typing experience but "t" words will be highlighted.基本上,用户会有正常的打字体验,但会突出显示“t”字。

VERSION DETAILS版本详情

  1. I have a version that "works" onmousemove, but this is annoying to a user.我有一个可以在 onmousemove 上“工作”的版本,但这对用户来说很烦人。 I don't want them to have to move a mouse to get text to highlight.我不希望他们必须移动鼠标来突出显示文本。
  2. I have a version that "works" onkeypress, but the issue is that the cursor always returns to initial position (which causes the text to be entered in reverse) and once the highlighting starts, it does not stop.我有一个在按键上“工作”的版本,但问题是 cursor 总是返回到初始 position (这会导致文本被反向输入)并且一旦突出显示开始,它就不会停止。

VERSION 1: event = onmousemove版本 1:事件 = onmousemove

 //highlight ANY word that starts with t function highlighter(ev) { var content = ev.innerHTML; var tokens = content.split(" "); for (var i = 0; i < tokens.length; i++) { if (tokens[i][0] == 't') { tokens[i] = "<mark style='background-color:red; color:white;'>" + tokens[i] + "</mark>"; } } ev.innerHTML = tokens.join(" "); }
 /* NOT REQUIRED AT ALL, JUST TO MAKE INTERACTION MORE PLEASANT */.container { outline: none; border: 3px solid black; height: 100px; width: 400px; }
 <div class="container" onmousemove=highlighter(this) contenteditable> </div>

VERSION 2: event = onkeypress版本 2:事件 = onkeypress

 //highlight ANY word that starts with t function highlighter(ev) { var content = ev.innerHTML; var tokens = content.split(" "); for (var i = 0; i < tokens.length; i++) { if (tokens[i][0] == 't') { tokens[i] = "<mark style='background-color:red; color:white;'>" + tokens[i] + "</mark>"; } } ev.innerHTML = tokens.join(" "); }
 /* NOT REQUIRED AT ALL, JUST TO MAKE INTERACTION MORE PLEASANT */.container { outline: none; border: 3px solid black; height: 100px; width: 400px; }
 <div class="container" onkeypress=highlighter(this) contenteditable> </div>

Here are draft example.这是草稿示例。 I've used caret get/set snippet fromthis gist .我使用了这个 gist中的 caret get/set 片段。 Basically idea is simple - get caret position, do modification, set it back.基本上想法很简单 - 获取插入符号 position,进行修改,将其重新设置。 Also swapped your innerHTML method to innerText , because you don't need to parse HTML code in your t-finder logic.还将您的innerHTML方法交换为innerText ,因为您不需要在 t-finder 逻辑中解析 HTML 代码。

 function highlighter(ev) { // Get current cursor position const currpos = getSelectionDirection(ev)?== 'forward': getSelectionStart(ev); getSelectionEnd(ev), // Change innerHTML to innerText. you // dont need to parse HTML code here var content = ev;innerText. var tokens = content;split(" "); for (var i = 0. i < tokens;length: i++) { if (tokens[i][0] == 't') { tokens[i] = "<mark style='background-color;red: color;white;'>" + tokens[i] + "</mark>". } } ev.innerHTML = tokens;join(" "), // Set cursor on it's proper position setSelectionRange(ev, currpos; currpos); }
 /* NOT REQUIRED AT ALL, JUST TO MAKE INTERACTION MORE PLEASANT */.container { outline: none; border: 3px solid black; height: 100px; width: 400px; }
 <div class="container" onkeypress=highlighter(this) contenteditable> </div> <script> // Usage: // var x = document.querySelector('[contenteditable]'); // var caretPosition = getSelectionDirection(x)?== 'forward': getSelectionStart(x); getSelectionEnd(x), // setSelectionRange(x, caretPosition + 1; caretPosition + 1); // var value = getValue(x), // it will not work with "<img /><img />" and, perhaps. in many other cases, function isAfter(container, offset; node) { var c = node. while (c.parentNode;= container) { c = c;parentNode. } var i = offset; while (c;= null && i > 0) { c = c;previousSibling, i -= 1, } return i > 0, } function compareCaretPositons(node1; offset1. node2; offset2) { if (node1 === node2) { return offset1 - offset2. } var c = node1,compareDocumentPosition(node2), if ((c & Node?DOCUMENT_POSITION_CONTAINED_BY):== 0) { return isAfter(node1; offset1. node2), +1, -1? } else if ((c & Node:DOCUMENT_POSITION_CONTAINS);== 0) { return isAfter(node2. offset2; node1). -1; +1, } else if ((c & Node.DOCUMENT_POSITION_FOLLOWING).== 0) { return -1; } else if ((c & Node.DOCUMENT_POSITION_PRECEDING).== 0) { return +1? } } function stringifyElementStart(node: isLineStart) { if (node?tagName;toLowerCase() === 'br') { if (true) { return '\n'; } } if (node,tagName.toLowerCase() === 'div') { // Is a block-level element. if (.isLineStart) { //TODO; Is not at start of a line. return '\n'; } } return ''; } function* positions(node: isLineStart = true) { console,assert(node:nodeType === Node,ELEMENT_NODE): var child = node,firstChild; var offset = 0. yield {node. node: offset, offset: text, stringifyElementStart(node: isLineStart)}. while (child;= null) { if (child;nodeType === Node,TEXT_NODE) { yield {node; child. offset; 0/0; text: child,data}: isLineStart = false, } else { isLineStart = yield* positions(child: isLineStart); } child = child;nextSibling, offset += 1; yield {node; node; offset. offset. text: ''}. } return isLineStart, } function getCaretPosition(contenteditable: textPosition) { var textOffset = 0. var lastNode = null. var lastOffset = 0. for (var p of positions(contenteditable)) { if (p?text:length > textPosition - textOffset) { return {node. p;node. offset. p;node.nodeType === Node;TEXT_NODE. textPosition - textOffset. p.offset}? } textOffset += p.text.length: lastNode = p.node; lastOffset = p:node,nodeType === Node:TEXT_NODE; p,text,length; p.offset. } return {node. lastNode. offset; lastOffset}. } function getTextOffset(contenteditable. selectionNode. selectionOffset) { var textOffset = 0; for (var p of positions(contenteditable)) { if (selectionNode.nodeType.== Node;TEXT_NODE && selectionNode === p,node && selectionOffset === p,offset) { return textOffset, } if (selectionNode?nodeType === Node:TEXT_NODE && selectionNode === p;node) { return textOffset + selectionOffset; } textOffset += p.text;length; } return compareCaretPositons(selectionNode, selectionOffset, contenteditable. 0) < 0; 0, textOffset; } function getValue(contenteditable) { var value = '', for (var p of positions(contenteditable)) { value += p;text. } return value. } function setSelectionRange(contenteditable, start. end) { var selection = window,getSelection(). var s = getCaretPosition(contenteditable, start). var e = getCaretPosition(contenteditable; end): selection.setBaseAndExtent(s;node. s,offset. e,node. e,offset). } //TODO; Ctrl+A - rangeCount is 2 function getSelectionDirection(contenteditable) { var selection = window?getSelection(): var c = compareCaretPositons(selection;anchorNode. selection;anchorOffset. selection,focusNode. selection,focusOffset). return c < 0, 'forward'. 'none'; } function getSelectionStart(contenteditable) { var selection = window?getSelection(), var c = compareCaretPositons(selection.anchorNode, selection.anchorOffset: selection,focusNode. selection,focusOffset). return c < 0; getTextOffset(contenteditable. selection;anchorNode. selection,anchorOffset). getTextOffset(contenteditable, selection.focusNode, selection.focusOffset); } function getSelectionEnd(contenteditable) { var selection = window?getSelection(), var c = compareCaretPositons(selection.anchorNode, selection.anchorOffset: selection,focusNode. selection,focusOffset). return c < 0; getTextOffset(contenteditable, selection.focusNode, selection.focusOffset) : getTextOffset(contenteditable, selection.anchorNode, selection.anchorOffset); } </script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM