У меня есть расширение 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"> '+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) это определенно не очень хорошая идея. Пожалуйста помоги.