Write a drop-down box that can realize fuzzy query through background interface (because layui.js does not meet the requirements).

Keywords: Javascript JSON git

Today, I encountered a problem that the fuzzy query function of the drop-down box of layui.js could not meet my needs, so I wrote a drop-down box myself.

In fact, the implementation idea is to imitate the pull-down box style of layui.js, and then listen to the input events. Once input, call the interface, and let the background return the data I found.

Let's go to the code:

html:

<form action="">
  <div class="box">
    <div class="select-container">
      <div class="select-title">
        <input type="text" class="select-search-input" />
        <i class="select-down select-icon"></i>
      </div>
      <ul class="select-items"></ul>
    </div>
  </div>
  <button class="submit" type="submit">Submission</button>
</form>

css:

body {
  background-color: #dcdbdb;
}
.box {
  width: 150px;
}
.select-container {
  position: relative;
}
.select-container > ul,
.select-container > ul li {
  list-style: none;
}
.select-container > .select-title {
  position: relative;
}
.select-container > .select-title > .select-search-input {
  height: 38px;
  border: 1px solid #e6e6e6;
  background-color: #ffffff;
  outline: none;
  border-radius: 2px;
  cursor: pointer;
  padding-left: 10px;
  padding-right: 22px;
  width: 100%;
  display: block;
  box-sizing: border-box;
}
.select-icon {
  position: relative;
  display: inline-block;
  vertical-align: middle;
  width: 0;
  height: 0;
  border-width: 6px;
  border-style: dashed;
  border-color: transparent;
  overflow: hidden;
}
.select-container > .select-title > .select-icon {
  position: absolute;
  right: 10px;
  top: 50%;
  cursor: pointer;
  border-top-color: #c2c2c2;
  border-top-style: solid;
  transition: all 0.3s;
  margin-top: -3px;
}
.select-container > .select-title > .select-up {
  margin-top: -9px;
  transform: rotate(180deg);
}
.select-container > .select-items {
  position: absolute;
  left: 0;
  top: 32px;
  padding: 5px 0;
  z-index: 899;
  min-width: 100%;
  border: 1px solid #d2d2d2;
  max-height: 300px;
  overflow-y: auto;
  background-color: #fff;
  border-radius: 2px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
  box-sizing: border-box;
}
.select-container > .select-items {
  display: none;
}
.select-container > .select-items .select-option {
  padding: 0 10px;
  line-height: 36px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: 0.5s all;
  background-color: #f2f2f2;
}
.select-container > .select-items .select-option:hover {
  background-color: #5fb878;
  color: #fff;
}
.select-container > .select-items > .select-this {
  background-color: #5fb878;
  color: #fff;
}

js:

 /*
 *  function:the ajax
 * params:interface url,request method,paramns,callback function
 */

function ewAjax(url, method, params, callback) {
  method = method.toUpperCase() === "GET" ? "GET" : "POST";
  var xhr = new XMLHttpRequest();
  if (method.toUpperCase() === "GET") {
    if (params) {
      url = url + params;
    }
    xhr.open(method, url);
    xhr.send();
  } else {
    if (typeof params === "string" && params) {
      xhr.open(method, url + "?" + params);
      xhr.send(JSON.stringify(params));
    } else if (params) {
      xhr.open(method, url);
      xhr.send(JSON.stringify(params));
    }
  }
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      callback(JSON.parse(xhr.responseText));
    }
  };
}

 /*
 *  function:Serialization parameters
 * params:params
 */

function ewParam(params) {
  var keys = Object.keys(params),
    key_len = keys.length;
  var str = "";
  for (var key in params) {
    str += key + "=" + params[key];
    if (key === keys[key_len - 1]) {
      break;
    } else {
      str += "&";
    }
  }
  return str;
}

 /*
 *  function:create the select component
 * params:params
 */

function createSelect(el1, el2, callback) {
  el1.oninput = function(e) {
    // get data
    ewAjax(url,"POST",ewParam({name: e.target.value}),function(res) {
        if (res.status === "200") {
          callback(res.data, el1, el2);
        }
      });
  };
}
var search_input = document.getElementsByClassName(
      "select-search-input"
    )[0],
    select_items = document.getElementsByClassName("select-items")[0];

  createSelect(search_input, select_items, function(data, el1, el2) {
    var li;
    if (data.length > 0) {
      el2.style.display = "block";
      el2.innerHTML = "";
      el1.nextElementSibling.classList.add("select-up");
    //   click the select arrow
      el1.nextElementSibling.onclick = function() {
        this.classList.toggle("select-up");
        if (this.className.indexOf("select-up") > -1) {
          el2.style.display = "block";
        } else {
          el2.style.display = "none";
        }
      };
      data.map(function(d, index) {
        li = document.createElement("li");
        // the value need to subbmit 
        li.setAttribute("data-value", d.id);
        // maybe you need to save the data by search
        li.setAttribute("data-info", JSON.stringify(d));
        li.textContent = d.name;
        li.className = "select-option";
        // the default select value
        if (index === 0) {
          li.classList.add("select-this");
        }
        li.onclick = function() {
          el2.style.display = "none";
          el1.value = this.textContent;
          el1.nextElementSibling.classList.remove("select-up");
        //change the value about submit the form data,so create a hidden input element
          var sm_input = document.createElement("input");
          sm_input.style.display = "none";
          sm_input.name = "name";
          sm_input.value = this.getAttribute("data-value");
          el1.parentElement.appendChild(sm_input);
        };
        el2.appendChild(li);
      });
    }
  });
  
  

In fact, the overall idea is not too difficult. It's just that when the background returns the data, the list will be displayed, and click events will be added to the list items. For this, add events to the drop-down arrows, and control the visibility of the list. Then there's nothing left. Share it, hoping to help people who can't start in the same situation as I met. Code uploaded to git source code , think it's good, hope to order a star, thank you.

Posted by daniel_lee_hill on Mon, 02 Dec 2019 09:27:12 -0800