const getReversedPaths = (arr, path = []) =>
arr.reduce((acc, { childItems, ...item }) => {
path.push(item);
if (childItems) {
acc.push(...getReversedPaths(childItems, path));
} else {
acc.push(path.length > 1
? path.map(({ packingLevel }, i, a) => ({ ...a[a.length - i - 1], packingLevel }))
: [ path[0] ]
);
}
path.pop();
return acc;
}, []);
const reverseThere = arr =>
getReversedPaths(arr).map(n =>
n.reduceRight((child, parent) => ({ ...parent, childItems: [ child ] }))
);
const reverseBackAgain = arr =>
(function createTree(arr) {
return Object.values(arr.reduce((acc, [ head, ...tail ]) => {
if (tail.length) {
(acc[head.name] = acc[head.name] || { ...head, childItems: [] }).childItems.push(tail);
} else {
acc[head.name] = head;
}
return acc;
}, {})).map(n => (n.childItems && (n.childItems = createTree(n.childItems)), n));
})(getReversedPaths(arr));
<Child onChange={onChange} />
useEffect(() => props.onChange(val), [ val ]);
const newArr2 = arr2.filter(n => arr1.includes(n.name));
// или
const newArr2 = arr2.filter(function(n) {
return this.has(n.name);
}, new Set(arr1));
// или
const obj2 = Object.fromEntries(arr2.map(n => [ n.name, n ]));
const newArr2 = arr1.reduce((acc, n) => ((n = obj2[n]) && acc.push(n), acc), []);
let numDeleted = 0;
for (let i = 0; i < arr2.length; i++) {
arr2[i - numDeleted] = arr2[i];
numDeleted += !arr1.includes(arr2[i].name);
}
arr2.length -= numDeleted;
// или
for (let i = arr2.length; i--;) {
if (!arr1.includes(arr2[i].name)) {
arr2.splice(i, 1);
}
}
// или
arr2.reduceRight((_, n, i, a) => arr1.includes(n.name) || a.splice(i, 1), null);
// или
arr2.splice(0, arr2.length, ...arr2.filter(n => arr1.includes(n.name)));
<select>
<option value="" hidden>здесь ваше описание</option>
...
select.innerHTML = '<option value="" hidden>...</option>' + select.innerHTML;
select.insertAdjacentHTML('afterbegin', '<option value="" hidden>...</option>');
const option = document.createElement('option');
option.value = '';
option.hidden = true;
option.innerText = '...';
select.prepend(option);
const option = new Option('...', '');
option.style.display = 'none';
select.insertBefore(option, select.firstElementChild);
<div id="items"></div>
document.querySelector('.map__filters').addEventListener('change', function() {
const values = Array.from(
this.querySelectorAll('.map__checkbox:checked'),
n => n.value
);
const filtered = values.length
? data.filter(n => values.every(m => n.features.includes(m)))
: [];
document.querySelector('#items').innerHTML = filtered
.map(n => `<div>${JSON.stringify(n, null, 2)}</div>`)
.join('');
});
computed: {
itemsWithBullshitCounter() {
let counter = -1; /* или 0, если хотите, чтобы нулевой элемент массива получил ненулевой индекс
в том случае, если для него не выполняется условие обнуления */
return this.items.map((n, i) => ({
...n,
counter: counter = (здесь проверяете, надо ли обнулить счётчик
? 0
: counter + 1
),
}));
},
},
<div v-for="n in itemsWithBullshitCounter">
вместо индекса используете значение добавленного свойства: {{ n.counter }}
</div>
computed: {
chunkedItems() {
return this.items.reduce((acc, n, i) => {
if (!i || на текущем элементе надо сбросить индексацию) {
acc.push([]);
}
acc[acc.length - 1].push(n);
return acc;
}, []);
},
},
<template v-for="chunk in chunkedItems">
у каждого куска индексация независимая:
<div v-for="(n, i) in chunk">{{ i }}</div>
</template>
methods: {
createStrangeIndex(arr, baseIndex) {
let index = 0;
while (baseIndex > 0 && на элементе arr[baseIndex--] сбрасывать индексацию не надо) {
index++;
}
return index;
},
},
<div v-for="(n, i) in items">{{ createStrangeIndex(items, i) }}</div>
есть метод orgajax - он тянет данные с сервера, в том числе и HTML код
function filter(obj, key, f) {
const keys = Object.keys(obj);
return (obj[key] || []).reduce((acc, n, i) => (
f(n) && keys.forEach(k => acc[k].push(obj[k][i])),
acc
), keys.reduce((acc, k) => (acc[k] = [], acc), {}));
}
const result = filter(obj, 'years', n => 2012 <= n && n <= 2014);
function filter(obj, f) {
const keys = Object.keys(obj);
const length = keys.length && obj[keys[0]].length;
const result = Object.fromEntries(keys.map(k => [ k, [] ]));
for (let i = 0; i < length; i++) {
if (f(i, obj)) {
keys.forEach(k => result[k].push(obj[k][i]));
}
}
return result;
}
const result = filter(obj, (i, { years: { [i]: n } }) => 2012 <= n && n <= 2014);
we can mark components asfunctional
, which means that they’re stateless (no reactive data) and instanceless (nothis
context)
- .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);
}
});
});
.hidden {
display: none;
}
const itemSelector = '.item-service';
const className = 'hidden';
function toggleUntilNextItem(el) {
while ((el = el.nextElementSibling) && !el.matches(itemSelector)) {
el.classList.toggle(className);
}
}
document.querySelectorAll(itemSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => toggleUntilNextItem(e.currentTarget));
// или
document.addEventListener('click', e => {
const item = e.target.closest(itemSelector);
if (item) {
toggleUntilNextItem(item);
}
});
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'))
);
$('.open-category').click(function() {
$(`.d-none[data-id="${this.dataset.id}"]`).toggleClass('active');
});
for (const n of document.getElementsByClassName('open-category')) {
n.addEventListener('click', onClick);
}
function onClick({ target: { dataset: { id } } }) {
document.querySelector(`.d-none[data-id="${id}"]`).classList.toggle('active');
}
const elements = new Map(Array.from(
document.querySelectorAll('.open-category'),
n => [ n, document.querySelector(`.d-none[data-id="${n.dataset.id}"]`) ]
));
document.addEventListener('click', e => {
elements.get(e.target)?.classList.toggle('active');
});
идет смещение индексов, но как это обойти, уже не знаю
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)));
let numDeleted = 0;
for (let i = 0; i < invItems.length; i++) {
invItems[i - numDeleted] = invItems[i];
numDeleted += i === arr[numDeleted];
}
invItems.length -= numDeleted;