Tengo una tabla con cuadros de selección en los encabezados de la tabla que filtran las filas. Esta es una tabla grande y el filtrado en una columna de texto con cadenas largas puede llevar algún tiempo. Me gustaría que aparezca una superposición mientras se realiza el filtrado y que se oculte cuando finalice el filtrado.
$('#budget-table select').change(e => { $('#overlay').show() // get the selected options of all the filters at the top. const filters = $('#budget-table th select').find(':selected').map((ind, elt) => elt.innerText) $(`#budget-table tr`).each((trInd, trElt) => { if (trInd == 0) return true // skip the header row let showRow = true // If the filter is not 'All' and the cell value doesn't match the filter, hide the row. $(trElt).children().each((tdInd, tdElt) => { if (filters[tdInd] !== 'All' && filters[tdInd] !== tdElt.innerText) { showRow = false return false } }) showRow ? $(trElt).show() : $(trElt).hide() }) $('#overlay').hide() }) #overlay { background-color: #333; display: none; height: 100%; left: 0; opacity: 0.6; position: fixed; top: 0; width: 100%; z-index: 100; } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="project-list"> <table class="table table-hover table-striped table-rwd" id="budget-table"> <tr> <th> <select class="filter-select" data-columnindex="0" id="filter-input-0"> <option>Option 1</option> <option>Option 2</option> <option>...</option> <option>Option n</option> </select> <div> Territory </div> </th> <th>...several more filters with the same structure</th> </tr> <tr><td colspan="2">...several hundred rows of table data</td></tr> </table> </div> <div id="overlay"> </div> La superposición no se muestra. Sin embargo, si muevo $('#overlay').show() después de la función externa each() , se mostrará la superposición. ¿Qué me estoy perdiendo?
each bucle se ejecutará de forma asíncrona. Para esperar a que finalice el bucle, haga que la devolución de llamada de change sea asíncrona y agregue await antes de each bucle.
$('#budget-table select').change(async e => { $('#overlay').show() // get the selected options of all the filters at the top. const filters = $('#budget-table th select').find(':selected').map((ind, elt) => elt.innerText) $(`#budget-table tr`).each((trInd, trElt) => { if (trInd == 0) return true // skip the header row let showRow = true // If the filter is not 'All' and the cell value doesn't match the filter, hide the row. await $(trElt).children().each((tdInd, tdElt) => { if (filters[tdInd] !== 'All' && filters[tdInd] !== tdElt.innerText) { showRow = false return false } }) showRow ? $(trElt).show() : $(trElt).hide() }) // artificial delay await new Promise(r => setTimeout(r, 500)); $('#overlay').hide() }) #overlay { background-color: #333; display: none; height: 100%; left: 0; opacity: 0.6; position: fixed; top: 0; width: 100%; z-index: 100; } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="project-list"> <table class="table table-hover table-striped table-rwd" id="budget-table"> <tr> <th> <select class="filter-select" data-columnindex="0" id="filter-input-0"> <option>Option 1</option> <option>Option 2</option> <option>...</option> <option>Option n</option> </select> <div> Territory </div> </th> <th>...several more filters with the same structure</th> </tr> <tr> <td colspan="2">...several hundred rows of table data</td> </tr> </table> </div> <div id="overlay"> </div>