const container = document.querySelector('селектор общего предка чекбоксов');
const checkboxSelector = 'селектор чекбоксов';
const minChecked = 1;
const maxChecked = Infinity;
const countChecked = checkboxes =>
Array.prototype.reduce.call(checkboxes, (acc, n) => acc + n.checked, 0);
const checkboxes = container.querySelectorAll(checkboxSelector);
const onChange = () => {
const count = countChecked(checkboxes);
const minReached = count <= minChecked;
const maxReached = count >= maxChecked;
checkboxes.forEach(n => n.disabled = minReached && n.checked || maxReached && !n.checked);
};
checkboxes.forEach(n => n.addEventListener('change', onChange));
container.addEventListener('change', function({ target: t }) {
if (t.matches(checkboxSelector)) {
const count = countChecked(this.querySelectorAll(checkboxSelector));
t.checked ||= count < minChecked;
t.checked &&= count <= maxChecked;
}
});
[Symbol.iterator]() { return this; }
и без:const iter = new Range(1, 5)[Symbol.iterator]();
console.log(iter.next().value);
console.log(iter.next().value);
console.log([...iter]);
Пытаюсь так:
let currentIndex = $(".js-practice_button.current").index();
Но значение всегда 0, у какой бы кнопки классcurrent
не присутствовал.
index
по умолчанию определяет индекс элемента среди соседей, а так как у каждой кнопки есть отдельный родитель... Ну да, получаете то, что получаете.const index = $('.js-practice_button.current').closest('li').index();
index
в качестве параметра селектор, то индекс будет определятся не среди соседей, а среди элементов, соответствующих селектору:const index = $('.js-practice_button.current').index('.js-practice_button');
const container = document.querySelector('.js-practices_buttons');
const itemSelector = '.practice_item';
const buttonSelector = `${itemSelector} .js-practice_button`;
const activeClass = 'current';
const activeSelector = `.${activeClass}`;
const index = Array.prototype.findIndex.call(
container.querySelectorAll(buttonSelector),
n => n.classList.contains(activeClass)
);
// или
const { children } = container;
let index = children.length;
while (index-- && !children[index].matches(`:has(${activeSelector})`)) ;
// или
const index =
(el => el ? [...el.parentNode.children].indexOf(el) : -1)
(container.querySelector(`${itemSelector}:has(${activeSelector})`));
// или
let index = -1;
for (
let el = container.querySelector(activeSelector)?.closest(itemSelector);
el;
el = el.previousElementSibling, index++
) ;
const noRepeatingDigits = num => !/(\d).*\1/.test(num);
// или
const noRepeatingDigits = num => -~Math.log10(num) === new Set(`${num}`).size;
// или
const noRepeatingDigits = num => [...'' + num].every((n, i, a) => i === a.indexOf(n));
// или
const noRepeatingDigits = num => String(num)
.split('')
.reduce((acc, n) => (acc[n]++, acc), Array(10).fill(0))
.every(n => n < 2);
// или
const noRepeatingDigits = num =>
!''.match.call(num, /./g).some(function(n) {
return this[n] = Object.hasOwn(this, n);
}, {});
// или
const noRepeatingDigits = num =>
!Array.from(num.toString()).sort().find((n, i, a) => n === a[i + 1]);
arr.splice(0, arr.length, ...arr.filter(noRepeatingDigits));
// или
let numDeleted = 0;
for (const [ i, n ] of arr.entries()) {
arr[i - numDeleted] = n;
numDeleted += !noRepeatingDigits(n);
}
arr.length -= numDeleted;
// или
for (let i = arr.length; i--;) {
if (!noRepeatingDigits(arr[i])) {
arr.splice(i, 1);
}
}
const newArr = arr.filter(noRepeatingDigits);
// или
const newArr = [];
for (const n of arr) {
if (noRepeatingDigits(n)) {
newArr.push(n);
}
}
// или
const newArr = [];
for (let i = 0; i < arr.length; i++) {
if (noRepeatingDigits(arr[i])) {
newArr[newArr.length] = arr[i];
}
}
// или
const newArr = (function xxx(arr, i = 0) {
return i < arr.length
? (noRepeatingDigits(arr[i]) ? [ arr[i] ] : []).concat(xxx(arr, i + 1))
: [];
})(arr);
const arrs = [
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11 ],
];
const result = [];
const max = Math.max(...arrs.map(n => n.length));
const index = Array(arrs.length).fill(0);
for (let i = 0; i < max; i++) {
for (let j = 0; j < index.length; j++) {
if (index[j] < arrs[j].length) {
result[result.length] = arrs[j][index[j]++];
}
}
}
const result = arrs
.reduce((acc, arr) => (
arr.forEach((n, i) => (acc[i] ??= []).push(n)),
acc
), [])
.flat();
const li = Array.prototype.filter.call(
document.querySelector('ul').children,
function(n) {
return this.every(([ k, v ]) => v === n.querySelector(`.${k}`).innerText);
},
Object.entries(items)
);
const li = [];
COLLECT_LI:
for (const n of document.querySelectorAll('li')) {
for (const k in items) {
if (Object.hasOwn(items, k) && items[k] !== n.querySelector('.' + k).textContent) {
continue COLLECT_LI;
}
}
li.push(n);
}
tags = Array.from(new Set(data.flatMap(n => n.tags)));
tags.splice(0, tags.length, ...new Set(data.flatMap(n => n.tags)));
async function getFirstLoadedImage(urls) {
for (const n of urls) {
try {
return await loadImage(n);
} catch (e) {}
}
throw 'ничего загрузить не удалось';
}
const getFirstLoadedImage = (urls, i = 0) => i < urls.length
? loadImage(urls[i]).catch(() => getFirstLoadedImage(urls, -~i))
: Promise.reject('ничего загрузить не удалось');
getFirstLoadedImage(resolutions.map(n => `https://i.ytimg.com/vi/${videoId}/${n}.jpg`))
.then(img => document.body.append(img))
.catch(console.error);
function groupValues(arr, defaultValue = null) {
const keys = [...new Set(arr.flatMap(Object.keys))];
return arr.reduce((acc, n) => {
keys.forEach(k => acc[k].push(Object.hasOwn(n, k) ? n[k] : defaultValue));
return acc;
}, Object.fromEntries(keys.map(k => [ k, [] ])));
}
const result = groupValues(arr);
const groupValues = (arr, defaultValue = null) =>
arr.reduce((acc, n, i, a) => (
Object.keys(n).forEach(k =>
(acc[k] ??= Array(a.length).fill(defaultValue))[i] = n[k]
),
acc
), {});
const containerSelector = '.selectboxss';
const itemClass = 'selectoption';
const itemSelector = `${containerSelector} .${itemClass}`;
const getClasses = el => Array.prototype.filter.call(el.classList, n => n !== itemClass);
//const getClass = el => el.className.match(RegExp(`${itemClass}-\\d+`))[0];
function updateClasses(item) {
const container = item.closest(containerSelector);
const { classList: cl } = container;
cl.remove(...Array.prototype.flatMap.call(container.querySelectorAll(itemSelector), getClasses));
cl.add(...getClasses(item));
//cl.remove(...Array.from(container.querySelectorAll(itemSelector), getClass));
//cl.add(getClass(li));
}
document.querySelectorAll(itemSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => updateClasses(e.currentTarget));
document.addEventListener('click', e => {
const item = e.target.closest(itemSelector);
if (item) {
updateClasses(item);
}
});
tableValues(element);
element.children
/element.childNodes
.document.querySelector('form').childNodes
children
вместо childNodes
. Ну и погуглите, в чём между ними разница.if (element.nodeType == 1 && element.nodeName == 'INPUT' || element.nodeName == 'SELECT') {
nodeType
лишняя. Кроме того, вам не помешает разобраться с приоритетом выполнения операторов - nodeType
вы тут проверяете только для input'а.let result = [];
const getValues = el =>
el instanceof Element
? [ 'INPUT', 'SELECT' ].includes(el.tagName)
? [ el.value ]
: [...el.children].flatMap(getValues)
: [];
// или
const getValues = el =>
[ 'INPUT', 'SELECT' ].includes(el?.tagName)
? [ el.value ]
: [].flatMap.call(el.children ?? [], getValues);
const values = getValues(document.querySelector('form'));
const values = Array.from(document.querySelector('form').elements, n => n.value);
const getFromDOMNodes = (node, test, getVal) =>
node instanceof Node
? Array.prototype.reduce.call(
node.childNodes,
(acc, n) => (acc.push(...getFromDOMNodes(n, test, getVal)), acc),
test(node) ? [ getVal(node) ] : []
)
: [];
// или
function getFromDOMNodes(root, test, getVal) {
const tw = document.createTreeWalker(root);
const result = [];
for (let n = null; n = tw.nextNode(); test(n) && result.push(getVal(n))) ;
return result;
}
const values = getFromDOMNodes(
document.querySelector('form'),
node => [ 'INPUT', 'SELECT' ].includes(node.nodeName),
node => node.value
);
const values = {
RUS: [ 'раз значение', 'два значение', 'три' ],
US: [ '...', '...', '...' ],
// ...
};
const items = document.querySelectorAll('li');
const buttons = document.querySelectorAll('button');
buttons.forEach(n => n.addEventListener('click', onClick));
function onClick({ target: { innerText: key } }) {
items.forEach(function(n, i) {
n.innerText = this[i] ?? `ЗНАЧЕНИЕ #${i} ДЛЯ ${key} НЕ ЗАДАНО`;
}, values[key] ?? []);
}
const buttonSelector = '.added';
const itemSelector = '.added-block';
const activeClass = '_active';
const notActiveSelector = `${itemSelector}:not(.${activeClass})`;
const newActiveCount = 2;
function onButtonClick(button) {
const items = [...button.parentNode.querySelectorAll(notActiveSelector)];
items.slice(0, newActiveCount).forEach(n => n.classList.add(activeClass));
button.disabled = items.length <= newActiveCount;
}
document.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => onButtonClick(e.currentTarget));
document.addEventListener('click', e => {
const button = e.target.closest(buttonSelector);
if (button) {
onButtonClick(button);
}
});
str.match(/\d+/g).join('.')
/[^\/]+(?=\/$)/.exec(str)[0]
str.match(/[^\/]+/g).pop()
str.split('/').at(-2)
Хук get не позволяет получить параметры вызова метода
function sequence(functions) {
return new Proxy(functions, {
get(target, key) {
const val = target[key];
return val instanceof Function
? (...args) => {
console.log(`${key} called with arguments: `, args);
return val.apply(target, args);
}
: val;
},
});
}