// при клике по кнопке определяем её индекс и хватаем .photos__like-count с таким же индексом
document.addEventListener('click', ({ target: t }) => {
if (t.classList.contains('photos__like-icon')) {
const index = [...document.querySelectorAll('.photos__like-icon')].indexOf(t);
const counter = document.querySelectorAll('.photos__like-count')[index];
const count = counter.textContent;
counter.textContent = t.classList.toggle('active') ? -~count : ~-count;
}
});
// но если у каждой пары icon-count если отдельный общий предок, то можно и попроще сделать
document.addEventListener('click', ({ target: t }) => {
if (t.matches('.photos__like-icon')) {
t
.closest('селектор общего предка кнопки и элемента с количеством')
.querySelector('.photos__like-count')
.textContent -= t.classList.toggle('active') ? -1 : 1;
}
});const toggleLike = function({ target: t }) {
this[t.dataset.index].innerText -= [ 1, -1 ][+t.classList.toggle('active')];
}.bind(document.querySelectorAll('.photos__like-count'));
document.querySelectorAll('.photos__like-icon').forEach((n, i) => {
n.dataset.index = i;
n.addEventListener('click', toggleLike);
});
// или, при наличии отдельных общих предков у каждой пары .photos__like-icon и .photos__like-count
const toggleLike = ({ target: t }) => t
.closest('селектор общего предка кнопки и элемента с количеством')
.querySelector('.photos__like-count')
.innerText -= t.classList.toggle('active') ? -1 : 1;
for (const n of document.querySelectorAll('.photos__like-icon')) {
n.addEventListener('click', toggleLike);
}
const Menu = ({ items }) =>
items instanceof Array && items.length
? <ul>
{items.map(n => (
<li key={n.id}>
<a>{n.title}</a>
<Menu items={n.children} />
</li>
))}
</ul>
: null;
const buttonSelector = '.arrowopen';.$(buttonSelector).click(e => $(e.currentTarget).prev().toggle());document.addEventListener('click', ({ target: t }) =>
(t = t.closest(buttonSelector)) &&
(t.previousElementSibling.hidden ^= 1)
);.hidden {
display: none;
}document.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => e.currentTarget.previousElementSibling.classList.toggle('hidden'));
function setAnimation(el) {
$(el).css('animation', `shadow-pulse ${1 + Math.random() * 3}s`);
}
$('.mr-2').on('animationend', function() {
$(this).css('animation', '');
setTimeout(setAnimation, 0, this);
}).get().forEach(setAnimation);
map.panTo(...).then(() => map.setZoom(...))
$('.search').on('input', function() {
const search = $(this).val().trim().toLowerCase();
$('.metro-line__item')
.hide()
.filter((i, n) => $('.metro__name', n).text().toLowerCase().includes(search))
.show();
$('.metro-line')
.show()
.not(':has(.metro-line__item:visible)')
.hide();
});.hidden {
display: none;
}document.querySelector('.search').addEventListener('input', e => {
const search = e.target.value.trim().toLowerCase();
document.querySelectorAll('.metro-line__item').forEach(n => {
const name = n.querySelector('.metro__name').textContent.toLowerCase();
n.classList.toggle('hidden', !name.includes(search));
});
document.querySelectorAll('.metro-line').forEach(n => {
n.classList.toggle('hidden', !n.querySelector('.metro-line__item:not(.hidden)'));
});
});
const className = 'класс, который не надо удалять';
// Если известно, что класс присутствует или должен быть добавлен в случае отсутствия:
element.className = className;
// Если известно, что класс отсутствует и не должен быть добавлен:
element.className = '';
// Если неизвестно, присутствует ли класс и в случае отсутствия он не должен быть добавлен:
element.className = element.classList.contains(className) ? className : '';
// или
element.classList.remove(...[...element.classList].filter(n => n !== className));
computed: {
fullData() {
return this.posts.map(post => ({
post,
user: this.users.find(user => user.id === post.userId) ?? {},
}));
},
},<div v-for="n in fullData">
<div>{{ n.post.title }}</div>
<div>{{ n.user.name }}</div>
<div>{{ n.post.body }}</div>
</div>
<input type="checkbox" v-model="sort">
<div v-for="dog in sortedDogs">data: () => ({
sort: false,
}),
computed: {
sortedDogs() {
return this.sort
? [...this.allDogs].sort((a, b) => a.breeds[0].name.localeCompare(b.breeds[0].name))
: this.allDogs;
},
},
function createTree(arr, structure) {
const tree = Object.fromEntries(arr.map(n => [ n.id, { ...n } ]));
const nonRootIds = new Set(structure.flatMap(n => n.children));
structure.forEach(n => tree[n.id].elements = n.children.map(m => tree[m]));
return Object.values(tree).filter(n => !nonRootIds.has(n.id));
}
v-model + watch:<input v-model="text">watch: {
text(newVal, oldVal) {
console.log(newVal, oldVal);
},
},
str.replace(/(\d)\1+/g, '$1')
// или
''.concat(...str.split(/(\d)\1+/))
// или
Array.from(str).filter((n, i, a) => Number.isNaN(+n) || a[~-i] !== n).join('')
// или
[...str.matchAll(/\D+|(\d)\1*/g)].reduce((acc, n) => acc + (n[1] ?? n[0]), '')