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'];
}
}
var found = false
, в случае если совпадение найдено - устанавливаете её в true. А код из блока else выносите за цикл и оборачиваете в if (!found)
. switch = !switch
происходит рендеринг двух разных списков
<transition name="fade">
transition-group
.<li v-for="elements in myData" v-if="elements.key == getKey()">
const getCard = num => cards.find(n => n.id === num);
// ...
const card = getCard(cardRandom(1, 51));
id
. Может, лучше использовать случайное число как индекс? Типа так:const card = cards[Math.random() * cards.length | 0];
const TYPES = {
1: 'region',
3: 'area',
7: 'street',
};
const newItems = items.map(({ parents_names, parents_levels, ...n }) =>
parents_names.reduce((acc, name, i) => (
acc[TYPES[parents_levels[i]]] = name,
acc
), n)
);
Подсказали что правильно сделать через атрибут data-*
data-key
, как у тех элементов, по клику на которые блоки надо показывать. По клику хватаете все блоки и показываете те, у которых data-key
совпал с кликнутым, остальные скрываете:$(document).on('click', 'a[data-key]', function() {
$('div[data-key]')
.hide()
.filter((i, n) => n.dataset.key === this.dataset.key)
.show();
});
<div v-if="my_dates['2018-04-23']">{{ myvalue }}</div>
myvalue() {
сonst date = this.my_dates['2018-04-23'];
return date ? Number(date.april) + Number(date.may) : null;
}
Имеется довольно большая матрица (чем больше- тем лучше).
Как правильно отрисовать её на странице?
Хотелось бы еще и с нормальной частотой, хотя-бы раз в 50 ms.
не будет ли быстрее преобразовывать матрицу в строку через arr.toString()...
Картинка
const index = str.search(/\d\D*$/);
// или
const index = str.replace(/\D*$/, '').length - 1;
// или
const index = [...str].reduce((max, n, i) => +n === +n ? i : max, -1);
// или
const index = +(Object.entries(str).filter(n => !isNaN(n[1])).pop() || [ -1 ])[0];
// или
let index = str.length;
while (--index >= 0 && !'0123456789'.includes(str[index])) ;
$('#imgTitle').find('img').remove().end().prepend(...
И еще почему всегда первый элемент в опций виден как undefined ?
И если убрать ng-model то 1-ая опций undefined не будет.
If the viewValue of ngModel does not match any of the options, then the control will automatically add an "unknown" option, which it then removes when the mismatch is resolved.
$('.mod__l').append(function() {
return ({
m1: mod__c1,
m2: mod__c2,
m3: mod__c3,
})[$('.mod__input', this).data('mod')];
});