create documentation in .md for <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chemical Supplies</title>
    <link rel="stylesheet" href="/style.css">
</head>

<body>
    <header class="show-toggle-form show-refresh show-save">
        <div class="container">
            <div class="header-inner-wrap">
                <h1>Chemical Supplies</h1>
                <div class="actions-wrap">
                    <button class="btn-mid transparent-overlay" data-action="toggle-form"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M256 48C141.125 48 48 141.125 48 256s93.125 208 208 208 208-93.125 208-208S370.875 48 256 48zm107 229h-86v86h-42v-86h-86v-42h86v-86h42v86h86v42z"></path></svg></button>
                    <button class="btn-mid transparent-overlay" data-action="edit"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a.996.996 0 0 0 0-1.41l-2.34-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"></path></svg></button>
                    <button class="btn-mid transparent-overlay" data-action="movedown"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="m20 12-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"></path></svg></button>
                    <button class="btn-mid transparent-overlay" data-action="moveup"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="m4 12 1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"></path></svg></button>
                    <button class="btn-mid btn-danger transparent-overlay" data-action="delete"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></svg></button>
                    <button class="btn-mid btn-danger transparent-overlay" data-action="refresh"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></svg></button>
                    <button class="btn-mid transparent-overlay" data-action="save"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M17 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"></path></svg></button>
                </div>

                <div class="form-wrap">
                    <div class="form-inner-wrap">
                        <h2>Add New Entry</h2>
                        <form id="form" class="form" data-mode="add">
                            <label for="chemical_name">Chemical Name:</label>
                            <input type="text" id="chemical_name" name="chemical_name" required>
                    
                            <label for="vendor">Vendor:</label>
                            <input type="text" id="vendor" name="vendor" required>
                    
                            <label for="density">Density (g/cm³):</label>
                            <input type="text" id="density" name="density" required>
                    
                            <label for="viscosity">Viscosity:</label>
                            <input type="text" id="viscosity" name="viscosity" required>
                    
                            <label for="packaging">Packaging:</label>
                            <select id="packaging" name="packaging" required>
                                <option value="Bottle">Bottle</option>
                                <option value="Bag">Bag</option>
                                <option value="Drum">Drum</option>
                                <option value="Barrel">Barrel</option>
                                <option value="Tank">Tank</option>
                                <option value="Box">Box</option>
                                <option value="Sack">Sack</option>
                                <option value="Can">Can</option>
                                <option value="Bulk">Bulk</option>
                            </select>
                    
                            <label for="pack_size">Pack Size:</label>
                            <input type="number" id="pack_size" name="pack_size" min="1" required>
                    
                            <label for="unit">Unit:</label>
                            <select id="unit" name="unit" required>
                                <option value="mL">mL</option>
                                <option value="L">L</option>
                                <option value="g">g</option>
                                <option value="kg">kg</option>
                            </select>
                    
                            <label for="quantity">Quantity:</label>
                            <input type="number" id="quantity" name="quantity" min="1" required>
                            <div>
                                <button type="submit">Add</button>&nbsp;<button type="reset">Cancel</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </header>
    <main>
        <div class="container">
            <div class="table-wrap">
                <table id="table">
                    <thead>
                        <tr>
                            <th class="select-box-all">&#10004;</th>
                            <th></th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Chemical Name</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="chemical_name"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                    <div class="th-content-bottom">
                                        <span class="unit"></span>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Vendor</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="vendor"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Density</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="density"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                    <div class="th-content-bottom">
                                        <span class="unit">g&sol;m<sup>3</sup></span>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Viscosity</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="viscosity"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                    <div class="th-content-bottom">
                                        <span class="unit">m<sup>2</sup>&sol;s</span>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Packaging</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="packaging"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Pack Size</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="pack_size"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Unit</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="unit"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                </div>
                            </th>
                            <th>
                                <div class="th-content-wrap">
                                    <div class="th-content-top">
                                        <span>Quantity</span><button class="btn-small transparent-overlay" data-sort-direction="asc" data-sort-property="quantity"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8H288c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"></path></svg></button>
                                    </div>
                                </div>
                            </th>
                        </tr>
                    </thead>
                </table>
            </div>
            
        </div>
    </main>
    <script src="/script.js"></script>
</body>

</html> and const HEADER = document.querySelector('header')
const FORM = document.querySelector('#form')
const TABLE = document.querySelector('#table')
const ACTIONS_WRAP = document.querySelector('.actions-wrap')
const API_URL = '/data.json'

