function filter(obj, key, f) {
const keys = Object.keys(obj);
return (obj[key] || []).reduce((acc, n, i) => (
f(n) && keys.forEach(k => acc[k].push(obj[k][i])),
acc
), keys.reduce((acc, k) => (acc[k] = [], acc), {}));
}
const result = filter(obj, 'years', n => 2012 <= n && n <= 2014);
function filter(obj, f) {
const keys = Object.keys(obj);
const length = keys.length && obj[keys[0]].length;
const result = Object.fromEntries(keys.map(k => [ k, [] ]));
for (let i = 0; i < length; i++) {
if (f(i, obj)) {
keys.forEach(k => result[k].push(obj[k][i]));
}
}
return result;
}
const result = filter(obj, (i, { years: { [i]: n } }) => 2012 <= n && n <= 2014);
const selector = '[type="tel"]';
const event = 'input';
const minLength = 10;
const classNames = [ 'какой-то класс', 'какой-то другой класс' ];
$(selector).on(event, function() {
const isLengthOK = $(this).val().length >= minLength;
$(this)
.toggleClass(classNames[0], !isLengthOK)
.toggleClass(classNames[1], isLengthOK);
});
document.querySelectorAll(selector).forEach(function(n) {
n.addEventListener(event, this);
}, ({ target: t }) => {
const isLengthOK = +(t.value.length >= minLength);
classNames.forEach((n, i) => t.classList.toggle(n, isLengthOK === i));
});
we can mark components asfunctional
, which means that they’re stateless (no reactive data) and instanceless (nothis
context)
- .dropdown__block.open {
+ .dropdown.open .dropdown__block {
const containerSelector = '.dropdown';
const buttonSelector = `${containerSelector} .dropdown__toggler`;
const activeClass = 'open';
// jquery, как вы и хотели
$(document).on('click', ({ target: t }) => {
const $container = $(t).closest(containerSelector);
const $button = $(t).closest(buttonSelector);
if ($button.length) {
$container.toggleClass(activeClass);
}
$(containerSelector).not($container).removeClass(activeClass);
});
// или, к чёрту jquery
document.addEventListener('click', ({ target: t }) => {
const container = t.closest(containerSelector);
const button = t.closest(buttonSelector);
if (button) {
container.classList.toggle(activeClass);
}
document.querySelectorAll(containerSelector).forEach(n => {
if (n !== container) {
n.classList.remove(activeClass);
}
});
});
.hidden {
display: none;
}
const itemSelector = '.item-service';
const className = 'hidden';
function toggleUntilNextItem(el) {
while ((el = el.nextElementSibling) && !el.matches(itemSelector)) {
el.classList.toggle(className);
}
}
document.querySelectorAll(itemSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => toggleUntilNextItem(e.currentTarget));
// или
document.addEventListener('click', e => {
const item = e.target.closest(itemSelector);
if (item) {
toggleUntilNextItem(item);
}
});
Object.entries(obj).filter(n => Number.isInteger(+n[0])).map(n => n[1]).join(';')
// или
Object.keys(obj).reduce((acc, n) => (`${+n}` === n && acc.push(obj[n]), acc), []).join(';')
// или
Array.from(obj).join(';')
// или
JSON.stringify(obj).match(/(?<="\d+":").*?(?=")/g).join(';')
$('.links').on('mouseover', 'a', function() {
$(this).closest('.block').find('img').attr('src', $(this).data('src'));
});
document.addEventListener('mouseover', ({ target: t }) => {
const { src } = t.dataset;
if (src) {
t.closest('.block').querySelector('img').src = src;
}
});
document.querySelectorAll('[data-src]').forEach(function(n) {
n.addEventListener('mouseenter', this);
}, ({ target: t }) => t
.parentNode
.parentNode
.nextElementSibling
.setAttribute('src', t.getAttribute('data-src'))
);
$('.open-category').click(function() {
$(`.d-none[data-id="${this.dataset.id}"]`).toggleClass('active');
});
for (const n of document.getElementsByClassName('open-category')) {
n.addEventListener('click', onClick);
}
function onClick({ target: { dataset: { id } } }) {
document.querySelector(`.d-none[data-id="${id}"]`).classList.toggle('active');
}
const elements = new Map(Array.from(
document.querySelectorAll('.open-category'),
n => [ n, document.querySelector(`.d-none[data-id="${n.dataset.id}"]`) ]
));
document.addEventListener('click', e => {
elements.get(e.target)?.classList.toggle('active');
});
идет смещение индексов, но как это обойти, уже не знаю
for (let i = arr.length; i--;) {
invItems.splice(arr[i], 1);
}
for (const n of [...arr].reverse()) {
invItems.splice(n, 1);
}
for (const [ i, n ] of arr.entries()) {
invItems.splice(n - i, 1);
}
invItems.splice(0, invItems.length, ...invItems.filter((n, i) => !arr.includes(i)));
let numDeleted = 0;
for (let i = 0; i < invItems.length; i++) {
invItems[i - numDeleted] = invItems[i];
numDeleted += i === arr[numDeleted];
}
invItems.length -= numDeleted;
async function fetchRecursive(arr) {
const result = [];
if (Array.isArray(arr)) {
for (const n of arr) {
try {
result.push({ status: true, result: await fetch(n.url).then(r => r.json()) });
} catch(error) {
result.push({ status: false, error });
}
result.push(...await fetchRecursive(n.children));
}
}
return result;
}
const flat = arr => (arr || []).flatMap(n => [ n.url, ...flat(n.children) ]);
const fetchRecursive = arr => Promise.allSettled(flat(arr).map(n => fetch(n).then(r => r.json())));
<div class="comment" data-id="187">
<a class="comment-edit">Редактировать</a>
<span class="comment-panel"></span>
</div>
.comment .comment-panel {
display: none;
}
.comment.editing .comment-panel {
display: inline;
}
.comment.editing .comment-edit {
color: red;
}
const containerSelector = '.comment';
const buttonSelector = '.comment-edit';
const activeClass = 'editing';
// вот вам ваш jquery
$(containerSelector).on('click', buttonSelector, e => {
const id = $(e.delegateTarget).toggleClass(activeClass).data('id');
console.log(id);
});
// или, к чёрту jquery
document
.querySelectorAll(`${containerSelector} ${buttonSelector}`)
.forEach(n => n.addEventListener('click', onClick));
function onClick() {
const container = this.closest(containerSelector);
container.classList.toggle(activeClass);
const { id } = container.dataset;
console.log(id);
}
document.querySelectorAll('.class-1').forEach(n => {
n.insertAdjacentHTML('afterbegin', `<div>${n.querySelector('span').dataset.name}</div>`);
});
$('.class-1').prepend(function() {
return $('<div>').text($('span', this).data('name'));
});
const onPlacemarkClick = e => {
const placemarkData = e.get('target').properties.get('placemarkData');
...
};
<Placemark
onClick={onPlacemarkClick}
properties={{
placemarkData: {
city: point.City,
address: point.Address,
...
},
...
}}
...
/>