【JavaScript】HTML要素を簡単に生成・編集する関数を自作する
すごい!なるほど!と感動した
わかる範囲で解読しつつ、自分の手に負えるように素朴なコードにした
結果的にほぼ別物のコードになった
やりたいこと
HTML要素を作る処理(createElement)とそれに色々データをくっつける処理(setAttribute、addEventListener、textContentほか)と要素を位置づける処理(append、prependほか)をひとつにまとめたい
子要素もまとめて書きたい
最終的にできる形
code:example.js
// 実行例
const div = createDOM('div', {
id: 'hoge',
className: 'test',
onclick: () => {
// クリック時イベント
},
css: {
color: 'red',
'font-size': '14px',
},
}, document.body, 'prepend')
editDOM(hoge, {
'$.foo': {
textContent: 'bar',
},
All$span: {
contenteditable: true,
onfocus: () => {
// フォーカス時の処理
},
},
})
↑は以下の処理と同じ
code:example2.js
const div = document.createElement('div');
document.body.prepend(div);
div.id = 'hoge';
div.className = 'test';
div.addEventListener('click', () => {
// クリック時イベント
})
div.style.color = 'red';
div.style.fontSize = '14px';
hoge.classList.add(...'fuga'); hoge.querySelector('.foo').textContent = 'bar';
hoge.querySelectorAll('span').forEach(elm => {
elm.setAttribute('contenteditable', true);
elm.addEventListener('focus', () => {
// フォーカス時の処理
})
})
関数を作る
code:js
// createElementを伴う処理
function createDOM(tagname, option = {}, target, position = 'append') {
const elm = document.createElement(tagname);
editDOM(elm, option, target, position); // createElement以外の処理は編集用関数を呼び出す
return elm; // 生成したHTML要素を返す
}
// 既に存在する要素を編集する処理
function editDOM(elm, option = {}, target, position = 'append') {
if (target) { // 要素の挿入先を指定している時
switch (position) {
case 'append': // 初期値はappend
target.append(elm);
break;
case 'prepend':
target.prepend(elm);
break;
case 'after':
target.after(elm);
break;
case 'before':
target.before(elm);
break;
default:
console.error('editDOM: position is invalid');
}
}
if (typeof option !== 'object') return;
for (const key in option) {
if (key.startsWith('on')) { // onで始まるイベントの処理
elm.addEventListener(key.slice(2), optionkey); continue;
} else if (key.startsWith('$')) { // 特定の子要素についてもまとめて書けるように
editDOM(elm.querySelector(key.replace('$', '')), optionkey) continue;
} else if (key.startsWith('All$')) { // queryに当てはまる全ての子要素について
elm.querySelectorAll(key.replace('All$', '')).forEach(element => {
editDOM(element, optionkey) })
continue;
}
switch (key) {
case '_addClass': // プロパティはArray
elm.classList.add(...optionkey); break;
case '_removeClass': // プロパティはArray
elm.classList.remove(...optionkey); break;
case 'css': // プロパティはObject
Object.entries(optionkey).forEach((key, value) => elm.style.setProperty(key, value)); break;
case 'id': // 以下プロパティはString
case 'className':
case 'value':
case 'innerText':
case 'innerHTML':
case 'textContent':
case 'checked':
break;
default:
elm.setAttribute(key, optionkey); // キーがいずれにも当てはまらなければ属性と解釈 }
}
}
※普段使っている処理のみを反映しているので他に必要が生じたらその都度書き足す