let LAST_SAVED_DATA = [];
let UI_DATA = [];
let IS_UNSAVED_CHANGES = false;
const SELECTED_ROW = { id: null, data: null, html: null }

async function fetchData(url) {
    try {
        const res = await fetch(url);
        const json = await res.json();
        return json
    } catch (e) {
        console.log(e)
        return []
    }
}

function getUIDataItemIndex(id) {
    return UI_DATA.findIndex(el => el.id === id)
}

function swapArrayIndex(arr, index1, index2) {
    const temp = arr[index1]
    arr[index1] = arr[index2]
    arr[index2] = temp
}

function swapRowIndex(row1, row2) {
    const index1 = row1.children[1].textContent
    const index2 = row2.children[1].textContent

    row1.children[1].textContent = index2
    row2.children[1].textContent = index1
}

function saveData() {
    LAST_SAVED_DATA = JSON.parse(JSON.stringify(UI_DATA))
}

function resetSelectionData() {
    SELECTED_ROW.data = null
    SELECTED_ROW.html = null
}

function refreshUIData() {
    UI_DATA = JSON.parse(JSON.stringify(LAST_SAVED_DATA))
}

function sortUIData(property, dir) {
    UI_DATA.sort((a, b) => {
        if (dir === 'asc') {
            return a[property].localeCompare(b[property], undefined, { numeric: true });
        } else {
            return b[property].localeCompare(a[property], undefined, { numeric: true });
        }
    });
}

function populateForm(data) {
    FORM.chemical_name.value = data.chemical_name;
    FORM.vendor.value = data.vendor;
    FORM.density.value = data.density;
    FORM.viscosity.value = data.viscosity;
    FORM.packaging.value = data.packaging;
    FORM.pack_size.value = data.pack_size;
    FORM.unit.value = data.unit;
    FORM.quantity.value = data.quantity;
}

function toggleForm() {
    HEADER.classList.toggle('show-form')

    removeAllModes()
    if (HEADER.classList.contains('show-form')) {
        formMode()
    } else {
        if (SELECTED_ROW.data) {
            selectedMode()
        } else {
            idealMode()
        }
    }
}

function createCell(text) {
    const cell = document.createElement('td');
    cell.textContent = text;
    return cell
}

function createRow(obj, index) {
    const row = document.createElement('tr');

    const selectBox = createCell(`\u2714`);
    selectBox.classList.add('select-box');
    row.appendChild(selectBox);

    row.dataset.id = obj['id']
    const rowIndexCell = createCell(index);
    row.appendChild(rowIndexCell)

    for (const key in obj) {
        if (key === 'id') {
            continue
        }

        const cell = createCell(obj[key])
        cell.dataset.property = key
        row.appendChild(cell);
    }

    return row
}

function createTableBody(arrayOfObjs) {
    const fragment = document.createDocumentFragment();

    const tbody = document.createElement('tbody');
    fragment.appendChild(tbody)

    arrayOfObjs.forEach((obj, index) => {
        const row = createRow(obj, index + 1)
        tbody.appendChild(row);
    });
    return fragment
}

function selectRow(clickedArea) {
    const cell = clickedArea

    if (!cell.classList.contains('select-box')) {
        return
    }

    const clickedRow = cell.parentElement

    removeAllModes()

    if (clickedRow.classList.contains('active')) {
        clickedRow.classList.remove('active')

        resetSelectionData()
        idealMode()
    } else {
        const allRows = TABLE.lastElementChild.children
        for (let i = 0; i < allRows.length; i++) {
            allRows[i].classList.remove('active')
        }
        clickedRow.classList.add('active')
        SELECTED_ROW.data = UI_DATA[getUIDataItemIndex(clickedRow.dataset.id)]
        SELECTED_ROW.html = clickedRow
        selectedMode()
    }
}

function deleteRow() {
    if (SELECTED_ROW.data === null || SELECTED_ROW.html === null) {
        return
    }

    // ui
    let currentRow = SELECTED_ROW.html;
    let currentRowIndex = parseInt(currentRow.children[1].textContent);
    while (currentRow) {
        currentRow.children[1].textContent = currentRowIndex - 1
        currentRowIndex++
        currentRow = currentRow.nextElementSibling
    }

    SELECTED_ROW.html.remove();

    // data
    const deletedItemDataIndex = getUIDataItemIndex(SELECTED_ROW.data)
    UI_DATA.splice(deletedItemDataIndex, 1)

    resetSelectionData()
}

