const labels = document.querySelectorAll('#price_block .change_model_iphone .item label');
const select = document.querySelector('#select_model');
const getFor = el => el.getAttribute('for');
// или
const getFor = el => el.attributes.for.value;
// или
const getFor = el => el.htmlFor;
// можно перезаписать разметку
select.innerHTML = Array
.from(labels, n => `<option value="${getFor(n)}">iPhone ${n.innerText}</option>`)
.join('');
// или, напрямую создавать новые элементы
select.append(...Array.prototype.map.call(
labels,
n => new Option(`iPhone ${n.textContent}`, getFor(n))
));
<div class="text">hello, world!!</div>
<div class="text">fuck the world</div>
<div class="text">fuck everything</div>
<select></select>
const texts = document.querySelectorAll('.text');
const select = document.querySelector('select');
select.append(...Array.from(texts, n => new Option(n.textContent)));
select.value = null;
select.addEventListener('change', ({ target: { selectedIndex } }) => {
texts.forEach((n, i) => n.classList.toggle('active', i === selectedIndex));
});
const select = document.querySelector('[name="select_model"]');
const radios = document.querySelectorAll('[name="model"]');
select.addEventListener('change', ({ target: { value } }) => {
Array.prototype.find.call(radios, n => n.value === value).checked = true;
});
radios.forEach(function(n) {
n.addEventListener('change', this);
}, e => select.value = e.target.value);
В компоненте так же прописано удаление "EventListener", но так как компонент сохраняет своё состояние (keep-alive), данный метод не удаляет "слушателя скролла".
<canvas width="400" height="400"></canvas>
const canvas = document.querySelector('canvas');
const w = canvas.width;
const h = canvas.height;
const ctx = canvas.getContext('2d');
ctx.translate(w / 2, h / 2);
ctx.fillStyle = 'red';
const steps = 30;
for (let i = 0; i < steps; i++) {
ctx.beginPath();
ctx.arc(w / 4, h / 4, 5, 0, 2 * Math.PI, false);
ctx.rotate(2 * Math.PI / steps);
ctx.fill();
ctx.closePath();
}
const classPrefix = 'toggle-';
.// вариант попроще - хватаем всё, что содержит указанную подстроку; так можно нарваться
// на выполнение бессмысленной работы, будут отобраны элементы, у которых ничего
// не будет удалено - это если подстрока находится не в начале класса, например xxx-toggle-xxx
const elements = document.querySelectorAll(`[class*="${classPrefix}"]`);
// вариант посложнее, поуродливее, но без обработки лишнего - хватаем элементы,
// у которых класс начинается с указанной подстроки, или содержит указанную подстроку,
// а перед ней ещё есть пробел
const elements = document.querySelectorAll(`[class^="${classPrefix}"], [class*=" ${classPrefix}"]`);
const reg = RegExp(`(^|\\s)${classPrefix}`);
elements.forEach(n => n.className = n.className.split(reg).join(' ').trim());
// или
elements.forEach(function(n) {
n.classList.value = n.classList.value.replace(this, '$1');
}, RegExp(`(^| )${classPrefix}`, 'g'));
// или
for (const { classList: cl } of elements) {
for (const n of [...cl]) {
if (n.startsWith(classPrefix)) {
cl.remove(n);
cl.add(n.slice(classPrefix.length));
}
}
}
$('#searchSity').autocomplete('search', '');
выводить содержимое данного тега в консоль...
<li v-for="n in items" @click="onClick(n)">
{{ n.message }}
</li>
methods: {
onClick(item) {
console.log(item.message);
}
}
...или в какой-то блок
<li v-for="n in items" @click="$emit('select', n)">
{{ n.message }}
</li>
<b-list @select="selected = $event"></b-list>
<div v-if="selected">{{ selected.message }}</div>
data: () => ({
selected: null,
...
})
shower[index] = !shower[index]
$set(shower, index, !shower[index])
data: () => ({
items: [
{ name: '...', show: false },
{ name: '...', show: false },
...
],
...
}),
<span @click="item.show = !item.show">{{ item.name }}</span>
<div class="dialog_show" v-if="item.show">{{ index }}</div>
const getValues = (obj, count) =>
count > 0
? Object.values(obj).slice(0, count)
: [];
function getValues(obj, count) {
const result = [];
for (const k in obj) {
if (result.length >= count) {
break;
} else if (obj.hasOwnProperty(k)) {
result.push(obj[k]);
}
}
return result;
}
const groupUnique = (arr, idKey, ...keys) => Object
.values(arr.reduce((acc, n) => {
const id = n[idKey];
acc[id] = acc[id] || keys.reduce((group, k) => (group[k] = [], group), {...n});
keys.forEach(k => acc[id][k].push(...n[k]));
return acc;
}, {}))
.map(n => (keys.forEach(k => n[k] = [...new Set(n[k])]), n));
const result = groupUnique(arr, 'family', 'variants', 'subsets');
Как лучше удалять весь текст с input полей при клонировании елемента ?
.form-row
, а не один из элементов, которые присутствуют в #BodyForm
.подскажите как избежать удаления последнего элемента
#BodyForm
- тоже очевидно: получаете последний элемент в функции удаления и сравниваете его с удаляемым, если равны, ничего не делаете.<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
<div id="BodyForm">
<div class="form-row form-row-data">
<div class="form-group col-sm-3">
<input type="text" class="form-control" placeholder="Name">
</div>
<div class="form-group col-sm">
<input type="text" class="form-control" placeholder="Value">
</div>
<div class="form-group col-sm-auto">
<button type="button" class="btn btn-secondary btn-block" onclick="delRow(this)">
<em class="fa fa-minus"></em>
</button>
</div>
</div>
<div class="form-row justify-content-end">
<div class="col-sm-4">
<button type="button" class="btn btn-outline-success btn-block pull-right" onclick="addRow()">
<i class="fa fa-plus"> Add</i>
</button>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-outline-danger btn-block pull-right">
<i class="fa fa-trash"> Clear all</i>
</button>
</div>
</div>
</div>
const form = document.querySelector('#BodyForm');
const rows = form.getElementsByClassName('form-row-data');
const row = rows[0].cloneNode(true);
const footer = form.querySelector('.justify-content-end');
const addRow = () => footer.before(row.cloneNode(true));
const delRow = el => rows.length > 1 && el.closest('.form-row-data').remove();
const locations = [
{ latlng: [55.692222,37.532778] },
{ latlng: [55.743889,37.4975] },
{ latlng: [55.793611,37.5875] },
{ latlng: [55.73852,37.61734] },
{ latlng: [55.7408,37.7469] },
];
const iconDefault = 'https://icons.iconarchive.com/icons/icons-land/vista-map-markers/32/Map-Marker-Marker-Outside-Pink-icon.png';
const iconActive = 'https://icons.iconarchive.com/icons/icons-land/vista-map-markers/32/Map-Marker-Marker-Outside-Chartreuse-icon.png';
function onClick() {
locations.forEach(n => n.marker.setIcon(n.marker !== this ? iconDefault : iconActive));
}
google.maps.event.addDomListener(window, 'load', function() {
const map = new google.maps.Map(document.querySelector('#map'), {
zoom: 11,
center: new google.maps.LatLng(55.74, 37.58),
});
locations.forEach(n => {
n.marker = new google.maps.Marker({
position: new google.maps.LatLng(...n.latlng),
map: map,
icon: iconDefault
});
n.marker.addListener('click', onClick);
});
});
<div id="e1">1</div>
<div id="e2">22</div>
<div id="e3">333</div>
<div id="e4">4444</div>
<div id="e5">55555</div>
#e1, #e2, #e3, #e4, #e5 {
position: absolute;
top: 0;
left: 0;
animation: change 1250ms infinite steps(1);
}
#e2 { animation-delay: -1000ms; }
#e3 { animation-delay: -750ms; }
#e4 { animation-delay: -500ms; }
#e5 { animation-delay: -250ms; }
@keyframes change {
0%, 20% {
opacity: 1;
}
20%, 100% {
opacity: 0;
}
}
$grouped = [];
foreach ($result as $r) {
$key = $r['date'];
if (!isset($grouped[$key])) {
$grouped[$key] = $r;
} else {
$grouped[$key]['item'] += $r['item'];
$grouped[$key]['summ'] += $r['summ'];
}
}