arr.reduce((acc, n) => acc + n.startsWith(`${currency} `) * /\d+$/.exec(n), 0)
arr.reduce((acc, n) => {
const [ currency, sum ] = n.split(' ');
acc[currency] = (acc[currency] ?? 0) + +sum;
return acc;
}, {})
const key = 'type';
const attr = `data-${key}`;
const attrSelector = `[${attr}]`;
const getTypeGroup = el => el.dataset[key].replace(/\d/g, '');
// или
const getTypeGroup = el => el.getAttribute(attr).match(/\D+/)[0];
// или
const getTypeGroup = el => el.attributes[attr].value.split(/\d/).shift();
document.addEventListener('click', e => {
const el = e.target.closest(attrSelector);
if (el) {
console.log(getTypeGroup(el));
}
});
// или
document.querySelectorAll(attrSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => console.log(getTypeGroup(e.currentTarget)));
const chunked = (data, chunkSize, slice = data.slice) =>
Array.from(
{ length: Math.ceil(data.length / chunkSize) },
function(_, i) {
return this(i * chunkSize, (i + 1) * chunkSize);
},
(slice instanceof Function ? slice : Array.prototype.slice).bind(data)
);
const parentSelector = '.row-module';
const wrapperTag = 'div';
const wrapperClass = 'wrap';
const wrapSize = 4;
for (const $n of chunked($(parentSelector).children(), wrapSize)) {
$n.wrapAll(`<${wrapperTag} class="${wrapperClass}">`);
}
const parent = document.querySelector(parentSelector);
chunked(parent.children, wrapSize).forEach(n => {
parent.append(document.createElement(wrapperTag));
parent.lastChild.classList.add(wrapperClass);
parent.lastChild.append(...n);
});
const containerSelector = '.tabs';
const headerSelector = `${containerSelector} .tabs-nav__item`;
const contentSelector = `${containerSelector} .tab`;
const activeClass = 'is-active';
function setActiveTab(header) {
if (header instanceof Element && header.matches(headerSelector)) {
const container = header.closest(containerSelector);
const headers = container.querySelectorAll(headerSelector);
const contents = container.querySelectorAll(contentSelector);
const index = Array.prototype.indexOf.call(headers, header);
const toggle = (n, i) => n.classList.toggle(activeClass, i === index);
headers.forEach(toggle);
contents.forEach(toggle);
}
}
// делегирование, подключаем обработчик клика один раз для всех
document.addEventListener('click', e => {
setActiveTab(e.target.closest(headerSelector));
});
// или, назначаем обработчик клика индивидуально каждому заголовку
document.querySelectorAll(headerSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => setActiveTab(e.currentTarget));
function getUsersInfo(ids, callback) {
const results = [...Array(ids.length)];
ids.forEach((n, i) => {
getUserInfo(n, user => {
results[i] = user;
if (results.every(Boolean)) {
callback(result);
}
});
});
}
<div class="title" data-name="first">
<div class="title" data-name="second">
...
<div class="list" data-name="first">
<div class="list" data-name="second">
...
$('.title').click(function() {
$(`.list[data-name="${this.dataset.name}"]`).slideToggle('fast');
});
$('.title').click(function() {
$('.list').eq($(this).index()).slideToggle('fast');
});
.title
/.list
, тогда можно так:$('.title').click(function() {
$(this).closest('здесь селектор общего предка').find('.list').slideToggle('fast');
});
document.addEventListener('input', function(e) {
const inputsWrapper = e.target.closest('.класс-блоков-которые-содержат-ваши-инпуты');
if (inputsWrapper) {
const inputs = [...inputsWrapper.querySelectorAll('input')];
const lastInput = inputs.pop();
lastInput.value = inputs.map(n => n.value).join(' ');
}
});
str.slice(0, 3) + '-'.repeat(Math.max(0, str.length - 3))
// или
str.replace(/(?<=.{3})./g, '-')
// или
Array.from(str, (n, i) => i < 3 ? n : '-').join('')
// или
str.replace(/./g, (m, i) => i < 3 ? m : '-')
// или
str.match(/.{0,3}/) + Array(Math.max(0, str.length - 2)).join`-`
// или
str.substring(0, 3).padEnd(str.length, '-')
$('button').click(e => $('.title').text($(e.target).text()));
const onClick = e => document.querySelector('.title').innerText = e.target.innerText;
document.querySelectorAll('button').forEach(n => n.addEventListener('click', onClick));
document.addEventListener('click', ({ target: t }) => {
if (t.tagName === 'BUTTON') {
document.querySelector('.title').textContent = t.textContent;
}
});
const itemSelector = '.product';
const activeClass = 'checked';
const disabledClass = 'unchecked';
const activeLimit = 3;
document.addEventListener('click', e => {
const cl = e.target.closest(itemSelector)?.classList;
if (cl && !cl.contains(disabledClass)) {
cl.toggle(activeClass);
updateDisabled();
}
});
updateDisabled();
function updateDisabled() {
const [ notActive, active ] = Array.prototype.reduce.call(
document.querySelectorAll(itemSelector),
(acc, n) => (acc[+n.classList.contains(activeClass)].push(n), acc),
[ [], [] ]
);
const limitReached = activeLimit <= active.length;
notActive.forEach(n => n.classList.toggle(disabledClass, limitReached));
}
const items = [...document.querySelectorAll(itemSelector)];
let activeCount = 0;
items.forEach(n => n.addEventListener('click', onClick));
updateDisabled(items.filter(n => n.classList.contains(activeClass)).length);
function onClick({ currentTarget: { classList: cl } }) {
if (!cl.contains(disabledClass)) {
updateDisabled(cl.toggle(activeClass) ? 1 : -1);
}
}
function updateDisabled(change) {
const limitReached = (activeCount += change) >= activeLimit;
for (const { classList: cl } of items) {
cl.toggle(disabledClass, !cl.contains(activeClass) && limitReached);
}
}
const arr = Array.from(str.matchAll(/[^\/]+/g), n => n[0]);
// или
const arr = str.match(/[^\/]+/g) ?? [];
// или
const arr = str.split('/').filter(Boolean);
// или
const arr = Array.prototype.reduce.call(str, (acc, n, i) => (
(n !== '/') && (
acc[1] !== i - 1 && acc[0].push(''),
acc[0][acc[0].length - 1] += n,
acc[1] = i
),
acc
), [ [], -Infinity ])[0];
<button data-step="-1">-</button>
<input value="1">
<button data-step="+1">+</button>
const values = [ 1, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 48, 56, 64 ];
for (const n of document.querySelectorAll('[data-step]')) {
n.addEventListener('click', onClick);
}
function onClick() {
const input = document.querySelector('input');
const index = +this.dataset.step + values.indexOf(+input.value);
input.value = values[Math.max(0, Math.min(values.length - 1, index))];
}
const elements = el.closest('.calc').querySelectorAll('.range__control');
// или
const { elements } = el.form;
const price = Array.prototype.reduce.call(
elements,
(acc, n) => acc * n.value,
1
);
// или
let price = 1;
for (const { value } of elements) {
price *= value;
}
// или
let price = 1;
for (let i = 0; i < elements.length; i++) {
price = price * elements.item(i).value;
}
// или
const price = (function mul(i, n = elements[i]) {
return n ? n.value * mul(-~i) : 1;
})(0);
// или
const price = eval(Array.from(elements, n => n.value).join('*')) ?? 1;
$('select').change(function() { ... }).change();
Object.values(arr.reduce((acc, { id, value }) => {
const type = typeof value;
acc[id] = acc[id] ?? { id };
acc[id][type] = (acc[id][type] ?? 0) + 1;
return acc;
}, {}))