.dropdown {
display: none;
}
.dropdown.show {
display: block;
}
const headerSelector = '.tabs__head';
const contentSelector = '.dropdown';
const activeClass = 'show';
// делегирование, назначаем обработчик клика один раз для всех хедеров;
// контент, соответствующий нажатому хедеру, находим через значение атрибута href
document.addEventListener('click', ({ target: t }) => {
const header = t.closest(headerSelector);
if (header) {
document.querySelectorAll(contentSelector).forEach(function(n, i) {
n.classList[n === this ? 'toggle' : 'remove'](activeClass);
}, document.querySelector(header.attributes.href.value));
}
});
// или, назначаем обработчик клика каждому хедеру индивидуально;
// контент, соответствующий нажатому хедеру, определяем по равенству индексов
const headers = document.querySelectorAll(headerSelector);
const contents = document.querySelectorAll(contentSelector);
headers.forEach(n => n.addEventListener('click', onClick));
function onClick() {
const index = Array.prototype.indexOf.call(headers, this);
contents.forEach((n, i) => n.classList[i === index ? 'toggle' : 'remove'](activeClass));
}
$('.price_tabs-content button').click(function() {
const $this = $(this);
const on = $this.siblings('p').toggleClass('on').hasClass('on');
$this.text(on ? 'Закрыть' : $this.data('text'));
}).each((i, n) => $(n).data('text', $(n).text()));
$('.price_tabs-content button').click(function() {
$(this).hide().next().show().end().prev().addClass('on');
}).after('<button>Закрыть</button>').next().hide().click(function() {
$(this).hide().prev().show().prev().removeClass('on');
});
const elements = document.querySelector('#list').children;
// или
const elements = document.querySelectorAll('#list li');
const getVal = el => +el.textContent.split(' - ').pop();
// или
const getVal = el => parseInt(el.innerText.replace(/.*\D/, ''));
// или
const getVal = el => el.innerHTML.match(/\d+$/) | 0;
const sum = Array.prototype.reduce.call(
elements,
(acc, n) => acc + getVal(n),
0
);
// или
let sum = 0;
for (const n of elements) {
sum += getVal(n);
}
// или
const sum = (function sum(i) {
return elements[i] ? getVal(elements[i]) + sum(i + 1) : 0;
})(0);
// или
const sum = eval(Array.from(elements, getVal).join('+')) ?? 0;
const digitsOnly = str => str.replace(/\D/g, '');
// или
const digitsOnly = str => (str.match(/\d/g) ?? []).join('');
// или
const digitsOnly = str => ''.concat(...str.matchAll(/\d/g));
// или
const digitsOnly = str => str.split(/\D/).join``;
// или
const digitsOnly = str =>
Array.prototype.reduce.call(
str,
(acc, n) => acc + ('0123456789'.includes(n) ? n : ''),
''
);
document.querySelectorAll('span').forEach(n => {
n.innerText = digitsOnly(n.innerText);
});
// или
for (const n of document.getElementsByTagName('span')) {
n.textContent = digitsOnly(n.textContent);
}
RegExp
в цепочке прототипов: x instanceof RegExp
.RegExp
конструктором значения: x?.constructor === RegExp
.const type = x => x == null ? x : x.constructor;
type() === undefined // true
type(null) === null // true
type(/./) === RegExp // true
type(666) === Number // true
type(type) === Function // true
const typename = x => x?.constructor.name ?? `${x}`;
typename() // 'undefined'
typename(null) // 'null'
typename(false) // 'Boolean'
typename(187) // 'Number'
typename('hello, world!!') // 'String'
typename(/./) // 'RegExp'
typename({}) // 'Object'
typename([]) // 'Array'
typename(document.body) // 'HTMLBodyElement'
typename(document.getElementsByClassName('xxx')) // 'HTMLCollection'
typename(new class XXX {}) // 'XXX'
typename(typename) // 'Function'
const newArr = arr.reduce((acc, n, i) => (acc.push(n + (acc[i - 1] ?? 0)), acc), []);
// или
const newArr = arr.reduce((acc, n) => (acc[0].push(acc[1] += n), acc), [ [], 0 ])[0];
// или
const newArr = arr.map((n, i, a) => eval(a.slice(0, i + 1).join('+')));
// или
const newArr = arr.map((n, i, a) => a.reduce((acc, m, j) => acc + m * (j <= i), 0));
arr.forEach((n, i, a) => a[i] += a[i - 1] ?? 0);
('0' + date.getMonth()).slice(-2)
// или
`${date.getMonth()}`.padStart(2, 0)
date.toLocaleDateString('ru-RU').split('.').reverse().join('.')
// или
date.toLocaleDateString('ru-RU').replace(/(\d+)(\.\d+\.)(\d+)/, '$3$2$1')
return X; // тут НУЖНО ...
return new Promise(resolve => {
const img = new Image();
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = 'тут ссылка на изображение';
});
document.querySelector('.menu').addEventListener('click', ({ target: t }) => {
if (t.tagName === 'A') {
const submenu = [...t.parentNode.children].find(n => n.classList.contains('sub-menu'));
if (submenu) {
submenu.classList.toggle('red');
}
}
});
for (const n of document.querySelectorAll('.menu a')) {
n.addEventListener('click', onClick);
}
function onClick() {
this.nextElementSibling?.classList.toggle('red');
}
// или
document.querySelectorAll('.sub-menu').forEach(function(n) {
n.previousElementSibling.addEventListener('click', this);
}, e => e.target.nextElementSibling.classList.toggle('red'));
Object.values(arr.reduce((acc, [ id, group, ...values ]) => {
const g = (acc[id] = acc[id] ?? { id, groups: {} }).groups;
(g[group] = g[group] ?? []).push(values);
return acc;
}, {}))
const delay = timeout => new Promise(r => setTimeout(r, timeout));
async function asyncDelayedForEach(arr, callback, timeout) {
for (let i = 0; i < arr.length; i++) {
await callback.call(arr, arr[i], i, arr);
await delay(timeout);
}
}
// или
const asyncDelayedForEach = (arr, callback, timeout) =>
arr.reduce((acc, n, i, a) => acc
.then(() => callback.call(a, n, i, a))
.then(() => delay(timeout))
, Promise.resolve());
Object.values(arr.reduce((acc, [ user, ...data ]) => {
(acc[user] = acc[user] ?? { user, data: [] }).data.push(data);
return acc;
}, {}))
document.querySelector('.todo-app__list').addEventListener('click', e => {
const li = e.target.closest('.todo-app__list-item');
if (li) {
console.log(li.dataset.id);
}
});