从输入字段中搜索一个术语并在没有值时将其重置,超过两个字符的单词有问题(包括延迟功能)

Search for a term from an input field and reset it if the is no value, problem with words with more than two character (delay function included)

我建立了一个输入字段来在我的问答页面上搜索一些关键字。我构建的系统不止于此,因为它还打开和关闭带有答案的 div(来自输入和其他不同的 HTML 标签),但我专注于输入字段.

首先是我的代码,然后是我的问题:

const searchfaq = $('#text-search');
const searchtarget = $(".nodisplay");
const htmltochange = searchtarget.map(function() {
  return $(this).children().find('p').html();
}).get();

function delay(callback, ms) {
  var timer = 0;
  return function() {
    var context = this,
      args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      callback.apply(context, args);
    }, ms || 0);
  };
}

searchfaq.keyup(delay(function(e) {
  let val = $(this).val().toLowerCase();
  searchtarget.hide();
  searchtarget.prev().children('.minus').removeClass('rotate');

  searchtarget.each(function(index) {
    let text = $(this).html().toLowerCase();
    let paragraph = $(this).children().find('p');
    let otherparagraph = searchtarget.children().find('p');

    if (text.indexOf(val) != -1) {
      $(this).show();
      $(this).prev().children('.minus').addClass('rotate');
      var re = new RegExp(val, 'gi');
      paragraph[0].innerHTML = htmltochange[index].replace(re, `<mark>$&</mark>`);
    }
    if (val.length === 0) {
      paragraph[0].innerHTML = htmltochange[index];
      $(this).hide();
      searchtarget.prev().children('.minus').removeClass('rotate');
    }
  });

}, 500));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="lazyblock-faq-search">
  <h1>Frequently Asked Questions</h1>
  <form _lpchecked="1">
    <input id="text-search" type="text" aria-label="search-for-answers" placeholder="Search for answers">
  </form>
</div>

<div class="lazyblock-faq">
  <div class="row">
    <aside class="col-md-3">
      <ul class="sticky-top">
        <li class="active">
          <a href="#chapter-1">Chapter 1</a>
        </li>
        <li class="">
          <a href="#chapter-2">Chapter 2</a>
        </li>
      </ul>
    </aside>
    <div class="question-and-answer col-md-9">
      <h2 id="chapter-1">Chapter 1</h2>
      <div class="single-faq">
        <h3>This is a question</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-Z2cLmzB">
            <div class="row">
              <div class="col-md-12">
                <p>This is the answer</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>This is a question 2</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-ZhBtAi">
            <div class="row">
              <div class="col-md-12">
                <p>This is the answer 2</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>Question 3 ?</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-ZPm3XU">
            <div class="row">
              <div class="col-md-12">
                <p>This is the answer 3</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <h2 id="chapter-2">Chapter 2</h2>
      <div class="single-faq">
        <h3>This is a question 4</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-1sQXGa">
            <div class="row">
              <div class="col-md-12">
                <p>This is just a test for question 4</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>This is a question 5</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-ZioRKT">
            <div class="row">
              <div class="col-md-12">
                <p>This is just a test for question 5</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>This is a quesition 6 and it has a weird layout</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-2fxKyB">
            <div class="row">
              <div class="col-md-12">
                <p>This is just a test for question 6</p>
              </div>
            </div>
          </div>

        </div>
      </div>
    </div>
  </div>
</div>

代码以这种方式工作。用户将在输入字段中插入一个字符串,并且将在 div 中使用 class 'no-display' 精确地在其 HTML 中搜索单词(我必须指定它因为,在原始代码中,特定的 div 内部将包含 HTML,而不仅仅是文本)。

该代码有两个注意事项:

  1. 我不得不添加一个延迟函数,因为出于某种原因,如果没有它,它只能用于前两个字符,然后它将无法找到任何其他单词。

  2. 连接到问题 1,如果您尝试在输入字段中插入另一个值(字符串),它不会在某种意义上正确重置,它将无法找到任何不同的词。让我们举个例子:我将插入单词 test,然后如果我试图从中删除一个单词,(string tes) 它仍然会将其包装在 mark 标记中的单词。但是,如果我在末尾再次添加字符 T,它将找不到带有单词 test 的 div,代码将失败。

  3. 此外,在重置为初始值(val.length === 0)之前,我会看到每个单词都包含在标签中。

