Нетривиальная задача
<svg
data-color-index="-1"
data-color-attr="fill"
...
<span
data-color-index="-1"
data-color-attr="color"
...
$('svg, span').mouseenter(function() {
const colorIndex = (+this.dataset.colorIndex + 1) % colors.length;
$(this).css(this.dataset.colorAttr, colors[colorIndex]);
this.dataset.colorIndex = colorIndex;
}).mouseleave(function() {
$(this).css(this.dataset.colorAttr, '');
});
let index = -1;
$('.demo').mouseenter(function() {
index = (index + 1) % colors.length;
updateColor(this, colors[index]);
}).mouseleave(function() {
updateColor(this, '');
});
function updateColor(el, color) {
$('[data-color-attr]', el).each(function() {
$(this).css(this.dataset.colorAttr, color);
});
}
function sum(...values) {
const s = values.reduce((acc, n) => acc + n, 0);
const f = sum.bind(null, s);
f.valueOf = () => s;
return f;
}
Object.entries(Obj).reduce((acc, [ k, v ]) => ((acc[v] = acc[v] || []).push(k), acc), {})
- .popup.visible {
+ .item.visible .popup {
const container = document.querySelector('.container');
const itemSelector = '.item';
const activeClass = 'visible';
const toggleItem = (item, items) =>
items.forEach(n => n.classList[n === item ? 'toggle' : 'remove'](activeClass));
// делегирование, назначаем обработчик клика один раз для всех item'ов
container.addEventListener('click', function({ target: t }) {
if (t.matches(itemSelector)) {
toggleItem(t, this.querySelectorAll(itemSelector));
}
});
// или, каждому item'у назначаем обработчик клика индивидуально
const items = container.querySelectorAll(itemSelector);
items.forEach(n => n.addEventListener('click', onClick));
function onClick({ target: t }) {
if (this === t) {
toggleItem(t, items);
}
}
const itemSelector = '.accordion_item';
const buttonSelector = `${itemSelector} .title_block`;
const contentSelector = '.info';
const activeClass = 'active_block';
const toggleEffect = 'slideToggle'; // или fadeToggle, или toggle
const onClick = e => $(e.currentTarget)
.closest(itemSelector)
.toggleClass(activeClass)
.find(contentSelector)
[toggleEffect]();
// обработчик клика подключаем к заголовкам
$(buttonSelector).click(onClick);
// или, если предполагается добавление новых секций аккордеона уже после
// подключения обработчика, то лучше будет повесить его на документ,
// дополнительно указав, у каких элементов надо слушать событие;
// в этом случае клики по динамически добавляемым элементам будут
// обрабатываться так же, как и по тем, что существовали изначально
$(document).on('click', buttonSelector, onClick);
function connectInputs(selector) {
const onInput = e => $inputs.val(e.target.value);
const $inputs = $(selector).on('input', onInput);
return () => $inputs.off('input', onInput);
}
connectInputs('#input, #output');
function connectInputs([...inputs]) {
const onInput = e => inputs.forEach(n => n.value = e.target.value);
inputs.forEach(n => n.addEventListener('input', onInput));
return () => inputs.forEach(n => n.removeEventListener('input', onInput));
}
connectInputs(document.querySelectorAll('#input, #output'));
const length = Math.max(...players.map(n => n.holes.length));
for (const { holes } of players) {
holes.push(...Array.from(
{ length: length - holes.length },
() => ({ score: '-' })
));
}
const newPlayers = players.map(n => ({
...n,
holes: Array.from({ length }, (_, i) => n.holes[i] || { score: '-' }),
}));
$('.select-list').change(function() {
const selected = $(':checked', this)
.parent()
.get()
.map(n => $(n).text().trim())
.join(', ');
$('.selected-name--filter').text(selected || 'Любой');
}).change();
const select = document.querySelector('.select-list');
select.addEventListener('change', function() {
const selected = Array
.from(this.querySelectorAll(':checked'), n => n.parentNode.textContent.trim())
.join(', ');
document.querySelector('.selected-name--filter').textContent = selected || 'Любой';
});
select.dispatchEvent(new Event('change'));
$('a').attr('title', function() {
return $(this).text();
});
document.querySelectorAll('a').forEach(n => n.title = n.innerText);
for (const n of document.getElementsByTagName('a')) {
n.setAttribute('title', n.textContent);
}
$('select').change(function() {
$('button').prop('disabled', $(this).val() === '0');
});
document.querySelector('select').addEventListener('change', function() {
document.querySelector('button').disabled = this.value === '0';
});
function getTree(data) {
let root = data.find(n => n.id === 0);
root = { title: root.name.slice(1,-1), id: root.id };
data.filter(n => n.id !== 0).forEach(item => {
const node = item.name.slice(1, -1).split('/').reduce((parent, title) => {
if (!parent.children) {
Object.assign(parent, { children: [], isDirectory: true });
}
let child = parent.children.find(m => m.title === title);
if (!child) {
child = { title };
parent.children.push(child);
}
return child;
}, root);
Object.assign(node, { id: item.id, isDirectory: !!node.isDirectory });
});
return root;
}
const input = document.querySelector('input');
const button = document.querySelector('button');
const num = 6;
input.addEventListener('input', e => {
button.disabled = e.target.value % num;
});
button.addEventListener('click', () => {
if (input.value % num) {
alert('такого нам не надо, пробуй ещё');
}
});
input.addEventListener('change', ({ target: t }) => {
t.value = Math.max(0, (t.value / num | 0) * num);
});
<button data-step="-1">-</button>
<button data-step="+1">+</button>
document.querySelectorAll('[data-step]').forEach(n => {
n.addEventListener('click', onClick);
});
function onClick({ target: { dataset: { step } } }) {
input.value = Math.max(0, +input.value + num * step);
}
const data = $('.price')
.filter((i, n) => +n.value)
.closest('tr')
.find('input[type="hidden"]')
.get()
.map(n => n.value);
const data = Array
.from(document.querySelectorAll('.price'))
.filter(n => +n.value)
.map(n => n.closest('tr').querySelector('input[type="hidden"]').value);