$('.button').click(function() {
const $this = $(this);
const $content = $this.closest('.item').find('.block');
if ($this.hasClass('closed')) {
$this.removeClass('closed').html('Скрыть ↑');
$content.slideDown();
} else {
$this.addClass('closed').html('Показать ↓');
$content.slideUp();
}
}).click();
function onClick() {
const color = `#${(Math.random() * 0xFFFFFF | 0).toString(16).padStart(6, 0)}`;
document.querySelectorAll(`.${this.id}`).forEach(n => {
n.style.backgroundColor = color;
});
}
document.querySelectorAll('li').forEach(n => n.addEventListener('click', onClick));
const audio = new Audio();
const queue = [];
audio.onended = function() {
if (queue.length) {
audio.src = queue.shift();
audio.play();
}
};
function play(srcArray) {
queue.push(...srcArray);
if (audio.paused) {
audio.onended();
}
}
play([ '1.mp3', '2.mp3', '3.mp3' ]);
Вешаю на него сеттер...
function test(m) {
let money = m;
Object.defineProperty(this, 'money', {
get() {
return money;
},
set(val) {
alert(`Значение свойства money меняется с ${money} на ${val}`);
money = val;
},
});
}
function test(m) {
this.money = m;
return new Proxy(this, {
set(target, prop, val) {
alert(`Значение свойства ${prop} меняется с ${target[prop]} на ${val}`);
target[prop] = val;
return true;
},
});
}
img
класс лучше переключать у article
- максимально дальних не общих предков картинок. Если вдруг захотите при кликах на кнопки стилизовать ещё что-то помимо картинок, или измените взаимное расположение элементов, то не придётся переписывать js-код. Стили, конечно, придётся немного поправить, вместо .active
будет .active img
.const container = document.querySelector('.container');
const itemSelector = 'article';
const buttonSelector = `${itemSelector} .btn`;
const activeClass = 'active';
container.addEventListener('click', e => {
const button = e.target.closest(buttonSelector);
if (button) {
button.closest(itemSelector).classList.toggle(activeClass);
}
});
container.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, e => e.currentTarget.closest(itemSelector).classList.toggle(activeClass));
<div id="container"></div>
const container = document.querySelector('#container');
const text = 'hello, world!!';
const delay = 300;
// можно сразу назначить таймауты для каждого из символов текста
for (const [ i, n ] of Array.prototype.entries.call(text)) {
setTimeout(() => {
container.insertAdjacentHTML('beforeend', `<span>${n}</span>`);
}, 300 * i);
}
// или, назначать следующий таймаут после выполнения предыдущего
(function step(i) {
if (i < text.length) {
const span = document.createElement('span');
span.textContent = text[i];
container.insertAdjacentElement('beforeend', span);
setTimeout(step, delay, i + 1);
}
})(0);
// или, вместо множества таймаутов назначить один интервал
let i = 0;
const intervalId = setInterval(() => {
const span = document.createElement('span');
span.innerText = text[i];
container.append(span);
if (++i >= text.length) {
clearInterval(intervalId);
}
}, delay);
span {
display: inline-block;
animation: span .2s ease-out;
font-size: 40px;
}
@keyframes span {
from {
transform: translateX(500px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
arr.sort((a, b) => moment(b.date, 'DD.MM.YY') - moment(a.date, 'DD.MM.YY'));
const newArr = arr
.map(n => [ n, +n.date.split('.').reverse().join('') ])
.sort((a, b) => b[1] - a[1])
.map(n => n[0]);
array[i+1]=true;
array[i+1]=true;
(или array[i+1]=false;
, в зависимости от условия) - массив снова увеличился, опять цикл не завершился, ну и так далее - массив будет жиреть до тех пор, пока станет невозможно выделить ему ещё памяти.const ops = {
OR: arr => arr.some(Boolean),
AND: arr => arr.every(Boolean),
XOR: arr => !!arr.reduce((p, c) => p ^ c, 0),
};
const logicalCalc = (arr, op) => ops[op](arr);
const ops = {
OR(arr) {
for (const n of arr) if (n) {
return true;
}
return false;
},
AND(arr) {
for (const n of arr) if (!n) {
return false;
}
return true;
},
XOR(arr) {
let result = 0;
for (const n of arr) {
result ^= n;
}
return !!result;
},
};
window.name
converts all stored values to their string representations using thetoString
method
Прежде всего мне непонятно зачем происходит сравнение с index.
true
ровно один раз - так как indexOf
возвращает первый индекс, по которому можно найти элемент, равный указанному. То есть, если indexOf
текущего элемента равен текущему индексу, значит элемент встречен впервые, и его надо оставить. const combinations = (
str,
{
charset = 'abcdefghijklmnopqrstuvwxyz',
placeholder = '&',
} = {}
) =>
str.includes(placeholder)
? [].concat(...Array.from(
charset,
n => combinations(str.replace(placeholder, n), { charset, placeholder })
))
: [ str ];
console.log(combinations('ih&v&'));
function combinations(
[...str],
{
charset = Array.from({ length: 26 }, (_, i) => String.fromCharCode(i + 97)),
placeholder = '&',
} = {}
) {
const numReplacements = str.filter(n => n === placeholder).length;
return Array.from(
{ length: charset.length ** numReplacements },
(_, i) => {
let j = numReplacements;
return str
.map(n => n === placeholder
? charset[(i / (charset.length ** --j) | 0) % charset.length]
: n)
.join('');
}
);
}
console.log(combinations('#**', { charset: '0123456789ABCDEF', placeholder: '*' }));
var aNum = $('.answers .answer').length;
var aNum = $(this).closest('.answers').find('.answer').length;
- change_element.attr('data-animation-in', $(this).val())
+ change_element.data('animation-in', $(this).val())
- dropdown_container.data('animation-in')
+ dropdown_container.attr('data-animation-in')
data-* attributes are used to initialize jQuery data. An element's data-* attributes are retrieved the first time the data() method is invoked upon it, and then are no longer accessed or mutated (all values are stored internally by jQuery)
$('.test').append('NEW BLOCK!');
$(this).closest('.test').append('NEW BLOCK!');