Como destacar o texto usando o javascript

Alguém pode me ajudar com uma function javascript que pode destacar o texto em uma página da web. E o requisito é – destacar apenas uma vez, não como destacar todas as ocorrências do texto como fazemos em caso de busca.

Você pode usar o efeito de destaque jquery.

Mas se você estiver interessado em código JavaScript, dê uma olhada no que eu consegui. Basta copiar e colar em um HTML, abrir o arquivo e clicar em “realçar” – isso deve destacar a palavra “fox”. Desempenho sábio Eu acho que isso faria para texto pequeno e uma única repetição (como você especificou)

function highlight(text) { var inputText = document.getElementById("inputText"); var innerHTML = inputText.innerHTML; var index = innerHTML.indexOf(text); if (index >= 0) { innerHTML = innerHTML.substring(0,index) + "" + innerHTML.substring(index,index+text.length) + "" + innerHTML.substring(index + text.length); inputText.innerHTML = innerHTML; } } 
 .highlight { background-color: yellow; } 
  
The fox went over the fence

As soluções oferecidas aqui são muito ruins.

  1. Você não pode usar regex, porque dessa forma, você procura / destaca nas tags html.
  2. Você não pode usar regex, porque não funciona corretamente com UTF * (qualquer coisa com caracteres não latinos / ingleses).
  3. Você não pode simplesmente fazer um innerHTML.replace, porque isso não funciona quando os caracteres têm uma notação HTML especial, por exemplo, & para &, < para <, > para>, ä para ä, ö para ö ü para ü ß para ß etc.

O que você precisa fazer:

Faça um loop pelo documento HTML, localize todos os nós de texto, obtenha o textContent , obtenha a posição do texto de destaque com indexOf (com um opcional toLowerCase se não toLowerCase maiúsculas de minúsculas), anexe tudo antes de textNode como textNode , anexe o texto correspondente com um intervalo de realce e repita para o restante do textnode (a cadeia de realce pode ocorrer várias vezes na cadeia textContent ).

Aqui está o código para isso:

 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 }; 

Então você pode usá-lo assim:

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

Aqui está um exemplo de documento HTML

    Example of Text Highlight    
This is a test This is another test äöüÄÖÜäöüÄÖÜ Test123äöüÄÖÜ

By the way, se você procurar em um database com LIKE ,
por exemplo, WHERE textField LIKE CONCAT('%', @query, '%') [que você não deve fazer, você deve usar pesquisa de texto completo ou Lucene], então você pode escaping de todos os caracteres com \ e adicionar um escape de SQL declaração, que você vai encontrar caracteres especiais que são expressões LIKE.

por exemplo

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

e o valor de @query não é '% completed' mas '\%\ \c\o\m\p\l\e\t\e\d'

(testado, funciona com SQL-Server e PostgreSQL, e todos os outros sistemas RDBMS que suportam ESCAPE)

Por que usar uma function de destaque selfmade é uma má ideia

A razão pela qual provavelmente é uma má idéia começar a criar sua própria function de destaque do zero é porque você certamente encontrará problemas que outras pessoas já resolveram. Desafios:

  • Você precisaria remover nós de texto com elementos HTML para destacar suas correspondências sem destruir events DOM e triggersr a regeneração do DOM repetidas vezes (o que seria o caso, por exemplo, do innerHTML )
  • Se você quiser remover os elementos destacados, deverá remover os elementos HTML com seu conteúdo e também combinar os nós de texto divididos para pesquisas adicionais. Isso é necessário porque cada plug-in de marcador pesquisa dentro de nós de texto por correspondências e, se suas palavras-chave forem divididas em vários nós de texto, elas não serão encontradas.
  • Você também precisa criar testes para garantir que o seu plug-in funcione em situações nas quais você não pensou. E estou falando de testes entre navegadores!

Soa complicado? Se você quiser alguns resources como ignorar alguns elementos de destaque, mapeamento diacrítico, mapeamento de sinônimos, pesquisa dentro de iframes, pesquisa de palavras separadas, etc., isso se torna mais e mais complicado.

Use um plugin existente

Ao usar um plugin existente e bem implementado, você não precisa se preocupar com as coisas acima mencionadas. O artigo 10 jQuery texto highlighter plugins no Sitepoint compara plugins populares highlighter.

Dê uma olhada no mark.js

O mark.js é um plugin que é escrito em JavaScript puro, mas também está disponível como plugin jQuery. Foi desenvolvido para oferecer mais oportunidades que os outros plugins com opções para:

  • pesquisar palavras-chave separadamente, em vez do termo completo
  • diacríticos do mapa (Por exemplo, se “justo” também deve corresponder a “justò”)
  • ignorar correspondências dentro de elementos personalizados
  • use elemento de destaque personalizado
  • usar class de destaque personalizada
  • sinônimos de mapas personalizados
  • busca também dentro de iframes
  • receber termos não encontrados

