Оптимизированный способ поиска всех вхождений текста через веб-страницу в JavaScript? - PullRequest
1 голос
/ 27 июня 2019

У меня есть расширение Chrome, которое выполняет поиск по веб-странице для поиска заданного массива строк. Если строка присутствует на веб-странице, она заменяется данным блоком HTML. До сих пор я искал строку только в тегах p (абзац). Но это не дает мне все вхождения строки. (некоторые размещаются в элементе div на некоторых веб-сайтах, некоторые имеют этот текст в теге h6).

Итак, я решил перебрать все возможные теги (p, h5, h2, h3, h6, h4, li, div), чтобы найти элемент. Вот где возникает проблема. Он просто отлично работает, когда я смотрю только на теги p, а веб-страница небольшого размера (около 2000-3000 слов). Но в целом браузер зависает, если я делаю такие тяжелые вещи со всеми тегами.

Вот мой код, и я ищу несколько хороших предложений по оптимизации.

Краткое описание того, что я сделал:

  • Итак, я получал данную строку как литерал объекта из хранилища Chrome.
  • Итерация объекта для каждого слова и извлечение элементов p со страницы.
  • Цикл по содержимому каждого элемента p, чтобы найти данное слово и заменить его чем-то.
  • Общий O (n ^ 2) только для тега p.

function isJson(item) {
  item = typeof item !== "string"
      ? JSON.stringify(item)
        : item;
  try {
      item = JSON.parse(item);
  } catch (e) {
      return false;
  }

  if (typeof item === "object" && item !== null) {
      return true;
  }
  return false;
}

function loop(elements, words) {
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    var text = element.innerHTML;
    for (k in words) {
      var ol = document.createElement('ol'); 
          ol.setAttribute("style", "padding: 15px !important; padding-right: 0px !important; margin: 0 auto !important;");
      if(isJson(words[k])){
        defObj = JSON.parse(words[k]);
        // console.log(defObj);
        for (var j = defObj["data"].length - 1; j >= 0; j--) {
          var li = document.createElement('li');
          li.setAttribute("style", "padding: 5px 0; color:white !important; font-weight: normal !important; list-style: decimal !important; font-size: 12px !important;  border-bottom: 1px solid #11998e !important;  margin: 0px !important; ");
          if (defObj["data"][j]["definition"]) {
            li.innerText = (defObj["data"][j]["wordtype"] ? defObj["data"][j]["wordtype"] : defObj["data"][j]["partOfSpeech"]) + ";  "+ defObj["data"][j]["definition"];
          }else{
            li.innerText =  defObj["data"][j]["translatedText"];
          }
          ol.appendChild(li);
        } 
      }else{
        var li = document.createElement('li');
        li.setAttribute("style", "padding: 5px 0; color:white !important; font-weight: normal !important; list-style: decimal !important; font-size: 12px !important;  border-bottom: 1px solid #11998e !important; margin: 0px !important; ");
        li.innerText = words[k];
        ol.appendChild(li);
      }

      // Create a dummy outer div and append the ol into it to get the DOM OL as text. 
      var tmp = document.createElement("div");
      tmp.appendChild(ol);
      // console.log(tmp.innerHTML); 
      var regex = new RegExp('(\\b)'+k+'(\\b)', 'ig');
      text = text.replace(regex, '<span class="dict-highlight">&nbsp;'+k.toLowerCase()+'</span> <div class="dict-tooltip">  <span class="dict-tooltiptext">'+tmp.innerHTML+'</span>  <img class="annotate-img" src="https://image.prntscr.com/image/ZShyfCKFTKKmXouhbBQ2Zw.png"></div>'); 
    }

    if (element.innerHTML !== text) {
        element.innerHTML = text;
    }
  }
}

// Add attribute to check weather extension is installed or not
body = document.getElementsByTagName("body");
body[0].setAttribute("data-dictozo-extension-installed", true);

chrome.storage.sync.get(null, function(result) {

  if (result) {
    var elementsP = document.getElementsByTagName('p');
    loop(elementsP, result);
    var elementsDIV = document.getElementsByTagName('div');
    loop(elementsDIV, result);
    var elementsH5 = document.getElementsByTagName('h5');
    loop(elementsH6, result);
    var elementsH6 = document.getElementsByTagName('h6');
    loop(elementsH6, result);
    var elementsLI = document.getElementsByTagName('li');
    loop(elementsLI, result);
  } 
}); 

Хотя поиск одного тега не показывает никаких признаков замедления, но для всех тегов (p, h5, h2, h3, h6, h4, li, div) это определенно не очень хорошая идея. Пожалуйста помоги.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...