Есть ли библиотека автозаполнения javascript, которая не зависит от каких-либо других библиотек?
Я не использую jQuery или подобных, поскольку я создаю мобильное приложение, которое мне нужно для обеспечения дополнительного освещения.
Есть ли библиотека автозаполнения javascript, которая не зависит от каких-либо других библиотек?
Я не использую jQuery или подобных, поскольку я создаю мобильное приложение, которое мне нужно для обеспечения дополнительного освещения.
Здесь - базовый пример JavaScript, который можно изменить в элемент управления автозаполнением:
var people = ['Steven', 'Sean', 'Stefan', 'Sam', 'Nathan'];
function matchPeople(input) {
var reg = new RegExp(input.split('').join('\\w*').replace(/\W/, ""), 'i');
return people.filter(function(person) {
if (person.match(reg)) {
return person;
}
});
}
function changeInput(val) {
var autoCompleteResult = matchPeople(val);
document.getElementById("result").innerHTML = autoCompleteResult;
}
<input type="text" onkeyup="changeInput(this.value)">
<div id="result"></div>
Для тех, кто смотрит на это в 2017 году, кому нужно простое решение, вы можете использовать встроенный <datalist>
HTML5 вместо того, чтобы полагаться на JavaScript.
Пример:
<datalist id="languages">
<option value="HTML">
<option value="CSS">
<option value="JavaScript">
<option value="Java">
<option value="Ruby">
<option value="PHP">
<option value="Go">
<option value="Erlang">
<option value="Python">
<option value="C">
<option value="C#">
<option value="C++">
</datalist>
<input type="text" list="languages">
Обратите внимание, что это не будет работать в Safari (по состоянию на апрель 2017 года).
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist
Ядром сценария автозаполнения будет аякс-вызов словаря терминов.
Я предполагаю, что ваше мобильное приложение уже включает функцию ajax, так что, может быть, вам лучше просто написать свой автозаполнение с нуля? В основном все, что вам нужно во входном теге, обработчик события keyup, который запускает вызов ajax, и div для сбора ответа.
[Обновление] Основываясь на комментариях, некоторые ссылки от John Resig blog:
Функция ES2016: Array.prototype.includes
без внешней библиотеки.
function autoComplete(Arr, Input) {
return Arr.filter(e =>e.toLowerCase().includes(Input.toLowerCase()));
}
Я исследовал это однажды вечером, и мое решение изначально было похоже на решение ES6 здесь, например:
return this.data.filter((option) => {
return option.first_name
.toString()
.toLowerCase()
.indexOf(this.searchTerms.toLowerCase()) >= 0
})
Но проблема в том, что он недостаточно надежен для фильтрации вложенных данных. Вы можете видеть, что он фильтрует this.data
с такой структурой данных:
[
{ first_name: 'Bob', },
{ first_name: 'Sally', },
]
Вы можете видеть его фильтрацию на основе this.searchTerms
после нижнего регистра как поискового термина, так и option.first_name
, но он слишком жесткий для поиска option.user.first_name
. Моя первоначальная попытка состояла в том, чтобы передать в поле для фильтрации, например:
this.field = 'user.first_name';
Но это включает в себя дикий, настраиваемый JavaScript для обработки чего-то вроде this.field.split('.')
и динамическую генерацию функции фильтра.
Вместо этого я вспомнил старую библиотеку, которую я использовал ранее, под названием fuse.js
, и она работает хорошо, потому что она не только обрабатывает случай произвольного вложения в то, что я только что назвал this.field
, но также обрабатывает нечеткое сопоставление на основе определенных порогов.
Проверьте здесь: https://fusejs.io/
[редактировать заметку]: я понимаю, что этот вопрос не требует никакой внешней библиотеки, но я хочу оставить этот пост здесь, так как он предоставляет смежные значения. Это не предназначено, чтобы быть "решением".
Вот как я сейчас его использую:
import Fuse from 'fuse.js';
const options = {
threshold: 0.3,
minMatchCharLength: 2,
keys: [this.field],
};
const fuse = new Fuse(this.data, options);
this.filteredData = fuse.search(this.searchTerms);
Чтобы лучше это понять, вам придется прочитать документацию по Fuse, но в целом вы можете видеть, что объект new Fuse()
создается с использованием данных для фильтрации и параметров.
Часть keys: [this.field]
важна, потому что там, где вы передаете ключи для поиска, вы можете передать их массив. Например, вы можете отфильтровать this.data
по keys: ['user.first_name', 'user.friends.first_name']
.
Я использую это в настоящее время в Vue JS, поэтому у меня есть вышеупомянутая логика внутри функции экземпляра watch
, поэтому каждый раз, когда изменяется this.searchTerms
, эта логика запускается и обновляет this.filteredData
, который помещается в мой выпадающий список в моем компоненте автозаполнения.
Кроме того, извините, я только что понял, что этот вопрос специально говорит без внешней библиотеки, но я все равно опубликую его, потому что я нахожу этот вопрос каждый раз, когда делаю автозаполнение ES6 в Vue JS или React JS. Я думаю, что очень важно иметь строгое или нечеткое сопоставление и поддерживать произвольно вложенные данные. Основанный на пакетном анализаторе Webpack, fuse.js
имеет размер 4,1 КБ в сжатом виде, поэтому он достаточно мал, поскольку может поддерживать "все" требования фильтрации на стороне клиента.
Если вы ограничены в своих возможностях использовать внешние библиотеки, рассмотрите мой первый пример кода. Это работает, если ваша структура данных статична, и вы можете легко изменить option.first_name
на что-то вроде option[this.field]
, если вы хотите варьировать искомое поле (т.е. если ваши объекты всегда плоские).
Вы также можете варьировать список для поиска. Попробуйте что-то вроде этого:
const radicalFilter = ({ list, field, searchTerms }) => {
return list.filter((option) => {
return option[field]
.toString()
.toLowerCase()
.indexOf(searchTerms.toLowerCase()) >= 0
})
}
radicalFilter({
list: [{ first_name: 'Bob' }, { first_name: 'Sally' }],
field: 'first_name',
searchTerms: 'bob',
})
Я сделал это один раз, отправив запрос JSON на сервер и используя код Python для выполнения автозаполнения. Он был немного медленным, но он сохранил передачу тонны данных.