строке - поиск и замена текста javascript




Найти и заменить определенные текстовые символы в документе с помощью JS (8)

ECMAScript 2015+ подход

Подводные камни при решении этой задачи

Это кажется легкой задачей, но вы должны позаботиться о нескольких вещах:

  • Простая замена всего HTML убивает все функциональные возможности DOM, такие как прослушиватели событий
  • Замена HTML также может заменить содержимое <script> или <style> , а также теги или атрибуты HTML, что не всегда желательно
  • Изменение HTML может привести к атаке xss
  • Вы также можете заменить такие атрибуты, как title и alt (контролируемым образом)

xss от xss атак, как правило, не может быть решена с помощью следующих подходов Например, если вызов fetch считывает URL-адрес где-то на странице, а затем отправляет запрос на этот URL-адрес, приведенные ниже функции не остановят это, поскольку этот сценарий по своей сути небезопасен.

Замена текстового содержимого всех элементов

Это в основном выбирает все элементы, которые содержат нормальный текст, проходит через их дочерние узлы - среди них также текстовые узлы -, ищет эти текстовые узлы и заменяет их содержимое.

При желании вы можете указать другую корневую target , например replaceOnDocument(/€/g, "$", { target: someElement }); ; по умолчанию выбрано <body> .

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

Замена текстовых узлов, атрибутов элементов и свойств

Теперь это немного сложнее: вам нужно проверить три случая: является ли узел текстовым узлом, следует ли заменить его элемент и его атрибут или же следует заменить элемент и его свойство . Объект- replacer предоставляет методы для текстовых узлов и для элементов.

Перед заменой атрибутов и свойств заменителю необходимо проверить, имеет ли элемент соответствующий атрибут; в противном случае новые атрибуты создаются нежелательно. Также необходимо проверить, является ли целевое свойство строкой, поскольку можно заменить только строки, или же свойство соответствия целевому атрибуту не является функцией, поскольку это может привести к атаке xss .

В приведенном ниже примере вы можете увидеть, как использовать расширенные функции: в необязательном третьем аргументе вы можете добавить свойство attrs и свойство props, каждое из которых является итеративным (например, массивом), для заменяемых атрибутов и свойства для замены соответственно.

Вы также заметите, что этот фрагмент использует flatMap . Если это не поддерживается, используйте полифилл или замените его конструкцией Reduce-Concat или Map-Reduce-Concat, как показано в связанной документации.

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

Замена сущностями HTML

Если вам нужно, чтобы он работал с такими объектами HTML, как &shy; вышеуказанные подходы буквально приведут к появлению строки &shy; , поскольку это сущность HTML и будет работать только при назначении .innerHTML или при использовании связанных методов.

Итак, давайте решим это, передав входную строку чему-то, что принимает строку HTML: новый, временный HTMLDocument . Это создается методом DOMParser parseFromString ; в конце мы читаем textContent его documentElement :

string = new DOMParser().parseFromString(string, "text/html").documentElement.textContent;

Если вы хотите использовать это, выберите один из подходов выше, в зависимости от того, хотите ли вы заменить атрибуты HTML и свойства DOM в дополнение к тексту; затем просто замените комментарий // Handle `string` — see the last section вышеупомянутой строкой.

Теперь вы можете использовать replaceOnDocument(/Güterzug/g, "G&uuml;ter&shy;zug"); ,

NB. Если вы не используете код обработки строк, вы также можете удалить { } вокруг тела функции стрелки.

Обратите внимание, что это анализирует сущности HTML, но по-прежнему не позволяет вставлять фактические теги HTML, поскольку мы читаем только textContent . Это также безопасно в большинстве случаев xss : поскольку мы используем parseFromString и document страницы не затрагивается, не загружается <script> и не onerror обработчик onerror .

Вам также следует рассмотреть возможность использования \xAD вместо &shy; непосредственно в вашей строке JavaScript, если это окажется проще.

Мне интересно, есть ли легкий способ, которым я мог бы использовать JavaScript или jQuery, чтобы вынюхивать определенный текстовый символ в документе; скажи и найди все экземпляры этого персонажа. А потом! Напишите возможность заменить все экземпляры этого слова, скажем, $ .

Я нашел этот фрагмент для начала:

var str = 'test: &#39;';

str = str.replace(/&#39;/g, "'");

По существу; Я хочу решение для одностраничного документа. Возьмите все экземпляры X и сделайте его XY. Только текстовые символы.


В JavaScript без использования JQuery

document.body.innerText.replace('actualword', 'replacementword');

Используйте метод split и join

$("#idBut").click(function() {
    $("body").children().each(function() {
        $(this).html($(this).html().split('@').join("$"));
    });
});

вот solution


Как насчет этого, заменив @ на $ :

$("body").children().each(function () {
    $(this).html( $(this).html().replace(/@/g,"$") );
});

http://jsfiddle.net/maximua/jp96C/1/


Мое собственное предложение заключается в следующем:

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,'€');
}

JS Fiddle demo .

Функция nativeSelector() на ответе (опубликованном Anurag ) на этот вопрос: эквивалент getElementsByTagName () для textNodes .


Подобно ответу @ max-malik, но без использования jQuery, вы также можете сделать это с помощью 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 $" />


Ты можешь использовать:

str.replace(/text/g, "replaced text");

str.replace(/replacetext/g,'actualtext')

Это заменяет все экземпляры replacetext actualtext





jquery