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));
});
- .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);
}
});
});
const itemSelector = '.item-service';.function toggleUntilNextItem(el) {
while ((el = el.nextElementSibling) && !el.matches(itemSelector)) {
el.hidden ^= 1;
// или (в стили надо будет добавить .hidden { display: none; })
el.classList.toggle('hidden');
}
}document.querySelectorAll(itemSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => toggleUntilNextItem(e.currentTarget));document.addEventListener('click', ({ target: t }) =>
(t = t.closest(itemSelector)) && toggleUntilNextItem(t)
);
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'))
);
const key = 'id';
const attr = `data-${key}`;const getVal = el => $(el).data(key);
// или
const getVal = el => $(el).attr(attr);
// или
const getVal = el => el.dataset[key];
// или
const getVal = el => el.getAttribute(attr);
// или
const getVal = el => el.attributes[attr].value;const buttonSelector = '.open-category';
const contentSelector = button => `.d-none[${attr}="${getVal(button)}"]`;
const activeClass = 'active';const toggle = button => $(contentSelector(button)).toggleClass(activeClass);
// или
const toggle = button => document
.querySelector(contentSelector(button))
.classList
.toggle(activeClass);$(buttonSelector).click(function() {
toggle(this);
});
// или
document.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => toggle(e.currentTarget));$(document).on('click', buttonSelector, e => toggle(e.currentTarget));
// или
document.addEventListener('click', ({ target: t }) =>
(t = t.closest(buttonSelector)) && toggle(t)
);
идет смещение индексов, но как это обойти, уже не знаю
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))
);invItems.length -=
invItems.reduce((acc, n, i, a) => (
a[i - acc] = n,
acc + (i === arr[acc])
), 0);
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);
}
const containerSelector = '.class-1';
const tag = 'div';
const key = 'name';
const attrSelector = `[data-${key}]`;$(containerSelector).prepend(function() {
return $(`<${tag}>`).text($(attrSelector, this).data(key));
});document.querySelectorAll(containerSelector).forEach(n => {
const val = n.querySelector(attrSelector).dataset[key];
// можем добавлять разметку
n.insertAdjacentHTML('afterbegin', `<${tag}>${val}</${tag}>`);
// или элемент
const el = document.createElement(tag);
el.textContent = val;
n.prepend(el);
// или
// n.firstChild.before(el);
// n.insertBefore(el, n.firstChild);
// n.insertAdjacentElement('afterbegin', el);
// n.firstChild.replaceWith(el, n.firstChild);
});
function codeAddress(address, geocoder, map) {
geocoder.geocode({ address }, function(results, status) {
if (status === 'OK') {
new google.maps.Marker({
map: map,
position: results[0].geometry.location,
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}address.forEach(n => codeAddress(n, geocoder, map));
const elements = document.querySelectorAll('li > ul');
const tag = 'span';
const text = 'hello, world!!';elements.forEach(n => {
n.before(document.createElement(tag));
n.previousSibling.textContent = text;
});for (const n of elements) {
const el = document.createElement(tag);
el.innerText = text;
n.parentNode.insertBefore(el, n);
}for (let i = 0; i < elements.length; i++) {
elements[i].insertAdjacentHTML('beforebegin', `<${tag}>${text}</${tag}>`);
}(function insert(i, n = elements.item(i)) {
if (n) {
const el = document.createElement(tag);
el.appendChild(new Text(text));
n.insertAdjacentElement('beforebegin', el);
insert(-~i);
}
})(0);
const selector = '.list-item';
const key1 = 'pagereview';
const key2 = 'pageslug';
const attr1 = `data-${key1}`;
const attr2 = `data-${key2}`;const $elements = $(selector);
// или
const elements = document.querySelectorAll(selector);$elements.show().filter((i, n) => $(n).data(key1) !== $(n).data(key2)).hide();
// или
$elements.each(function() {
const $this = $(this);
$this.toggle($this.attr(attr1) === $this.attr(attr2));
});
// или
elements.forEach(n => {
n.hidden = n.getAttribute(attr1) !== n.getAttribute(attr2);
});
// или
for (const { style, dataset } of elements) {
style.display = dataset[key1] === dataset[key2] ? 'block' : 'none';
}
// или (в стили надо будет добавить .hidden { display: none; })
for (let i = 0; i < elements.length; i++) {
const { classList: c, attributes: a } = elements[i];
c.toggle('hidden', a[attr1].value !== a[attr2].value);
}
const widgetsTransform = Object
.values(widgets.reduce((acc, n) => ((acc[n.type] = acc[n.type] ?? []).push(n), acc), {}))
.map(n => n.length > 1 ? ({ type: `Section${n[0].type}`, children: n }) : n[0]);const widgetsTransform = widgets
.reduce((acc, n, i, a) => (
(i && n.type === a[~-i].type) || acc.push([]),
acc[~-acc.length].push(n),
acc
), [])
.map(n => ~-n.length ? ({ type: 'Section' + n[0].type, children: n }) : n[0]);
$('.price_min_max_btn').click(function() {
const min = +$('.price_min').val() || 0;
const max = +$('.price_max').val() || Infinity;
$('.item_block_filter')
.hide()
.filter(function() {
const price = +this.dataset.price;
return min <= price && price <= max;
})
.show();
});
document.querySelector('table').addEventListener('click', e => {
const td = e.target.closest('td');
if (td) {
// поскольку речь идёт о ячейках таблицы, то нет причин использовать что-то иное
const index = td.cellIndex;
// но вообще, можно и метод массива припахать
const index = Array.prototype.indexOf.call(td.parentNode.children, td);
// или вручную посчитать, как далеко удастся уйти по ссылкам на предыдущие элементы
let index = 0;
for (let el = td; el = el.previousElementSibling; index++) ;
}
});
const arr = str.split('-');
const end = 'final';const obj = arr.reduceRight((acc, n) => ({ [n]: acc }), end);const obj = (function createObj(i) {
return i < arr.length
? { [arr[i]]: createObj(i + 1) }
: end;
})(0);
const result = graphData.map((n, i) => ({ ...n, color: palette[i % palette.length] }));const combine = (arr, keys, values) =>
arr.map(({ ...n }, i) => (
values.forEach((m, j) => n[keys[j]] = m[i % m.length]),
n
));
const result = combine(graphData, [ 'color' ], [ palette ]);