网页素材设计--如何制作自动完成输入法

问题描述 投票:1回答:1

我使用谷歌的 网页素材设计. 我想用他们的 选择部件 作为一个自动完成组件。我的目标是 自动完成 你可以看到在反应mui。我已经删除了 disabledreadonly 输入属性,但我还是不能往输入栏里写东西。

<div class="mdc-select demo-width-class">
  <div class="mdc-select__anchor">
    <span class="mdc-select__ripple"></span>
    <input type="text" class="mdc-select__selected-text">
    <i class="mdc-select__dropdown-icon"></i>
    <span class="mdc-floating-label">Pick a Food Group</span>
    <span class="mdc-line-ripple"></span>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
    <ul class="mdc-list">
      <li class="mdc-list-item mdc-list-item--selected" data-value="" aria-selected="true"></li>
      <li class="mdc-list-item" data-value="grains">
        <span class="mdc-list-item__text">
          Bread, Cereal, Rice, and Pasta
        </span>
      </li>
      <li class="mdc-list-item" data-value="vegetables">
        <span class="mdc-list-item__text">
          Vegetables
        </span>
      </li>
      <li class="mdc-list-item" data-value="fruit">
        <span class="mdc-list-item__text">
          Fruit
        </span>
      </li>
    </ul>
  </div>
</div>

如何才能启用输入字段,让我写进输入字段,这样就能适应和制作一个自动完成的输入字段?

html material-design
1个回答
1
投票

既然你提到你想在不使用react的情况下看到一个答案,因此在普通的javascript中。我已经设法做到这一点。我已经结合了css和标记从 @Sifat Haque的答案和完整的自动完成逻辑。w3schools. 虽然看似简单,但要做到这一点还是挺麻烦的。

const select = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));

function autocomplete(inp, arr) {
   var currentFocus;
 
  inp.addEventListener("input", autocomp);
  inp.addEventListener("click", autocomp);

  inp.addEventListener("focus", autocomp);

  function autocomp(e) {
    var a, b, i, val = this.value;
    closeAllLists();
    currentFocus = -1;

    a = document.createElement("ul");
    a.setAttribute("id", this.id + "autocomplete-list");
    a.setAttribute("class", "autocomplete-items mdc-list");

    document.getElementById("autocomp").appendChild(a);

    for (i = 0; i < arr.length; i++) {
      if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase() || (val.trim()).length == 0) {
        b = document.createElement("li");
        b.setAttribute("class", "mdc-list-item")
        b.innerHTML = "<span class='mdc-list-item__text'>" + arr[i] + "</span>";
        b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";

        b.addEventListener("click", function(e) {
          inp.value = this.getElementsByTagName("input")[0].value;
          closeAllLists();
        });
        a.appendChild(b);
      }
    }
  }
  inp.addEventListener("keydown", function(e) {
    var x = document.getElementById(this.id + "autocomplete-list");
    if (x) x = x.getElementsByTagName("li");
    if (e.keyCode == 40) {
      currentFocus++;
      addActive(x);
    } else if (e.keyCode == 38) { //up
      currentFocus--;
      addActive(x);
    } else if (e.keyCode == 13) {
      e.preventDefault();
      if (currentFocus > -1) {
        if (x) x[currentFocus].click();
      }
    }
  });

  function addActive(x) {
    if (!x) return false;
    removeActive(x);
    if (currentFocus >= x.length) currentFocus = 0;
    if (currentFocus < 0) currentFocus = (x.length - 1);
    x[currentFocus].classList.add("autocomplete-active");
    x[currentFocus].classList.add("mdc-list-item--selected");
  }

  function removeActive(x) {
    for (var i = 0; i < x.length; i++) {
      x[i].classList.remove("autocomplete-active");
      x[i].classList.remove("mdc-list-item--selected");
    }
  }

  function closeAllLists(elmnt) {
    var x = document.getElementsByClassName("autocomplete-items");
    for (var i = 0; i < x.length; i++) {
      if (elmnt != x[i] && elmnt != inp) {
        x[i].parentNode.removeChild(x[i]);
      }
    }
  }

}

/*An array containing all the foods :*/
var foods = ["fruit", "vegetables", "grains", "fries"];

/*initiate the autocomplete function on the "myInput" element, and pass along the foods array as possible autocomplete values:*/
autocomplete(document.getElementById("name-input"), foods);

function makeActive(element) {
  document.getElementById("name-input").focus();
  element.classList.add("mdc-select--focused");
  element.classList.add("mdc-select--activated")
}
* {
  box-sizing: border-box;
}

.autocomplete {
  position: relative;
  display: inline-block;
}

input {
  border: 1px solid transparent;
  background-color: #f1f1f1;
  padding: 10px;
  font-size: 16px;
}

input[type=text] {
  background-color: transparent;
  width: 100%;
  margin-left: -200px;
  margin-top: 30px;
  z-index: -2;
}

input[type=text]:active {
  border: none;
}

