Tengo el siguiente 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>Y en javascript actualmente estoy aplicando filtros y ordenando los resultados de una matriz:
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'); }); Esto funciona muy bien. El problema es que ahora necesito mover los elementos HTML de acuerdo con la matriz de results , específicamente con el campo de id .
A) Salida esperada : 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) Salida esperada : 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>Una forma sería
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>Puede mover elementos a la parte superior, usando la función prepend .
En el siguiente ejemplo, solo implemento la lógica sobre mover elementos, y no me protegí contra elementos inexistentes. Debe agregar su lógica sobre filtrado, etc. y protegerse de posibles errores.
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>Resuelto
Tuve varios problemas:
El primero fue en lugar de usar Object.keys(results).filter , debería usar results.filter , porque no necesito obtener solo las claves, lo que dificultaba mucho las cosas.
En segundo lugar, la lógica a aplicar para que todo se reorganice de acuerdo con múltiples filtros es:
d-none )const wrapperItems = wrapper.childrenwrapperNewItems que contenga los nuevos elementos ordenados/filtradosd-noned-noneTraducido a código:
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;