Markdownでドロップダウンメニュー付きテーブルを作成するWebツールを作った話
はじめに
なんとなく、Markdownドキュメントでドロップダウンメニュー付きのテーブルを作成したいと思ったので、READMEや技術文書で、インタラクティブな要素を含むテーブルを表示できるMarkdown用HTML生成ツールを作った。
※GithubやQiita、zenn等ではドロップダウンメニューは表示されない仕様らしい
この記事では、そんな課題を解決するためのWebツール「Markdown Dropdown Generator」について解説する。
以下がMarkdownに貼り付けたHTMLコードのTable
ツールの概要
Markdown Dropdown Generatorは、以下の特徴を持つWebツール:
主な機能
- 行数・列数を自由に設定可能なテーブル生成
- 各セルにドロップダウンメニューを配置
- 行ヘッダー、列ヘッダー名の設定
- 選択状態を保持したHTMLコードの生成
- ブラウザだけで動作するため、インストール不要
- 直感的なUIで簡単にテーブルを作成可能
- リアルタイムプレビューで確認しながら表生成が編集可能
- 各列のドロップダウン選択肢を列ごとに設定可能
- 行ヘッダー列ヘッダーの有無を切り替え可能
技術的なポイント(ここから先は開発者向けの説明)
1. シンプルな実装
このツールは、純粋なHTML、CSS、JavaScriptのみで実装している。
- 依存関係がなく、ブラウザだけで動作
- コードの理解と保守が容易
2. モジュール分割による保守性
機能ごとにJavaScriptファイルを分割した。
- コードの見通しが良くなる
- 機能の追加や修正が容易
- バグの特定と修正が簡単
3. 実装の工夫
シンプルながらも実用的な機能を実現するため、以下の工夫を施した。
- セルの選択状態管理
let cellSelections = {
[cellId]: selectedValue
};
- セルの選択状態をオブジェクトで管理することで、複雑なデータ構造より簡潔に実装でき、状態の保存と復元をする。
- セルIDをキーとして使用することで、配列よりも高速にセルの状態にアクセスでき、テーブル再生成時も選択状態を保持できる。
- ヘッダー設定の動的更新
// チェックボックスの状態に応じて設定UIの表示/非表示を制御
const showColumnHeaders = document.getElementById('show-column-headers').checked;
const showRowHeaders = document.getElementById('show-row-headers').checked;
const headerSettings = document.getElementById('header-settings');
if (!showColumnHeaders && !showRowHeaders) {
headerSettings.style.display = 'none';
return;
}
- 直接
style.display
プロパティを操作することで、CSSクラスの切り替えよりもコードがシンプルになり、即時に反映できます。設定変更の頻度が低いため、この方法が最適だと思われる。
// 既存の設定値を保持しながら、新しい設定を生成
const headerValue = document.getElementById(`header_col_${i}`) ?
document.getElementById(`header_col_${i}`).value :
`列${i+1}`;
const optionsValue = document.getElementById(`options_col_${i}`) ?
document.getElementById(`options_col_${i}`).value :
'A,B,C';
- テーブル再生成時に、ユーザーが入力した設定値を維持するため、既存の入力フィールドの値をチェックしてから新しい設定を生成する。この条件分岐を使用することで、値が存在する場合はその値を使用し、存在しない場合はデフォルト値を使用するという実装にした。
// 入力フィールドのIDを動的に生成し、一意性を確保
columnHeadersHTML += `
<div style="margin-bottom: 10px;">
<div>列${i+1}:
<input type="text" id="header_col_${i}" value="${headerValue}" style="width: 150px;">
<input type="text" id="options_col_${i}" value="${optionsValue}" style="width: 250px;" placeholder="プルダウンの選択肢(カンマ区切り)">
</div>
</div>`;
- 入力フィールドにインデックスを含む一意のIDを付与することで、列数が変更されても既存の列の設定が保持される。これにより、テーブル構造を変更してもユーザーの入力データが失われない。
- イベント伝播の制御
// ドロップダウンの変更イベントをリスニング
document.querySelector('.dropdown-table').addEventListener('change', function(e) {
if (e.target.tagName === 'SELECT') {
// セル選択状態の保存
const cellId = e.target.id;
cellSelections[cellId] = e.target.value;
// コード生成の更新
updateDropdownHTML();
}
});
- イベント委譲パターンを使用することで、多数のドロップダウン要素に個別にイベントリスナーを設定する必要がなくなり、テーブルのサイズが大きくなっても、メモリ使用量などパフォーマンスが低下しないよう最適化されるはず。
- テーブル生成の効率化
// テーブル生成の最適化
function generateTable() {
const rows = parseInt(document.getElementById('row-count').value);
const cols = parseInt(document.getElementById('col-count').value);
// DOMの操作回数を最小限に抑える
let tableHTML = '<table class="dropdown-table">';
// 一度にまとめてHTMLを生成
for (let i = 0; i < rows; i++) {
tableHTML += '<tr>';
for (let j = 0; j < cols; j++) {
// セルの生成
}
tableHTML += '</tr>';
}
tableHTML += '</table>';
// DOMの更新は1回だけ
document.getElementById('table-container').innerHTML = tableHTML;
}
- 複数回のDOM操作を避け、一度にHTMLを生成してからDOMに追加することで、ページのレンダリングパフォーマンスが向上すると思われる。
- 特に行数や列数が多い場合に効果的な最適化手法と思われる。
まとめ
Markdown Dropdown Generatorは、シンプルな実装ながらも実用的な機能を提供するWebツールを作成した。ユーザーの視点に立った使いやすさと技術的なシンプルさを両立させた。