.autocomplete-items {
  position: absolute;
  border: 1px solid #d4d4d4;
  border-bottom: none;
  border-top: none;
  z-index: 99;
  /*position the autocomplete items to be the same width as the container:*/
  top: 100%;
  left: 0;
  right: 0;
  max-height: 200px;
  /*overflow-y: scroll; */
}

.autocomplete-items li {
  padding: 10px;
  cursor: pointer;
  background-color: #fff;
  border-bottom: 1px solid #d4d4d4;
}

.mdc-select__menu {
  margin-top: -30px;
  z-index: 1;
  height: 150px;
  box-shadow: none;
  background-color: transparent;
  overflow-x: hidden !important;
}
<!DOCTYPE html>
<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!DOCTYPE html>
  <html>

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <link href="https://unpkg.com/[email protected]/dist/material-components-web.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

    <script src="https://unpkg.com/[email protected]/dist/material-components-web.min.js"></script>

  </head>

  <body>


    <h2>Autocomplete</h2>

    <p>Start typing:</p>

    <!--Make sure the form has the autocomplete function switched off:-->

    <form autocomplete="off" action="" method="post">

      <div class="mdc-select" onclick="makeActive(this)">
        <div class="mdc-select__anchor demo-width-class">
          <i class="mdc-select__dropdown-icon"></i>
          <div class="mdc-select__selected-text"></div>
          <span class="mdc-floating-label">Pick a Food Group</span>
          <div class="mdc-line-ripple"></div>
          <input type="text" id="name-input" name="selectione">


        </div>
        <div class="mdc-select__menu mdc-menu mdc-menu-surface">
          <div class="autocomplete" id='autocomp' style="width:200px;">
          </div>
        </div>
      </div>

      <input type="submit">
    </form>

希望这能帮助你

编辑:增加了标准选择选项


0
投票

你需要把输入字段和选择一起组合起来,得到一个输入字段,然后写一些javascript来得到自动完成功能。你可以看看我的解决方案。

console.clear();
const select = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));

select.listen('MDCSelect:change', () => {
  alert(`Selected option at index ${select.selectedIndex} with value "${select.value}"`);
});
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link href="https://unpkg.com/[email protected]/dist/material-components-web.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <script src="https://unpkg.com/[email protected]/dist/material-components-web.min.js"></script>
</head>
<body>
  <div class="mdc-select">
  <div class="mdc-select__anchor demo-width-class">
    <i class="mdc-select__dropdown-icon"></i>
    <div class="mdc-select__selected-text"></div>
    <span class="mdc-floating-label">Pick a Food Group</span>
    <div class="mdc-line-ripple"></div>
  </div>

  <div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class">
    <ul class="mdc-list">
      <input type="text" class="mdc-list-item--selected mdc-text-field__input" id="name-input">
      <label for="name-input" class="mdc-floating-label">search....</label>
      <li class="mdc-list-item" data-value="grains">
        Bread, Cereal, Rice, and Pasta
      </li>
      <li class="mdc-list-item" data-value="vegetables">
        Vegetables
      </li>
      <li class="mdc-list-item" data-value="fruit">
        Fruit
      </li>
      
      <input type="hidden" name="input_name" value="input_value" class="my_mdc-select__value" />
    
    </ul>
  </div>
</div>


  


</body>
</html>

0
投票

我已经创建了一个演示,它有点做你想要的东西。它存在的两个问题是

  1. 用户需要点击两次(双击)才能输入数值(我不能让它在单次点击时工作)
  2. 的位置。label 重叠选定的值(即使在赋予其他类或动态样式后)

如果有谁有什么办法可以解决这些问题,欢迎提出自己的想法。 @Leff,你自己看起来是个有经验的人,你能解决这些问题吗?如果可以,请您解决,也请您给我们(我)指点迷津。

另外。我用过 jquery 在此代码中 如果你只想 vanilla javascript你可能要自己做或者找一个人做,因为我不是这方面的专家,但这是逻辑上的部分。你的主要问题似乎是 HTML 应该可以解决。下面是演示,看看对你有没有帮助。

// initialize
const select = new mdc.select.MDCSelect(document.querySelector('.mdc-select'));

// stop the original propagation so that input field remains editable
$('#food').on('click', (event) => {
  return false;
});

// Demo Data
const foodArr = ['Bread, Cereal, Rice, and Pasta', 'Vegetables', 'Fruit'];

// You'll have to use ajax here to get the data
$('#food').on('keyup', (event) => {

  //console.clear();
  let $this = $(event.currentTarget);
  let currValue = $this.val();

  let search = new RegExp(currValue, 'i'); // prepare a regex object // Your custom condition

  let matchArr = foodArr.filter(item => search.test(item)); //store the result in an array
  let $select = "";

  // check if array is empty
  if (matchArr.length > 0) {

    // map the elements of the array and create option html
    matchArr.forEach((item) => {

      $select += `<li class="mdc-list-item" data-value="${item}"> ${item}</li>`;

    })

  } else { // if array is empty, display no match

    $select += `<li class="mdc-list-item" id="no_match"> No match found!</li>`;

  }
  //console.log(matchArr);

  // if the data was selected before, unselect it
  $('.mdc-list-item--selected:first').attr({'data-value': ''});
  $('.mdc-list-item--selected:first').text('');
  $('.mdc-list-item--selected:not(:first)').removeClass('mdc-list-item--selected');

  // remove all previous option elements
  $('.mdc-list-item:not(.mdc-list-item--selected:first)').remove();

  // add new option elements
  $('.mdc-list-item--selected').after($select);

  // start the click function, so that dropdown doesn't close
  $this.click();
});

