0

I have a JSON file with 15000+ items. My JSON file has about 7MB. I'd like to display all results in a table (without pagination) and add a few checkboxes to display or hide the items under certain conditions. To simplify as much as possible, let's say I have a checkbox to display items from Paris only:

List of items from Paris

The problem is that the UI is not smooth. Clicking on the checkbox takes about one second to refresh the table. It's unacceptable.

I'm using fetch() to download JSON data and then keep it locally. When user clicks on the checkbox, here's what I did:

document.getElementById('paris-only').addEventListener('click', updateTable);

function updateTable() {
    const parisOnly = document.getElementById('paris-only').checked;

    items.forEach(item => item.visible = !parisOnly || item.city === 'Paris');

    refreshTable();
}

function refreshTable() {
    [...document.getElementById('items-table').children].forEach((tr, index) => {
        tr.classList.toggle('hidden', !items[index].visible);
    });
}
.hidden {
    display: none;
}

I tried to play with setTimeout(_, 0), but it doesn't help much. It makes the UI freeze less, but it still takes a lot of time to refresh the table.

Is there any strategy available to make such an interface snappy? One of my ideas was to consider <canvas>, which makes drawing many elements quick, but it doesn't seem very natural for the task.

Another option would be to load data with fetch() on scroll, but I'd like to have all data loaded just once if possible.

What else should I consider?

Robo Robok
  • 21,132
  • 17
  • 68
  • 126
  • instead of iterating over the full list of dom nodes, filter over positions in item and directly modify just those dom nodes by index. works for the example you've given since you're only manipulating Paris entries. there's a lot of infinite scroll table libraries out there that are pretty straightforward to use, and they usually have filtering and sorting built-in. with 15000+ entries it's probably going to be slow no matter what you do. – user120242 May 16 '20 at 19:06
  • @user120242 I'm still curious if that's possible to update DOM smoothly. It's a little disappointing that you can't have a few thousands simple DOM nodes updated instantly in XXI century. – Robo Robok May 16 '20 at 19:17

1 Answers1

0

I'd recommend using classes to signify if a given node should be shown or hidden (e.g. every node with name !== 'Paris' is in the notparis class. You can use javascript to initialize these categories (How do I add a class to a given element?) when you fetch the JSON table, and then showing/hiding can use for (tr of document.getElementsByClassName('notparis')) tr.visible = !parisOnly. If these categories overlap (i.e. you want notparis and notcoldweather), you could probably record which classes are currently visible or hidden and use document.getElementsByClassName('notparis notcoldweather') (this may be a bit more complex, but should maintain performance).

Also, changing the items directly instead of using an intermediate list might be more performant.

Holden Rohrer
  • 586
  • 5
  • 16
  • I'm using `hidden` class already and working on DOM directly instead of pure array is actually slower. – Robo Robok May 16 '20 at 20:20
  • @RoboRobok That's true in general, but I think in this case you _might_ be using the same number of DOM manipulations as if you did it directly, but looking at this problem after some more testing, it doesn't look like there's a way to avoid halting for nearly a second because you still have to hide/show thousands of elements, which is probably breaking at the rendering layer instead of the underlying data manipulation – Holden Rohrer May 16 '20 at 23:58
  • 1
    The data manipulation is really fast, 15k array is not that large. The bottleneck is the DOM itself, which is super slow to manipulate. – Robo Robok May 17 '20 at 00:05