const selector = '.box';
.document.addEventListener('click', ({ target: t }) => {
if (t = t.closest(selector)) {
for (const n of document.querySelectorAll(selector)) {
n.style.background = n === t ? 'red' : 'black';
}
}
});
.box { background: black; }
.box.active { background: red; }
document.addEventListener('click', function({ target: t }) {
if (t = this.find(n => n.contains(t))) {
this.forEach(n => n.classList.toggle('active', n === t));
}
}.bind([...document.querySelectorAll(selector)]));
document.querySelectorAll(selector).forEach(function(n) {
n.addEventListener('click', this);
}, function() {
document.querySelector(`${selector}.active`)?.classList.remove('active');
this.classList.add('active');
});
function getDatesGroupedByWeekday(year, month) {
const d = new Date(`${month} 1, ${year}`);
const iMonth = d.getMonth();
const result = {};
while (d.getMonth() === iMonth) {
const date = d.getDate();
const weekday = d.toLocaleString('en-US', { weekday: 'long' });
(result[weekday] = result[weekday] ?? []).push(date);
d.setDate(date + 1);
}
return result;
}
const block = document.querySelector('.block');
const wrapper = document.createElement('div');
wrapper.classList.add('another__block');
const parent = block.parentNode;
const childNodes = [...parent.childNodes];
wrapper.append(...childNodes.slice(-~childNodes.indexOf(block)));
parent.append(wrapper);
for (let n; n = block.nextSibling; wrapper.appendChild(n)) ;
block.after(wrapper);
fetch('https://jsonplaceholder.typicode.com/albums')
.then(r => r.json())
.then(r => {
const keys = [ 'userId', 'id', 'title' ];
// собираем разметку
document.body.insertAdjacentHTML('beforeend', `
<div class="wrapper">${r.map(n => `
<div class="item">${keys.map(k => `
<div>${k}: ${n[k]}</div>`).join('')}
</div>`).join('')}
</div>
`);
// или, создаём элементы напрямую
function createElement(tag, className, children) {
const el = document.createElement(tag);
el.className = className;
el.append(...children);
return el;
}
document.body.append(
createElement('div', 'wrapper', r.map(n =>
createElement('div', 'item', keys.map(k =>
createElement('div', '', [ `${k}: ${n[k]}` ])
))
))
);
});
.wrapper {
border: 3px solid black;
padding: 10px;
margin: 10px;
}
.item {
border: 1px solid silver;
padding: 5px;
margin: 5px;
}
.img-block
, а у их самых дальних не общих предков, т.е., у .documents_block
. В этом случае не придётся переписывать js-код, если вдруг потребуется стилизовать ещё-что то, кроме .img-block
, или если решите изменить внутреннюю структуру .documents_block
. Вместо .класс
дополнительные стили надо будет прописывать у .класс .img-block
.const itemSelector = '.documents_block';
const buttonSelector = `${itemSelector} .open-doc-list`;
const contentSelector = '.documents-content';
const activeClass = 'active';
const toggleEffect = 'slideToggle'; // или fadeToggle, или toggle
const onClick = e => $(e.currentTarget)
.closest(itemSelector)
.toggleClass(activeClass)
.find(contentSelector)
[toggleEffect]();
// обработчик клика подключаем к кнопкам
$(buttonSelector).click(onClick);
// или, если предполагается добавление новых блоков уже после подключения
// обработчика, то лучше будет повесить его на документ, тогда всё будет
// работать как надо без каких-либо дополнительных действий
$(document).on('click', buttonSelector, onClick);
const fourValues = four.map(Object.values);
const result = three.map(n => {
const values = Object.values(n);
const intersections = fourValues.filter(m => values.every(v => m.includes(v)));
return `${values} - ${intersections.length
? `входит в / ${intersections.map(m => `${m}`).join(' / ')} /`
: 'нет вхождений'}`;
});
const containerSelector = '.bakeries-slider';
const itemSelector = '.bakeries-slider__span';
const getNumber = i => (i + 1) + '.';
// или
const getNumber = i => `${-~i}.`;
// или
const getNumber = i => ''.concat(++i, '.');
$(containerSelector).each(function() {
$(itemSelector, this).text((i, text) => text + getNumber(i));
});
document.querySelectorAll(containerSelector).forEach(container => {
const items = container.querySelectorAll(itemSelector);
// индекс передаётся в коллбек forEach'а
items.forEach((n, i) => n.textContent += getNumber(i));
// или, отдаётся итератором entries
for (const [ i, n ] of items.entries()) {
n.appendChild(document.createTextNode(getNumber(i)));
}
// или, можно самостоятельно обновлять переменную с индексом
for (let i = 0; i < items.length; i++) {
items[i].insertBefore(new Text(getNumber(i)), null);
}
// причём цикл для этого не обязателен
(function next(i, n = items.item(i)) {
n && (n.append(getNumber(i)), next(-~i));
})(0);
});
$('#m_prev').click
и $('#m_next').click
за пределы $('.norutyun img').click
. const key = 'status';
const value = 'maybe';
const newArr = arr.filter(n => !n[key].includes(value));
const reg = RegExp(`\\b${value}\\b`);
const newArr = arr.filter(n => !reg.test(n[key]));
// или
const newArr = arr.filter(function(n) {
return !n[key].match(this);
}, RegExp(`(^| )${value}( |$)`));
// или
const newArr = arr.filter(n => !n[key].split(' ').includes(value));
$('#sortable').sortable({
stop() {
const values = $('input[name="slider-id"]', this).get().map(n => n.value);
},
});
const key = 'workplace';
const values = [ 'office', 'hotel' ];
const result = arr.filter(function(n) {
return this.has(n[key]);
}, new Set(values));
// или
const result = values.flatMap(((grouped, n) => grouped[n] ?? []).bind(
null,
arr.reduce((acc, n) => ((acc[n[key]] = acc[n[key]] ?? []).push(n), acc), {})
));
// или
const result = [];
for (const n of arr) {
for (const m of values) {
if (m === n[key]) {
result.push(n);
break;
}
}
}
// или
const result = [];
for (let i = 0; i < arr.length; i++) {
if (~values.indexOf(arr[i][key])) {
result[result.length] = arr[i];
}
}
// или
const result = (function get(i, n = arr[i]) {
return n
? [].concat(values.includes(n[key]) ? n : [], get(-~i))
: [];
})(0);
#list-case
вы назначаете обработчики клика всем существующим .img
и .show
, а не только свежесозданным. Если срабатывает два (или четыре, или шесть, или...) обработчика, которые выполняют toggleClass, то конечное состояние от начального отличаться не будет. Отсюда ваше кажущееся "не работает"..case
, делайте это один раз, используя делегирование:$('#list-case')
.on('click', '.img', function() {
$(this).closest('.case').remove();
})
.on('click', '.show', function() {
$(this).toggleClass('none').closest('.case').find('.case-bottom').toggleClass('invise');
});
const placeholders = [ 'hello, world!!', 'fuck the world', 'fuck everything' ];
const delay = 200;
const input = document.querySelector('input');
function interval(arr, delay, callback) {
let i = -1;
return arr.length
? setInterval(() => callback(arr[i = -~i % arr.length]), delay)
: null;
}
const intervalId = interval(placeholders, delay, n => input.placeholder = n);
// хотим остановить, делаем так: clearInterval(intervalId);
function interval(arr, delay, callback) {
let timeoutId = null;
arr.length && (function next(i) {
timeoutId = setTimeout(() => {
callback(arr[i]);
next((i + 1) % arr.length);
}, delay);
})(0);
return () => clearTimeout(timeoutId);
}
const stop = interval(
placeholders,
delay,
Element.prototype.setAttribute.bind(input, 'placeholder')
);
// хотим остановить, делаем так: stop();
return false;
toggle дважды начинает срабатывать
const comparators = [
[ 'city', (itemVal, filterVal) => itemVal === filterVal ],
[ 'title', (itemVal, filterVal) => itemVal.includes(filterVal) ],
[ 'type', (itemVal, filterVal) => itemVal.includes(filterVal) ],
];
const filteredArr = arr.filter(n => comparators.every(([ k, f ]) => f(n[k], filter[k])));