const statsMeta = [
{ title: 'отредактированные', count: item => +item.edited },
{ title: 'неотредактированные', count: item => +!item.edited },
{ title: 'всего', count: () => 1 },
];
const statsData = allMessages.reduce((acc, n) => (
statsMeta.forEach((m, i) => acc[i] += m.count(n)),
acc
), Array(statsMeta.length).fill(0));
console.log(statsMeta.map((n, i) => `${n.title}: ${statsData[i]}`).join('\n'));
const classPrefix = 'modal--';
Array.from(el.classList).forEach(n => el.classList.toggle(n, !!n.indexOf(classPrefix)));
el.classList.remove(...[...el.classList].filter(n => n.startsWith(classPrefix)));
for (let i = el.classList.length; i--;) {
if (el.classList[i].search(classPrefix) === 0) {
el.classList.remove(el.classList[i]);
}
}
el.classList.value = el.classList.value
.split(' ')
.filter(RegExp.prototype.test.bind(RegExp(`^(?!${classPrefix})`)))
.join(' ');
el.className = el.className.replace(RegExp(`(^| )${classPrefix}\\S*`, 'g'), '').trim();
const result = arr2.map(function(n) {
return Object.fromEntries(this.map(m => [ m[1], n[m[0]] ]));
}, arr1.flatMap(Object.entries));
const keys = Object.entries(Object.assign({}, ...arr1));
const result = arr2.map(n => keys.reduce((acc, m) => (acc[m[1]] = n[m[0]], acc), {}));
const xxx = str => Array
.from(str, (n, i) => n.toUpperCase() + n.toLowerCase().repeat(i))
.join('-');
const xxx = str => str
.toUpperCase()
.split('')
.reduce((acc, n, i) => `${acc}${i ? '-' : ''}${n}${Array(-~i).join(n.toLowerCase())}`, '');
const xxx = str => str
.toUpperCase()
.replace(/(?<=.)./g, (m, i) => '-'.concat(m, ...Array(i).fill(m.toLowerCase())));
const hidden = (str, count = 4) => '*'.repeat(count) + str.slice(-4);
const hidden = (str, count = 4) => str.replace(/.*?(?=.{0,4}$)/, Array(count + 1).join('*'));
const form = document.querySelector('form');
form.addEventListener('change', () => {
form.querySelector('.result').innerText = Array
.from(form.querySelectorAll(':checked'))
.reduce((acc, n) => acc + +n.getAttribute('rel'), 0);
});
form.dispatchEvent(new Event('change'));
const blockSelector = 'селектор блоков';
const buttonSelector = 'селектор кнопок';
const activeClass = 'класс, показывающий блок';
const blocks = document.querySelectorAll(blockSelector);
const buttons = document.querySelectorAll(buttonSelector);
buttons.forEach((n, i) => {
n.addEventListener('click', () => {
blocks[i].classList.toggle(activeClass);
});
});
const onClick = function({ currentTarget: { dataset: { index } } }) {
this[index].classList.toggle(activeClass);
}.bind(document.querySelectorAll(blockSelector));
document.querySelectorAll(buttonSelector).forEach((n, i) => {
n.dataset.index = i;
n.addEventListener('click', onClick);
});
const blocks = document.querySelectorAll(blockSelector);
const buttons = document.querySelectorAll(buttonSelector);
buttons.forEach(n => n.addEventListener('click', onClick));
function onClick() {
const index = Array.prototype.indexOf.call(buttons, this);
blocks[index].classList.toggle(activeClass);
}
const containerSelector = '...';
), то индексы не нужны. Достаточно от нажатой кнопки подняться до общего предка кнопки и блока, и найти внутри блок (а можно даже и не искать, если добавлять класс контейнеру; конечно, стили придётся в этом случае немного изменить, вместо .блок.класс
будет .контейнер.класс .блок
):const toggleBlock = button => button
?.closest(containerSelector)
?.querySelector(blockSelector)
.classList
.toggle(activeClass);
// можно добавить обработчик клика каждой кнопке индивидуально
document.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => toggleBlock(e.currentTarget));
// или один раз на всю страницу
document.addEventListener('click', e => {
toggleBlock(e.target.closest(buttonSelector));
});
const getNestedItems = (data, test) =>
data instanceof Object
? Object.values(data).flatMap(n => getNestedItems(n, test))
: test(data) ? [ data ] : [];
const result = getNestedItems(obj, x => /^[A-Z]+$/.test(x)).join('');
if (this.frame < 0) { this.frame = this.slides.lenght-1; this.setBackground(this.slides[this.frame]) }
frame
неотрицательный, то вызывать setBackground
уже не надо?undefined
. А после вычитания единицы - NaN
. Элемента с индексом NaN
в массиве нет, так что в setBackground
улетает undefined
- его вы и видите в стилях.if (this.frame > this.slides.length) {
buttonLeft.addEventListener('click', slider.left());
Array.from(
arr.reduce((acc, n) => acc.set(n, -~acc.get(n)), new Map),
n => [ n[0], (n[1] / arr.length * 100).toFixed(2) + '%' ]
)
const clone = (data, replacements) =>
data instanceof Object
? data instanceof Array
? data.map(n => clone(replacements?.hasOwnProperty(n) ? replacements[n] : n, replacements))
: Object.fromEntries(Object.entries(data).map(([ k, v ]) => [
k,
clone(replacements?.hasOwnProperty(k) ? replacements[k] : v, replacements)
]))
: data;
const products = arr.map(n => clone(obj.product[0], n));
"[object Object]"
. Всё.toString
(конечно, поступать так имеет смысл только в том случае, если вы можете гарантировать, что строковые представления будут уникальны). let index = -1;
setInterval(el => {
const show = !el.classList.contains('_active');
index = (index + show) % infoModal.length;
el.innerText = infoModal[index].title;
el.classList.toggle('_active', show);
}, 1000, document.querySelector('.modal__title'));
Если, к примеру, нужно скрывать блок каждый раз через5 сек, а показывать блок через рандомный промежуток времени?
(function updateText(el, i) {
const show = el.classList.toggle('_active');
i = (i + show) % infoModal.length;
el.textContent = infoModal[i].title;
setTimeout(updateText, 1000 + !show * Math.random() * 3000, el, i);
})(document.querySelector('.modal__title'), -1);
document.querySelector('form').addEventListener('input', e => {
document.querySelector('button').disabled = ![
[ 'input', el => el.value ],
[ 'select', el => el.selectedIndex ],
].every(([ selector, validator ]) => {
return [...e.currentTarget.querySelectorAll(selector)].every(validator);
});
});
const entries = Object.entries(obj); for (const entry of entries) { if (!isObject(entry)) { result = Object.assign(result, Object.fromEntries(entry)); } else return cloneDeep(entry);
const merge = (...arrs) =>
Array.from(
{ length: Math.max(...arrs.map(n => n.length)) },
(_, i) => Object.assign({}, ...arrs.map(n => n[i]))
);
const arr = merge(arr1, arr2);
const merge = (...arrs) =>
arrs.reduce((acc, n) => (
n.forEach((m, i) => Object.assign(acc[i] ??= {}, m)),
acc
), []);
function replaceText(node, replacer) {
if (node.nodeType === Node.ELEMENT_NODE) {
node.childNodes.forEach(n => replaceText(n, replacer));
} else if (node.nodeType === Node.TEXT_NODE) {
node.textContent = replacer(node.textContent);
}
}
replaceText(document.body, str => str.replace(/\d/g, 'hello, world!!'));
function replaceText(node, replacer) {
const iter = document.createNodeIterator(node, NodeFilter.SHOW_TEXT);
for (let n = null; n = iter.nextNode();) {
n.nodeValue = replacer(n.nodeValue);
}
}