UNPKG

nadesiko3

Version:
634 lines (630 loc) 24.7 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親要素設定': { // @「ボタン作成」「エディタ作成」など『DOM部品作成』で追加する要素の親要素を指定(デフォルトはdocument)して要素を返す。 // @DOMおやようそせってい type: 'func', josi: [['に', 'へ']], pure: true, fn: function(el: any, sys: any) { if (typeof el === 'string') { el = document.querySelector(el) || document.getElementById(el) } sys.__setSysVar('DOM親要素', el) sys.__addPropMethod(el) return el } }, 'DOM親部品設定': { // @ DOM部品作成でDOM要素を追加する親の対象を指定。『DOM親要素設定』と同じ。// @DOMおやぶひんせってい type: 'func', josi: [['に', 'へ']], pure: true, fn: function(el: any, sys: any) { return sys.__exec('DOM親要素設定', [el, sys]) } }, 'DOMスキン': { type: 'const', value: '' }, // @DOMすきん 'DOMスキン辞書': { type: 'const', value: {} }, // @DOMすきんじしょ 'DOMスキン設定': { // @「ボタン作成」「エディタ作成」などで適用するスキンを指定する(#1033) // @DOMすきんせってい type: 'func', josi: [['を', 'に', 'の']], pure: true, fn: function(skin: any, sys: any) { sys.__setSysVar('DOMスキン', skin) }, return_none: true }, 'DOM部品作成': { // @elmの要素を作成して『DOM親要素設定』で指定した要素に追加して、DOMオブジェクトを返す。(elmがDOM要素なら追加する) // @DOMぶひんさくせい type: 'func', josi: [['の']], pure: true, fn: function(elm: any, sys: any) { 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部品削除': { // @elmの要素を削除する // @DOMぶひんさくじょ type: 'func', josi: [['の', 'を']], pure: true, fn: function(elm: any) { if (typeof elm === 'string') { elm = document.querySelector(elm) } if (elm) { elm.parentNode.removeChild(elm) } }, return_none: true }, 'ボタン作成': { // @ラベルlabelを持つbutton要素を追加しDOMオブジェクトを返す // @ぼたんさくせい type: 'func', josi: [['の']], pure: true, fn: function(label: any, sys: any) { const btn = sys.__exec('DOM部品作成', ['button', sys]) btn.innerHTML = label return btn } }, 'エディタ作成': { // @textの値を持つテキストボックス(input[type='text'])の要素を追加しDOMオブジェクトを返す // @えでぃたさくせい type: 'func', josi: [['の']], pure: true, fn: function(text: any, sys: any) { const inp = sys.__exec('DOM部品作成', ['input', sys]) inp.type = 'text' inp.value = text return inp } }, 'テキストエリア作成': { // @textの値を持つtextarea要素を追加しDOMオブジェクトを返す // @てきすとえりあさくせい type: 'func', josi: [['の']], pure: true, fn: function(text: any, sys: any) { const te = sys.__exec('DOM部品作成', ['textarea', sys]) te.value = text return te } }, 'ラベル作成': { // @textの値を持つラベル(span要素)を追加しDOMオブジェクトを返す // @らべるさくせい type: 'func', josi: [['の']], pure: true, fn: function(text: any, sys: any) { const lbl = sys.__exec('DOM部品作成', ['span', sys]) lbl.innerHTML = text return lbl } }, 'キャンバス作成': { // @大きさ[幅, 高]のcanvas要素を追加しDOMオブジェクトを返す // @きゃんばすさくせい type: 'func', josi: [['の']], pure: true, fn: function(size: any, sys: any) { 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 } }, '画像作成': { // @URLを指定してimg要素を追加しDOMオブジェクトを返す // @がぞうさくせい type: 'func', josi: [['の', 'から']], pure: true, fn: function(url: any, sys: any) { const img = sys.__exec('DOM部品作成', ['img', sys]) img.src = url return img } }, '改行作成': { // @改行(br要素)を追加しDOMオブジェクトを返す // @かいぎょうさくせい type: 'func', josi: [], pure: true, fn: function(sys: any) { const br = sys.__exec('DOM部品作成', ['br', sys]) return br } }, 'チェックボックス作成': { // @textのラベルを持つチェックボックス(input[type='checkbox'])要素を追加しDOMオブジェクトを返す // @ちぇっくぼっくすさくせい type: 'func', josi: [['の']], pure: true, fn: function(text: any, sys: any) { // チェックボックスは、<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 } }, 'セレクトボックス作成': { // @配列optionsの選択肢を持つselect要素を追加しDOMオブジェクトを返す // @せれくとぼっくすさくせい type: 'func', josi: [['の']], pure: true, fn: function(options: any, sys: any) { 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 } }, 'セレクトボックスアイテム設定': { // @配列データをセレクトボックスdomのアイテムに差し替える // @せれくとぼっくすあいてむせってい type: 'func', josi: [['を'], ['へ', 'に']], pure: true, fn: function(options: any, dom: any) { 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 }, '色選択ボックス作成': { // @色選択ボックス(input[type='color'])を作成しDOMオブジェクトを返す // @いろせんたくぼっくすさくせい type: 'func', josi: [], pure: true, fn: function(sys: any) { const inp = sys.__exec('DOM部品作成', ['input', sys]) inp.type = 'color' return inp } }, '日付選択ボックス作成': { // @日付選択ボックス(input[type='date'])を作成しDOMオブジェクトを返す // @ひづけせんたくぼっくすさくせい type: 'func', josi: [], pure: true, fn: function(sys: any) { const inp = sys.__exec('DOM部品作成', ['input', sys]) inp.type = 'date' return inp } }, 'パスワード入力エディタ作成': { // @パスワード入力エディタ(input[type='password'])を作成し初期値Sを設定し、DOMオブジェクトを返す // @ぱすわーどにゅうりょくえでぃたさくせい type: 'func', josi: [['の', 'で']], pure: true, fn: function(s: any, sys: any) { const inp = sys.__exec('DOM部品作成', ['input', sys]) inp.type = 'password' inp.value = s return inp } }, '値指定バー作成': { // @範囲RANGE(配列で[最小,最大[,値]])を指定するバー(input[type='range'])を作成しDOMオブジェクトを返す // @あたいしていばーさくせい type: 'func', josi: [['の', 'で']], pure: true, fn: function(range: any, sys: any) { 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 } }, '送信ボタン作成': { // @ラベルSの送信ボタン(input[type='submit'])を作成しDOMオブジェクトを返す // @そうしんぼたんさくせい type: 'func', josi: [['の']], pure: true, fn: function(label: any, sys: any) { const inp = sys.__exec('DOM部品作成', ['input', sys]) inp.type = 'submit' inp.value = label return inp } }, 'フォーム作成': { // @属性OBJ{method:"GET",action:"..."}で項目一覧S「項目1=初期値1{改行}項目2=初期値2{改行}…」を送信フォームを作成しDOMオブジェクトを返す。「=?」でオプションの指定が可能 // @ふぉーむさくせい type: 'func', josi: [['で', 'の'], ['を']], pure: true, fn: function(obj: any, s: string|Array<string>|Array<Array<string>>, sys: any) { 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: Array<string>|Array<Array<string>> if (typeof s === 'string') { rows = s.split('\n') } else { rows = s } // 入力項目に合わせて行を追加 for (const rowIndex in rows) { const row: Array<string>|string = rows[rowIndex] let cols: Array<string> 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 } }, 'フォーム入力一括取得': { // @DOMのフォームを取得し、そのフォーム以下にある入力項目のnameとvalueを辞書形式で返す // @ふぉーむにゅうりょくいっかつしゅとく type: 'func', josi: [['の', 'から']], pure: true, fn: function(dom: any) { if (typeof (dom) === 'string') { dom = document.querySelector(dom) } const res: any = {} const getChildren = (pa: any) => { 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 } }, 'テーブル作成': { // @二次元配列AA(あるいは文字列の簡易CSVデータ)からTABLE要素を作成し、DOMオブジェクトを返す // @てーぶるさくせい type: 'func', josi: [['の', 'から']], pure: true, fn: function(aa: any, sys: any) { const table = sys.__exec('DOM部品作成', ['table', sys]) return sys.__exec('テーブル更新', [table, aa, sys]) } }, 'ヘッダ有テーブル作成': { // @二次元配列AA(あるいは文字列の簡易CSVデータ)からヘッダ有りのTABLE要素を作成し、DOMオブジェクトを返す // @へっだありてーぶるさくせい type: 'func', josi: [['の', 'から']], pure: true, fn: function(aa: any, sys: any) { const domOption = sys.__getSysVar('DOM部品オプション') const tmpTableHeader = domOption['テーブルヘッダ'] domOption['テーブルヘッダ'] = true const obj = sys.__exec('テーブル作成', [aa, sys]) domOption['テーブルヘッダ'] = tmpTableHeader return obj } }, 'ヘッダ無テーブル作成': { // @二次元配列AA(あるいは文字列の簡易CSVデータ)からヘッダ無しのTABLE要素を作成し、DOMオブジェクトを返す // @へっだなしてーぶるさくせい type: 'func', josi: [['の', 'から']], pure: true, fn: function(aa: any, sys: any) { const domOption = sys.__getSysVar('DOM部品オプション') const tmpTableHeader = domOption['テーブルヘッダ'] domOption['テーブルヘッダ'] = false const obj = sys.__exec('テーブル作成', [aa, sys]) domOption['テーブルヘッダ'] = tmpTableHeader return obj } }, 'テーブル更新': { // @既に作成したテーブルTBLを二次元配列AA(あるいは文字列の簡易CSVデータ)で更新する // @てーぶるこうしん type: 'func', josi: [['を'], ['に', 'へ']], pure: true, fn: function(tbl: any, aa: any, sys: any) { // 既存のテーブルを取得 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: Array<string> = JSON.parse( JSON.stringify(domOption['テーブル背景色']) ) for (let i = 0; i < 3; i++) { bgColor.push('') } const bgHead = bgColor.shift() || '' let hasHeader: boolean = domOption['テーブルヘッダ'] let isNumRight: boolean = 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 } }, 'テーブルセル変更': { // @TABLE要素のセル[行,列]をVへ変更する。Vが二次元配列変数であれば複数のセルを一括変更する // @てーぶるせるへんこう type: 'func', josi: [['の'], ['を'], ['に', 'へ']], pure: true, fn: function(t: any, cell: any, v: string|Array<Array<string>>, sys: any) { 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: boolean = 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 }, 'マーメイド作成': { // @ Mermaid記法を使ってSRCのチャートを作成する // @ まーめいどさくせい type: 'func', josi: [['の']], pure: true, asyncFn: true, fn: async function(src: string, sys: any) { 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: any) { const video = sys.__exec('DOM部品作成', ['video', sys]) return video } } }