Highlight Keywords in a Paragraph

Highlight keywords in a paragraph

If it contains html (note that this is a pretty robust solution):

$string = '<p>foo<b>bar</b></p>';
$keyword = 'foo';
$dom = new DomDocument();
$dom->loadHtml($string);
$xpath = new DomXpath($dom);
$elements = $xpath->query('//*[contains(.,"'.$keyword.'")]');
foreach ($elements as $element) {
foreach ($element->childNodes as $child) {
if (!$child instanceof DomText) continue;
$fragment = $dom->createDocumentFragment();
$text = $child->textContent;
$stubs = array();
while (($pos = stripos($text, $keyword)) !== false) {
$fragment->appendChild(new DomText(substr($text, 0, $pos)));
$word = substr($text, $pos, strlen($keyword));
$highlight = $dom->createElement('span');
$highlight->appendChild(new DomText($word));
$highlight->setAttribute('class', 'highlight');
$fragment->appendChild($highlight);
$text = substr($text, $pos + strlen($keyword));
}
if (!empty($text)) $fragment->appendChild(new DomText($text));
$element->replaceChild($fragment, $child);
}
}
$string = $dom->saveXml($dom->getElementsByTagName('body')->item(0)->firstChild);

Results in:

<p><span class="highlight">foo</span><b>bar</b></p>

And with:

$string = '<body><p>foobarbaz<b>bar</b></p></body>';
$keyword = 'bar';

You get (broken onto multiple lines for readability):

<p>foo
<span class="highlight">bar</span>
baz
<b>
<span class="highlight">bar</span>
</b>
</p>

Beware of non-dom solutions (like regex or str_replace) since highlighting something like "div" has a tendency of completely destroying your HTML... This will only ever "highlight" strings in the body, never inside of a tag...


Edit Since you want Google style results, here's one way of doing it:

function getKeywordStubs($string, array $keywords, $maxStubSize = 10) {
$dom = new DomDocument();
$dom->loadHtml($string);
$xpath = new DomXpath($dom);
$results = array();
$maxStubHalf = ceil($maxStubSize / 2);
foreach ($keywords as $keyword) {
$elements = $xpath->query('//*[contains(.,"'.$keyword.'")]');
$replace = '<span class="highlight">'.$keyword.'</span>';
foreach ($elements as $element) {
$stub = $element->textContent;
$regex = '#^.*?((\w*\W*){'.
$maxStubHalf.'})('.
preg_quote($keyword, '#').
')((\w*\W*){'.
$maxStubHalf.'}).*?$#ims';
preg_match($regex, $stub, $match);
var_dump($regex, $match);
$stub = preg_replace($regex, '\\1\\3\\4', $stub);
$stub = str_ireplace($keyword, $replace, $stub);
$results[] = $stub;
}
}
$results = array_unique($results);
return $results;
}

Ok, so what that does is return an array of matches with $maxStubSize words around it (namely up to half that number before, and half after)...

So, given a string:

<p>a whole 
<b>bunch of</b> text
<a>here for</a>
us to foo bar baz replace out from this string
<b>bar</b>
</p>

Calling getKeywordStubs($string, array('bar', 'bunch')) will result in:

array(4) {
[0]=>
string(75) "here for us to foo <span class="highlight">bar</span> baz replace out from "
[3]=>
string(34) "<span class="highlight">bar</span>"
[4]=>
string(62) "a whole <span class="highlight">bunch</span> of text here for "
[7]=>
string(39) "<span class="highlight">bunch</span> of"
}

So, then you could build your result blurb by sorting the list by strlen and then picking the two longest matches... (assuming php 5.3+):

usort($results, function($str1, $str2) { 
return strlen($str2) - strlen($str1);
});
$description = implode('...', array_slice($results, 0, 2));

Which results in:

here for us to foo <span class="highlight">bar</span> baz replace out...a whole <span class="highlight">bunch</span> of text here for 

I hope that helps... (I do feel this is a bit... bloated... I'm sure there are better ways to do this, but here's one way)...

Highlighting all occurrences of specific words in a paragraph from an array of keywords

Probably you don't need match(re).forEach, Just use replace(re) alone

