如何使用JavaScript突出显示文本

有人可以帮助我一个JavaScriptfunction,可以突出显示网页上的文字。 要求是 – 只突出显示一次,而不是像在search的情况下突出显示文本的所有出现。

你可以使用jQuery的高亮效果 。

但是,如果您对原始JavaScript代码感兴趣,请查看我所获得的内容。只需将复制粘贴到HTML中,打开文件并单击“突出显示” – 应突出显示“fox”一词。 性能明智,我认为这将做小文本和一个单一的重复(就像你指定)

<script> function highlight(text) { inputText = document.getElementById("inputText"); var innerHTML = inputText.innerHTML; var index = innerHTML.indexOf(text); if ( index >= 0 ) { innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length); inputText.innerHTML = innerHTML; } } </script> <button onclick="highlight('fox')">Highlight</button> <style> .highlight { background-color:yellow; } </style> <div id="inputText"> The fox went over the fence </div> 

编辑:

使用replace

我看到这个答案获得了一些人气,我想我可以补充一点。 您也可以轻松使用replace

"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");

或者对于多个事件(与问题无关,但在评论中被问到),您只需在replace正则expression式中添加global

"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");

希望这对有趣的评论者有帮助。

将HTMLreplace为整个网页

要replace整个网页的HTML,你应该引用文档正文的innerHTML

document.body.innerHTML

这里提供的解决scheme非常糟糕。

  1. 你不能使用正则expression式,因为这样,你在html标签中search/突出显示。
  2. 你不能使用正则expression式,因为它不能正确使用UTF *(任何非拉丁/英文字符)。
  3. 你不能只是做一个innerHTML.replace,因为当字符有一个特殊的HTML符号时,这不起作用,例如&auml; 对于ä, &ouml; 为ö &uuml; 为ü &szlig; 对于ß等

你需要做什么:

循环浏览HTML文档,find所有文本节点,获取textContent ,使用indexOf获取高亮文本的位置(如果应该不区分大小写,则使用可选的toLowerCase ),将indexof之前的所有内容追加为textNode ,追加匹配的Text使用高亮度范围,并重复其余的textnode(高亮string可能会在textContentstring中出现多次)。

