Les solutions proposées ici sont assez mauvaises.
- Vous ne pouvez pas utiliser l'expression rationnelle, car de cette façon, vous recherchez/surlignez dans les balises html.
- Vous ne pouvez pas utiliser l'expression rationnelle, car elle ne fonctionne pas correctement avec l'UTF* (tout ce qui contient des caractères non latins/anglais).
- Vous ne pouvez pas simplement faire un innerHTML.replace, parce que cela ne fonctionne pas lorsque les caractères ont une notation HTML spéciale, par ex.
&
pour &, <
pour <, >
pour >, ä
pour ä, ö
pour ö ü
pour ü ß
pour ß, etc.
Ce que vous devez faire :
Boucle à travers le document HTML, trouve tous les nœuds de texte, récupère l'adresse de l'utilisateur. textContent
, obtenir la position du texte en surbrillance avec indexOf
(avec une option toLowerCase
s'il doit être insensible à la casse), ajouter tout ce qui se trouve avant indexof
comme textNode
ajoutez le texte correspondant à un espace de surbrillance, et répétez l'opération pour le reste du noeud de texte (la chaîne de surbrillance peut apparaître plusieurs fois dans la chaîne de texte). textContent
string).
Voici le code pour cela :
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
};
Alors vous pouvez l'utiliser comme ceci :
function TestTextHighlighting(highlightText)
{
var container = document.getElementById("testDocument");
InstantSearch.highlight(container, highlightText);
}
Voici un exemple de document 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äöüÄÖÜ</span>
</div>
</body>
</html>
D'ailleurs, si vous effectuez une recherche dans une base de données avec LIKE
,
par exemple WHERE textField LIKE CONCAT('%', @query, '%')
[ce que vous ne devriez pas faire, vous devriez utiliser la recherche plein texte ou Lucene], alors vous pouvez échapper à chaque caractère avec \ et ajouter un SQL-escape-statement, de cette façon vous trouverez les caractères spéciaux qui sont des expressions LIKE.
par exemple
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
et la valeur de @query n'est pas '%completed%'
mais '%\c\o\m\p\l\e\t\e\d%'
(testé, fonctionne avec SQL-Server et PostgreSQL, et tout autre système RDBMS qui supporte ESCAPE)
Une version révisée du manuscrit :
namespace SearchTools
{
export interface IToken
{
token: string;
className: string;
sensitiveSearch: boolean;
}
export class InstantSearch
{
protected m_container: Node;
protected m_defaultClassName: string;
protected m_defaultCaseSensitivity: boolean;
protected m_highlightTokens: IToken[];
constructor(container: Node, tokens: IToken[], defaultClassName?: string, defaultCaseSensitivity?: boolean)
{
this.iterator = this.iterator.bind(this);
this.checkAndReplace = this.checkAndReplace.bind(this);
this.highlight = this.highlight.bind(this);
this.highlightNode = this.highlightNode.bind(this);
this.m_container = container;
this.m_defaultClassName = defaultClassName || "highlight";
this.m_defaultCaseSensitivity = defaultCaseSensitivity || false;
this.m_highlightTokens = tokens || [{
token: "test",
className: this.m_defaultClassName,
sensitiveSearch: this.m_defaultCaseSensitivity
}];
}
protected checkAndReplace(node: Node)
{
let nodeVal: string = node.nodeValue;
let parentNode: Node = node.parentNode;
let textNode: Text = null;
for (let i = 0, j = this.m_highlightTokens.length; i < j; i++)
{
let curToken: IToken = this.m_highlightTokens[i];
let textToHighlight: string = curToken.token;
let highlightClassName: string = curToken.className || this.m_defaultClassName;
let caseSensitive: boolean = curToken.sensitiveSearch || this.m_defaultCaseSensitivity;
let isFirst: boolean = true;
while (true)
{
let foundIndex: number = caseSensitive ?
nodeVal.indexOf(textToHighlight)
: nodeVal.toLowerCase().indexOf(textToHighlight.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;
let begin: string = nodeVal.substring(0, foundIndex);
let matched: string = nodeVal.substr(foundIndex, textToHighlight.length);
if (begin)
{
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
} // End if (begin)
let span: HTMLSpanElement = document.createElement("span");
if (!span.classList.contains(highlightClassName))
span.classList.add(highlightClassName);
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + textToHighlight.length);
} // Whend
} // Next i
} // End Sub checkAndReplace
protected iterator(p: Node)
{
if (p == null)
return;
let children: Node[] = Array.prototype.slice.call(p.childNodes);
if (children.length)
{
for (let i = 0; i < children.length; i++)
{
let cur: Node = children[i];
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
if (cur.nodeType === Node.TEXT_NODE)
{
this.checkAndReplace(cur);
}
else if (cur.nodeType === Node.ELEMENT_NODE)
{
this.iterator(cur);
}
} // Next i
} // End if (children.length)
} // End Sub iterator
public highlightNode(n:Node)
{
this.iterator(n);
} // End Sub highlight
public highlight()
{
this.iterator(this.m_container);
} // End Sub highlight
} // End Class InstantSearch
} // End Namespace SearchTools
Uso:
let searchText = document.getElementById("txtSearchText");
let searchContainer = document.body; // document.getElementById("someTable");
let highlighter = new SearchTools.InstantSearch(searchContainer, [
{
token: "this is the text to highlight" // searchText.value,
className: "highlight", // this is the individual highlight class
sensitiveSearch: false
}
]);
// highlighter.highlight(); // this would highlight in the entire table
// foreach tr - for each td2
highlighter.highlightNode(td2); // this highlights in the second column of table
5 votes
Si vous postez le code de la fonction, nous pourrons vous aider. Si vous nous demandez de créer une telle fonction pour vous... c'est moins probable. Vous devez faire quelque chose par vous-même. Commencez à faire quelque chose et revenez quand vous êtes bloqué.
7 votes
Oui, j'ai lu How to Ask et j'ai fait quelque chose par moi-même, mais je suis resté bloqué et c'est pourquoi j'ai demandé. Je travaille sur Android et j'ai peu de connaissances en javasript, c'est pourquoi je ne suis pas en mesure de le faire moi-même. Auparavant, j'utilisais un autre javascript qui faisait le travail mais pas sans certaines limitations. Je n'ai peut-être pas utilisé les bons mots en posant cette question et j'en suis désolé, mais s'il vous plaît, ne pensez pas le contraire.
1 votes
Ce plugin peut vous intéresser : github.com/julmot/jmHighlight . Il peut mettre en évidence les mots clés séparément ou en tant que terme, peut mettre en évidence la correspondance avec votre élément personnalisé et votre nom de classe et peut également rechercher les diacritiques. En outre, il vous permet de filtrer le contexte dans lequel vous recherchez des correspondances.
1 votes
Vérifier la méthode regex suivante... stackoverflow.com/a/45519242/2792959
0 votes
J'ai préparé un article à ce sujet ici, exhesham.com/2017/11/20/…