I have the following HTML:
<div class="wrapper">
<div class="item" id="item-1">
</div>
<div class="item" id="item-2">
</div>
<div class="item" id="item-3">
</div>
</div>
And in javascript I'm currently applying filters & sort to the results of an array:
results = Object.keys(list).filter(.....);
results = results.sort((a, b) => (....) ? 1 : -1);
// After the results have been filtered & sorted, hide all HTML elements:
document.querySelectorAll('.item').forEach(i => i.classList.add('d-none'));
// And then proceed to show only the results that have been filtered & sorted:
results.forEach(index =>
{
let id = list[index].id;
let item = document.getElementById('item-' + id);
item.classList.remove('d-none');
});
This works great. The problem is that now I need to move the HTML elements according to the results array, specifically with the id field.
A) Expected output: Array ids [2, 1]
<div class="wrapper">
<div class="item" id="item-2">
</div>
<div class="item" id="item-1">
</div>
<div class="item d-none" id="item-3">
</div>
</div>
B) Expected output: Array ids [2]
<div class="wrapper">
<div class="item" id="item-2">
</div>
<div class="item d-none" id="item-1">
</div>
<div class="item d-none" id="item-3">
</div>
</div>
One way would be to
let results = [2,1]
let wrapper = document.getElementById('wrapper-id')
wrapper.innerHTML = results.map(id => document.querySelector('#item-' + id))
.concat([...document.querySelectorAll('.d-none')])
.map(elem => elem.outerHTML)
.join('')
<div class="wrapper" id="wrapper-id">
<div class="item" id="item-1">
item-1
</div>
<div class="item" id="item-2">
item-2
</div>
<div class="item d-none" id="item-3">
item-3
</div>
</div>
You can move elements to the top, using prepend function.
On bellow example, I only implement the logic about move elements, and I didn't protected against non existent elements. You should add your logic's about filtering, etc. and protect for possible errors.
function sortDivs() {
let list = [2, 1];
let mainDiv = document.querySelectorAll('.wrapper')[0];
list.reverse().forEach(n => mainDiv.prepend(document.getElementById('item-'+n)));
}
.item {
border: black solid;
}
<div class="wrapper">
<div class="item" id="item-1">
item-1
</div>
<div class="item" id="item-2">
item-2
</div>
<div class="item" id="item-3">
item-3
</div>
</div>
<br>
<button onClick="sortDivs()"> sort DIVs</button>
Solved.
I had several problems:
The first one was instead of using Object.keys(results).filter I should be using results.filter, because I don't need to get only the Keys, which was making things way harder.
Secondly, the logic to apply in order to have everything re-organizing according to multiple filters is:
d-none)const wrapperItems = wrapper.childrenwrapperNewItems that holds the new sorted/filtered itemsd-noned-noneTranslated into code:
document.querySelectorAll('.item').forEach(i => i.classList.add('d-none'));
const wrapper = document.getElementsByClassName('wrapper')[0];
// Saves the existing children
const wrapperItems = wrapper.children;
// Holds the new items ordered perfectly
let wrapperNewItems = [];
// Holds names that were filtered (item-1, item-2, etc)
let listOfNamesFiltered = [];
// Shows only the items filtered
results.forEach(item =>
{
let name = 'item-' + item.id;
let el = document.getElementById(name);
el.classList.remove('d-none');
wrapperNewItems.push(el);
listOfNamesFiltered.push(name);
});
for (let i = 0; i < wrapperItems.length; i++)
{
let item = wrapperItems[i];
let name = item.id; // id="" already contains "item-{id}"
// If the name already exists in the list, we won't add it again
if (listOfNamesFiltered.includes(name))
continue;
wrapperNewItems.push(item);
}
// Clears the div
wrapper.innerHTML = '';
// Appends the items once again
for (let i = 0; i < wrapperNewItems.length; i++)
wrapper.innerHTML += wrapperNewItems[i].outerHTML;