tym-table-editor
Version:
'tym-table-editor' is a simple table editor component.
1 lines • 101 kB
Source Map (JSON)
{"version":3,"file":"tym-table-editor.mjs","sources":["../../../projects/tym-table-editor/src/lib/tym-table-editor.component.ts","../../../projects/tym-table-editor/src/lib/tym-table-input.component.ts","../../../projects/tym-table-editor/src/lib/tym-table-editor.module.ts","../../../projects/tym-table-editor/src/public-api.ts","../../../projects/tym-table-editor/src/tym-table-editor.ts"],"sourcesContent":["/*!\r\n * tym-table-editor.js\r\n * Copyright (c) 2022 shinichi tayama\r\n * Released under the MIT license.\r\n * see https://opensource.org/licenses/MIT\r\n */\r\n\r\nimport { Component, AfterViewInit, ElementRef, Renderer2, Input, HostBinding } from '@angular/core';\r\n\r\nconst AUTO = 'auto';\r\nconst SCROLL = 'scroll';\r\n\r\nconst num2 = (n: number) => ('00' + n).slice(-2);\r\nconst FIRST_ELEMENT_CHILD = (elm: HTMLElement) => elm?.firstElementChild as HTMLElement;\r\ntype HIST = { r: number, c: number, b: string, a: string, d?: TYM_EDITOR_DEF };\r\ntype HISTS = HIST[];\r\ntype RANGE = { r1: number, c1: number, r2: number, c2: number };\r\n/** カラム定義 */\r\nexport type TYM_EDITOR_DEF = {\r\n /** 対象列番号(1~) */\r\n col: number;\r\n /** 対象列タイプ */\r\n type?: string;\r\n /** 対象列揃え指定 {'left' | 'center' | 'right'}, 規定値: 'left' */\r\n align?: 'left' | 'center' | 'right';\r\n /** 表示モードだけにする, 規定値: false */\r\n readonly?: boolean;\r\n /** 値を表示文字に変換する関数, 規定値: なし */\r\n viewfnc?: (val: string, type?: string, col?: number) => string;\r\n /** 値を編集する関数, 規定値: なし */\r\n editfnc?: (elm: HTMLElement, val: string, type?: string, col?: number) => Promise<string | null>;\r\n}\r\n/** オプション定義 */\r\nexport type TYM_EDITOR_OPTS = {\r\n /** 選択, カレントセルを折り返ししない */\r\n whiteSpaceNoWrap?: boolean;\r\n /** 編集モードの解除時に列のリサイズを実行する */\r\n editModeAutoResize?: boolean;\r\n /** フラットデザインにする */\r\n flatDesign?: boolean;\r\n /** 垂直方向のリサイズを無しにする */\r\n noVerticalResize?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-tym-table-editor',\r\n template: '<table><tbody></tbody></table>',\r\n styleUrls: ['./tym-table-editor.component.scss']\r\n})\r\nexport class TymTableEditorComponent implements AfterViewInit {\r\n\r\n private static idnum = 0;\r\n private _thisElm: HTMLElement; // this table element\r\n\r\n @Input() row: number = 30;\r\n @Input() col: number = 20;\r\n @Input() defs: TYM_EDITOR_DEF[] = [];\r\n @Input() data: any[][] = [['']];\r\n @Input() menu = (event: MouseEvent, row1: number, col1: number, row2: number, col2: number) => false;\r\n private _opts: TYM_EDITOR_OPTS = {}\r\n @Input() set opts(opts: TYM_EDITOR_OPTS) {\r\n this._opts = opts;\r\n this._setopt();\r\n }\r\n private _setopt() {\r\n const tableElm = FIRST_ELEMENT_CHILD(this._thisElm);\r\n const tbodyElm = FIRST_ELEMENT_CHILD(tableElm);\r\n setTimeout(() => {\r\n if (tbodyElm) {\r\n const [cl, opts] = [tbodyElm.classList, this._opts];\r\n if (opts.whiteSpaceNoWrap) { cl.add('nowrap'); } else { cl.remove('nowrap'); }\r\n if (opts.noVerticalResize) { cl.add('novrsz'); } else { cl.remove('novrsz'); }\r\n }\r\n });\r\n [this.thFont, this.thWidth, this.thBgColor, this.thBorder, this.thWidth1, this.thWidth2, this.tdShadow]\r\n = (this._opts.flatDesign)\r\n ? ['700 9pt/12pt system-ui', '1.40em', '#eee', 'solid 1px #666', '1px 1px 1px 0', '0 1px 1px 1px', 'none']\r\n : ['700 8pt/10pt system-ui', '1.25em', '#ccc', 'outset 2px #eee', '2px', '2px', '.5px .5px 0px #000 inset'];\r\n }\r\n\r\n /** Host Binding style */\r\n @HostBinding('style.--th-fo') protected thFont!: string; //700 8pt/10pt system-ui / 700 9pt/12pt system-ui\r\n @HostBinding('style.--th-wd') protected thWidth!: string; //1.25em / 1.40em\r\n @HostBinding('style.--th-bc') protected thBgColor!: string; //#ccc / #eee\r\n @HostBinding('style.--th-bo') protected thBorder!: string; //outset 2px #eee / solid 1px #666\r\n @HostBinding('style.--th-w1') protected thWidth1!: string; //2px / 0 1px 1px 0\r\n @HostBinding('style.--th-w2') protected thWidth2!: string; //2px / 0 1px 1px 0\r\n @HostBinding('style.--td-bs') protected tdShadow!: string; //.5px .5px 0px #000 inset / none\r\n\r\n /**\r\n * コンストラクタ\r\n *\r\n * @memberof TymTreeViewComponent\r\n */\r\n constructor(\r\n private _elmRef: ElementRef,\r\n private _renderer: Renderer2\r\n ) {\r\n this._thisElm = this._elmRef.nativeElement as HTMLElement;\r\n };\r\n\r\n /**\r\n * ビューを初期化した後の処理\r\n */\r\n public ngAfterViewInit(): void {\r\n //---------------------------------------------------------------\r\n // ..\r\n const thisElm = this._thisElm;\r\n const tableElm = FIRST_ELEMENT_CHILD(thisElm);\r\n const tbodyElm = FIRST_ELEMENT_CHILD(tableElm);\r\n const contentName = '_tymtableeditor-' + TymTableEditorComponent.idnum++;\r\n tableElm.setAttribute(contentName,'');\r\n //---------------------------------------------------------------\r\n // ..\r\n const maxrow = this.row;\r\n const maxcol = this.col;\r\n const nosels = { r1: -1, c1: -1, r2: -1, c2: -1 };\r\n const editordefs = new Map<number, TYM_EDITOR_DEF>();\r\n /** 0:not move, 1:cell, 2:col, 3:row */\r\n let mousemv: number = 0;\r\n let selects: RANGE = { ...nosels };\r\n let cpysels: RANGE = { ...nosels };\r\n //---------------------------------------------------------------\r\n // ..\r\n let editElm: HTMLTableCellElement | null = null; // edited td cell\r\n let crntElm: HTMLTableCellElement | null = null; // current td cell \r\n //---------------------------------------------------------------\r\n // ..\r\n const { overflowX, overflowY } = window.getComputedStyle(thisElm);\r\n const scrollElm = (!(overflowX == AUTO || overflowX == SCROLL || overflowY == AUTO || overflowY == SCROLL))\r\n ? thisElm.parentElement as HTMLElement : thisElm;\r\n //---------------------------------------------------------------\r\n // ..\r\n const cell = (r: number, c: number) => tbodyElm.children[r]?.children[c] as HTMLTableCellElement;\r\n const crntRange = () => {\r\n const [r, c] = cellRowCol(crntElm);\r\n return { r1: r, c1: c, r2: r, c2: c };\r\n }\r\n const cellRowCol = (td: HTMLTableCellElement | null) =>\r\n (td) ? [(td.parentElement as HTMLTableRowElement).rowIndex, td.cellIndex] : [1, 1];\r\n //---------------------------------------------------------------\r\n // create element\r\n const createElm = (name: string) => this._renderer.createElement(name) as HTMLElement;\r\n //---------------------------------------------------------------\r\n // create th element\r\n const createTh = (tx: string) => {\r\n const th = createElm('th') as HTMLTableCellElement;\r\n th.innerText = tx;\r\n return th;\r\n }\r\n //---------------------------------------------------------------\r\n // create td element\r\n const createTd = () => {\r\n const td = createElm('td') as HTMLTableCellElement;\r\n td.tabIndex = -1;\r\n return td;\r\n }\r\n //---------------------------------------------------------------\r\n // get TYM_EDITOR_DEF\r\n const _getEditorDef = (th: HTMLTableCellElement) =>\r\n th.onprogress!(new ProgressEvent('')) as TYM_EDITOR_DEF | undefined;\r\n const getEditorDef = (td: HTMLTableCellElement) =>\r\n _getEditorDef(headTrElm.children[td.cellIndex] as HTMLTableCellElement);\r\n //---------------------------------------------------------------\r\n // get editFunc\r\n const getEditFunc = (td: HTMLTableCellElement) => {\r\n const def = getEditorDef(td);\r\n return (def?.editfnc)\r\n ? (td: HTMLTableCellElement, val: string) => def.editfnc!(td, val, def.type)\r\n : undefined;\r\n }\r\n //---------------------------------------------------------------\r\n // get viewFunc\r\n const getViewFunc = (td: HTMLTableCellElement) => {\r\n const def = getEditorDef(td);\r\n return (def?.viewfnc) ? (val: string) => def.viewfnc!(val, def.type) : undefined;\r\n }\r\n //---------------------------------------------------------------\r\n // get align / background style\r\n const getDynamicStyle = (td: HTMLTableCellElement) => {\r\n const def = getEditorDef(td);\r\n const style = ''\r\n + ((def?.align) ? `text-align:${def?.align};` : '')\r\n + ((def?.readonly) ? 'background-color:#f8f8f8;' : '');\r\n return (style == '') ? '' : `table[${contentName}] td:nth-child(${td.cellIndex + 1}){${style}}`;\r\n }\r\n //---------------------------------------------------------------\r\n // get style texts\r\n const getStyleText = () =>\r\n Array.from(headTrElm.children).map(th => getDynamicStyle(th as HTMLTableCellElement)).join('');\r\n //---------------------------------------------------------------\r\n // create header th element\r\n const createRowTh = (col: number, def?: TYM_EDITOR_DEF) => {\r\n const tx = num2(col);\r\n const th = createTh(tx);\r\n th.onprogress = (e: Event) => {\r\n const _editordef = { ...def }\r\n return _editordef;\r\n };\r\n return th;\r\n }\r\n\r\n //---------------------------------------------------------------\r\n // ..\r\n const classlist = (elm: HTMLElement) => elm.classList;\r\n const classrm = (elm: HTMLElement, cls: string) => classlist(elm).remove(cls);\r\n const classadd = (elm: HTMLElement, cls: string) => classlist(elm).add(cls);\r\n /****************************************************************\r\n * set current element (crntElm, style)\r\n * @param elm 対象エレメント\r\n */\r\n const setCurrent = (elm: HTMLTableCellElement) => {\r\n const crn = 'crn';\r\n if (crntElm) classrm(crntElm, crn);\r\n classadd(elm, crn);\r\n crntElm = elm;\r\n }\r\n /****************************************************************\r\n * get select range\r\n * @param _selects target RANGE\r\n * @returns { r1: number, c1: number, r2: number, c2: number }\r\n */\r\n const range = (_selects: RANGE = selects) => {\r\n let { r1, c1, r2, c2 } = (_selects.c2 < 0) ? (crntElm) ? crntRange() : nosels : _selects;\r\n [r1, r2] = r2 > r1 ? [r1, r2] : [r2, r1];\r\n [c1, c2] = c2 > c1 ? [c1, c2] : [c2, c1];\r\n return { r1: r1, c1: c1, r2: r2, c2: c2 };\r\n }\r\n /****************************************************************\r\n * exec range function\r\n * @param fnc call back function\r\n * @param _selects target RANGE\r\n */\r\n const execRange = (fnc: (elm: HTMLTableCellElement, eol?: boolean) => void, _selects: RANGE = selects) => {\r\n const { r1, c1, r2, c2 } = range(_selects);\r\n if (c2 < 0) return;\r\n for (let _row = r1; _row <= r2; _row++) {\r\n for (let _col = c1; _col <= c2; _col++) {\r\n fnc(cell(_row, _col), _col == c2);\r\n }\r\n }\r\n }\r\n //---------------------------------------------------------------\r\n // set selection range functions\r\n const checkset = (max: number, n: number) => (-1 > n) ? -1 : (n > max) ? max : n;\r\n const setSelRange1stRowCol = (r1: number, c1: number) =>\r\n [selects.r1, selects.c1] = [checkset(maxrow, r1), checkset(maxcol, c1)];\r\n const setSelRangeLstRowCol = (r2: number, c2: number) =>\r\n [selects.r2, selects.c2] = [checkset(maxrow, r2), checkset(maxcol, c2)];\r\n const setSelRange1st = (td: HTMLTableCellElement) => [selects.r1, selects.c1] = cellRowCol(td);\r\n const setSelRangeLst = (td: HTMLTableCellElement) => [selects.r2, selects.c2] = cellRowCol(td);\r\n /****************************************************************\r\n * clear selection range style\r\n * @param clear true:clear \"selects\"\r\n */\r\n const clearSelRangeStyle = (clear?: boolean) => {\r\n execRange(elm => classrm(elm, 'msel'));\r\n if (clear) selects = { ...nosels };\r\n }\r\n /****************************************************************\r\n * set selection range style\r\n */\r\n const drawSelRangeStyle = () => execRange(elm => classadd(elm, 'msel'));\r\n /****************************************************************\r\n * set converted text to cell (if converted, save to dataset-val)\r\n * @param elm 対象エレメント\r\n * @param val 値\r\n */\r\n const setText = (elm: HTMLTableCellElement, val: string) => {\r\n const viewfnc = getViewFunc(elm);\r\n elm.innerText = (viewfnc) ? viewfnc(elm.dataset.val = val) : val;\r\n }\r\n /****************************************************************\r\n * get real text (if converted, restore from dataset-val)\r\n * @param elm 対象エレメント\r\n * @returns 値\r\n */\r\n const text = (elm: HTMLTableCellElement): string => elm.dataset.val || elm.innerText;\r\n /****************************************************************\r\n * set data to table\r\n * @param data データ\r\n */\r\n const setData2Table = (data: any[][]) => {\r\n const maxcol = data.reduce((a, b) => a.length > b.length ? a : b);\r\n setSelRange1stRowCol(1, 1);\r\n setSelRangeLstRowCol(data.length, maxcol.length);\r\n let r = 0, c = 0;\r\n execRange((elm, eol) => {\r\n const v = data[r][c] || '';\r\n setText(elm, v);\r\n if (eol) c = 0, r++; else c++\r\n });\r\n };\r\n /****************************************************************\r\n * set data to range\r\n * @param data データ\r\n * @param row 行番号\r\n * @param col 列番号\r\n */\r\n const setData2Range = (data: any[][], row: number, col: number) => {\r\n const maxcol = data.reduce((a, b) => a.length > b.length ? a : b);\r\n clearSelRangeStyle();\r\n setSelRange1stRowCol(row, col);\r\n setSelRangeLstRowCol(row + data.length - 1, col + maxcol.length - 1);\r\n let hists: any = [];\r\n let r = 0, c = 0;\r\n execRange((elm, eol) => {\r\n const v = data[r][c] || '';\r\n hists.push({ r: row + r, c: col + c, b: text(elm), a: v });\r\n setText(elm, v);\r\n classadd(elm, 'msel');\r\n if (eol) c = 0, r++; else c++\r\n });\r\n // 編集履歴に追加\r\n addhists(hists);\r\n }\r\n /****************************************************************\r\n * set public function (setData)\r\n */\r\n this.setData = (data: any[][], row1?: number, col1?: number) => {\r\n if (row1 && col1) {\r\n setData2Range(data, row1, col1);\r\n } else {\r\n clearAllData();\r\n setData2Table(data);\r\n }\r\n }\r\n /****************************************************************\r\n * set public function (getData)\r\n */\r\n this.getData = (rownum: number, colnum: number, row?: number, col?: number): any[][] => {\r\n const [r1, c1, r2, c2] = (row && col) ? [rownum, colnum, row, col] : [1, 1, rownum, colnum];\r\n let cols: any[] = [];\r\n let data: any[][] = [];\r\n for (let _row = r1; _row <= r2; _row++) {\r\n for (let _col = c1; _col <= c2; _col++) {\r\n const td = cell(_row, _col);\r\n cols.push((td) ? td.dataset.val || td.innerText : '');\r\n }\r\n data.push(cols);\r\n cols = [];\r\n }\r\n return data;\r\n }\r\n //---------------------------------------------------------------\r\n // renumber row header\r\n const renumberRow = () => {\r\n for (let index = 1; index <= maxrow; index++) {\r\n const tr = tbodyElm.childNodes[index] as HTMLTableRowElement;\r\n const th = FIRST_ELEMENT_CHILD(tr);\r\n th.innerText = num2(index);\r\n }\r\n }\r\n //---------------------------------------------------------------\r\n // renumber col header\r\n const renumberCol = () => {\r\n for (let index = 1; index <= maxcol; index++) {\r\n const th = headTrElm.childNodes[index] as HTMLTableCellElement;\r\n th.innerText = num2(index);\r\n }\r\n }\r\n //---------------------------------------------------------------\r\n // create row\r\n const createrow = (row: number) => {\r\n const tr = createElm('tr');\r\n tr.appendChild(createTh(num2(row)));\r\n for (let index = 1; index <= maxcol; index++) {\r\n tr.appendChild(createTd())\r\n }\r\n return tr;\r\n }\r\n //---------------------------------------------------------------\r\n // view insert / remove row\r\n const viewInsertRemoveRow = (insRowNum: number, rmRowNum: number) => {\r\n clearSelRangeStyle(true);\r\n clearCpyRangeStyle();\r\n const [insRow, rmRow] = [tbodyElm.childNodes[insRowNum], tbodyElm.childNodes[rmRowNum]];\r\n tbodyElm.insertBefore(createrow(insRowNum), insRow);\r\n tbodyElm.removeChild(rmRow!);\r\n if (crntElm && !crntElm?.isConnected) {\r\n crntElm = null;\r\n }\r\n renumberRow();\r\n }\r\n //---------------------------------------------------------------\r\n // history insert / remove row\r\n const histInsertRemoveRow = (row: number, rmRowNum: number, ir: string) => {\r\n const trElm = tbodyElm.childNodes[rmRowNum];\r\n let hists: any = [{ r: row, c: 0, b: '', a: ir }]; // c:0,a:i/r => insert/remove row\r\n for (let index = 1; index <= maxcol; index++) {\r\n const v = text(trElm.childNodes[index] as HTMLTableCellElement);\r\n if (v != '') hists.push({ r: rmRowNum, c: index, b: v, a: '' });\r\n }\r\n addhists(hists);\r\n }\r\n //---------------------------------------------------------------\r\n // insert row\r\n const insertRow = (row: number) => viewInsertRemoveRow(row, maxrow);\r\n /****************************************************************\r\n * set public function (insertRow)\r\n */\r\n this.insertRow = (row: number) => {\r\n histInsertRemoveRow(row, maxrow, 'i');\r\n insertRow(row);\r\n }\r\n //---------------------------------------------------------------\r\n // remove row\r\n const removeRow = (row: number) => viewInsertRemoveRow(maxrow + 1, row);\r\n /****************************************************************\r\n * set public function (removeRow)\r\n */\r\n this.removeRow = (row: number) => {\r\n histInsertRemoveRow(row, row, 'r');\r\n removeRow(row);\r\n }\r\n //---------------------------------------------------------------\r\n // view insert / remove col\r\n const viewInsertRemoveCol = (insColNum: number, rmColNum: number, def?: TYM_EDITOR_DEF) => {\r\n clearSelRangeStyle(true);\r\n clearCpyRangeStyle();\r\n const [insHeadCol, rmHeadCol] = [headTrElm.childNodes[insColNum], headTrElm.childNodes[rmColNum]];\r\n headTrElm.insertBefore(createRowTh(insColNum, def), insHeadCol);\r\n headTrElm.removeChild(rmHeadCol!);\r\n for (let index = 1; index <= maxrow; index++) {\r\n const tr = tbodyElm.childNodes[index] as HTMLTableRowElement;\r\n const [insCol, rmCol] = [tr.childNodes[insColNum], tr.childNodes[rmColNum]];\r\n tr.insertBefore(createTd(), insCol);\r\n tr.removeChild(rmCol!);\r\n }\r\n if (crntElm && !crntElm?.isConnected) {\r\n crntElm = null;\r\n }\r\n styleElement.innerText = getStyleText();\r\n renumberCol();\r\n }\r\n //---------------------------------------------------------------\r\n // history insert col\r\n const histInsertRemoveCol = (col: number, rmColNum: number, ir: string) => {\r\n const th = headTrElm.children[col] as HTMLTableCellElement;\r\n const def = _getEditorDef(th);\r\n let hists: any = [{ r: 0, c: col, b: '', a: ir, d: def }]; // r:0,a:i/r => insert/remove col\r\n for (let index = 1; index <= maxrow; index++) {\r\n const tr = tbodyElm.childNodes[index] as HTMLTableRowElement;\r\n const v = text(tr.childNodes[rmColNum] as HTMLTableCellElement);\r\n if (v != '') hists.push({ r: index, c: rmColNum, b: v, a: '' });\r\n }\r\n addhists(hists);\r\n }\r\n //---------------------------------------------------------------\r\n // insert col\r\n const insertCol = (col: number, def?: TYM_EDITOR_DEF) => viewInsertRemoveCol(col, maxcol, def);\r\n //---------------------------------------------------------------\r\n // remove col\r\n const removeCol = (col: number) => viewInsertRemoveCol(maxcol + 1, col);\r\n /****************************************************************\r\n * set public function (insertCol)\r\n */\r\n this.insertCol = (col: number, def?: TYM_EDITOR_DEF) => {\r\n histInsertRemoveCol(col, maxcol, 'i');\r\n insertCol(col, def);\r\n }\r\n /****************************************************************\r\n * set public function (removeCol)\r\n */\r\n this.removeCol = (col: number) => {\r\n histInsertRemoveCol(col, col, 'r');\r\n removeCol(col);\r\n }\r\n /****************************************************************\r\n * set public function (copy)\r\n */\r\n this.copy = () => elm2clipboard();\r\n /****************************************************************\r\n * set public function (paste)\r\n */\r\n this.paste = () => clipboard2elm();\r\n /****************************************************************\r\n * set public function (delete)\r\n */\r\n this.delete = () => deleteTexts();\r\n /****************************************************************\r\n * set public function (undo)\r\n */\r\n this.undo = () => {\r\n undoredo(false);\r\n }\r\n /****************************************************************\r\n * set public function (redo)\r\n */\r\n this.redo = () => {\r\n undoredo(true);\r\n }\r\n\r\n /****************************************************************\r\n * clear all data in table (history, select range/style, copy range/style)\r\n */\r\n const clearAllData = () => {\r\n tbodyElm.childNodes.forEach(tr => {\r\n const _tr = tr as HTMLTableRowElement;\r\n if (_tr.rowIndex > 0) tr.childNodes.forEach(cell => {\r\n const td = cell as HTMLTableCellElement;\r\n if (td.cellIndex > 0) setText(td, '');\r\n });\r\n });\r\n clearSelRangeStyle(true);\r\n clearCpyRangeStyle();\r\n clearHistory();\r\n }\r\n //---------------------------------------------------------------\r\n // clipboard data\r\n const clipboard = navigator.clipboard;\r\n let clipdata: string;\r\n let copydat: any[][] = [];\r\n /****************************************************************\r\n * clear copy range / style\r\n */\r\n const clearCpyRangeStyle = () => {\r\n execRange(elm => classrm(elm, 'cpy'), cpysels);\r\n cpysels = { ...nosels };\r\n }\r\n /****************************************************************\r\n * set copy range / style\r\n * @param range \r\n */\r\n const setCpyRangeStyle = (range: RANGE) => {\r\n cpysels = range;\r\n execRange(elm => classadd(elm, 'cpy'), cpysels);\r\n }\r\n /****************************************************************\r\n * clear copy data (clear clipboard data)\r\n */\r\n const clearCpyData = async () => {\r\n copydat = [];\r\n try {\r\n await clipboard.writeText('');\r\n } catch (err) {\r\n console.error('failed to writeText: ', err);\r\n }\r\n }\r\n /****************************************************************\r\n * クリップボードからの(\\r\\n,/\\t区切りテキストの)貼り付け (use copydat)\r\n */\r\n const clipboard2elm = async () => {\r\n if (!crntElm) return;\r\n let data: any[][] = [];\r\n try {\r\n const text = await clipboard.readText();\r\n if (clipdata != text) {\r\n clearCpyRangeStyle();\r\n }\r\n const rows = text.split('\\r\\n');\r\n rows.forEach(row => data.push(row.split('\\t')));\r\n } catch (err) {\r\n console.error('failed to readText: ', err);\r\n data = copydat;\r\n }\r\n const [r, c] = cellRowCol(crntElm);\r\n setData2Range(data, r, c);\r\n }\r\n /****************************************************************\r\n * クリップボードへの(\\r\\n,/\\t区切りテキストの)設定 (set copydat)\r\n */\r\n const elm2clipboard = async () => {\r\n clearCpyRangeStyle();\r\n let cols: any[] = [];\r\n copydat = [];\r\n execRange((elm, eol) => {\r\n cols.push(text(elm));\r\n if (eol) {\r\n copydat.push(cols);\r\n cols = [];\r\n }\r\n });\r\n let rows: any[] = [];\r\n copydat.forEach(cols => rows.push(cols.join('\\t')));\r\n setCpyRangeStyle((selects.c2 >= 0) ? { ...selects } : crntRange());\r\n try {\r\n clipdata = rows.join('\\r\\n');\r\n await clipboard.writeText(rows.join('\\r\\n'));\r\n } catch (err) {\r\n console.error('failed to writeText: ', err);\r\n }\r\n }\r\n /****************************************************************\r\n * 選択範囲を消す\r\n */\r\n const deleteTexts = (): void => {\r\n let hists: any = [];\r\n execRange(elm => {\r\n const [r, c] = cellRowCol(elm);\r\n hists.push({ r: r, c: c, b: text(elm), a: '' });\r\n setText(elm, '');\r\n });\r\n // 編集履歴に追加\r\n addhists(hists);\r\n }\r\n\r\n //---------------------------------------------------------------\r\n // prepare def(TYM_EDITOR_DEF) data\r\n this.defs.forEach(def => editordefs.set(def.col, def));\r\n\r\n //---------------------------------------------------------------\r\n // create : table - tbody - [1st tr:header - th]\r\n const headTrElm = tbodyElm.appendChild(createElm('tr'));\r\n {\r\n headTrElm.appendChild(createTh('')); // top&left\r\n (headTrElm.lastElementChild as HTMLElement).onprogress = () => { };\r\n for (let index = 1; index <= maxcol; index++) {\r\n headTrElm.appendChild(createRowTh(index, editordefs.get(index))); // top\r\n }\r\n }\r\n\r\n //---------------------------------------------------------------\r\n // create : table - tbody - [tr - td]\r\n {\r\n for (let index = 1; index <= maxrow; index++) {\r\n tbodyElm.appendChild(createrow(index));\r\n }\r\n }\r\n\r\n //---------------------------------------------------------------\r\n // create : style\r\n const styleElement = createElm('style');\r\n thisElm.append(styleElement);\r\n styleElement.innerText = styleElement.innerText = getStyleText();\r\n\r\n //---------------------------------------------------------------\r\n // set cell data\r\n setData2Table(this.data || [['']]);\r\n\r\n //---------------------------------------------------------------\r\n // set width\r\n headTrElm.childNodes.forEach(node => {\r\n const elm = node as HTMLElement;\r\n if (elm.tagName == 'TH') { // #comment 除去\r\n const realStyle = window.getComputedStyle(elm);\r\n elm.style.width = (elm.clientWidth > 200) ? '200px' : realStyle.width;\r\n }\r\n });\r\n tableElm.style.width = 'fit-content';\r\n\r\n //---------------------------------------------------------------\r\n // set 1st cell\r\n clearSelRangeStyle();\r\n setCurrent(cell(1, 1));\r\n\r\n /****************************************************************\r\n * mouse down event\r\n * @param e MouseEvent\r\n */\r\n const event_mousedown = (e: MouseEvent) => {\r\n let td = e.target as HTMLTableCellElement;\r\n if (e.button == 2) {\r\n const { r1, c1, r2, c2 } = range();\r\n const [r, c] = cellRowCol(td);\r\n if (r1 <= r && r <= r2 && c1 <= c && c <= c2) return;\r\n }\r\n if (e.detail == 1) {\r\n clearSelRangeStyle();\r\n if (td.tagName == 'TH') {\r\n // 1st click header:th or row top:th element\r\n const [thRowIx, thColIx] = cellRowCol(td);\r\n const [crRowIx, crColIx] = (e.shiftKey)\r\n ? ((crntElm) ? cellRowCol(crntElm) : [1, 1])\r\n : [thRowIx, thColIx];\r\n const isHead = (thRowIx == 0);\r\n selects = (isHead)\r\n ? { r1: 1, c1: crColIx, r2: maxrow, c2: thColIx }\r\n : { r1: crRowIx, c1: 1, r2: thRowIx, c2: maxcol };\r\n if (e.shiftKey) {\r\n mousemv = 0;\r\n drawSelRangeStyle();\r\n } else {\r\n mousemv = (isHead) ? 2 : 3;\r\n setCurrent(cell(selects.r1, selects.c1));\r\n }\r\n } else {\r\n // 1st click => change current\r\n if (e.shiftKey) {\r\n const [r, c] = cellRowCol(crntElm);\r\n setSelRange1stRowCol(r, c)\r\n setSelRangeLst(td);\r\n drawSelRangeStyle();\r\n mousemv = 0;\r\n } else {\r\n setCurrent(td);\r\n setSelRange1st(td);\r\n mousemv = 1;\r\n }\r\n }\r\n } if (e.detail == 2) {\r\n if (td.tagName == 'TH') {\r\n // duble click => widen cell\r\n clearSelRangeStyle();\r\n widen(td);\r\n drawSelRangeStyle();\r\n } else {\r\n // duble click => change edit mode\r\n toEdit(td);\r\n e.preventDefault();\r\n }\r\n }\r\n }\r\n tableElm.addEventListener('mousedown', event_mousedown);\r\n /****************************************************************\r\n * mouse move event\r\n * @param e MouseEvent\r\n */\r\n const event_mousemove = (e: MouseEvent) => {\r\n if (mousemv == 0) return;\r\n const td = e.target as HTMLTableCellElement;\r\n let [r, c] = cellRowCol(td);\r\n if (mousemv == 1 && selects.r2 == r && selects.c2 == c) return;\r\n if (mousemv == 2) r = selects.r2;\r\n if (mousemv == 3) c = selects.c2;\r\n clearSelRangeStyle();\r\n [selects.r2, selects.c2] = [r, c];\r\n drawSelRangeStyle();\r\n }\r\n tableElm.addEventListener('mousemove', event_mousemove);\r\n /****************************************************************\r\n * mouse leave event\r\n * @param e MouseEvent\r\n */\r\n const event_mouseleave = (e: MouseEvent) => {\r\n if (mousemv == 0) return;\r\n clearSelRangeStyle(true);\r\n mousemv = 0;\r\n }\r\n tableElm.addEventListener('mouseleave', event_mouseleave);\r\n /****************************************************************\r\n * mouse up event\r\n * @param e MouseEvent\r\n */\r\n const event_mouseup = (e: MouseEvent) => {\r\n const td = e.target as HTMLTableCellElement;\r\n const [r, c] = cellRowCol(td);\r\n if (mousemv == 1 && selects.r1 == r && selects.c1 == c) {\r\n clearSelRangeStyle(true);\r\n }\r\n if (mousemv == 2 && selects.c1 == c) drawSelRangeStyle();\r\n if (mousemv == 3 && selects.r1 == r) drawSelRangeStyle();\r\n mousemv = 0;\r\n crntElm?.focus({ preventScroll: true });\r\n }\r\n tableElm.addEventListener('mouseup', event_mouseup);\r\n /****************************************************************\r\n * contextmenu event\r\n * @param e MouseEvent\r\n */\r\n const event_contextmenu = (e: MouseEvent) => {\r\n const { r1, c1, r2, c2 } = range();\r\n const ret = this.menu(e, r1, c1, r2, c2);\r\n if (ret) {\r\n e.preventDefault();\r\n }\r\n return ret;\r\n }\r\n tableElm.addEventListener('contextmenu', event_contextmenu);\r\n\r\n /****************************************************************\r\n * keypress event\r\n * @param e KeyboardEvent\r\n */\r\n const event_keypress = (e: KeyboardEvent) => {\r\n const td = e.target as HTMLTableCellElement;\r\n if (!editElm) {\r\n toEdit(td, e.key);\r\n }\r\n }\r\n tableElm.addEventListener('keypress', event_keypress);\r\n let escapecnt = 0;\r\n const { offsetWidth: zzWidth, offsetHeight: zzHeight } = cell(0, 0);\r\n /****************************************************************\r\n * key down event\r\n * @param e KeyboardEvent\r\n */\r\n const event_keydown = (e: KeyboardEvent) => {\r\n const thisCell = e.target as HTMLTableCellElement;\r\n const [thisRowIx, thisColIx] = cellRowCol(thisCell);\r\n const rangeAll = { r1: 1, c1: 1, r2: maxrow, c2: maxcol };\r\n //-------------------------------------------------------------\r\n /** 矢印によるフォーカスの移動 */\r\n const arrow = (opt: ScrollToOptions, rowix: number, colix: number): HTMLTableCellElement => {\r\n const td = cell(rowix, colix);\r\n {\r\n const ofLeft = td.offsetLeft - zzWidth;\r\n if (ofLeft < scrollElm.scrollLeft) scrollElm.scroll({ left: ofLeft } as ScrollToOptions);\r\n }\r\n {\r\n const ofLeft = td.offsetLeft + td.clientWidth + scrollElm.clientLeft - scrollElm.clientWidth;\r\n if (ofLeft > scrollElm.scrollLeft) scrollElm.scroll({ left: ofLeft } as ScrollToOptions);\r\n }\r\n {\r\n const ofTop = td.offsetTop - zzHeight;\r\n if (ofTop < scrollElm.scrollTop) scrollElm.scroll({ top: ofTop } as ScrollToOptions)\r\n }\r\n td.blur();\r\n td.focus();\r\n setCurrent(td);\r\n e.preventDefault();\r\n return td;\r\n }\r\n //-------------------------------------------------------------\r\n /** 上下左右端用のスクロール指示情報取得 */\r\n const getScroll = (row: number, col: number) => {\r\n let scroll: { left?: number, top?: number } = {}\r\n const { r1, c1, r2, c2 } = rangeAll;\r\n if (col == c1) scroll.left = 0;\r\n if (col == c2) scroll.left = 9999;\r\n if (row == r1) scroll.top = 0;\r\n if (row == r2) scroll.top = 9999;\r\n return scroll;\r\n }\r\n //-------------------------------------------------------------\r\n /** 矢印によるフォーカスの上下左右移動 */\r\n const updownleftright = (isUpDown: boolean, isUpOrLeft: boolean, range: boolean = false): HTMLTableCellElement => {\r\n const b = (range && selects.c2 >= 0);\r\n const { r1, c1, r2, c2 } = b ? selects : rangeAll;\r\n let [rowIx, colIx] = [thisRowIx, thisColIx];\r\n const [A, B, C, D, E] = (isUpDown)\r\n ? (isUpOrLeft)\r\n ? [(rowIx > r1), -1, 0, r2, (colIx > c1) ? colIx - 1 : c2]\r\n : [(rowIx < r2), +1, 0, r1, (colIx < c2) ? colIx + 1 : c1]\r\n : (isUpOrLeft)\r\n ? [(colIx > c1), 0, -1, (rowIx > r1) ? rowIx - 1 : r2, c2]\r\n : [(colIx < c2), 0, +1, (rowIx < r2) ? rowIx + 1 : r1, c1];\r\n [rowIx, colIx] = A ? [rowIx + B, colIx + C] : ((b) ? [D, E] : [rowIx, colIx]);\r\n return arrow(getScroll(rowIx, colIx), rowIx, colIx);\r\n }\r\n //-------------------------------------------------------------\r\n /** 矢印によるフォーカスの移動 */\r\n const arrowmove = (isUpDown: boolean, isShift: boolean, dir: boolean) => {\r\n if (isShift) {\r\n clearSelRangeStyle();\r\n if (selects.c1 < 0) {\r\n setSelRange1st(thisCell);\r\n }\r\n const _td = updownleftright(isUpDown, dir);\r\n setSelRangeLst(_td);\r\n drawSelRangeStyle();\r\n } else {\r\n clearSelRangeStyle(true);\r\n updownleftright(isUpDown, dir);\r\n }\r\n }\r\n //-------------------------------------------------------------\r\n // 編集モード時のキー処理\r\n if (editElm) {\r\n switch (e.key) {\r\n case 'Tab':\r\n updownleftright(false, e.shiftKey, true);\r\n break;\r\n case 'Enter':\r\n updownleftright(true, e.shiftKey, true);\r\n break;\r\n case 'Escape':\r\n thisCell.innerText = beforeValue!;\r\n thisCell.blur();\r\n thisCell.focus();\r\n e.preventDefault();\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n //-------------------------------------------------------------\r\n // 表示モード時のキー処理\r\n else {\r\n escapecnt--;\r\n switch (e.key) {\r\n case 'ArrowDown':\r\n arrowmove(true, e.shiftKey, false);\r\n break;\r\n case 'ArrowUp':\r\n arrowmove(true, e.shiftKey, true);\r\n break;\r\n case 'ArrowRight':\r\n arrowmove(false, e.shiftKey, false);\r\n break;\r\n case 'ArrowLeft':\r\n arrowmove(false, e.shiftKey, true);\r\n break;\r\n case 'Home':\r\n if (e.ctrlKey) {\r\n arrow(getScroll(1, 1), 1, 1);\r\n } else {\r\n arrow(getScroll(thisRowIx, 1), thisRowIx, 1);\r\n }\r\n break;\r\n case 'End':\r\n if (e.ctrlKey) {\r\n arrow(getScroll(maxrow, maxcol), maxrow, maxcol);\r\n } else {\r\n arrow(getScroll(thisRowIx, maxcol), thisRowIx, maxcol);\r\n }\r\n break;\r\n case 'Tab':\r\n updownleftright(false, e.shiftKey, true);\r\n break;\r\n case 'Enter':\r\n updownleftright(true, e.shiftKey, true);\r\n break;\r\n case 'F2':\r\n toEdit(thisCell);\r\n e.preventDefault();\r\n break;\r\n case 'Backspace':\r\n const newtd = toEdit(thisCell, '');\r\n if (newtd) setText(newtd, '');\r\n e.preventDefault();\r\n break;\r\n case 'Delete':\r\n if (e.shiftKey) {\r\n // cut\r\n elm2clipboard();\r\n }\r\n deleteTexts();\r\n e.preventDefault();\r\n break;\r\n case 'x':\r\n if (e.ctrlKey) {\r\n // cut\r\n elm2clipboard();\r\n deleteTexts();\r\n e.preventDefault();\r\n }\r\n break;\r\n case 'c':\r\n if (e.ctrlKey) {\r\n // copy\r\n elm2clipboard();\r\n e.preventDefault();\r\n }\r\n break;\r\n case 'v':\r\n if (e.ctrlKey) {\r\n // paste\r\n clipboard2elm();\r\n e.preventDefault();\r\n }\r\n break;\r\n case 'Insert':\r\n if (e.ctrlKey) {\r\n // copy\r\n elm2clipboard();\r\n e.preventDefault();\r\n }\r\n if (e.shiftKey) {\r\n // paste\r\n clipboard2elm();\r\n e.preventDefault();\r\n }\r\n break;\r\n case 'z':\r\n case 'Z':\r\n if (e.ctrlKey) {\r\n // true(redo: Ctrl+Shift+z), false(undo: Ctrl+z)\r\n undoredo(e.shiftKey);\r\n e.preventDefault();\r\n }\r\n break;\r\n case 'y':\r\n if (e.ctrlKey) {\r\n // redo: Ctrl+y\r\n undoredo(true);\r\n e.preventDefault();\r\n }\r\n break;\r\n case 'Escape':\r\n if (escapecnt < 0) {\r\n escapecnt = 1;\r\n } else if (escapecnt >= 0) {\r\n clearCpyRangeStyle();\r\n clearCpyData();\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n tableElm.addEventListener('keydown', event_keydown);\r\n /****************************************************************\r\n * Escapeキー戻値用\r\n */\r\n let beforeValue: string | null;\r\n\r\n /****************************************************************\r\n * フォーカスアウトイベント処理,表示モードにする\r\n */\r\n const editBlue = () => {\r\n if (editElm) {\r\n const thisValue = editElm.innerText;\r\n editElm.scrollLeft = 0\r\n editElm.removeEventListener('blur', editBlue);\r\n editElm.removeAttribute('contentEditable');\r\n const [r, c] = cellRowCol(editElm);\r\n setText(editElm, thisValue);\r\n if (thisValue != beforeValue && beforeValue != null) {\r\n const hist = { r: r, c: c, b: beforeValue, a: thisValue };\r\n addhists([hist]);\r\n }\r\n if (this._opts.editModeAutoResize) {\r\n widen(headTrElm.children[editElm.cellIndex] as HTMLTableCellElement);\r\n }\r\n }\r\n beforeValue = null;\r\n editElm = null;\r\n }\r\n\r\n /****************************************************************\r\n * 対象セルを編集モードにする\r\n * @param td 対象エレメント\r\n * @param val キーイベントによる値\r\n * @returns 対象セルエレメント または 作り直したセルエレメント\r\n */\r\n const toEdit = (td: HTMLTableCellElement, val?: string) => {\r\n const realStyle = window.getComputedStyle(td);\r\n if (realStyle.backgroundColor == 'rgb(248, 248, 248)') return null;\r\n clearCpyRangeStyle();\r\n const [r, c] = cellRowCol(td);\r\n const editfnc = getEditFunc(td);\r\n beforeValue = text(td);\r\n if (editfnc) {\r\n // 編集機能あり\r\n editfnc(td, val || beforeValue).then(v => {\r\n if (v != null) {\r\n setText(td, v);\r\n addhists([{ r: r, c: c, b: beforeValue!, a: v }]);\r\n }\r\n });\r\n return td;\r\n } else {\r\n // 編集機能なし\r\n td.innerText = beforeValue;\r\n td.contentEditable = 'true';\r\n const newtd = td.parentElement?.insertBefore(td.cloneNode(true), td) as HTMLTableCellElement;\r\n setCurrent(newtd);\r\n newtd.addEventListener('blur', editBlue);\r\n const [sel, rng] = [window.getSelection(), document.createRange()];\r\n rng.selectNodeContents(newtd);\r\n sel?.removeAllRanges();\r\n sel?.addRange(rng)\r\n td.remove();\r\n editElm = newtd;\r\n return newtd;\r\n }\r\n }\r\n\r\n //---------------------------------------------------------------\r\n // ..\r\n let history: HISTS[] = [];\r\n let history_pos: number = -1;\r\n let history_dwn: boolean = false;\r\n /****************************************************************\r\n * 編集履歴:履歴クリア\r\n */\r\n const clearHistory = () => {\r\n history.length = 0;\r\n history_pos = -1;\r\n history_dwn = false;\r\n }\r\n /****************************************************************\r\n * 編集履歴:履歴追加\r\n * @param hists 履歴情報\r\n */\r\n const addhists = (hists: HISTS) => {\r\n if ((history.length - 1 == history_pos && history_dwn) || history_pos == -1) {\r\n history.push(hists);\r\n history_pos++;\r\n } else {\r\n if (history_dwn) history_pos++;\r\n history.splice(history_pos, 99999, hists);\r\n }\r\n history_dwn = true;\r\n }\r\n //---------------------------------------------------------------\r\n // ..\r\n const undoredoRange = (r1: number, c1: number, r2: number, c2: number) => {\r\n if (r1 != r2 || c1 != c2) {\r\n setSelRange1stRowCol(r1, c1);\r\n setSelRangeLstRowCol(r2, c2);\r\n drawSelRangeStyle();\r\n }\r\n const td = cell(r1, c1);\r\n td.focus();\r\n setCurrent(td);\r\n }\r\n /****************************************************************\r\n * 編集履歴:アンドゥ&リドゥ処理\r\n * @param redo true:リドゥ, false:アンドゥ\r\n */\r\n const undoredo = (redo: boolean) => {\r\n let pos = history_pos;\r\n if (\r\n (pos < 0) ||\r\n (!redo && pos <= 0 && !history_dwn) ||\r\n (redo && history.length - 1 == pos && history_dwn)) return;\r\n if (redo != history_dwn) {\r\n history_dwn = redo;\r\n } else {\r\n pos += (redo ? history.length - 1 > pos : pos > 0) ? (redo ? 1 : -1) : 0;\r\n }\r\n const hist = history[pos];\r\n history_pos = pos;\r\n const [v1, v2] = [hist[0], hist[hist.length - 1]];\r\n let index;\r\n clearCpyRangeStyle();\r\n clearSelRangeStyle();\r\n if (v1.c == 0) {\r\n // c:0,a:r => remove row / c:0,a:i => insert row\r\n const { a, r } = v1;\r\n if (a == 'i') {\r\n if (redo) { insertRow(r); } else { removeRow(r); }\r\n } else if (a == 'r') {\r\n if (redo) { removeRow(r); } else { insertRow(r); }\r\n }\r\n index = (redo) ? hist.length : 1;\r\n undoredoRange(r, 1, r, maxcol);\r\n } else if (v1.r == 0) {\r\n // r:0,a:r => remove col / r:0,a:i => insert col\r\n const { a, c, d } = v1;\r\n if (a == 'i') {\r\n if (redo) { insertCol(c, d); } else { removeCol(c); }\r\n } else if (a == 'r') {\r\n if (redo) { removeCol(c); } else { insertCol(c, d); }\r\n }\r\n index = (redo) ? hist.length : 1;\r\n undoredoRange(1, c, maxrow, c);\r\n } else {\r\n index = 0;\r\n undoredoRange(v1.r, v1.c, v2.r, v2.c);\r\n }\r\n for (; index < hist.length; index++) {\r\n const { r, c, a, b } = hist[index];\r\n setText(cell(r, c), (redo) ? a : b);\r\n }\r\n }\r\n\r\n /****************************************************************\r\n * カラムリサイズ\r\n * @param thElm 対象エレメント\r\n */\r\n const widen = (thElm: HTMLTableCellElement) => {\r\n const scrollLeft = scrollElm.scrollLeft; // スクロール状態を保持\r\n const cntnrRect = FIRST_ELEMENT_CHILD(scrollElm)!.getBoundingClientRect();\r\n const cellElms = tableElm.querySelectorAll(`tbody tr td:nth-child(${thElm.cellIndex + 1})`);\r\n if (cellElms.length <= 0) return;\r\n // padding, margin サイズを求める\r\n const realStyle = window.getComputedStyle(cellElms.item(0));\r\n const padSize = ''\r\n + `${realStyle.paddingLeft} + ${realStyle.paddingRight} + `\r\n + `${realStyle.marginLeft} + ${realStyle.marginRight}`;\r\n thElm.style.width = '4em';// 一時的にセルのサイズを縮める\r\n tbodyElm.classList.add('widen');\r\n // 全ての行をチェックし最大widthを求める (tbody > tr > td)\r\n let maxWidth = Array.from(cellElms).reduce((a, b) => a.scrollWidth > b.scrollWidth ? a : b).scrollWidth;\r\n thElm.style.width = `calc(${Math.min(maxWidth, (cntnrRect.width * .7))}px + ${padSize})`;\r\n tbodyElm.classList.remove('widen');\r\n scrollElm.scrollLeft = scrollLeft; // スクロール状態を回復\r\n }\r\n }\r\n\r\n //-----------------------------------------------------------------\r\n // 公開関数\r\n //-----------------------------------------------------------------\r\n\r\n /******************************************************************\r\n * セルの文字列を取得する\r\n * @param rownum 取得する行数\r\n * @param colnum 取得する列数\r\n * @param fnc 取得用コールバック関数\r\n */\r\n public getCells(rownum: number, colnum: number, fnc: (row: number, col: number, val: string, eol: boolean) => void) {\r\n const tableElm = FIRST_ELEMENT_CHILD(this._thisElm);\r\n const tbodyElm = FIRST_ELEMENT_CHILD(tableElm);\r\n for (let _row = 1; _row <= rownum; _row++) {\r\n for (let _col = 1; _col <= colnum; _col++) {\r\n const td = tbodyElm.children[_row].children[_col] as HTMLTableCellElement;\r\n fnc(_row, _col, td.innerText, colnum == _col);\r\n }\r\n }\r\n }\r\n\r\n /******************************************************************\r\n * テーブルにデータを設定する\r\n * @param data 設定するデータ\r\n */\r\n public setData(data: any[][]): void;\r\n\r\n /******************************************************************\r\n * テーブルにデータを設定する\r\n * @param data 設定するデータ\r\n * @param row1 設定する開始行番号\r\n * @param col1 設定する開始列番号\r\n */\r\n public setData(data: any[][], row1: number, col1: number): void;\r\n\r\n /******************************************************************\r\n * テーブルにデータを設定する\r\n * @param data 設定するデータ\r\n * @param row1 設定する開始行番号\r\n * @param col1 設定する開始列番号\r\n */\r\n public setData(data: any[][], row1?: number, col1?: number): void { }\r\n\r\n /******************************************************************\r\n * テーブルからデータを取得する\r\n * @param rownum 取得する行数\r\n * @param colnum 取得する列数\r\n * @returns data: any[][]\r\n */\r\n public getData(rownum: number, colnum: number): any[][];\r\n\r\n /******************************************************************\r\n * テーブルからデータを取得する\r\n * @param row1 取得する開始行番号\r\n * @param col1 取得する開始列番号\r\n * @param row2 取得する終了行番号\r\n * @param col2 取得する終了列番号\r\n * @returns data: any[][]\r\n */\r\n public getData(row1: number, col1: number, row2: number, col2: number): any[][];\r\n\r\n /******************************************************************\r\n * テーブルからデータを取得する\r\n * @param rownum 取得する行数 or 取得する開始行番号\r\n * @param colnum 取得する列数 or 取得する開始列番号\r\n * @param row 取得する終了行番号\r\n * @param col 取得する終了列番号\r\n * @returns data: any[][]\r\n */\r\n public getData(rownum: number, colnum: number, row?: number, col?: number): any[][] { return [] }\r\n\r\n /******************************************************************\r\n * テーブルに行の挿入する\r\n * @param row 挿入する位置の行番号\r\n */\r\n public insertRow(row: number): void { }\r\n\r\n /******************************************************************\r\n * テーブルから行を削除する\r\n * @param row 削除する位置の行番号\r\n */\r\n public removeRow(row: number): void { }\r\n\r\n /******************************************************************\r\n * テーブルに列の挿入する\r\n * @param col 挿入する位置の列番号\r\n * @param def 定義\r\n */\r\n public insertCol(col: number, def?: TYM_EDITOR_DEF):