map
складывает в выходной массив результат переданной функции. Поскольку она у вас возвращает отфильтрованный массив items
, то в итоге у вас получается массив массивов items
. Если вам нужно, чтоб возвращались категории - возвращайте категории.reduce
: сonst filterData = filter(arr, input.value);
interface Category {
category: string;
list: Array<{
item: string;
}>;
}
function filter<T extends Category>(data: T[], value: string): T[] {
if (!value) return data.slice(); // или [] если при пустом value нужен пустой массив
value = value.toLowerCase();
return data.reduce((result, category) => {
if(category.category.toLowerCase().includes(value)) {
result.push(category);
} else {
const list = category.list.filter(({ item }) => item.toLowerCase().includes(value));
if (list.length) {
result.push({
...category,
list
});
}
}
return result;
}, [] as T[])
}
async
и await
, они здесь не нужны:const ApiServiceModule = {
get: <T>(url: string): Promise<T> => fetch(url)
.then(response => response.json())
.catch(err => console.error(err))
}
async
/await
всего лишь сахар над Promise
и в данном случае ничего не делают, т.к fetch
и так возвращает Promise
.this
. data binding
, которая будет заботится о таких вещах за тебя. Мне лично нравится Vue
, но есть и множество решений по-проще и по-традиционней.value
: const valueDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
Object.defineProperty(two, 'value', {
...valueDescriptor,
set(value) {
valueDescriptor.set.call(this, value);
this.dispatchEvent(new Event('input', {
bubbles: true,
cancelable: true,
}));
}
})
p
на span
или выбирать не сам тег, а его содержимое: selectNode
-> selectNodeContents
. width
задаётся в неких единицах измерения, а offsetWidth
возвращает просто число: border.style.width = link.offsetWidth + 'px';
let link = document.querySelector('#link');
let border = document.querySelector('#border');
new ResizeObserver(() => border.style.width = link.offsetWidth + 'px').observe(link);
document.activeElement
.function onInputFocus(){
console.log(this)
}
var inputs = document.getElementsByTagName('input');
for(var i = inputs.length; i--;)
inputs[i].addEventListener('focus', onInputFocus);
или, если нужна поддержка динамически добавленного: document.addEventListener('focus', function(event){
var target = event.target;
if(!target || target.tagName !== 'INPUT') return;
console.log(target)
}, true)
'0'
у undefined
значения, очевидно. В ошибке всё написано.'0'.
Нашли? undefined
). А уж разобраться почему он отсутствует - ваша задача.response.items[0]
items
отсутствует в response
items
из сырого необработанного Response
.let func = eval(userfunc);
func.call(arg);
let func = new Function('return ' + userfunc)();
func.call(arg);
let funcs = {
func1(){console.log('Функция вызвана!!!');};
};
funcs[userfunc].call(arg);
===
точное сравнение с учётом типа. clientWidth
- число, '769'
- строка, число никогда не равно строке. Уберите кавычки.clientWidth
точно будет равно числу с правой стороны. Вы уверены, что это именно то, что вам нужно? Возможно стоит использовать >=
или <=
?function get(value, str) {
for(const key of str.split('.')) {
if(value && key in value) value = value[key];
else return void 0;
}
return value;
}
arr.slice().sort((a,b) => get(b,proper) - get(a,proper));
var newArray = [];
for(var i = 0; i < list.length; i++) { // list - твой список ссылок
var link = list[i].href; // если в списке уже строки, а не элементы, то убрать .href
if(link.indexOf('#') === -1) { // если нет # в строке
newArray.push('определенный текст' + link.slice(5)); // берём определенный текст и добавляем к нему строку начиная с 5 символа
}
}