我将一些简单搜索栏的代码与预定义的搜索词列表放在一起,以突出显示页面上与搜索匹配的单词。 一切正常,但是在单击搜索结果以突出显示页面上的单词后,JavaScript 完全停止工作,直到页面刷新。这是代码片段。
function ShowSearchResults() {
FindSearchResults();
resultListContainer.style.display = 'block';
setTimeout(() => {
resultListContainer.style.transitionDuration = '300ms'
resultListContainer.style.opacity = '1';
}, 1);
}
function HideSearchResults() {
resultListContainer.style.transitionDuration = '500ms'
resultListContainer.style.opacity = '0';
setTimeout(() => {
resultListContainer.style.display = 'block';
}, 500);
}
function FindSearchResults(){
let result = [];
let input = searchInput.value;
if (input.length > 0){
result = searchTerms.filter((keyword) => {
return keyword.toLowerCase().includes(input.toLowerCase());
});
}
else{
result = searchTerms
}
DisplaySearchResults(result);
}
function DisplaySearchResults(result) {
const content = result.map((list) => {
return "<li>" + list + "</li>";
});
resultList.innerHTML = "<ul>" + content.join('') + "</ul>";
document.querySelectorAll('.result-list li').forEach((item) => {
item.addEventListener('click', function () {
const searchText = item.textContent;
highlightMatches(searchText);
scrollToFirstMatch(searchText);
});
});
}
function highlightMatches(searchText) {
clearHighlights();
const regex = new RegExp(searchText, 'gi');
const highlightedText = bodyText.replace(regex, (match) => {
return `<span class="highlight-span">${match}</span>`;
});
document.body.innerHTML = highlightedText;
searchInput.focus();
}
function scrollToFirstMatch(searchText) {
const firstMatch = document.querySelector('.highlight-span');
if (firstMatch) {
firstMatch.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
function clearHighlights() {
document.body.innerHTML = document.body.innerHTML.replace(/<span class="highlight-span">(.*?)<\/span>/g, '$1');
}
如果需要任何进一步的代码,请告诉我!
避免完全修改“document.body.innerHTML”。
function highlightMatches(searchText) {
clearHighlights();
const regex = new RegExp(searchText, 'gi');
// Recursive function to highlight text without replacing the entire
// innerHTML
walkAndHighlight(document.body, regex);
searchInput.focus();
}
function walkAndHighlight(node, regex) {
if (node.nodeType === 3) { // Text node
const matches = node.nodeValue.match(regex);
if (matches) {
const spanWrapper = document.createElement('span');
spanWrapper.innerHTML = node.nodeValue.replace(regex, (match) => `<span class="highlight-span">${match}</span>`);
node.replaceWith(spanWrapper);
}
} else if (node.nodeType === 1 && node.nodeName !== 'SCRIPT' && node.nodeName !== 'STYLE') {
// Recursively search child nodes
for (let i = 0; i < node.childNodes.length; i++) {
walkAndHighlight(node.childNodes[i], regex);
}
}
}
此函数的原因是为了确保突出显示的文本返回到其正常外观,而不会干扰 DOM 的其余部分。
function clearHighlights() {
document.querySelectorAll('.highlight-span').forEach(span => {
span.replaceWith(document.createTextNode(span.textContent));
});
}
您正在替换代码中
document
的内容。这意味着替换后的元素与之前不一样。这也意味着附加到它们的任何事件处理程序都不再工作。
要解决此问题,您需要再次运行能够附加事件处理程序的代码。您已经拥有此代码。将其移至额外函数并调用两次。
您可以像这样更新代码来解决问题:
// This function adds event handlers
function addEventhandlers() {
document.querySelectorAll('.result-list li').forEach((item) => {
item.addEventListener('click', function () {
const searchText = item.textContent;
highlightMatches(searchText);
scrollToFirstMatch(searchText);
});
});
}
function DisplaySearchResults(result) {
const content = result.map((list) => {
return "<li>" + list + "</li>";
});
resultList.innerHTML = "<ul>" + content.join('') + "</ul>";
addEventhandlers(); // This call replaces the old handlers
}
function highlightMatches(searchText) {
clearHighlights();
const regex = new RegExp(searchText, 'gi');
const highlightedText = bodyText.replace(regex, (match) => {
return `<span class="highlight-span">${match}</span>`;
});
document.body.innerHTML = highlightedText;
searchInput.focus();
addEventhandlers(); // This call is new
}