Home Reference Source

cables_dev/cables_ui/src/ui/components/tabs/tab_spreadsheet.js

import { ele, Events } from "cables-shared-client";

export default class SpreadSheetTab extends Events
{
    constructor(tabs, port, data, options)
    {
        super();
        this._tabs = tabs;

        options = options || {};

        this._numCols = options.numColumns || 3;
        this._rows = 25;

        this._port = port;
        this.cells = [];
        this._inputs = [];
        this._options = options;
        this.colNames = [];

        this._tab = new CABLES.UI.Tab(options.title || "", { "icon": "edit", "infotext": "tab_spreadsheet", "padding": true, "singleton": "false", });
        this._tabs.addTab(this._tab, true);

        port.on("onUiAttrChange", this._updateUiAttribs.bind(this));

        this.data = { "cells": this.cells, "colNames": this.colNames };

        if (data) this.initData(data);
        else
        {
            for (let i = 0; i < this._numCols; i++) this.getColName(i);
        }


        this._id = "spread" + CABLES.uuid();
        this._updateUiAttribs();
    }

    _updateUiAttribs()
    {
        this._numCols = this._port.uiAttribs.spread_numColumns || 1;
        this.rebuildHtml();
    }

    rebuildHtml()
    {
        this._tab.html("<div id='" + this._id + "' ></div>");
        this._ele = document.getElementById(this._id);
        if (!this._ele) return;
        this._ele.classList.add("editor_spreadsheet");
        this._ele.classList.add("tabcontent-scroll");

        this._eleTable = ele.create("table");
        this._ele.appendChild(this._eleTable);

        this.cells.length = this._rows;

        this._html();
    }

    getColName(_c)
    {
        _c = parseFloat(_c);

        if (this.colNames.length > _c && this.colNames[_c])
        {
            return this.colNames[_c];
        }

        let str = "";
        let c = parseFloat(_c);

        if (c < 0) throw new Error("col invalid");

        while (c >= 0)
        {
            str = "abcdefghijklmnopqrstuvwxyz"[c % 26] + str;
            c = Math.floor(c / 26) - 1;
        }

        this.colNames[_c] = str;

        return str;
    }


    _html()
    {
        for (let i = 0; i < this._inputs.length; i++) this._inputs[i].remove();

        this._inputs.length = 0;
        const table = this._eleTable;

        for (let y = -1; y < this._rows; y++)
        {
            const tr = ele.create("tr");
            table.appendChild(tr);

            const tdr = ele.create("td");
            if (y >= 0)
            {
                tdr.innerHTML = y;
                tdr.classList.add("rownum");
            }
            tr.appendChild(tdr);

            for (let x = 0; x < this._numCols; x++)
            {
                const td = ele.create("td");
                tr.appendChild(td);

                const input = ele.create("input");
                input.dataset.x = x;
                input.dataset.y = y;
                this._inputs[x + y * this._numCols] = input;

                if (y == -1)
                {
                    input.classList.add("colname");
                    input.value = this.getColName(x);
                }
                else
                {
                    input.value = this.get(x, y) || "";
                }

                td.appendChild(input);


                input.addEventListener("change", this._checkNumRows.bind(this));
                input.addEventListener("input", this._onInputChange.bind(this));
                input.addEventListener("keydown", this._onKey.bind(this), false);
            }
        }
    }

    _focusCell(x, y)
    {
        const inp = this._inputs[(y * this._numCols) + x];

        if (inp)
        {
            inp.focus();

            setTimeout(() =>
            {
                // inp.select();
            }, 50);
        }
    }


    _onKey(e)
    {
        const x = parseFloat(e.target.dataset.x);
        const y = parseFloat(e.target.dataset.y);

        if (e.keyCode == 38)
        {
            this._focusCell(x, y - 1);
        }
        else if (e.keyCode == 40)
        {
            this._focusCell(x, y + 1);
        }
        else if (e.keyCode == 37)
        {
            this._focusCell(x - 1, y);
        }
        else if (e.keyCode == 39)
        {
            this._focusCell(x + 1, y);
        }
        else this._onInputChange(e);
        // else console.log(e.keyCode);
    }

    _checkNumRows()
    {
        console.log(this.cells);


        let lastLine = this.cells.length - 1;
        for (let i = this.cells.length - 1; i > 0; i--)
        {
            if (this.cells[i])
            {
                let foundContent = false;
                for (let x = 0; x < this._numCols; x++)
                    if (this.cells[i][x] && this.cells[i][x].length > 0)
                    {
                        console.log(i, this.cells[i]);
                        foundContent = true;
                        lastLine = i;
                    }

                if (foundContent) break;
            }


            // for (let x = 0; x < this._numCols; x++)
            // {
            //     console.log(this.cells[x]);
            // }
        }

        console.log("lastLine", lastLine);

        lastLine += 10;
        if (this._rows != lastLine)
        {
            this._rows = lastLine;
            this.rebuildHtml();
        }

        console.log("lastline", lastLine);

        // const newRows = lastLine + 10;
        // if (this._rows != newRows)
        // {
        //     this._rows = this.cells.length + 10;
        //     this.rebuildHtml();
        // }
        // if()

        // if (this.cells.length >= this._rows)
        // {
        // }
    }

    initData(data)
    {
        this.cells = data.cells || [];
        this.colNames = data.colNames || [];
        this._checkNumRows();
    }

    get(x, y)
    {
        if (y == -1) return this.getColName(x);
        if (!this.cells) return undefined;
        if (!this.cells[y]) return [];
        return this.cells[y][x];
    }

    set(x, y, v)
    {
        if (y == -1)
        {
            console.log("set colname", x, v);
            this.colNames[x] = v;
            return;
        }

        this.cells[y] = this.cells[y] || [];
        this.cells[y][x] = v;
        this._sendChange();
    }

    _sendChange()
    {
        this.data.cols = this._numCols;
        this.data.cells = this.cells;
        this.data.colNames = this.colNames;
        this.data.colNames.length = this._numCols;
        this._options.onchange(null);
        if (this._options.onchange) this._options.onchange(this.data);
    }

    _onInputChange(e)
    {
        console.log("onchange...", e.target.value);
        const x = e.target.dataset.x;
        const y = e.target.dataset.y;

        this.set(x, y, e.target.value);
        // for (let i = 0; i < this._numCols; i++) this.getColName(i);
    }

    show()
    {
    }
}