DEMO

Alternativamente, você pode ver este violino .

Exemplo de uso :

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

É gratuito e desenvolvido de código aberto no GitHub ( referência do projeto ).

 function stylizeHighlightedString() { var text = window.getSelection(); // For diagnostics var start = text.anchorOffset; var end = text.focusOffset - text.anchorOffset; range = window.getSelection().getRangeAt(0); var selectionContents = range.extractContents(); var span = document.createElement("span"); span.appendChild(selectionContents); span.style.backgroundColor = "yellow"; span.style.color = "black"; range.insertNode(span); } 

Eu tenho o mesmo problema, um monte de texto vem através de uma solicitação xmlhttp. Este texto é formatado em html. Eu preciso destacar cada ocorrência.

 str='' +'

some text containing fox.

'

O problema é que não preciso destacar o texto nas tags. Por exemplo, preciso destacar fox:

Agora posso substituí-lo por:

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

Para responder à sua pergunta: você pode deixar de lado o g nas opções de regexp e somente a primeira ocorrência será substituída, mas esta ainda é a da propriedade img src e destrói a tag de imagem:

 ' +'

some text containing fox.

' 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,"$1"); });

Exemplo simples de TypeScript

NOTA: Embora eu concorde com o @Stefan em muitas coisas, eu só precisei de uma correspondência simples :

 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 + ''; } static highlightSearchTerm(term: string, searchResult: string): string { let regex = new RegExp(term, Utils.regexFlags); return searchResult.replace(regex, match => Utils.wrap(match)); } } } 

E então, construindo o resultado real:

 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; } } } 

Aqui está a minha solução JavaScript regexp pura:

 function highlight(text) { document.body.innerHTML = document.body.innerHTML.replace( new RegExp(text + '(?!([^<]+)?<)', 'gi'), '$&' ); } 

Eu encontrei o plugin de destaque para ser o melhor jogo, com ele você pode destacar parte do conteúdo :

$ (‘li’). highlight (‘bla’);

Eu queria saber disso também, você poderia tentar o que eu aprendi neste post.

Eu usei:

 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); } 
      

this is text, select and right click to high light me! if you can`t see the option, please use this

Nenhuma das outras soluções realmente atende às minhas necessidades e, embora a solução de Stefan Steiger tenha funcionado como eu esperava, achei-a um pouco detalhada demais.

A seguir está minha tentativa:

 /** * Highlight keywords inside a DOM element * @param {string} elem Element to search for keywords in * @param {string[]} keywords Keywords to highlight * @param {boolean} caseSensitive Differenciate between capital and lowercase letters * @param {string} cls Class to apply to the highlighted keyword */ function highlight(elem, keywords, caseSensitive = false, cls = 'highlight') { const flags = caseSensitive ? 'gi' : 'g'; // Sort longer matches first to avoid // highlighting keywords within keywords. keywords.sort((a, b) => b.length - a.length); Array.from(elem.childNodes).forEach(child => { const keywordRegex = RegExp(keywords.join('|'), flags); if (child.nodeType !== 3) { // not a text node highlight(child, keywords, caseSensitive, cls); } else if (keywordRegex.test(child.textContent)) { const frag = document.createDocumentFragment(); let lastIdx = 0; child.textContent.replace(keywordRegex, (match, idx) => { const part = document.createTextNode(child.textContent.slice(lastIdx, idx)); const highlighted = document.createElement('span'); highlighted.textContent = match; highlighted.classList.add(cls); frag.appendChild(part); frag.appendChild(highlighted); lastIdx = idx + match.length; }); const end = document.createTextNode(child.textContent.slice(lastIdx)); frag.appendChild(end); child.parentNode.replaceChild(frag, child); } }); } // Highlight all keywords found in the page highlight(document.body, ['lorem', 'amet', 'autem']); 
 .highlight { background: lightpink; } 
 

Hello world lorem ipsum dolor sit amet, consectetur adipisicing elit. Est vel accusantium totam, ipsum delectus et dignissimos mollitia!

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam, corporis. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium autem voluptas perferendis dolores ducimus velit error voluptatem, qui rerum modi?

Desde o HTML5, você pode usar as para realçar o texto. Você pode usar o javascript para agrupar algum texto / palavra-chave entre essas tags. Aqui está um pequeno exemplo de como marcar e desmarcar o texto.

JSFIDDLE DEMO

Usando o método surroundContents () no tipo Range . Seu único argumento é um elemento que envolverá esse intervalo.

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