var arr = ("The dog ran through the field.  The dog ate."); //paragraph from which to searchdocument.getElementById("x").innerHTML = arr;
var words = ["dog", "field"]; //array of keywords
var str = document.getElementById("x").innerHTML;var re = new RegExp(words.join("|"), "gi"); // create a a | b | c regex
str = str.replace(re, function replace(match) { // wrap the found strings return '<em>' + match + '</em>';});
document.getElementById("x").innerHTML = str
<p id="x"></p>

How to search multiple keywords in paragraph and highlight the each keyword with different color in javascript using ReactJS?

You can first define an object to hold the color for each of the keyword, then use it later

const styles = {
"sea": {
fontWeight: "bold", color: "red"
},
"sky": {
fontWeight: "bold", color: "blue"
}
}

// use it
<span style={styles[keyword] || {}}>...</span>

Next nested looping of of both parts and KeywordsTosearch is causing the randomly repeated text

parts.map((part, i) => KeywordsTosearch.map((keyword,i) => { })

Since 'KeywordsTosearch' had already done it's job in splitting the sentence, you just need to loop 'parts' to apply the styles

var tempKeyword = [];
tempKeyword = parts.map((part, i) =>
<span
key={i}
style={this.getStyle(part)}>
{part}
</span>
)

See working example https://codesandbox.io/s/recursing-turing-7m56b

How can I can highlight words that are more or equal to 8 characters in paragraph? JavaScript

Welcome! You had many of the right pieces there, just needed to put them together a bit differently.

I have put together a complete HTML that has it all working together, with some comments on how things are working - hope this helps.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.lightext {
background-color: yellow;
}
</style>
</head>
<body>
<p id="targetp">This is the extremely long paragraph that we want to highlight all words longer than eight characters in.</p>
<script>

function highlightWords() {
const txt = document.getElementById("targetp").innerText;
let output = "";
let words = txt.split(" ");
let size = 8 //don't really need this - size as a variable isn't used anywhere else,
let replacementword = ""; //this will store our output - it's easier than trying to update thee text "in place"
for (let i = 0; i < words.length; i++) {
let word = words[i];
if (word.length >= 8) { //this is where we figure out if the word is longer than 8
replacementword = "<span class='lightext'>" + word + "</span>"; //if it is, we just need to wrap it in a span with lighttext class - assuming you have a "highlighted" style applied to class lightext, see styles above for mine
}
else {
replacementword = word; //shorter than 8, don't need to change anything
}
output = output + " " + replacementword + " "; //add the updated word to our output
}

return output; //return our finished output string to the function call
}

document.getElementById("targetp").innerHTML = highlightWords(); //actually update the <p> tag with the new text, WHICH is now HTML rather than just plain text
</script>

</body>
</html>

How to highlight text using javascript

You can use the jquery highlight effect.

But if you are interested in raw javascript code, take a look at what I got
Simply copy paste into an HTML, open the file and click "highlight" - this should highlight the word "fox". Performance wise I think this would do for small text and a single repetition (like you specified)

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) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);   inputText.innerHTML = innerHTML;  }}
.highlight {  background-color: yellow;}
<button onclick="highlight('fox')">Highlight</button>
<div id="inputText"> The fox went over the fence</div>

how to use react-highlight-words to highlight multiple keywords with different colors

const Highlight = ({ children, highlightIndex }) => (
<span className={highlighted-text keyword-${highlightword.indexOf(children)}}>{children}
);

and add tag - highlightTag={Highlight}

how to highlight a word in a paragraph in angular 2?

In case someone is interested in a simple (generic) solution, I came up with a directive (based on Thierry Templier work !).

This directive allows you to pass the text to work with, the search text and a class to apply :

import { Directive, ElementRef, Renderer, Input, OnInit } from '@angular/core';
import { escapeStringRegexp } from '../helpers/helper';

@Directive({
selector: '[appColorSearchedLetters]'
})
export class ColorSearchedLettersDirective implements OnInit {
@Input() search: string;
@Input() text: string;
@Input() classToApply: string;

constructor(private el: ElementRef, private renderer: Renderer) { }

ngOnInit() {
if (typeof this.classToApply === 'undefined') {
this.classToApply = '';
}

if (typeof this.search === 'undefined') {
this.renderer.setElementProperty(this.el.nativeElement, 'innerHTML', this.text);
return;
}

let search = escapeStringRegexp(this.search.toString());
this.renderer.setElementProperty(this.el.nativeElement, 'innerHTML', this.replace(this.text, search));
}

replace(txt: string, search: string) {
let searchRgx = new RegExp('('+search+')', 'gi');

return txt.replace(searchRgx, `<span class="${this.classToApply}">$1</span>`);
}
}

And the helper

import { escapeStringRegexp } from '../helpers/helper';

contains :

let matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;

export function escapeStringRegexp (str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}

return str.replace(matchOperatorsRe, '\\$&');
};

This function is from https://www.npmjs.com/package/escape-string-regexp and credit goes to Sindresorhus.

Here's how I use it :

<span appColorSearchedLetters [search]="search" [text]="user.name" classToApply="searched"></span>

highlight the word in the string, if it contains the keyword

Try this:

preg_replace("/\w*?$keyword\w*/i", "<b>$0</b>", $str)

\w*? matches any word characters before the keyword (as least as possible) and \w* any word characters after the keyword.

And I recommend you to use preg_quote to escape the keyword:

preg_replace("/\w*?".preg_quote($keyword)."\w*/i", "<b>$0</b>", $str)

For Unicode support, use the u flag and \p{L} instead of \w:

preg_replace("/\p{L}*?".preg_quote($keyword)."\p{L}*/ui", "<b>$0</b>", $str)


Related Topics



Leave a reply



Submit