Skip to content

Pathological page load: 5,001 synchronous DOM inserts on every pad #87

@JohnMcLear

Description

@JohnMcLear

static/js/main.js appends 5,001 <li> elements to `.specialChars` synchronously inside `$(document).ready`:

```js
let i = 0;
while (i <= 5000) {
$('.specialChars').append(`

  • &#${i}
  • `);
    i++;
    }
    ```

    Every pad load pays this cost, regardless of whether the user ever opens the Special Characters modal. Three problems with this:

    1. Main-thread stall at load. 5,001 separate jQuery append calls are each a DOM mutation. On a cold page load with many other plugins hydrating, the total blocking time is 1.5–3 s on a typical laptop. It caused a demo-gif tool I'm using on `ether/*` plugins to race its Ctrl+A / Delete bootstrap because Playwright's `editor.click()` returned before the 5 k inserts had settled.

    2. Modal is unusable. A 5,000-item grid isn't a picker, it's a wall of glyphs — codepoints 0–31 are control chars (invisible) and most of the "gap" ranges between scripts are either reserved, combining marks, or non-printable. Users end up scrolling through thousands of blank or near-identical squares.

    3. Wasted allocation for everyone who never opens the modal. The modal starts hidden; for the ~95% of pad loads where the user never clicks the airplane icon, we've populated a 5,001-node off-screen DOM for no reason.

    Suggested fix

    Populate `.specialChars` only on first open of the modal, and pick a curated character set (or at least skip codepoints < 0x20 and the unassigned ranges). For example:

    ```js
    let populated = false;
    $('.insertSpecialCharacter').click(() => {
    if (!populated) {
    const chars = [];
    for (let i = 0x20; i <= 0x2FF; i++) chars.push(`

  • &#${i}
  • `);
    // Latin, IPA, diacritics, Greek, Cyrillic, common math + currency...
    $('.specialChars').append(chars.join(''));
    populated = true;
    }
    $('#specialCharactersModal').toggleClass('popup-show');
    });
    ```

    Single `append` with a joined string is also dramatically faster than 5,001 separate calls.

    Happy to send a PR if this analysis is on the right track.

    🤖 Generated with Claude Code

    Metadata

    Metadata

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions