1, review

In the jQuery version, we have developed the homepage search function and news recommendation function. The next step is to improve the search function. The original search function only contains fuzzy queries, so we need to add two more search modes: Full-text index and custom word segmentation query, which is divided into TFIDF and Bayes query, also need to provide the lift sort option, of course, we also need to develop the page function, OK, next to do ~

2. Improve the home page

1. Develop search options

Open index.html, put the code for the search options between the search box and the search results, and set some options to be selected by default. Our default search mode is switched to a custom query. The sort field is TFIDF, so put checked properties on them

<! -- Search options Settings -->
<div class="search-options">
  <span>Search mode:</span>
  <label for="fuzzy">
    <input type="radio" name="searchMode" id="fuzzy" value="fuzzy">Fuzzy query</label>
  <label for="fulltext">
    <input type="radio" name="searchMode" id="fulltext" value="fulltext">The full text indexing</label>
  <label for="custom">
    <input type="radio" name="searchMode" id="custom" value="custom" checked>Custom query</label>
</div>
<div class="search-options">
  <span>Sort field:</span>
  <label for="tfidf">
    <input type="radio" name="orderBy" id="tfidf" value="tfidf" checked>tfidf
  </label>
  <label for="bayes">
    <input type="radio" name="orderBy" id="bayes" value="bayes">bayes
  </label>
</div>
<div class="search-options">
  <span>Search results sorted by:</span>
  <label for="asc">
    <input type="radio" name="order" id="asc" value="asc">ascending</label>
  <label for="desc">
    <input type="radio" name="order" id="desc" value="desc" checked>Descending order</label>
</div>
Copy the code

Corresponding styles:

.search-options {
  padding: 0 15px;
  margin-bottom: 5px;
  font-size: 14px;
}
Copy the code

Effect:

Note that the value of the name attribute for the same set of options must be set to the same value

Then start writing js, first getting the value of the selected option

// Get the search options
let searchMode = $('input[name="searchMode"]:checked').val()
let orderBy = $('input[name="orderBy"]:checked').val()
let order = $('input[name="order"]:checked').val()
Copy the code

Then we have to switch the URL according to the search mode, and if else is less elegant and less extensible, so we use the object:

// Background interface path
let searchUrl = {
  // Fuzzy query
  fuzzy: 'http://localhost:8080/demo/article-fuzzy'.// Full-text index
  fulltext: 'http://localhost:8080/demo/article-fulltext'.// Custom participles
  custom: 'http://localhost:8080/demo/article-custom'
}
Copy the code

Add pageNumber, pageSize, Order by, order by, of course, Order is used for custom segmentation queries. It is not used for other queries, so it is ok to pass it

