UNPKG

nadesiko3

Version:
679 lines (678 loc) 25.3 kB
export default { // @DOM部品操作 'DOM親要素': { type: 'const', value: '' }, // @DOMおやようそ 'DOM部品個数': { type: 'const', value: 0 }, // @DOMせいせいこすう 'DOM部品オプション': { type: 'const', value: { '自動改行': false, 'テーブルヘッダ': true, 'テーブル背景色': ['#AA4040', '#ffffff', '#fff0f0'], 'テーブル数値右寄せ': true } }, // @DOMぶひんおぷしょん 'DOM親要素設定': { type: 'func', josi: [['に', 'へ']], pure: true, fn: function (el, sys) { if (typeof el === 'string') { el = document.querySelector(el) || document.getElementById(el); } sys.__setSysVar('DOM親要素', el); sys.__addPropMethod(el); return el; } }, 'DOM親部品設定': { type: 'func', josi: [['に', 'へ']], pure: true, fn: function (el, sys) { return sys.__exec('DOM親要素設定', [el, sys]); } }, 'DOMスキン': { type: 'const', value: '' }, // @DOMすきん 'DOMスキン辞書': { type: 'const', value: {} }, // @DOMすきんじしょ 'DOMスキン設定': { type: 'func', josi: [['を', 'に', 'の']], pure: true, fn: function (skin, sys) { sys.__setSysVar('DOMスキン', skin); }, return_none: true }, 'DOM部品作成': { type: 'func', josi: [['の']], pure: true, fn: function (elm, sys) { const parent = sys.__getSysVar('DOM親要素'); const btn = (typeof (elm) === 'string') ? document.createElement(elm) : elm; btn.id = 'nadesi-dom-' + sys.__getSysVar('DOM部品個数'); sys.__addPropMethod(btn); // スキン適用 const func = sys.__getSysVar('DOMスキン辞書')[sys.__getSysVar('DOMスキン')]; if (typeof (func) === 'function') { func(elm, btn, sys); } // DOM追加 parent.appendChild(btn); sys.__setSysVar('DOM部品個数', sys.__getSysVar('DOM部品個数', 0) + 1); // オプションを適用 const opt = sys.__getSysVar('DOM部品オプション'); if (opt['自動改行']) { parent.appendChild(document.createElement('br')); } // 「その」を設定 sys.__setSysVar('そ', btn); return btn; } }, 'DOM部品削除': { type: 'func', josi: [['の', 'を']], pure: true, fn: function (elm) { if (typeof elm === 'string') { elm = document.querySelector(elm); } if (elm) { elm.parentNode.removeChild(elm); } }, return_none: true }, 'ボタン作成': { type: 'func', josi: [['の']], pure: true, fn: function (label, sys) { const btn = sys.__exec('DOM部品作成', ['button', sys]); btn.innerHTML = label; return btn; } }, 'エディタ作成': { type: 'func', josi: [['の']], pure: true, fn: function (text, sys) { const inp = sys.__exec('DOM部品作成', ['input', sys]); inp.type = 'text'; inp.value = text; return inp; } }, 'テキストエリア作成': { type: 'func', josi: [['の']], pure: true, fn: function (text, sys) { const te = sys.__exec('DOM部品作成', ['textarea', sys]); te.value = text; return te; } }, 'ラベル作成': { type: 'func', josi: [['の']], pure: true, fn: function (text, sys) { const lbl = sys.__exec('DOM部品作成', ['span', sys]); lbl.innerHTML = text; return lbl; } }, 'キャンバス作成': { type: 'func', josi: [['の']], pure: true, fn: function (size, sys) { const cv = sys.__exec('DOM部品作成', ['canvas', sys]); cv.width = size[0]; cv.height = size[1]; cv.style.width = size[0]; cv.style.height = size[1]; // 描画中キャンバスを移動する sys.__exec('描画開始', [cv, sys]); return cv; } }, '画像作成': { type: 'func', josi: [['の', 'から']], pure: true, fn: function (url, sys) { const img = sys.__exec('DOM部品作成', ['img', sys]); img.src = url; return img; } }, '改行作成': { type: 'func', josi: [], pure: true, fn: function (sys) { const br = sys.__exec('DOM部品作成', ['br', sys]); return br; } }, 'チェックボックス作成': { type: 'func', josi: [['の']], pure: true, fn: function (text, sys) { // チェックボックスは、<span><input><label></span>で成り立つように構築 const span = document.createElement('span'); const inp = document.createElement('input'); inp.type = 'checkbox'; inp.id = 'nadesi-dom-' + sys.__getSysVar('DOM部品個数', 0); sys.__setSysVar('DOM部品個数', sys.__getSysVar('DOM部品個数', 0) + 1); const label = document.createElement('label'); label.innerHTML = text; label.htmlFor = inp.id; span.appendChild(inp); span.appendChild(label); // 親部品に追加 sys.__exec('DOM部品作成', [span, sys]); return inp; } }, 'セレクトボックス作成': { type: 'func', josi: [['の']], pure: true, fn: function (options, sys) { const dom = document.createElement('select'); for (let i = 0; i < options.length; i++) { const item = document.createElement('option'); item.value = options[i]; item.appendChild(document.createTextNode(options[i])); dom.appendChild(item); } // 親部品に追加 sys.__exec('DOM部品作成', [dom, sys]); return dom; } }, 'セレクトボックスアイテム設定': { type: 'func', josi: [['を'], ['へ', 'に']], pure: true, fn: function (options, dom) { if (typeof dom === 'string') { dom = document.querySelector(dom); } // 既存のoptionsをクリア dom.options.length = 0; // アイテムを追加 for (let i = 0; i < options.length; i++) { const item = document.createElement('option'); item.value = options[i]; item.appendChild(document.createTextNode(options[i])); dom.appendChild(item); } }, return_none: true }, '色選択ボックス作成': { type: 'func', josi: [], pure: true, fn: function (sys) { const inp = sys.__exec('DOM部品作成', ['input', sys]); inp.type = 'color'; return inp; } }, '日付選択ボックス作成': { type: 'func', josi: [], pure: true, fn: function (sys) { const inp = sys.__exec('DOM部品作成', ['input', sys]); inp.type = 'date'; return inp; } }, 'パスワード入力エディタ作成': { type: 'func', josi: [['の', 'で']], pure: true, fn: function (s, sys) { const inp = sys.__exec('DOM部品作成', ['input', sys]); inp.type = 'password'; inp.value = s; return inp; } }, '値指定バー作成': { type: 'func', josi: [['の', 'で']], pure: true, fn: function (range, sys) { if (!(range instanceof Array) || range.length < 2) { range = [0, 100, 50]; } if (range.length <= 2) { // 3つ目を省略したとき range.push(Math.floor((range[1] - range[0]) / 2)); } const inp = sys.__exec('DOM部品作成', ['input', sys]); inp.type = 'range'; inp.min = range[0]; inp.max = range[1]; inp.value = range[2]; return inp; } }, '送信ボタン作成': { type: 'func', josi: [['の']], pure: true, fn: function (label, sys) { const inp = sys.__exec('DOM部品作成', ['input', sys]); inp.type = 'submit'; inp.value = label; return inp; } }, 'フォーム作成': { type: 'func', josi: [['で', 'の'], ['を']], pure: true, fn: function (obj, s, sys) { const frm = sys.__exec('DOM部品作成', ['form', sys]); // 可能ならformにobjの値を移し替える if (obj instanceof Object) { for (const key in obj) { if (frm[key]) { frm[key] = obj[key]; } } } // 入力項目をtableで作る const table = document.createElement('table'); // 入力項目がstringの場合、改行で分割 let rows; if (typeof s === 'string') { rows = s.split('\n'); } else { rows = s; } // 入力項目に合わせて行を追加 for (const rowIndex in rows) { const row = rows[rowIndex]; let cols; if (typeof row === 'string') { cols = row.split('='); } else { cols = row; } while (cols.length < 4) { cols.push(''); } const key = cols[0]; const val = cols[1]; const opt1 = cols[2]; const opt2 = cols[3]; let isHidden = false; if (key === '' && val === '') { continue; } // 空行は無視 // key const th = document.createElement('th'); const lbl = document.createElement('label'); lbl.innerHTML = sys.__tohtmlQ(key); th.appendChild(lbl); // val const td = document.createElement('td'); if (val.substring(0, 2) === '?(') { // select box const it = val.substring(2) + ')'; const ita = it.split(')'); const its = ita[0]; const def = ita[1]; const items = its.split('|'); const select = document.createElement('select'); select.name = key; for (const it of items) { const option = document.createElement('option'); option.value = it; option.text = it; select.appendChild(option); } const idx = items.indexOf(def); if (idx >= 0) { select.selectedIndex = idx; } td.appendChild(select); } else { // input element const inp = document.createElement('input'); td.appendChild(inp); const lbl2 = document.createElement('label'); td.appendChild(lbl2); inp.id = 'nako3form_' + key; lbl.htmlFor = inp.id; // check type v3.6.37 if (val === '?text') { inp.type = 'text'; inp.value = opt1; inp.placeholder = opt2; inp.name = key; } else if (val === '?password') { inp.type = 'password'; inp.value = opt1; inp.placeholder = opt2; inp.name = key; } else if (val === '?number') { inp.type = 'number'; inp.value = opt1; inp.placeholder = opt2; inp.name = key; } else if (val === '?email') { inp.type = 'email'; inp.value = opt1; inp.placeholder = opt2; inp.name = key; } else if (val === '?tel') { inp.type = 'tel'; inp.value = opt1; inp.placeholder = opt2; inp.name = key; } else if (val === '?file') { inp.type = 'file'; inp.name = key; } else if (val === '?date') { inp.type = 'date'; inp.value = opt1.replace(/\//g, '-'); inp.name = key; } else if (val === '?month') { inp.type = 'month'; inp.value = opt1.replace(/\//g, '-'); inp.name = key; } else if (val === '?time') { inp.type = 'time'; inp.value = opt1; inp.name = key; } else if (val === '?color') { inp.type = 'color'; inp.value = opt1; inp.name = key; } else if (val === '?hidden') { inp.type = 'hidden'; inp.value = opt1; inp.name = key; isHidden = true; frm.appendChild(inp); } else if (val === '?checkbox') { inp.type = 'checkbox'; inp.value = opt1; inp.name = key; lbl2.innerHTML = ' ' + sys.__tohtmlQ(opt2); lbl2.htmlFor = inp.id; } else if (val === '?送信' || val === '?submit') { // v3.2.33での拡張 inp.type = 'submit'; inp.value = val.substring(1); if (key !== '') { inp.name = key; } } else if (val.substring(0, 3) === '?c#') { inp.type = 'color'; inp.value = val.substring(2); inp.name = key; } else { inp.type = 'text'; inp.value = val; inp.name = key; } } if (isHidden) { continue; } const tr = document.createElement('tr'); tr.appendChild(th); tr.appendChild(td); table.appendChild(tr); } frm.appendChild(table); return frm; } }, 'フォーム入力一括取得': { type: 'func', josi: [['の', 'から']], pure: true, fn: function (dom) { if (typeof (dom) === 'string') { dom = document.querySelector(dom); } const res = {}; const getChildren = (pa) => { if (!pa || !pa.childNodes) { return; } for (let i = 0; i < pa.childNodes.length; i++) { const el = pa.childNodes[i]; if (!el.tagName) { return; } const tag = el.tagName.toLowerCase(); if (tag === 'input') { if (el.type === 'checkbox') { res[el.name] = el.checked ? el.value : ''; continue; } res[el.name] = el.value; continue; } else if (tag === 'textarea') { res[el.name] = el.value; } else if (tag === 'select') { if (el.selectedIndex >= 0) { res[el.name] = el.options[el.selectedIndex].value; } else { res[el.name] = ''; } } getChildren(el); } }; getChildren(dom); return res; } }, 'テーブル作成': { type: 'func', josi: [['の', 'から']], pure: true, fn: function (aa, sys) { const table = sys.__exec('DOM部品作成', ['table', sys]); return sys.__exec('テーブル更新', [table, aa, sys]); } }, 'ヘッダ有テーブル作成': { type: 'func', josi: [['の', 'から']], pure: true, fn: function (aa, sys) { const domOption = sys.__getSysVar('DOM部品オプション'); const tmpTableHeader = domOption['テーブルヘッダ']; domOption['テーブルヘッダ'] = true; const obj = sys.__exec('テーブル作成', [aa, sys]); domOption['テーブルヘッダ'] = tmpTableHeader; return obj; } }, 'ヘッダ無テーブル作成': { type: 'func', josi: [['の', 'から']], pure: true, fn: function (aa, sys) { const domOption = sys.__getSysVar('DOM部品オプション'); const tmpTableHeader = domOption['テーブルヘッダ']; domOption['テーブルヘッダ'] = false; const obj = sys.__exec('テーブル作成', [aa, sys]); domOption['テーブルヘッダ'] = tmpTableHeader; return obj; } }, 'テーブル更新': { type: 'func', josi: [['を'], ['に', 'へ']], pure: true, fn: function (tbl, aa, sys) { // 既存のテーブルを取得 if (typeof tbl === 'string') { tbl = sys.__query(tbl, 'テーブル更新', false); } tbl.innerHTML = ''; // 初期化 // テーブルに差し込むデータを確認 - 文字列ならarray[array[str]]に変換 if (typeof aa === 'string') { aa = sys.__exec('CSV取得', [aa, sys]); } const table = tbl; // テーブル作成/テーブル更新の設定を読み取る const domOption = sys.__getSysVar('DOM部品オプション'); // 背景色は複製して使う const bgColor = JSON.parse(JSON.stringify(domOption['テーブル背景色'])); for (let i = 0; i < 3; i++) { bgColor.push(''); } const bgHead = bgColor.shift() || ''; let hasHeader = domOption['テーブルヘッダ']; let isNumRight = domOption['テーブル数値右寄せ']; // 既存のテーブルに設定があれば読み取る if (table.dataset.nakoOptions !== undefined) { const nakoOptions = JSON.parse(table.dataset.nakoOptions); hasHeader = nakoOptions.hasHeader; isNumRight = nakoOptions.isNumRight; } // 設定をDOMに保存 table.dataset.nakoOptions = JSON.stringify({ hasHeader, isNumRight }); // テーブルにデータを追加していく for (let i = 0; i < aa.length; i++) { const rowNo = i; const row = aa[rowNo]; const tr = document.createElement('tr'); // 色指定 if (bgHead !== '') { const no = hasHeader ? rowNo : rowNo + 1; tr.style.backgroundColor = no === 0 ? bgHead : bgColor[no % 2]; tr.style.color = no === 0 ? 'white' : 'black'; } for (let col of row) { col = '' + col; const td = document.createElement(rowNo === 0 && hasHeader ? 'th' : 'td'); td.innerHTML = sys.__tohtml(col); if (isNumRight && col.match(/^(\+|-)?\d+(\.\d+)?$/)) { // number? td.style.textAlign = 'right'; } tr.appendChild(td); } table.appendChild(tr); } return table; } }, 'テーブルセル変更': { type: 'func', josi: [['の'], ['を'], ['に', 'へ']], pure: true, fn: function (t, cell, v, sys) { if (typeof (t) === 'string') { t = document.querySelector(t); } if (typeof (cell) === 'string') { cell = cell.split(','); } if (cell.length !== 2) { throw new Error('『テーブルセル変更』の引数「を」は[行,列]の形式で指定してください。'); } const row = cell[0]; const col = cell[1]; if (!(v instanceof Array)) { v = [[v]]; } // オプションを取得 const domOption = sys.__getSysVar('DOM部品オプション'); const bgColor = JSON.parse(JSON.stringify(domOption['テーブル背景色'])); // 複製して使う const isNumRight = domOption['テーブル数値右寄せ']; while (bgColor.length < 3) { // オプションが壊れていた時のための補完 bgColor.push('white'); } // 複数の範囲を一気に変更 for (let y = 0; y < v.length; y++) { const vRow = v[y]; for (let x = 0; x < vRow.length; x++) { const yy = row + y; let domTR = t.childNodes[yy]; while (!domTR) { const newTR = document.createElement('tr'); t.appendChild(newTR); domTR = t.childNodes[yy]; domTR.style.backgroundColor = bgColor[yy % 2 + 1]; } let td = domTR.childNodes[col + x]; while (!td) { const newTD = document.createElement('td'); domTR.appendChild(newTD); td = domTR.childNodes[col + x]; } const v = String(vRow[x]); td.innerHTML = sys.__tohtml(v); if (isNumRight && v.match(/^(\+|-)?\d+(\.\d+)?$/)) { // number? td.style.textAlign = 'right'; } } } }, return_none: true }, 'マーメイド作成': { type: 'func', josi: [['の']], pure: true, asyncFn: true, fn: async function (src, sys) { const div = sys.__exec('DOM部品作成', ['div', sys]); div.classList.add('mermaid'); div.innerHTML = src; // ライブラリを読み込む const win = sys.__getSysVar('WINDOW'); if (typeof win.mermaid === 'undefined') { console.log('try to load mermaid'); await sys.__loadScript('https://cdn.jsdelivr.net/npm/mermaid@10.5.0/dist/mermaid.min.js'); console.log('mermaid.jsを読み込みました'); } await win.mermaid.run(); return div; } }, 'ビデオ作成': { type: 'func', josi: [], pure: true, fn: function (sys) { const video = sys.__exec('DOM部品作成', ['video', sys]); return video; } } };