document.querySelectorAll('.slider__itm img').forEach(n => {
const link = document.createElement('a');
n.parentNode.append(link);
link.append(n);
});
for (const n of document.querySelectorAll('.slider__itm')) {
n.innerHTML = `<a>${n.innerHTML}</a>`;
}
for (const n of document.getElementsByClassName('slider__itm')) {
const link = document.createElement('a');
link.appendChild(n.replaceChild(link, n.children[0]));
}
const imgs = document.querySelectorAll('.slider__itm img');
for (let i = 0; i < imgs.length; i++) {
const link = document.createElement('a');
imgs[i].replaceWith(link);
link.insertAdjacentElement('afterbegin', imgs[i]);
}
{ точка: сегмент }
). Находим начальный сегмент маршрута - такой, начальная точка которого не является ничьей конечной. Следующий сегмент маршрута - такой, начальная точка которого является конечной точкой текущего сегмента. Ну и крутим цикл до тех пор, пока текущий сегмент маршрута существует, не забывая сохранять его в результирующий массив:function sort(route) {
const pointsFrom = Object.fromEntries(route.map(n => [ n.from, n ]));
const pointsTo = Object.fromEntries(route.map(n => [ n.to, n ]));
const sorted = [];
for (
let segment = route.find(n => !pointsTo[n.from]);
segment;
segment = pointsFrom[segment.to]
) {
sorted.push(segment);
}
return sorted;
}
const remove = str => str.split(' ').slice(0, -1).join(' ');
// или
const remove = str => str.replace(/\s\S+$/, '');
// или
const remove = str => str.match(/.+(?=\s)/);
// или
const remove = str => str.slice(0, str.lastIndexOf(' '));
for (const n of document.getElementsByClassName('startdate')) {
n.textContent = remove(n.textContent);
}
// или, раз уж полной даты уже не будет, пусть начало и конец интервала дат
// располагаются внутри одного элемента - вместе с куском строки также
// удаляем и родительский элемент
document.querySelectorAll('.startdate').forEach(n => {
n.outerHTML = remove(n.innerHTML);
// или
n.replaceWith(remove(n.innerText));
});
map
, filter
, some
и т.д.), принимающую элемент массива и возвращающую true
в случае, если элемент должен быть удалён. Если элемент удалять не надо, то следует обработать массив вложенных элементов - выполняется рекурсивный вызов. Как это может выглядеть:function deleteNested(arr, fn) {
arr?.reduceRight?.((_, n, i, a) =>
fn(n, i, a)
? a.splice(i, 1)
: deleteNested(n.children, fn)
, null);
}
function deleteNested(arr, fn) {
if (Array.isArray(arr)) {
arr.splice(0, arr.length, ...arr.filter((n, i, a) => {
return !fn(n, i, a) && (deleteNested(n.children, fn), true);
}));
}
}
function deleteNested(arr, fn) {
if (arr instanceof Array) {
let numDeleted = 0;
for (const [ i, n ] of arr.entries()) {
if (fn(n, i, arr)) {
numDeleted++;
} else {
arr[i - numDeleted] = n;
deleteNested(n.children, fn);
}
}
arr.length -= numDeleted;
}
}
deleteNested(itemsData, n => n.id === id_объекта_который_надо_удалить);
document.querySelector('.calendar-days').addEventListener('click', e => {
if (e.target.classList.contains('calendar-day-hover')) {
currDate = new Date(curr_year.value, curr_month.value, e.target.innerText);
document.querySelector('.heading').innerText = currDate.toLocaleDateString('ru-RU');
e.currentTarget.querySelector('.curr-date')?.classList.remove('curr-date');
e.target.classList.add('curr-date');
}
});
const point = { latitude: lat, longtitude: lon };
const closest = arr.reduce((closest, n) => {
const d = sphericalDistance(point, n);
return d < closest[1] ? [ n, d ] : closest;
}, [ null, Infinity ])[0];
function sphericalDistance(p1, p2) {
// https://en.wikipedia.org/wiki/Great-circle_distance
}
const SHOW_INITIAL = 2;
const SHOW_MORE = 3;
const $button = $('.btn-search-more');
const $items = $('.catalog-list__items-top').hide();
showItems(SHOW_INITIAL);
$button.click(() => showItems(SHOW_MORE));
function showItems(count) {
const $hidden = $items.filter(':hidden');
$hidden.slice(0, count).show();
$button.toggle($hidden.length > count);
}
const result = Array.prototype.flatMap.call(
document.forms,
function(form) {
return form.className.match(this) ?? [];
},
/(?<=(^| )js-)[a-z-]*(?=-form( |$))/g
);
const result = [];
const reg = /^js-([a-z-]*)-form$/;
for (const form of document.querySelectorAll('form')) {
for (const cls of form.classList) {
const name = reg.exec(cls)?.[1];
if (name != null) {
result.push(name);
}
}
}
$('#cityFilter').on('input', function() {
const value = this.value.toLowerCase();
$('#city-list .city')
.hide()
.filter((i, n) => $(n).text().toLowerCase().includes(value))
.show();
$('#city-list .state')
.hide()
.filter((i, n) => $(n).nextUntil('.state').is(':visible'))
.show();
});
document.querySelector('#cityFilter').addEventListener('input', e => {
const value = e.target.value.toLowerCase();
document.querySelectorAll('#city-list li').forEach(function(n) {
if (n.matches('.state')) {
this.splice(0, 2, n, true);
} else {
const hide = n.textContent.toLowerCase().indexOf(value) === -1;
this[1] &&= hide;
n.classList.toggle('hidden', hide);
if (!n.nextElementSibling?.matches('.city')) {
this[0].classList.toggle('hidden', this[1]);
}
}
}, [ null, true ]);
});
document.querySelectorAll('.col').forEach(n => {
n.querySelectorAll('a').forEach((m, i) => m.classList.toggle('d-none', !!i));
});
document.querySelectorAll('.col a').forEach(n => {
n.classList.toggle('d-none', !!n.previousElementSibling);
});
const filterSelector = '.js-filter';
const itemSelector = '.dfth__item';
const checkboxSelector = '.dfth__check:checked';
const labelSelector = '.dfth__label';
const resetSelector = '.dfth__reset';
const selectedSelector = '.js-type-result';
const defaultValue = 'ничего не выбрано';
const $filter = $(filterSelector).change(function() {
const selected = $(checkboxSelector, this)
.closest(itemSelector)
.find(labelSelector)
.get()
.map(n => $(n).text())
.join(', ');
$(selectedSelector, this).text(selected || defaultValue);
});
$filter.find(resetSelector).click(() => {
$filter.find(checkboxSelector).prop('checked', false);
$filter.trigger('change');
});
const filter = document.querySelector(filterSelector);
filter.addEventListener('change', ({ currentTarget: ct }) => {
const selected = Array
.from(
ct.querySelectorAll(checkboxSelector),
n => n.closest(itemSelector).querySelector(labelSelector).textContent)
.join(', ');
ct.querySelector(selectedSelector).textContent = selected || defaultValue;
});
filter.querySelector(resetSelector).addEventListener('click', () => {
filter.querySelectorAll(checkboxSelector).forEach(n => n.checked = false);
filter.dispatchEvent(new Event('change'));
});
const hasDuplicates = map.size > new Set(Array.from(map, n => n[1].id)).size;
const duplicates = Array
.from([...map].reduce((acc, [ , { id } ]) => acc.set(id, acc.has(id)), new Map))
.reduce((acc, n) => (n[1] && acc.push(n[0]), acc), []);
const count = Array
.from(map.values())
.reduce((acc, { id }) => acc.set(id, -~acc.get(id)), new Map);
const containerSelector = '.block-btn';
const itemSelector = `${containerSelector} [data-cost]`;
const activeClass = 'active';
const onClick = ({ currentTarget: t }) => t
.closest(containerSelector)
.querySelectorAll(itemSelector)
.forEach(n => n.classList.toggle(activeClass, n === t));
document.querySelectorAll(itemSelector).forEach(n => {
n.addEventListener('click', onClick);
});
for (const n of document.querySelectorAll(containerSelector)) {
n.addEventListener('click', onClick);
}
function onClick(e) {
const item = e.target.closest(itemSelector);
if (item) {
this.querySelector(`.${activeClass}`)?.classList.remove(activeClass);
item.classList.add(activeClass);
}
}
document.addEventListener('click', ({ target: t }) => t
.closest(itemSelector)
?.closest(containerSelector)
.querySelectorAll(itemSelector)
.forEach(n => n.classList.toggle(activeClass, n.contains(t)))
);
const delimiter = str.match(/\D/)[0];
// или
const delimiter = str[str.search(/\D/)];
// или
const [ delimiter ] = str.replace(/^\d+/, '');
// или
const delimiter = Array.prototype.find.call(str, n => Number.isNaN(+n));
// или
const delimiter = [...str].filter(n => !'0123456789'.includes(n)).shift();
const parent = document.querySelector('.container');
const className = 'green';
const startFrom = 4;
parent
.querySelectorAll(`:scope > :nth-child(n + ${startFrom + 1})`)
.forEach(n => n.classList.add(className));
// или
for (const n of Array.prototype.slice.call(parent.children, startFrom)) {
n.classList.add(className);
}
// или
for (let el = parent.children[startFrom]; el; el = el.nextElementSibling) {
el.classList.add(className);
}
// или, также удаляем класс (если вдруг есть) у тех, кому он не должен быть добавлен
for (let i = 0; i < parent.children.length; i++) {
parent.children[i].classList.toggle(className, i >= startFrom);
}
function createRandomArr(length, min, max) {
if (length > max - min + 1) {
throw 'такого массива быть не может';
}
const values = new Set;
for (; values.size < length; values.add(min + Math.random() * (max - min + 1) | 0)) ;
return [...values];
}
const createRandomArr = (length, min, max) => Array
.from({ length }, function() {
return this.splice(Math.random() * this.length | 0, 1);
}, Array.from({ length: max - min + 1 }, (n, i) => i + min))
.flat();
function createRandomArr(length, min, max) {
const arr = Array.from({ length: max - min + 1 }, (n, i) => min + i);
for (let i = arr.length; --i > 0;) {
const j = Math.random() * (i + 1) | 0;
[ arr[i], arr[j] ] = [ arr[j], arr[i] ];
}
return arr.slice(0, length);
}
const values = [ id, sum, system, date ];
.payment.innerHTML = values.map(n => `<td>${n}</td>`).join('');
// или
values.forEach(n => payment.insertCell().textContent = n);
// или
payment.append(...values.map(n => {
const td = document.createElement('td');
td.innerText = n;
return td;
}));
- function createPayment({id, sum, system, date}) {
+ function createPayment(data) {
- const values = [ id, sum, system, date ];
+ const keys = [ 'id', 'sum', 'system', 'date' ];
- values.forEach(n => payment.insertCell().textContent = n);
+ keys.forEach(n => payment.insertCell().textContent = data[n]);