const average = arr => arr.reduce((acc, n) => acc + n, 0) / arr.length;
const extractValues = (group, item, key) =>
item[key].forEach(({ id, name, value }) => {
((group.values[id] ||= { id, name })[key] ||= []).push(value);
});
const result = Object
.values(arr
.flatMap(n => n.properties.groups)
.reduce((acc, n) => (
acc[n.id] ||= {
id: n.id,
name: n.name,
wellBeing: [],
values: {},
},
acc[n.id].wellBeing.push(n['well-being']),
extractValues(acc[n.id], n, 'needs'),
extractValues(acc[n.id], n, 'provision'),
acc
), {}))
.map(n => ({
id: n.id,
name: n.name,
value: average(n.wellBeing),
values: Object.values(n.values).map(m => (
m.needs = average(m.needs),
m.provision = average(m.provision),
m
))
}));
const xxx = ([...str]) => [...new Set(Array.from(
{ length: str.length * 10 },
(n, i) => str.map((m, j) => (j === (i / 10 | 0)) ? i % 10 : m).join('')
))];
function xxx(str) {
const arr = str.split('');
const result = [ str ];
for (const [ i, n ] of arr.entries()) {
for (let j = 0; j < 10; j++) {
if (j !== +n) {
arr[i] = j;
result.push(arr.join(''));
}
}
arr[i] = n;
}
return result;
}
const first = document.querySelector('#first');
const second = document.querySelector('#second');
const hideOptions = {
1: [ '12', '14', '15' ],
2: [ '1', '11', '16' ],
};
first.addEventListener('change', function() {
Array.prototype.forEach.call(second, function(n) {
n.hidden = this.includes(n.value);
}, hideOptions[this.value] ?? []);
});
.hidden {
display: none;
}
first.onchange = e => {
const toHide = hideOptions[e.target.value];
for (const n of second) {
n.classList.toggle('hidden', toHide?.indexOf(n.value) > -1);
}
};
const nav = document.querySelector('.nav');
const itemSelector = '.nav-link';
const image = document.querySelector('.preview-img');
const category = document.querySelector('.preview-head');
function updatePreview(data) {
image.src = data.img;
category.textContent = data.category;
}
nav.querySelectorAll(itemSelector).forEach(function(n) {
n.addEventListener('mouseenter', this);
}, e => updatePreview(e.target.dataset));
nav.addEventListener('mouseover', e => {
const data = e.target.closest(itemSelector)?.dataset;
if (data) {
updatePreview(data);
}
});
function output(value) {
const digits = document.querySelectorAll('селектор span`ов');
const { length } = digits;
Array
.from(`${value}`.padStart(length, 0).slice(-length))
.forEach((n, i) => digits[i].innerText = n);
}
function output(value) {
document.querySelector('селектор родительского элемента span`ов').innerHTML = Array
.from(`${value}`, n => `<span>${n}</span>`)
.join('');
}
const [ first, ...rest ] = document.querySelectorAll('[type="checkbox"]');
const onChange = () => first.checked = rest.every(n => n.checked);
first.addEventListener('change', () => rest.forEach(n => n.checked = first.checked));
rest.forEach(n => n.addEventListener('change', onChange));
img
:const { images } = new DOMParser().parseFromString(html, 'text/html');
// или
const images = document
.createRange()
.createContextualFragment(html)
.querySelectorAll('img');
// или
const images =
(el => (el.innerHTML = html, el.getElementsByTagName('img')))
(document.createElement('div'));
img
извлечь значения src
и srcset
:const getSrc = img => [ img.src, img.srcset ];
// или
const getSrc = img => [ 'src', 'srcset' ].map(n => img.getAttribute(n));
// или
const getSrc = ({ attributes: a }) => [ a.src.value, a.srcset.value ];
const result = Array.from(images, getSrc);
// или
const result = Array.prototype.map.call(images, getSrc);
// или
const result = [];
for (const n of images) {
result.push(getSrc(n));
}
// или
const result = [];
for (let i = 0; i < images.length; i++) {
result[i] = getSrc(images[i]);
}
// или
const result = (function get(i, n = images.item(i)) {
return n ? [ getSrc(n), ...get(i + 1) ] : [];
})(0);
const parent = document.querySelector('селектор элемента, из которого надо кого-то удалить');
const elements = parent.children;
const toRemove = [ 3, 1, 666, 2 ];
toRemove
.map(n => elements[n])
.filter(Boolean)
.forEach(n => n.remove());
// или
for (const n of toRemove.sort((a, b) => b - a)) {
elements.item(n)?.replaceWith();
}
// или
parent.replaceChildren(...Array.prototype.filter.call(
elements,
((index, _, i) => !index.has(i)).bind(null, new Set(toRemove))
));
// или
Array.prototype.reduceRight.call(
elements,
(_, n, i) => toRemove.includes(i) && parent.removeChild(n),
null
);
// или
parent.innerHTML = Array
.from(elements, n => n.outerHTML)
.filter((_, i) => !~toRemove.indexOf(i))
.join('');
// или
parent
.querySelectorAll(toRemove.map(n => `:scope > :nth-child(${-~n})`))
.forEach(n => n.outerHTML = '');
const getStrs = (arrs, len) => [
'*'.repeat(len + 2),
...arrs.flatMap(arr => arr
.reduce((acc, n) => {
let g = acc[acc.length - 1];
(g && (g[1] + n.length + !!g[0].length) <= len) || acc.push(g = [ [], 0 ]);
g[1] += n.length + !!g[0].length;
g[0].push(n);
return acc;
}, [])
.map((n, i, a) => `*${n[0].join(' ')[a.length > 1 ? 'padStart' : 'padEnd'](len, ' ')}*`)),
'*'.repeat(len + 2),
];
console.log(getStrs(textArray, 16));
.children(i)
$.each(res, function(i, n) {
this
.eq(i)
.html(`${n[1]}<input type="hidden" value="${n[0]}">`)
.css('display', 'block');
}.bind($('.box-results-search').children()));
{ key: первый индекс, где встречается key }
:const keyIndex = arr.reduce((acc, n, i) => (acc[n.key] ??= i, acc), {});
id
. Можно отсортировать существующий массив:arr.sort((a, b) => (keyIndex[a.key] - keyIndex[b.key]) || (a.id - b.id));
const sorted = (arr, keys) => arr
.map(n => [ n ].concat(keys(n)))
.sort((a, b) => {
let diff = 0;
for (let i = 0; ++i < a.length && !(diff = a[i] - b[i]);) ;
return diff;
})
.map(n => n[0]);
const sortedArr = sorted(arr, n => [ keyIndex[n.key], n.id ]);
const reverse = num =>
+[...`${Math.abs(num)}`].reverse().join('');
function reverse(num) {
let result = 0;
for (num *= Math.sign(num); num;) {
result = result * 10 + (num % 10);
num = Math.floor(num / 10);
}
return result;
}
function getWinner(points) {
const [ a, b ] = points.reduce((acc, n) => (
n.split('-').forEach((m, i) => acc[i] += +m),
acc
), [ 0, 0 ]);
return a === b
? undefined
: a < b ? 2 : 1;
}
const getWinner = points =>
[ 2, , 1 ][-~Math.sign(eval(points.join('+')))];
pre
вместо div
)white-space: pre;
font-family: monospace;
JSON.stringify
, и почитайте. При чтении обратите внимание на то, что параметров у него больше одного. const buttonSelector = 'input[name="group"]';
const contentSelector = '.click';
const activeClass = 'show';
// делегирование, обработчик события добавляем один раз, на документ;
// соответствие между радиокнопками и блоками устанавливаем через равенство атрибутов
document.addEventListener('change', ({ target: t }) => {
if (t.matches(buttonSelector)) {
document.querySelectorAll(contentSelector).forEach(n => {
n.classList.toggle(activeClass, n.dataset.click === t.id);
});
}
});
// или, назначаем обработчик события каждой кнопке индивидуально;
// соответствие между радиокнопками и блоками устанавливаем через равенство индексов
const buttons = document.querySelectorAll(buttonSelector);
const contents = document.querySelectorAll(contentSelector);
const onChange = ({ target: t }) =>
buttons.forEach((n, i) => contents[i].classList.toggle(activeClass, n === t));
buttons.forEach(n => n.addEventListener('change', onChange));
Object.values(data.reduce((acc, n) => {
(acc[n.code] ||= {
code: n.code,
name: n.name,
variants: [],
}).variants.push(n);
return acc;
}, {}))
function xxx(arr, num) {
let index = -1;
return () => num * arr[index = (index + 1) % arr.length];
}
const f = xxx([ 5, 6, 9 ], 2);
console.log([...Array(10)].map(f)); // [10, 12, 18, 10, 12, 18, 10, 12, 18, 10]
код до вложенной функции менять нельзя
То есть засовывать переменные в массив нечестно
function xxx(num) {
let a = 5;
let b = 6;
let c = 9;
return () => num * ([ a, b, c ] = [ b, c, a ])[2];
// или
return () => num * (t => (a = b, b = c, c = t))(a);
// или
return function() {
return num * this[0][++this[1] % this[0].length];
}.bind([ [ a, b, c ], -1 ]);
// или
return (iter => () => num * iter.next().value)((function*() {
for (;; yield a, yield b, yield c) ;
})());
// или
return (i => () => num * (
i = -~i % 3,
i === 0 ? a :
i === 1 ? b :
c
))(-1);
}
const itemSelector = 'селектор блока';
const buttonSelector = 'селектор кнопки';
$(document).on('click', buttonSelector, function() {
$(this)
.closest(itemSelector)
.prev()
.find(buttonSelector)
.prop('disabled', false);
});
// или
document.addEventListener('click', ({ target: t }) => {
const prev = t
.closest(buttonSelector)
?.closest(itemSelector)
.previousElementSibling
?.querySelector(buttonSelector);
if (prev) {
prev.disabled = false;
}
});
const getFromTree = (tree, childrenKey, getter = n => n) =>
Array.isArray(tree)
? tree.flatMap(n => [
getter(n),
...getFromTree(n[childrenKey], childrenKey, getter),
])
: [];
// или
function* flatTree(tree, childrenKey) {
if (
tree instanceof Object &&
tree[Symbol.iterator] instanceof Function
) {
for (const n of tree) {
yield n;
yield* getFromTree(n[childrenKey], childrenKey);
}
}
}
const getFromTree = function(tree, childrenKey, getter = n => n) {
const result = [];
for (const stack = this(tree); stack.length;) {
const n = stack.pop();
result.push(getter(n));
stack.push(...this(n[childrenKey]));
}
return result;
}.bind(x => x instanceof Array ? [...x].reverse() : []);
// или
const flatTree = function*(tree, childrenKey) {
const stack = [];
for (let [ i, arr ] = this(tree); ++i < arr.length || stack.length;) {
if (i === arr.length) {
[ i, arr ] = stack.pop();
} else {
yield arr[i];
stack.push([ i, arr ]);
[ i, arr ] = this(arr[i][childrenKey]);
}
}
}.bind(x => [ -1, x?.constructor === Array ? x : [] ]);
// т.к. id верхнего уровня получать не желаете, избавимся от него
const withoutTopLevel = data.flatMap(n => n.children);
// если использовать обычную функцию
const ids = getFromTree(withoutTopLevel, 'children', n => n.id);
// или, генератор
const ids = Array.from(flatTree(withoutTopLevel, 'children'), n => n.id);
const createItem = obj => ({ key: `${obj.name}-${obj.id}`, title: obj.name });
const result = Object.values(columnList.reduce((acc, n) => {
(acc[n.table.id] ??= {
...createItem(n.table),
children: [],
}).children.push(createItem(n));
return acc;
}, {}));