wii remote eeprom reader from July 2025, still in WIP state

by arian_

HTML

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>wiimote eeprom</title>

    <style>
        body {
            font-family: sans-serif;
        }

        table, table * {
            margin: 0;
            padding: 0;
            vertical-align: top;
            font: 1em/1em monospace;
        }

        .hex-textarea {
            height: 1.5em;
            resize: none;
            width: 100%;
        }

        .table-padding {
            padding: 0 2px;
        }
    </style>
</head>
<body>

    <button onclick="init()">Connect to Wii Remote</button>
    <br /><br />
    Connecting a Wii Remote to Windows is tricky, try this video: <a href="https://www.youtube.com/watch?v=J-s9gZJNp8o$0" target="_blank">https://www.youtube.com/watch?v=J-s9gZJNp8o$0</a>
    <div id="device"></div>
    <div id="message"></div>

    <h4>hex editor for eeprom contents</h4>
    <table id="hex-editor-eeprom" border="1">
        <tr>
            <td></td>
            <td><pre class="table-padding"></pre></td>
        </tr>
        <tr>
            <td class="line-numbers" width="80"></td>
            <td>
                <textarea spellcheck="false" class="hex-textarea" cols="48"></textarea>
            </td>
            <td width="160" class="ascii-output">.</td>
        </tr>
    </table>

    <script src="wiimote-eeprom.js"></script>

</body>
</html>

JavaScript

// @ts-check

// Hex Editor

/** A hex editor class for displaying and editing hex data within a container. */
class HexEditor {
  /**
   * Creates an instance of HexEditor.
   * @param {HTMLElement|null} container - The container element that holds the hex editor components.
   * @param {boolean} [isReadOnly] - Determines if the hex editor should be read-only.
   * @throws {Error} Throws if any of the required elements do not exist.
   */
  constructor(container, isReadOnly = false) {
    if (!container) {
      throw new Error('HexEditor: Passed in container is null.');
    }
    /**
     * Text area for hex input.
     * @type {HTMLTextAreaElement|null}
     */
    const textArea = container.querySelector('.hex-textarea');
    if (!(textArea instanceof HTMLTextAreaElement)) {
      throw new Error('HexEditor: Missing or invalid .hex-textarea element.');
    }
    this.textArea = textArea;

    /**
     * Element for storing line numbers.
     * @type {HTMLElement|null}
     */
    const lineNumbers = container.querySelector('.line-numbers');
    if (!(lineNumbers instanceof HTMLElement)) {
      throw new Error('HexEditor: Missing or invalid .line-numbers element.');
    }
    this.lineNumbers = lineNumbers;

    /**
     * Element for ASCII/Unicode output.
     * @type {HTMLElement|null}
     */
    const asciiOutput = container.querySelector('.ascii-output');
    if (!(asciiOutput instanceof HTMLElement)) {
      throw new Error('HexEditor: Missing or invalid .ascii-output element.');
    }
    this.asciiOutput = asciiOutput;

    /**
     * Hex header element (00, 01, 02...)
     * @type {HTMLElement|null}
     */
    const header = container.querySelector('.table-padding');
    if (!(header instanceof HTMLElement)) {
      throw new Error('HexEditor: Missing or invalid .table-padding element.');
    }
    this.header = header;

    /**
     * Reference to the table container.
     * @type...