这是一个错误还是我遗漏了什么?

对于 1) 和 2)(延迟无关)你的问题是你的比较 let text= 使用 current html,而不是原来的 htmltochange.

经过搜索,当前 html 现在有 <mark> 个标签。

因此,如果您搜索 " is ",您的 html 从 This is the 更改为 This<mark> is </mark>the - 当您搜索 " is the" 时,它不匹配在 <mark> is </mark>the.

而不是.html(),使用.text()获取没有标记的文本,然后它工作正常(至少那部分,没有检查其余部分,例如也改变原来的htmltochange).这也意味着你没有得到 false-positives,例如在你的原始代码中搜索“div”,“div”出现在每个答案的 html 中,所以他们都显示出来了。

  searchtarget.each(function(index) {
    let text = $(this).text().toLowerCase();
  1. resetting to the initial value (val.length === 0) will see every word wrapped in a tag

这是由于 if 的顺序 - 您的第一个 if 查找空白并突出显示它们,第二个然后隐藏它们。

颠倒顺序,使其首先检查 length===0,然后仅在不为 0 时才进行搜索。

已更新fiddle:

const searchfaq = $('#text-search');
const searchtarget = $(".nodisplay");
const htmltochange = searchtarget.map(function() {
  return $(this).children().find('p').text();
}).get();

function delay(callback, ms) {
  var timer = 0;
  return function() {
    var context = this,
      args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      callback.apply(context, args);
    }, ms || 0);
  };
}

searchfaq.keyup(delay(function(e) {
  let val = $(this).val().toLowerCase();
  //console.log(val)
  searchtarget.hide();
  searchtarget.prev().children('.minus').removeClass('rotate');

  searchtarget.each(function(index) {
    let text = $(this).text().toLowerCase();
    let paragraph = $(this).children().find('p');
    let otherparagraph = searchtarget.children().find('p');

    if (val.length === 0) {
      paragraph[0].innerHTML = htmltochange[index];
      $(this).hide();
      searchtarget.prev().children('.minus').removeClass('rotate');
    }
    else if (text.indexOf(val) != -1) {
      $(this).show();
      $(this).prev().children('.minus').addClass('rotate');
      var re = new RegExp(val, 'gi');
      paragraph[0].innerHTML = htmltochange[index].replace(re, `<mark>$&</mark>`);
    }
  });

}, 500));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="lazyblock-faq-search">
  <h1>Frequently Asked Questions</h1>
  <form _lpchecked="1">
    <input id="text-search" type="text" aria-label="search-for-answers" placeholder="Search for answers">
  </form>
</div>

<div class="lazyblock-faq">
  <div class="row">
    <aside class="col-md-3">
      <ul class="sticky-top">
        <li class="active">
          <a href="#chapter-1">Chapter 1</a>
        </li>
        <li class="">
          <a href="#chapter-2">Chapter 2</a>
        </li>
      </ul>
    </aside>
    <div class="question-and-answer col-md-9">
      <h2 id="chapter-1">Chapter 1</h2>
      <div class="single-faq">
        <h3>This is a question</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-Z2cLmzB">
            <div class="row">
              <div class="col-md-12">
                <p>This is the answer</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>This is a question 2</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-ZhBtAi">
            <div class="row">
              <div class="col-md-12">
                <p>This is the answer 2</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>Question 3 ?</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-ZPm3XU">
            <div class="row">
              <div class="col-md-12">
                <p>This is the answer 3</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <h2 id="chapter-2">Chapter 2</h2>
      <div class="single-faq">
        <h3>This is a question 4</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-1sQXGa">
            <div class="row">
              <div class="col-md-12">
                <p>This is just a test for question 4</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>This is a question 5</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-ZioRKT">
            <div class="row">
              <div class="col-md-12">
                <p>This is just a test for question 5</p>
              </div>
            </div>
          </div>

        </div>
      </div>
      <div class="single-faq">
        <h3>This is a quesition 6 and it has a weird layout</h3>
        <div class="icon-faq">
          <span class="minus">+</span>
          <span class="plus">–</span>
        </div>
        <div class="nodisplay collapse" style="display: none;">

          <div class="lazyblock-content " id="content-extra-2fxKyB">
            <div class="row">
              <div class="col-md-12">
                <p>This is just a test for question 6</p>
              </div>
            </div>
          </div>

        </div>
      </div>
    </div>
  </div>
</div>