// When any option is selected, show it on input field
$(document).on('click', '.mdc-list-item:not(#no_match)', (event) => {
  
  let $this = $(event.currentTarget);
  $this.addClass('mdc-list-item--selected');
  
  $('.mdc-floating-label').addClass('mdc-floating-label--float-above');
  
  $('.mdc-select__anchor').addClass('demo-width-class mdc-ripple-upgraded')
  $('.mdc-line-ripple').addClass('mdc-line-ripple--active mdc-line-ripple--deactivating')
  $('.mdc-line-ripple').css({'transform-origin': '182px center'})
  
  $('#food').val($this.attr('data-value'));
  // return false;
  // event.stopImmediatePropagation()
});

// if clicked on no match, value of input field should be empty, alternatively you can also make option disabled
$(document).on('click', '#no_match', (event) => {
  
  $('#food').val('');
  
});
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>@sauhardnc</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <link href="https://unpkg.com/[email protected]/dist/material-components-web.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <script src="https://unpkg.com/[email protected]/dist/material-components-web.min.js"></script>
</head>

<body>
  <div class="mdc-select">
    <div class="mdc-select__anchor demo-width-class" style="width: 100%">
      <i class="mdc-select__dropdown-icon"></i>
      <input type="text" class="mdc-select__selected-text" id="food"></input>
      <!-- Give a unique id -->
      <!--<div contenteditable="true" class="mdc-select__selected-text" id="fruit"></div>-->
      <span class="mdc-floating-label">Pick a Food Group</span>
      <div class="mdc-line-ripple"></div>
    </div>

    <div class="mdc-select__menu mdc-menu mdc-menu-surface demo-width-class" style="width: 100%">
      <ul class="mdc-list">
        <li class="mdc-list-item mdc-list-item--selected" data-value="" aria-selected="true"></li>
        <li class="mdc-list-item" data-value="Bread, Cereal, Rice, and Pasta">
          Bread, Cereal, Rice, and Pasta
        </li>
        <li class="mdc-list-item" data-value="Vegetables">
          Vegetables
        </li>
        <li class="mdc-list-item" data-value="Fruit">
          Fruit
        </li>
      </ul>
    </div>
  </div>
</body>

</html>

0
投票

这是我能够实现的,希望对你的实现有所帮助。我没有完全实现过滤逻辑和所有,但能够同时输入输入和显示下拉。

const menuElement = document.querySelector(".mdc-menu");
// const menu = new mdc.menu.MDCMenu(menuElement);

const inputLabel = document.querySelector(".mdc-text-field");
const inputElem = inputLabel.querySelector("input");
const dropdownIcon = document.querySelector(".mdc-select__dropdown-icon");
let isMenuOpen = false;

inputLabel.addEventListener("click", () => {
  inputElem.focus();
  // menu.open = true;
  if (!isMenuOpen) {
    menuElement.classList.remove("list-menu-close");
    menuElement.classList.add("list-menu-open");
    dropdownIcon.classList.add("dropdown-icon-up");
  } else {
    menuElement.classList.remove("list-menu-open");
    menuElement.classList.add("list-menu-close");
    dropdownIcon.classList.remove("dropdown-icon-up");
  }
  isMenuOpen = !isMenuOpen;
});

inputElem.addEventListener("blur", () => {
  menuElement.classList.remove("list-menu-open");
  menuElement.classList.add("list-menu-close");
  dropdownIcon.classList.remove("dropdown-icon-up");
  isMenuOpen = false;
});

    <div class="dropdown-container">
      <label class="mdc-text-field mdc-text-field--filled">
        <span class="mdc-text-field__ripple"></span>
        <input
          class="mdc-text-field__input"
          type="text"
          aria-labelledby="my-label-id"
        />
        <i class="mdc-select__dropdown-icon"></i>
      </label>
      <div>
        <div class="mdc-menu mdc-menu-surface list-menu">
          <ul
            class="mdc-list"
            role="menu"
            aria-hidden="true"
            aria-orientation="vertical"
            tabindex="-1"
          >
            <li class="mdc-list-item" role="menuitem">
              <span class="mdc-list-item__text">A Menu Item</span>
            </li>
            <li class="mdc-list-item" role="menuitem">
              <span class="mdc-list-item__text">Another Menu Item</span>
            </li>
          </ul>
        </div>
      </div>
    </div>
.dropdown-container {
  position: relative;
}

.list-menu {
  position: absolute;
  top: 60px;
}

.list-menu-open {
  display: block;
  opacity: 1;
}

.list-menu-close {
  display: none;
  opacity: 0;
}

.dropdown-icon-up {
  transform: rotate(180deg) translateY(-5px);
}

© www.soinside.com 2019 - 2024. All rights reserved.