MTAppJSONTable
JSON を値に持つ textarea を表形式の入力 UI(テーブル)に変換する jQuery プラグイン。行・列の追加/削除・並べ替え・セル結合に対応し、保存時に内容を JSON へ書き戻す。値は HTML エスケープして表示。
JSON を値に持つ textarea を、表形式の入力 UI(テーブル)に変換する jQuery プラグインです。各行・各列をフォームのセルとして編集でき、保存時に内容を JSON へ書き戻します。行・列の追加、削除、ドラッグ並べ替え、セル結合などに対応します。
構文
$(selector).MTAppJSONTable(options);$.fn プラグイン(JSON を保持する textarea に対して呼び出します)です。
パラメータ(主要)
options {Object} — 以下のプロパティを持ちます(headerOrder は必須)。
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
headerOrder | Array | [] | 必須。列(プロパティ)の並び順(例 ['title', 'url']) |
header | Object | null | 列の表示名(例 { title: 'タイトル', url: 'URL' }) |
headerPosition | string | 'top' | ヘッダー位置。'top'(行方向に追加)/ 'left'(列方向に追加) |
caption | string | null | テーブルのキャプション |
footer | boolean | false | true でテーブルフッターを表示(headerPosition: 'top' 時) |
itemsRootKey | string | 'items' | JSON のルートキー({ "items": [...] }) |
items | Array | null | 初期データ(textarea が空のとき使う) |
inputType | string | Object | 'textarea' | セルの入力欄。'textarea' / 'input'、または列ごとに指定する Object(例 { title: 'input', body: 'textarea' }) |
edit | boolean | true | false で閲覧専用(入力欄ではなくテキスト表示) |
add | boolean | false | true で行/列の追加ボタンを表示 |
clear | boolean | true | 削除ボタンを表示(チェックした行/列を削除) |
sortable | boolean | false | true で行のドラッグ並べ替えを有効化(headerPosition: 'top' 時) |
cellMerge | boolean | false | true でセル結合(colspan / rowspan)を有効化 |
optionButtons | Array | null | 追加ボタン定義 [{ classname, text }] |
debug | boolean | false | true で元の textarea(生の JSON)も表示 |
リスティングモード・コールバック
選択 UI(チェックボックス/ラジオ)として使う listingCheckbox / listingCheckboxType / listingTargetKey / listingTargetEscape や、各操作のフック(cbAfterBuild, cbBeforeAdd, cbAfterAdd, cbBeforeClear, cbAfterSelectRow, cbAfterSelectColumn, cbBeforeSave, cbAfterSave など)も指定できます。
戻り値
{jQuery} — 対象要素(チェーン可能)。
保存される値
テーブルの編集内容を直列化した JSON 文字列が、元のフィールドへ保存されます。headerOrder で定義した各列をキーに持つオブジェクトの配列が、itemsRootKey(既定 items)配下に入ります(具体例は次の「使用例」を参照)。
使用例
// タイトルと URL の 2 列テーブル。行の追加・削除を許可
$('#customfield_links').MTAppJSONTable({
header: { title: 'タイトル', url: 'URL' },
headerOrder: ['title', 'url'],
add: true
});保存される JSON の例:
{ "items": [ { "title": "記事A", "url": "/a" }, { "title": "記事B", "url": "/b" } ] }user.js での記述例
user.js(「デザイン → user.js を編集」)に書く場合は、mtappVars.screen_id で画面を判定して呼び出します。
(function ($) {
if (typeof mtappVars !== 'object') return;
if (mtappVars.screen_id === 'edit-entry') {
$('#customfield_links').MTAppJSONTable({
header: { title: 'タイトル', url: 'URL' },
headerOrder: ['title', 'url'],
add: true
});
}
})(jQuery);応用: 特定の列のセルをリッチテキスト(TinyMCE)にする
inputType で textarea にした列のセルを、コールバックの中で MT.EditorManager(MTAppApplyTinyMCE と同じ仕組み)にかけると、セル単位のリッチテキストエディタにできます。テーブル内のセルに装飾やリンクを入れたいときに使えます。
// 「本文」列のセル(textarea)を TinyMCE 化する
let richSeq = 0;
const applyRichToBodyCells = ($container) => {
if (!(window.MT && MT.EditorManager)) {
return; // エディタ基盤が無ければ何もしない
}
$container.find('textarea.jsontable-input[data-name="body"]').each(function () {
if (this.id && tinymce.get(this.id)) {
return; // 適用済みはスキップ
}
if (!this.id) {
this.id = `jt-rich-body-${++richSeq}`; // EditorManager は id で要素を探すので id を付与
}
new MT.EditorManager(this.id, { format: 'richtext' });
});
};
$('#customfield_table').MTAppJSONTable({
header: { title: 'タイトル', body: '本文' },
headerOrder: ['title', 'body'],
inputType: { title: 'input', body: 'textarea' }, // 本文だけ textarea にする
add: true,
cellMerge: true,
// 初回描画時と行追加時に「本文」セルを TinyMCE 化する
cbAfterBuild: (e, $container) => applyRichToBodyCells($container),
cbAfterAdd: (e, $container) => applyRichToBodyCells($container),
// 保存の直前に TinyMCE の内容を textarea へ書き戻す(JSONTable はその後に直列化する)
cbBeforeSave: (e, $container) => {
$container.find('textarea.jsontable-input[data-name="body"]').each(function () {
const editor = tinymce.get(this.id);
if (editor) {
editor.save();
}
});
}
});ポイント:
cbAfterBuild/cbAfterAddで対象列のセル(textarea.jsontable-input[data-name="..."])に id を付け、new MT.EditorManager(id, { format: 'richtext' })でリッチ化します(行を追加したセルにも適用するため両方で呼びます)。cbBeforeSaveで、保存の直前に各エディタのsave()を呼んで内容をtextareaへ書き戻します。これをしないと TinyMCE で編集した内容がtextareaに反映されないまま直列化されます。- 保存される値はその列の HTML(例
<p>…</p>)になります。再描画時はencodeHTMLで安全にtextareaへ入り、上のコールバックで TinyMCE を再適用するとリッチ表示に戻ります。 cellMerge: trueと併用する場合、JSONTable はheaderOrderのキー補完を行わないため、初期データの各 item に全列のキー(この例ではtitleとbody)を必ず含めてください。列を増やした場合は、過去に保存済みのデータにも新しい列のキーが必要です(無いセルは描画されず表が崩れます)。- セル内の TinyMCE はそのままだと縦に大きくなります。
.mtapp-json-table .tox-tinymce { height: 230px; }のように高さを抑え、.mtapp-json-table td { vertical-align: top; }で上揃えにすると、隣の列の入力欄と並んで見やすくなります。
補足
headerOrderは必須です(指定が無いとアラートを出して中断します)。- 元の
textareaは隠され、直後にテーブルが挿入されます。フォーム送信時(またはMTAppJSONTableSaveイベント発火時)に、テーブルの入力内容を JSON へ直列化してtextareaに書き戻します。 - 値は HTML エスケープして表示します(各セルの文字列値に
encodeHTMLを適用してから描画するため、保存値に HTML が含まれていてもそのまま実行されません)。header/captionなどの設定値はそのまま使われます。 inputTypeを Object にすると列ごとにinput/textareaを使い分けられます。- テンプレート描画には Movable Type / PowerCMS の
Templateエンジンを使用します。
関連
MTAppApplyTinyMCE—textareaをリッチテキストエディタ(TinyMCE)化する。MTAppLineBreakField— 改行区切りのテキストを行ごとの入力欄にする。