function moveRowUp() {
    if (SELECTED_ROW.data === null || SELECTED_ROW.html === null) {
        return
    }

    const currentRow = SELECTED_ROW.html
    const previousRow = currentRow.previousElementSibling;

    if (previousRow) {
        const previousRowDataId = getUIDataItemIndex(previousRow.dataset.id)
        currentRow.parentNode.insertBefore(currentRow, previousRow);
        swapRowIndex(previousRow, currentRow)
        swapArrayIndex(UI_DATA, previousRowDataId, previousRowDataId + 1)
    }
}

function moveRowDown() {
    if (SELECTED_ROW.data === null || SELECTED_ROW.html === null) {
        return
    }

    const currentRow = SELECTED_ROW.html
    const nextRow = currentRow.nextElementSibling;

    if (nextRow) {
        const nextItemDataIndex = getUIDataItemIndex(nextRow.dataset.id)
        currentRow.parentNode.insertBefore(nextRow, currentRow);
        swapRowIndex(nextRow, currentRow)
        swapArrayIndex(UI_DATA, nextItemDataIndex, nextItemDataIndex - 1)
    }
}

function refreshTableUI(data) {
    const html = createTableBody(data)
    TABLE.lastElementChild.remove()
    TABLE.append(html)
}

function removeAllModes() {
    HEADER.classList.remove('show-toggle-form', 'show-edit', 'show-delete', 'show-moveup', 'show-movedown', 'show-refresh', 'show-save')
}

function idealMode() {
    HEADER.classList.add('show-toggle-form', 'show-refresh', 'show-save')
}

function selectedMode() {
    HEADER.classList.add('show-edit', 'show-delete', 'show-moveup', 'show-movedown', 'show-refresh', 'show-save')
}

function formMode() {
    HEADER.classList.add('show-toggle-form')
}

// init
fetchData(API_URL)
    .then(res => {
        LAST_SAVED_DATA = JSON.parse(JSON.stringify(res));
        UI_DATA = JSON.parse(JSON.stringify(LAST_SAVED_DATA));

        const html = createTableBody(UI_DATA)
        TABLE.append(html)

        // changes observer
        const observer = new MutationObserver(function () {
            IS_UNSAVED_CHANGES = true
        });
        const observerConfig = { attributes: true, childList: true, subtree: true }
        observer.observe(TABLE, observerConfig);

        TABLE.addEventListener('click', function (e) {

            const clickedArea = e.target;

            selectRow(clickedArea)

            // sorting
            if (clickedArea.dataset.sortProperty !== undefined) {
                const direction = clickedArea.dataset.sortDirection
                sortUIData(clickedArea.dataset.sortProperty, direction)
                clickedArea.dataset.sortDirection = direction === "asc" ? "dsc" : "asc"

                refreshTableUI(UI_DATA)
                resetSelectionData()
            }
        });

        ACTIONS_WRAP.addEventListener('click', function (e) {

            const action = e.target.dataset.action;

            switch (action) {
                case 'edit':
                    FORM.dataset.mode = 'edit'
                    toggleForm()
                    populateForm(SELECTED_ROW.data)
                    break

                case 'toggle-form':
                    toggleForm()
                    break

                case 'moveup':
                    moveRowUp()
                    break

                case 'movedown':
                    moveRowDown()
                    break

                case 'delete':
                    deleteRow()
                    break

                case 'refresh':
                    if (IS_UNSAVED_CHANGES) {
                        const userConfimation = window.confirm('Contains Unsaved Changes, Refresh?')

                        if (!userConfimation) {
                            return
                        }
                    } else {
                        observer.disconnect()
                        refreshUIData()
                        refreshTableUI(LAST_SAVED_DATA)
                        removeAllModes()
                        idealMode()
                        IS_UNSAVED_CHANGES = false
                        observer.observe(TABLE, observerConfig)
                    }
                    break

                case 'save':
                    saveData()
                    IS_UNSAVED_CHANGES = false
                    break

                default:
                    return
            }
        })

        FORM.addEventListener('submit', function (e) {
            e.preventDefault()
            const formData = new FormData(e.target)
            const data = Object.fromEntries(formData.entries())

            if (FORM.dataset.mode === 'edit') {
                FORM.dataset.mode = 'add'
                UI_DATA[getUIDataItemIndex(SELECTED_ROW.data)] = data
            } else {
                UI_DATA.push(data)
            }

            FORM.reset()
            toggleForm()

            refreshTableUI(UI_DATA)
            resetSelectionData()
            removeAllModes()
            idealMode()
        });

        FORM.addEventListener('reset', function(e){
            FORM.reset()
            toggleForm();
            removeAllModes();
            idealMode();
        })
    }).catch(function (e) {
        console.log(e)
    })