突出显示搜索结果后 JavaScript 停止工作

问题描述 投票:0回答:2

我将一些简单搜索栏的代码与预定义的搜索词列表放在一起,以突出显示页面上与搜索匹配的单词。 一切正常,但是在单击搜索结果以突出显示页面上的单词后,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');
}

如果需要任何进一步的代码,请告诉我!

javascript html css
2个回答
0
投票

避免完全修改“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));
    });
}

0
投票

您正在替换代码中

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
}
© www.soinside.com 2019 - 2024. All rights reserved.