Je me demande s'il est possible d'utiliser JavaScript ou jQuery de manière légère pour détecter un caractère de texte spécifique dans un document; dites € et trouvez toutes les occurrences de ce caractère. Et alors! Ecrit une capacité à remplacer toutes les instances de celle-ci avec, par exemple, un $ .
J'ai trouvé cet extrait pour commencer:
var str = 'test: '';
str = str.replace(/'/g, "'");
Essentiellement; Je cherche une solution pour un document d'une page. Prenez toutes les instances de X et faites-le XY. Seuls les caractères du texte.
Que diriez-vous de ceci, en remplaçant @
par $
:
$("body").children().each(function () {
$(this).html( $(this).html().replace(/@/g,"$") );
});
Ma propre suggestion est la suivante:
function nativeSelector() {
var elements = document.querySelectorAll("body, body *");
var results = [];
var child;
for(var i = 0; i < elements.length; i++) {
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3) {
results.Push(child);
}
}
return results;
}
var textnodes = nativeSelector(),
_nv;
for (var i = 0, len = textnodes.length; i<len; i++){
_nv = textnodes[i].nodeValue;
textnodes[i].nodeValue = _nv.replace(/£/g,'€');
}
La fonction nativeSelector()
provient de une réponse (publiée par Anurag ) à cette question: getElementsByTagName () équivalente pour textNodes .
Cela semble être une tâche facile, mais vous devez prendre en charge plusieurs choses:
<script>
ou <style>
, ou les balises ou attributs HTML, ce qui n'est pas toujours souhaitabletitle
et alt
(de manière contrôlée)La protection contre les attaques xss ne peut généralement pas être résolue en utilisant les approches ci-dessous. Par exemple. Si un appel fetch
lit une URL quelque part sur la page, puis envoie une demande à cette URL, les fonctions ci-dessous n'arrêteront pas cela, car ce scénario est intrinsèquement dangereux.
Cela sélectionne essentiellement tous les éléments contenant du texte normal, passe par leurs nœuds enfants (parmi ceux-ci également des nœuds de texte), recherche ces nœuds de texte et remplace leur contenu.
Vous pouvez éventuellement spécifier une racine différente target
, par exemple. replaceOnDocument(/€/g, "$", { target: someElement });
; Par défaut, le <body>
est choisi.
const replaceOnDocument = (pattern, string, {target = document.body} = {}) => {
// Handle `string` — see the last section
[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].forEach(({childNodes: [...nodes]}) => nodes
.filter(({nodeType}) => nodeType === document.TEXT_NODE)
.forEach((textNode) => textNode.textContent = textNode.textContent.replace(pattern, string)));
};
replaceOnDocument(/€/g, "$");
Maintenant, ceci est un peu plus complexe: vous devez vérifier trois cas: si un nœud est un nœud text, s’il s’agit d’un élément et que son attribut doit être remplacé, ou s’il s’agit d’un élément et de son property doit être remplacé. Un objet replacer
fournit des méthodes pour les nœuds de texte et pour les éléments.
Avant de remplacer des attributs et des propriétés, le remplaçant doit vérifier si l'élément a un attribut correspondant. sinon, de nouveaux attributs sont créés, de manière non souhaitable. Il doit également vérifier si la propriété ciblée est une chaîne, car seules les chaînes peuvent être remplacées, ou si la propriété correspondante à l'attribut ciblé n'est pas une fonction, car cela peut entraîner une attaque xss .
Dans l'exemple ci-dessous, vous pouvez voir comment utiliser les fonctionnalités étendues: dans le troisième argument facultatif, vous pouvez ajouter une propriété attrs
et une propriété props
, qui est un élément itératif (par exemple, un tableau), pour les attributs à remplacer et les propriétés à remplacer, respectivement.
Vous remarquerez également que cet extrait utilise flatMap
. Si cela n’est pas pris en charge, utilisez un polyfill ou remplacez-le par la construction reduce
– concat
ou map
– reduce
– concat
, comme indiqué dans la documentation liée.
const replaceOnDocument = (() => {
const replacer = {
[document.TEXT_NODE](node, pattern, string){
node.textContent = node.textContent.replace(pattern, string);
},
[document.ELEMENT_NODE](node, pattern, string, {attrs, props} = {}){
attrs.forEach((attr) => {
if(typeof node[attr] !== "function" && node.hasAttribute(attr)){
node.setAttribute(attr, node.getAttribute(attr).replace(pattern, string));
}
});
props.forEach((prop) => {
if(typeof node[prop] === "string" && node.hasAttribute(prop)){
node[prop] = node[prop].replace(pattern, string);
}
});
}
};
return (pattern, string, {target = document.body, attrs: [...attrs] = [], props: [...props] = []} = {}) => {
// Handle `string` — see the last section
[
target,
...[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].flatMap(({childNodes: [...nodes]}) => nodes)
].filter(({nodeType}) => replacer.hasOwnProperty(nodeType))
.forEach((node) => replacer[node.nodeType](node, pattern, string, {
attrs,
props
}));
};
})();
replaceOnDocument(/€/g, "$", {
attrs: [
"title",
"alt",
"onerror" // This will be ignored
],
props: [
"value" // Changing an `<input>`’s `value` attribute won’t change its current value, so the property needs to be accessed here
]
});
Si vous avez besoin de le faire fonctionner avec des entités HTML telles que ­
, les approches ci-dessus ne produiront littéralement que la chaîne ­
, car il s’agit d’une entité HTML et ne fonctionnera que lors de l’affectation de .innerHTML
ou de l’utilisation de méthodes connexes.
Réservons-le en passant la chaîne d’entrée à quelque chose qui accepte une chaîne HTML: une nouvelle variable temporaire HTMLDocument
. Ceci est créé par la méthode DOMParser
’s parseFromString
; à la fin nous lisons sa documentElement
’s textContent
:
string = new DOMParser().parseFromString(string, "text/html").documentElement.textContent;
Si vous souhaitez utiliser cela, choisissez l'une des approches ci-dessus, selon que vous souhaitez ou non remplacer les attributs HTML et les propriétés DOM en plus du texte; remplacez simplement le commentaire // Handle `string` — see the last section
par la ligne ci-dessus.
Vous pouvez maintenant utiliser replaceOnDocument(/Güterzug/g, "Güter­zug");
.
NB: Si vous n’utilisez pas le code de traitement de chaîne, vous pouvez également supprimer le {
}
autour du corps de la flèche.
Notez que ceci analyse les entités HTML mais n'autorise toujours pas l'insertion de balises HTML réelles, car nous ne lisons que la variable textContent
. Ceci est également sûr contre la plupart des cas de xss : puisque nous utilisons parseFromString
et que la page document
n’est pas affectée, aucun <script>
n’est téléchargé et aucun gestionnaire onerror
ne s’exécute.
Vous devriez également envisager d'utiliser \xAD
au lieu de ­
directement dans votre chaîne JavaScript, si cela s'avère plus simple.
En javascript sans utiliser jquery
document.body.innerText.replace('actualword', 'replacementword');
Pour chaque élément du document body
, modifiez son texte à l'aide de la fonction .text (fn).
$("body *").text(function() {
return $(this).text().replace("x", "xy");
});
Utiliser la méthode split and join
$("#idBut").click(function() {
$("body").children().each(function() {
$(this).html($(this).html().split('@').join("$"));
});
});
voici solution
Le mieux serait d’effectuer cette opération côté serveur ou d’envelopper les symboles monétaires dans un élément que vous pouvez sélectionner avant de le renvoyer au navigateur. Toutefois, si aucune option n’est proposée, vous pouvez sélectionner tous les nœuds de texte dans le corps et les remplacer . Ci-dessous, je le fais à l'aide d'un plug-in que j'ai écrit il y a 2 ans et qui était destiné à mettre en évidence du texte. Ce que je fais est de trouver toutes les occurrences de € et de l'envelopper dans une étendue avec le symbole de devise de classe, puis je remplace le texte de ces étendues.
(function($){
$.fn.highlightText = function () {
// handler first parameter
// is the first parameter a regexp?
var re,
hClass,
reStr,
argType = $.type(arguments[0]),
defaultTagName = $.fn.highlightText.defaultTagName;
if ( argType === "regexp" ) {
// first argument is a regular expression
re = arguments[0];
}
// is the first parameter an array?
else if ( argType === "array" ) {
// first argument is an array, generate
// regular expression string for later use
reStr = arguments[0].join("|");
}
// is the first parameter a string?
else if ( argType === "string" ) {
// store string in regular expression string
// for later use
reStr = arguments[0];
}
// else, return out and do nothing because this
// argument is required.
else {
return;
}
// the second parameter is optional, however,
// it must be a string or boolean value. If it is
// a string, it will be used as the highlight class.
// If it is a boolean value and equal to true, it
// will be used as the third parameter and the highlight
// class will default to "highlight". If it is undefined,
// the highlight class will default to "highlight" and
// the third parameter will default to false, allowing
// the plugin to match partial matches.
// ** The exception is if the first parameter is a regular
// expression, the third parameter will be ignored.
argType = $.type(arguments[1]);
if ( argType === "string" ) {
hClass = arguments[1];
}
else if ( argType === "boolean" ) {
hClass = "highlight";
if ( reStr ) {
reStr = "\\b" + reStr + "\\b";
}
}
else {
hClass = "highlight";
}
if ( arguments[2] && reStr ) {
reStr = reStr = "\\b" + reStr + "\\b";
}
// if re is not defined ( which means either an array or
// string was passed as the first parameter ) create the
// regular expression.
if (!re) {
re = new RegExp( "(" + reStr + ")", "ig" );
}
// iterate through each matched element
return this.each( function() {
// select all contents of this element
$( this ).find( "*" ).andSelf().contents()
// filter to only text nodes that aren't already highlighted
.filter( function () {
return this.nodeType === 3 && $( this ).closest( "." + hClass ).length === 0;
})
// loop through each text node
.each( function () {
var output;
output = this.nodeValue
.replace( re, "<" + defaultTagName + " class='" + hClass + "'>$1</" + defaultTagName +">" );
if ( output !== this.nodeValue ) {
$( this ).wrap( "<p></p>" ).parent()
.html( output ).contents().unwrap();
}
});
});
};
$.fn.highlightText.defaultTagName = "span";
})( jQuery );
$("body").highlightText("€","currency-symbol");
$("span.currency-symbol").text("$");
Comme vous utiliserez de toute façon jQuery, essayez:
https://github.com/cowboy/jquery-replacetext
Alors fais juste
$("p").replaceText("£", "$")
Cela semble bien faire de ne remplacer que du texte et de ne pas jouer avec d'autres éléments
str.replace(/replacetext/g,'actualtext')
Ceci remplace toutes les instances de replacetext
par actualtext
Semblable à la réponse de @ max-malik, mais sans utiliser jQuery, vous pouvez le faire avec document.createTreeWalker :
button.addEventListener('click', e => {
const treeWalker = document.createTreeWalker(document.body);
while (treeWalker.nextNode()) {
const node = treeWalker.currentNode;
node.textContent = node.textContent.replace(/@/g, '$');
}
})
<div>This is an @ that we are @ replacing.</div>
<div>This is another @ that we are replacing.</div>
<div>
<span>This is an @ in a span in @ div.</span>
</div>
<br>
<input id="button" type="button" value="Replace @ with $" />
Vous pouvez utiliser:
str.replace(/text/g, "replaced text");