这里是这个代码:

 var InstantSearch = { "highlight": function (container, highlightText) { var internalHighlighter = function (options) { var id = { container: "container", tokens: "tokens", all: "all", token: "token", className: "className", sensitiveSearch: "sensitiveSearch" }, tokens = options[id.tokens], allClassName = options[id.all][id.className], allSensitiveSearch = options[id.all][id.sensitiveSearch]; function checkAndReplace(node, tokenArr, classNameAll, sensitiveSearchAll) { var nodeVal = node.nodeValue, parentNode = node.parentNode, i, j, curToken, myToken, myClassName, mySensitiveSearch, finalClassName, finalSensitiveSearch, foundIndex, begin, matched, end, textNode, span, isFirst; for (i = 0, j = tokenArr.length; i < j; i++) { curToken = tokenArr[i]; myToken = curToken[id.token]; myClassName = curToken[id.className]; mySensitiveSearch = curToken[id.sensitiveSearch]; finalClassName = (classNameAll ? myClassName + " " + classNameAll : myClassName); finalSensitiveSearch = (typeof sensitiveSearchAll !== "undefined" ? sensitiveSearchAll : mySensitiveSearch); isFirst = true; while (true) { if (finalSensitiveSearch) foundIndex = nodeVal.indexOf(myToken); else foundIndex = nodeVal.toLowerCase().indexOf(myToken.toLowerCase()); if (foundIndex < 0) { if (isFirst) break; if (nodeVal) { textNode = document.createTextNode(nodeVal); parentNode.insertBefore(textNode, node); } // End if (nodeVal) parentNode.removeChild(node); break; } // End if (foundIndex < 0) isFirst = false; begin = nodeVal.substring(0, foundIndex); matched = nodeVal.substr(foundIndex, myToken.length); if (begin) { textNode = document.createTextNode(begin); parentNode.insertBefore(textNode, node); } // End if (begin) span = document.createElement("span"); span.className += finalClassName; span.appendChild(document.createTextNode(matched)); parentNode.insertBefore(span, node); nodeVal = nodeVal.substring(foundIndex + myToken.length); } // Whend } // Next i }; // End Function checkAndReplace function iterator(p) { if (p === null) return; var children = Array.prototype.slice.call(p.childNodes), i, cur; if (children.length) { for (i = 0; i < children.length; i++) { cur = children[i]; if (cur.nodeType === 3) { checkAndReplace(cur, tokens, allClassName, allSensitiveSearch); } else if (cur.nodeType === 1) { iterator(cur); } } } }; // End Function iterator iterator(options[id.container]); } // End Function highlighter ; internalHighlighter( { container: container , all: { className: "highlighter" } , tokens: [ { token: highlightText , className: "highlight" , sensitiveSearch: false } ] } ); // End Call internalHighlighter } // End Function highlight }; 

那么你可以像这样使用它:

 function TestTextHighlighting(highlightText) { var container = document.getElementById("testDocument"); InstantSearch.highlight(container, highlightText); } 

这是一个示例HTML文档

 <!DOCTYPE html> <html> <head> <title>Example of Text Highlight</title> <style type="text/css" media="screen"> .highlight{ background: #D3E18A;} .light{ background-color: yellow;} </style> </head> <body> <div id="testDocument"> This is a test <span> This is another test</span> äöüÄÖÜäöüÄÖÜ <span>Test123&auml;&ouml;&uuml;&Auml;&Ouml;&Uuml;</span> </div> </body> </html> 

顺便说一句,如果你用LIKE在数据库中search,
例如WHERE textField LIKE CONCAT('%', @query, '%') [你不应该这样做,你应该使用fulltext-search或者Lucene],然后你可以用\转义每个字符,并且添加一个SQL-escape-语句,你会发现LIKEexpression式的特殊字符。

例如

 WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\' 

并且@query的值不是'% completed'而是'\%\ \c\o\m\p\l\e\t\e\d'

(经testing,适用于SQL-Server和PostgreSQL,以及其他支持ESCAPE的RDBMS系统)

为什么使用自制的突出显示function是一个坏主意

从零开始构build自己的突出显示function可能是一个糟糕的主意,因为您肯定会遇到其他人已经解决的问题。 挑战:

  • 您将需要使用HTML元素删除文本节点,以突出显示您的匹配,而不会破坏DOM事件并一次又一次地触发DOM重新生成(例如,对于如innerHTML
  • 如果你想删除突出显示的元素,你将不得不删除HTML元素与他们的内容,也必须结合拆分文本节点进一步search。 这是必要的,因为每个荧光笔插件search文本节点内匹配,如果您的关键字将被拆分成几个文本节点,他们将不会被发现。
  • 您还需要构buildtesting以确保您的插件能够在您没有想到的情况下工作。 而我正在谈论跨浏览器testing!

听起来很复杂? 如果您想要某些function忽略突出显示的某些元素,变音符映射,同义词映射,内部iframesearch,分词search等,这变得越来越复杂。

使用现有的插件

当使用现有的,很好实施的插件,你不必担心上述命名的事情。 第10条jQuery文字荧光笔插件 Sitepoint比较stream行的荧光笔插件。

看看mark.js

mark.js是一个用纯JavaScript编写的插件,也可以作为jQuery插件使用。 它的开发提供了更多的机会比其他插件与选项:

  • 单独search关键字而不是完整的术语
  • 地图变音符号(例如,如果“justo”也应该匹配“justò”)
  • 忽略自定义元素内的匹配
  • 使用自定义高亮元素
  • 使用自定义高亮类
  • 映射自定义同义词
  • 也search内部框架
  • 收不到条款

DEMO

或者你可以看到这个小提琴 。

用法示例

 // Highlight "keyword" in the specified context $(".context").mark("keyword"); // Highlight the custom regular expression in the specified context $(".context").markRegExp(/Lorem/gmi); 

它是免费的,在GitHub上开发开源( 项目参考 )。

 function stylizeHighlightedString() { //alert(text.focusOffset - text.anchorOffset); var text = window.getSelection(); var start = text.anchorOffset; alert(start); var end = text.focusOffset - text.anchorOffset; alert(end); range = window.getSelection().getRangeAt(0); range1 = window.getSelection().toString(); var selectionContents = range.extractContents(); var span = document.createElement("span"); span.appendChild(selectionContents); span.setAttribute("class", "uiWebviewHighlight"); span.style.backgroundColor = "yellow"; span.style.color = "black"; range.insertNode(span); } 

我有同样的问题,一堆文本通过xmlhttp请求进来。 这个文本是html格式的。 我需要突出每一个事件。

 str='<img src="brown fox.jpg" title="The brown fox" />' +'<p>some text containing fox.</p>' 

问题是我不需要突出显示标签中的文本。 例如,我需要突出显示狐狸:

现在我可以用它来replace它:

 var word="fox"; word="(\\b"+ word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1") + "\\b)"; var r = new RegExp(word,"igm"); str.replace(r,"<span class='hl'>$1</span>") 

要回答你的问题:你可以在正则expression式选项中省略g,只有第一次出现才会被replace,但是这仍然是img src属性中的一个,并且销毁了image标签:

 <img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span class='hl'>fox</span> /> 

这是我解决它的方式,但想知道是否有更好的方法,我在正则expression式中错过了:

 str='<img src="brown fox.jpg" title="The brown fox" />' +'<p>some text containing fox.</p>' var word="fox"; word="(\\b"+ word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1") + "\\b)"; var r = new RegExp(word,"igm"); str.replace(/(>[^<]+<)/igm,function(a){ return a.replace(r,"<span class='hl'>$1</span>"); }); 

简单的TypeScript示例

注意:虽然我很同意@Stefan,但我只需要一个简单的匹配高亮显示:

 module myApp.Search { 'use strict'; export class Utils { private static regexFlags = 'gi'; private static wrapper = 'mark'; private static wrap(match: string): string { return '<' + Utils.wrapper + '>' + match + '</' + Utils.wrapper + '>'; } static highlightSearchTerm(term: string, searchResult: string): string { let regex = new RegExp(term, Utils.regexFlags); return searchResult.replace(regex, match => Utils.wrap(match)); } } } 

然后构build实际的结果:

 module myApp.Search { 'use strict'; export class SearchResult { id: string; title: string; constructor(result, term?: string) { this.id = result.id; this.title = term ? Utils.highlightSearchTerm(term, result.title) : result.title; } } } 

我发现高亮插件是最好的搭配,它可以突出显示部分内容

$( '礼')亮点(以 'bla');

我也想知道,你可以尝试我在这篇文章中学到的东西。

我用了:

 function highlightSelection() { var userSelection = window.getSelection(); for(var i = 0; i < userSelection.rangeCount; i++) { highlightRange(userSelection.getRangeAt(i)); } } function highlightRange(range) { var newNode = document.createElement("span"); newNode.setAttribute( "style", "background-color: yellow; display: inline;" ); range.surroundContents(newNode); } 
 <html> <body contextmenu="mymenu"> <menu type="context" id="mymenu"> <menuitem label="Highlight Yellow" onclick="highlightSelection()" icon="http://img.dovov.comcomment_icon.gif"></menuitem> </menu> <p>this is text, select and right click to high light me! if you can`t see the option, please use this<button onclick="highlightSelection()">button </button><p> 

这是我的正则expression式纯JavaScript解决scheme:

 function highlight(text) { document.body.innerHTML = document.body.innerHTML.replace( new RegExp(text + '(?!([^<]+)?<)', 'gi'), '<b style="background-color:#ff0;font-size:100%">$&</b>' ); } 

自HTML5以来,您可以使用<mark></mark>标记来突出显示文本。 您可以使用JavaScript来包装这些标签之间的文字/关键字。 这里是一个如何标记和取消标记文本的例子。

JSFIDDLE DEMO

使用Rangetypes的surroundContents()方法。 它唯一的参数是一个将包裹该范围的元素。

 function styleSelected() { bg = document.createElement("span"); bg.style.backgroundColor = "yellow"; window.getSelection().getRangeAt(0).surroundContents(bg); }