$.ajax({
  url: searchUrl[searchMode],
  method: 'get'.data: {
    word: word,
    pageNumber: 1.pageSize: 10.orderBy: orderBy,
    order: order
  },
  success: function (result) {
    // ...}})Copy the code

Then you can test, all three are ok ~

But when switching search mode to search again, there is a problem!

The reason for this problem is that the template has been replaced. The following code does not report an error, but gets undefined

let template = $('#search-result-template').html();
Copy the code

So let’s just put it outside and make it a global variable

let searchResultTemplate = $('#search-result-template').html();
let resultInfoTemplate = $('#real-tips').html();
Copy the code

And then it’s OK

Final code:

// Initialize the mode box
let modal = new Modal({
  width: 300.height: 200.title: "Tip".text: "Ongoing search..."
});
modal.init();

// Background interface path
let searchUrl = {
  // Fuzzy query
  fuzzy: 'http://localhost:8080/demo/article-fuzzy'.// Full-text index
  fulltext: 'http://localhost:8080/demo/article-fulltext'.// Custom participles
  custom: 'http://localhost:8080/demo/article-custom'
}

// Search the callback function
function search() {
  // Get the input value of the search box and remove the first and last Spaces
  let word = $('#search-input').val().trim();
  // The keyword is empty or blank
  if (word === "") {
    // Prompt the user to enter keywords before searching
    alert('What are you looking for, dear?');
    return;
  }

  // Get the search options
  let searchMode = $('input[name="searchMode"]:checked').val()
  let orderBy = $('input[name="orderBy"]:checked').val()
  let order = $('input[name="order"]:checked').val()

  // Display the mode box
  modal.show();
  // Make a network request to invoke the back-end search interface
  $.ajax({
    url: searchUrl[searchMode],
    method: 'get'.data: {
      word: word,
      pageNumber: 1.pageSize: 10.orderBy: orderBy,
      order: order
    },
    success: function (result) {
      console.log(result)

      let html = ' ';
      let baseUrl = "news-view.html? id=";
      result.list.forEach(function (item) {
        html += searchResultTemplate.replace('{url}', baseUrl + item.id)
          .replace('{title}', item.title); $(})'#search-result').html(html);

      // Render the search result information
      let tips = resultInfoTemplate.replace('{word}', word)
        .replace('{duration}', result.duration)
        .replace('{size}', result.size);
      $('#tips').html(tips);

      // Hide the mode box
      modal.hide()
    }
  })
}

// Search for related functions
let searchResultTemplate = $('#search-result-template').html();
let resultInfoTemplate = $('#real-tips').html();
$('#search-btn').click(search);
$('#search-input').keyup(function (e) {
  if (e.code === "NumpadEnter" || e.code === "Enter") { search(); }})Copy the code

2. Develop paging

Now there is still a paging, for convenience, this time I will not hand tear, directly online to find the plug-in, after looking for a wave of transformation, now, I put it into jK-paging, including style and logic files, directly introduced in the home page ~ then you can start to use ~

Usage:

Create a new TAB on the page

<! - page - >
<div id="page"></div>
Copy the code

Use it in the Success callback for Ajax

// Render a new page
new Paging("page", {
  nowPage: currentPage, // Current page number
  pageNum: result.size, / / total page number
  buttonNum: 5.// Number of pages to display
  canJump: 0.// Whether it can jump. 0: do not display (default), 1: display
  showOne: 0.// If only one page is displayed. 0: no display,1: display (default)
  callback: function (num) {
    // The callback function after clicking the button}});Copy the code

Each successful request rerenders the page. To do this, we need to set the current page number and the page number clicked by the user to global variables

let currentPage = 1;
let pageNumber = 1;
Copy the code

Then modify the data in Ajax:

data: {
  word: word,
  pageNumber: pageNumber, // The number of pages the user clicked on
  pageSize: 10.orderBy: orderBy,
  order: order
},
Copy the code

In the callback function after the button is clicked, we’re going to update the current page number and the page number that the user clicked on, and then we’re going to call the search function, which may be a little confusing here, so let’s just read it a few more times

// Re-render paging
new Paging("page", {
  nowPage: currentPage, // Current page number
  pageNum: result.pages, / / total page number
  buttonNum: 5.// Number of pages to display
  canJump: 0.// Whether it can jump. 0: do not display (default), 1: display
  showOne: 0.// If only one page is displayed. 0: no display,1: display (default)
  callback: function (num) {
    // Update the page number that the user clicked on
    pageNumber = num
    // Update current page number
    currentPage = pageNumber
    search()
  },
});
Copy the code

Then there you go:

However, when the search option is switched, there is a bug that the page does not reset, so we need to improve it by resetting the current page number and the page number clicked by the user whenever the search option changes

// Check whether the search options have changed. If so, both the current page number and the page number the user clicked on will be reset
if(searchMode ! == globalSearchMode || orderBy ! == globalOrderBy || order ! == globalOrder) { currentPage =1;
  pageNumber = 1;
}
Copy the code

Global **** is a global variable, so we need to create three new global variables to store the search options for each search. Of course, we can combine them into objects, but I’ll use the former

let globalSearchMode, globalOrderBy, globalOrder;
Copy the code

or

let globalSearchOptions = {  globalSearchMode: ' '.globalOrderBy: ' '.globalOrder: ' '}
Copy the code

Now the bug is solved

When the keyword changes, the page is not reset, so we need to improve the judgment

Add a global variable globalKeyWord to store the keyword

let globalSearchMode, globalOrderBy, globalOrder, globalKeyword;
Copy the code

Increase the judgment of keywords

// Store the search options for comparison on the next search
globalSearchMode = searchMode;
globalOrderBy = orderBy;
globalOrder = order;
globalKeyword = word;
Copy the code

Search the storage keyword to globalKeyWord

// Store the search options so that you can compare them to globalSearchMode = searchMode next time; globalOrderBy = orderBy; globalOrder = order; globalKeyword = word;
Copy the code

Complete code:

html:

<! DOCTYPEhtml>
<html lang="zh-CN">
<head>
 <meta charset="UTF-8">
 <title>News Recommendation system</title>
 <link rel="stylesheet" href="css/normalize.css">
 <link rel="stylesheet" href="jk-modal/jk-modal.css">
 <link rel="stylesheet" href="jk-paging/jk-paging.css">
 <link rel="stylesheet" href="css/index.css">
 <script src="js/jQuery.js"></script>
 <script src="jk-modal/jk-modal.js"></script>
 <script src="jk-paging/jk-paging.js"></script>
 <script src="js/common.js"></script>

</head>
<body>
<! -- Page container -->
<div id="app">
 <! - the head -- -- >
 <div class="header">
  <h3 class="header-title">NewsDemo</h3>
 </div>

 <! - main body - - >
 <div class="main clearfix">

  <! - the left column -- -- >
  <div class="main-left">
   <! -- Search box -->
   <div class="search">
    <label>
     <input id="search-input" type="text" class="search-input">
    </label>
    <button id="search-btn" class="search-btn">search</button>
   </div>

   <! -- Search options Settings -->
   <div class="search-options">
    <span>Search mode:</span>
    <label for="fuzzy">
     <input type="radio" name="searchMode" id="fuzzy" value="fuzzy">Fuzzy query</label>
    <label for="fulltext">
     <input type="radio" name="searchMode" id="fulltext" value="fulltext">The full text indexing</label>
    <label for="custom">
     <input type="radio" name="searchMode" id="custom" value="custom" checked>Custom query</label>
   </div>
   <div class="search-options">
    <span>Sort field:</span>
    <label for="tfidf">
     <input type="radio" name="orderBy" id="tfidf" value="tfidf" checked>tfidf
    </label>
    <label for="bayes">
     <input type="radio" name="orderBy" id="bayes" value="bayes">bayes
    </label>
   </div>
   <div class="search-options">
    <span>Search results sorted by:</span>
    <label for="asc">
     <input type="radio" name="order" id="asc" value="asc">ascending</label>
    <label for="desc">
     <input type="radio" name="order" id="desc" value="desc" checked>Descending order</label>
   </div>

   <p id="tips" class="tips">
    <template id="real-tips">Search keywords:<span>{word}</span>And time consuming:<span>{duration}</span>Milliseconds, return:<span>{size}</span>news</template>
   </p>

   <div class="container">
    <h3 class="news-list-title">The search results</h3>
    <ul id="search-result">
     <template id="search-result-template">
      <li class="news-list-item">
       <a href="{url}" target="_blank">
        {title}
       </a>
      </li>
     </template>
    </ul>
   </div>

   <! - page - >
   <div id="page"></div>
  </div>

  <! -- > - the right hand column
  <div class="main-right">
   <div class="container">
    <h3 class="news-list-title">The news is recommended</h3>
    <ul id="recommend-result">
     <template id="recommend-result-template">
      <li class="news-list-item">
       <a href="{url}" target="_blank">
        {title}
       </a>
      </li>
     </template>
    </ul>
   </div>
  </div>
 </div>
 <! - the footer - >
 <div class="footer">
  <p>Copyright 2021-2077 Jack All rights reserved.</p>
 </div>
</div>
<script src="js/index.js"></script>
</body>
</html>
Copy the code

js:

// Initialize the mode box
let modal = new Modal({
  width: 300.height: 200.title: "Tip".text: "Ongoing search..."
});
modal.init();

// Background interface path
let searchUrl = {
  // Fuzzy query
  fuzzy: 'http://localhost:8080/demo/article-fuzzy'.// Full-text index
  fulltext: 'http://localhost:8080/demo/article-fulltext'.// Custom participles
  custom: 'http://localhost:8080/demo/article-custom'
}

// Search the callback function
function search() {
  // Get the input value of the search box and remove the first and last Spaces
  let word = $('#search-input').val().trim();
  // The keyword is empty or blank
  if (word === "") {
    // Prompt the user to enter keywords before searching
    alert('What are you looking for, dear?');
    return;
  }

  // Get the search options
  let searchMode = $('input[name="searchMode"]:checked').val()
  let orderBy = $('input[name="orderBy"]:checked').val()
  let order = $('input[name="order"]:checked').val()

  // Compare keywords and search options. If so, the current page number and the page number the user clicked on should be reset
  if(word ! == globalKeyword || searchMode ! == globalSearchMode || orderBy ! == globalOrderBy || order ! == globalOrder) { currentPage =1;
    pageNumber = 1;
  }

  // Display the mode box
  modal.show();
  // Make a network request to invoke the back-end search interface
  $.ajax({
    url: searchUrl[searchMode],
    method: 'get'.data: {
      word: word,
      pageNumber: pageNumber,
      pageSize: 10.orderBy: orderBy,
      order: order
    },
    success: function (result) {
      // Render search results
      let html = ' ';
      let baseUrl = "news-view.html? id=";
      result.list.forEach(function (item) {
        html += searchResultTemplate.replace('{url}', baseUrl + item.id)
          .replace('{title}', item.title); $(})'#search-result').html(html);

      // Render the search result information
      let tips = resultInfoTemplate.replace('{word}', word)
      .replace('{duration}', result.duration)
      .replace('{size}', result.size);
      $('#tips').html(tips);

      // Re-render paging
      new Paging("page", {
        nowPage: currentPage, // Current page number
        pageNum: result.pages, / / total page number
        buttonNum: 5.// Number of pages to display
        canJump: 0.// Whether it can jump. 0: do not display (default), 1: display
        showOne: 0.// If only one page is displayed. 0: no display,1: display (default)
        callback: function (num) {
          // Update the page number that the user clicked on
          pageNumber = num;
          // Update current page numbercurrentPage = pageNumber; search(); }});// Store the search options for comparison on the next search
      globalSearchMode = searchMode;
      globalOrderBy = orderBy;
      globalOrder = order;
      globalKeyword = word;
      // Hide the mode box
      modal.hide()
    }
  })
}

// Search for related functions
let searchResultTemplate = $('#search-result-template').html();
let resultInfoTemplate = $('#real-tips').html();
let currentPage = 1;
let pageNumber = 1;
let globalSearchMode, globalOrderBy, globalOrder, globalKeyword;
$('#search-btn').click(search);
$('#search-input').keyup(function (e) {
  if (e.code === "NumpadEnter" || e.code === "Enter") { search(); }})Copy the code