リファレンス

目次

プラグイン API


管理画面のプラグインを登録する ACMS.plugins と、setup(ctx) で受け取る ctx のリファレンスです。

実験的機能

この API は、Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。引数や ctx の構成はマイナーバージョンアップで変更される可能性があります。管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。

このドキュメントに掲載している API を公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。PHP 側のフック処理・テンプレート挿入・アセット API は、この実験的機能の対象外です(従来どおりの仕様として提供しています)。

はじめてプラグインを書く場合は はじめてのプラグイン から読んでください。

ACMS.plugins

register(name, definition)

プラグインを登録します。

ACMS.adminReady(() => {
  ACMS.plugins.register('my-plugin', {
    version: '1.0.0',
    setup(ctx) {
      // ここでイベント購読・UI 差し込み・機能登録を行う
    },
  });
});
引数型説明
namestringプラグイン名。管理画面全体で一意にします。同じ名前で2回登録するとエラーになります。
definition.versionstring(省略可)プラグインのバージョン。ACMS.plugins.get() / getAll() の戻り値に入ります。
definition.setupfunction登録直後に呼ばれる関数。ctx を受け取ります。

register() は、ACMS.adminReady() の中で呼びます(登録するタイミング を参照)。

プラグイン名は、他のプラグインと衝突しないよう配布名やベンダー名を含めた形(acme-media-tools など)を推奨します。

unregister(name)

プラグインを登録解除します。setup(ctx) の中で行ったイベント購読・機能登録・UI 差し込みはすべて自動的に解除されます。個別に後片付けを書く必要はありません。

ACMS.plugins.unregister('my-plugin'); // 登録されていた場合 true を返す

get(name) / getAll()

登録済みのプラグインを取得します。デバッグ用です。

ACMS.plugins.getAll();
// [{ name: 'my-plugin', version: '1.0.0', registrations: [{ kind: 'event', key: 'media.upload.before' }, ...] }]

registrations には、そのプラグインが何を登録したかが登録順に入ります。イベント名や Slot 名の書き間違いを調べるときに使えます。

withFillProps(Component)

Slot が渡す値を React コンポーネントで受け取るためのラッパーです。使い方は UI の差し込み(Slot / Fill) を参照してください。

setup(ctx) で使える API

ctx は次のプロパティを持ちます。

プロパティ用途詳細
ctx.name自分のプラグイン名(読み取り専用)—
ctx.events.on(type, handler)イベントを購読するイベント
ctx.ui.fill(slotName, entry)UI を差し込むSlot / Fill
ctx.unitEditor.registerUnitDefinition(name, def)ユニットの種類を追加するオリジナルユニット
ctx.blockEditor.registerBlockDefinition(name, factory)ブロックの種類を追加するオリジナルブロック
ctx.blockEditor.registerExtension(name, factory)ブロックエディターに要素・機能を追加するオリジナルブロック
ctx.dataview.registerColumnType(name, type)一覧画面のカラム型を追加するレジストリ
ctx.dataview.registerAction(view, name, def)一覧画面の行アクションを追加する一覧画面のカスタマイズ
ctx.dataview.registerBulkAction(view, name, def)一覧画面の一括アクションを追加する同上
ctx.dataview.registerMenu(view, name, def)一覧画面のメニュー項目を追加する同上
ctx.keyboardShortcuts.registerCategory(id, category) / registerShortcut(id, shortcut)キーボードショートカット一覧にカテゴリーとショートカットを追加するこのページ下部
ctx.i18n.addResources(lng, resources)翻訳を追加するこのページ下部
ctx.configPHP から渡された設定値このページ下部

登録系のメソッドはすべて解除用の関数を返します。ふつうは使う必要はありません(unregister で一括解除されます)が、条件によって途中で外したい場合に使えます。

const off = ctx.events.on('media.upload.before', handler);
off(); // 購読を解除する

登録するタイミング

ACMS.plugins は、管理画面の JavaScript(admin.js)が実行されるまで存在しません。 admin.js は非同期で読み込まれるため、<script type="module"> のプラグインのほうが先に実行されることがあります。登録は ACMS.adminReady() の中で行ってください。admin.js の初期化が終わってから呼ばれ、すでに終わっていれば、すぐに呼ばれます。

// ○ 正しい
ACMS.adminReady(() => {
  ACMS.plugins.register('my-plugin', {
    setup(ctx) {
      ctx.events.on('media.upload.before', handler);
    },
  });
});

// × 動かないことがあります(ACMS.plugins が未定義のことがあります)
ACMS.plugins.register('my-plugin', {
  setup(ctx) {
    ctx.events.on('media.upload.before', handler);
  },
});

// × 動きません
document.addEventListener('DOMContentLoaded', () => {
  ACMS.adminReady(() => {
    ACMS.plugins.register('my-plugin', { setup(ctx) { /* ... */ } });
  });
});

DOMContentLoaded を待ったり、時間のかかる非同期処理のあとで登録したりすると、管理画面側がすでに処理を進めているため、購読が間に合わないことがあります。ACMS.adminReady() の呼び出し自体は、スクリプトが読み込まれた時点で同期的に行ってください。ACMS.adminReady() を使っても、初期化中にすでに発生したイベントは購読できません。

読み込みは <script type="module"> で行ってください(アセット API の attrs に ['type' => 'module'] を指定)。type="module" のスクリプトは、ページの解析が終わってから記述順に実行されます。

複数プラグインの実行順

同じイベントを複数のプラグインが購読した場合、登録した順に実行されます。type="module" のスクリプトは記述順に実行されるため、ふつうは JS ファイルが読み込まれた順になります。優先度の指定はありません。順序を制御したい場合は、アセット API を呼ぶ順番で調整してください。

setup が失敗したとき

setup(ctx) の中で例外が発生した場合、そのプラグインが途中まで行った登録はすべて取り消されます。半分だけ有効な状態にはなりません。

PHP から設定値を渡す(ctx.config)

PHP 側で jsModule() を使って渡した値を、ctx.config から読み取れます。

// PHP(プラグインの ServiceProvider::init() や Hook.php の afterBuild() など)
jsModule('myPlugin', [
    'apiEndpoint' => '/api/my-plugin/',
    'maxItems' => '20',
]);
// JavaScript
ACMS.plugins.register('my-plugin', {
  setup(ctx) {
    console.log(ctx.config.apiEndpoint); // '/api/my-plugin/'
  },
});

キーはプラグイン名をキャメルケースに変換したものを使います(my-plugin → myPlugin)。設定が渡されていない場合、ctx.config は空のオブジェクトになります。

値の受け渡しの制約

この値は URL のクエリ文字列として渡される仕組みのため、次の制約があります。

  • 数値・真偽値はすべて文字列になります。 PHP の 20(数値)は JavaScript では '20'(文字列)、true / false は '1' / '0' になります。数値として使う場合は Number() で変換してください。
  • null はキーごと消えます。 JavaScript 側でそのキー自体が存在しなくなります。
  • 入れ子は5段までです。 それより深い構造は正しく復元されません。深い設定を渡したい場合は、フラットなキーにするか、JSON 文字列を1つ渡して JavaScript 側で JSON.parse() してください。

API キーやトークンを ctx.config に渡さないでください

この値はブラウザの開発者ツールやアクセスログから閲覧できます。秘密にすべき情報を扱う連携は、PHP 側(フック処理や独自のエンドポイント)で行ってください。

翻訳を追加する(ctx.i18n)

ctx.i18n.addResources(lng, resources) で、プラグインの文言を追加できます。名前空間はプラグイン名に固定されるため、本体や他のプラグインとキーが衝突しません。同じ言語へ何度でも追加でき、既存の内容とマージされます。

ACMS.adminReady(() => {
  ACMS.plugins.register('my-plugin', {
    setup(ctx) {
      ctx.i18n.addResources('ja', { greeting: 'こんにちは' });
      ctx.i18n.addResources('en', { greeting: 'Hello' });
    },
  });
});

参照するときは 名前空間:キー の形で書きます。上の例なら、ACMS.i18n('my-plugin:greeting') が現在の言語の文言を返します。setup(ctx) の実行中は翻訳の準備が終わっていないことがあるため、文言の参照は画面を操作したときの処理(イベントのハンドラなど)の中で行ってください。unregister すると、そのプラグインの翻訳も破棄されます。

キーボードショートカット一覧への追加(ctx.keyboardShortcuts)

registerCategory(id, category) と registerShortcut(id, shortcut) で、キーボードショートカット一覧のモーダルに項目を追加できます。shortcut.categoryId には、同じプラグインで登録したカテゴリーの id を指定します。

引数内容
category.headingカテゴリーの見出し
category.order表示順(小さい値が先。省略可)
shortcut.labelショートカットの説明
shortcut.commandsコマンド ID の配列
shortcut.categoryId所属するカテゴリーの id
shortcut.order表示順(小さい値が先。省略可)

デバッグ

  • ACMS.plugins.getAll() — 登録内容を確認する。
  • 開発中はコンソールの警告を確認してください。 すでに発生済みのイベントを後から購読した場合など、動かない原因になる状況で警告が出ます(本番ビルドでは出ません)。

変更履歴

バージョン変更内容
Ver. 3.2新規追加(実験的機能)

イベント(ACMS.events)


管理画面の操作に処理を割り込ませる仕組みです。購読できるイベントの一覧は イベント一覧 にあります。

実験的機能

この機能は Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。

  • 変わりうる範囲: イベント名と、イベントが受け取る値の構造は、マイナーバージョンアップで変更される可能性があります。
  • 変わらない範囲: 従来の DOM イベント(acms.media-updated など)と ACMS.addListener は今後も動作します。既存のコードを書き換える必要はありません。
  • 公開 API の線引き: イベント一覧 に掲載しているイベント名を公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。
  • サポート対象外: 管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。

基本の使い方

ACMS.plugins.register('my-plugin', {
  setup(ctx) {
    ctx.events.on('media.upload.success', (event) => {
      console.log(`${event.items.length} 件アップロードされました`);
    });
  },
});

プラグインを作らずに購読することもできます。

ACMS.events.on('media.upload.success', (event) => { /* ... */ });

ただし ctx.events.on() を使うと、プラグインの登録解除時に自動で購読も解除されるため、通常はプラグインの中で書くことを推奨します。

API説明
ACMS.events.on(type, handler)購読する。type は配列で複数指定できます。戻り値は購読解除用の関数。
ACMS.events.off(type, handler)購読を解除する。
ACMS.events.notify(type, payload)通知イベントを発火する(Promise を返します)。
ACMS.events.gate(type, payload)中止・書き換えができるイベントを発火する(Promise を返します)。

イベント名の読み方

{機能}.{操作}.{タイミング}     例: media.upload.before

タイミングは6種類あります。

タイミング意味処理を止められるか
.before操作の直前多くは止められる(中止・値の書き換え・非同期の待機)。一部は通知のみ(下記)
.success失敗しうる処理(保存・通信など)が成功した後通知のみ
.failure処理が失敗した後通知のみ
.change値や選択状態が変わった後通知のみ
.after操作が完了した直後(成功・失敗の区別がない操作)通知のみ
.ready初期化が一度だけ完了したとき通知のみ(後述の注意あり)

イベントには、処理を止められるゲートと、知らせるだけの通知の2種類があります。どちらかは名前では決まらず、イベント一覧 の「種別」列(中止可 / 通知)で確認してください。たとえば unit-editor.command.before は名前が .before で終わりますが、通知のみのイベントです。

処理を止めたり値を書き換えたりできるのは、種別が「中止可」のイベントだけです。 通知イベントのハンドラには中止のための引数が渡されず、戻り値も無視されます。

ゲートでできること

種別が「中止可」のイベントのハンドラは、第2引数に中止用のオブジェクト(以降 gateCtx)を受け取ります。できることは4つです。

やりたいこと書き方
何もしない(見るだけ)何もしない
値を書き換える受け取った event のプロパティを直接書き換える
操作を中止するgateCtx.cancel() または gateCtx.cancel('理由') を呼ぶ
非同期の処理を待たせるasync 関数にする(Promise を返すと a-blog cms が待ちます)
ctx.events.on('media.upload.before', async (event, gateCtx) => {
  // 非同期のチェック
  if (!(await isAllowed(event.files))) {
    gateCtx.cancel('この操作は許可されていません');
    return;
  }

  // 中止(理由なし)
  if (event.files.length === 0) {
    gateCtx.cancel();
    return;
  }

  // 値の書き換え(大きすぎるファイルを除く)
  event.files = event.files.filter((file) => file.size < 5_000_000);
});

中止のしかた

  • gateCtx.cancel() — 理由を表示せずに中止します。
  • gateCtx.cancel('理由') — 理由を添えて中止します。この文字列はそのまま利用者に表示されます(画面によってはダイアログや通知として表示されます)。ユーザーの操作を止める場合は、理由を添える方を推奨します。

cancel() は呼んだ時点で中止が確定します。return false や { cancel: true } のような戻り値では中止できません(jQuery の return false など、別の目的で書いた戻り値で意図せず中止されるのを避けるためです)。

値の書き換えについて

書き換えられる範囲はイベントごとに違います(イベント一覧 の「変更できるもの」列を参照)。たとえば、

  • media.update.before — 送信内容(formData)を書き換えられます。
  • media.upload.before — すでにあるファイルを除外することはできますが、新しいファイルに差し替えることはできません。
  • media.delete.before — 対象の絞り込みはできません。除外したい場合は全体を中止してください。

実行順とルール

  • ハンドラは登録順に1つずつ実行されます。並列実行はされません。
  • ゲートのイベントでは、前のハンドラが書き換えた値が次のハンドラに渡ります。
  • どれか1つのハンドラが gateCtx.cancel() を呼んだ場合、そのハンドラの処理が終わった後、残りのハンドラは実行されません。
  • ハンドラの中で例外が発生した場合も中止として扱われ、コンソールにエラーが記録されます。
  • 通知イベントでは、あるハンドラが例外を投げても他のハンドラと管理画面の動作は継続します。
  • 優先度の指定はありません。 実行順は登録順(=JS の読み込み順)だけで決まります。

過去のイベントは届きません

ACMS.events は、購読した時点より後に発生したイベントにだけ反応します。すでに発生済みのイベントは再生されません。

そのため、購読はスクリプトの読み込み時にトップレベルで行ってください(プラグイン API の「登録するタイミング」参照)。

起動時の処理を書く

「管理画面の準備ができたら実行したい」処理は、購読より先にすでに完了しているかどうかを確認してください。準備完了は一度しか発生しないため、購読が間に合わないことがあります。

function onAdminReady() {
  // 実行したい処理
}

if (ACMS.readyStates.adminReady === 'complete') {
  onAdminReady();
} else {
  ACMS.events.on('acms.state.admin-ready', onAdminReady);
}
イベント確認するプロパティ意味
acms.state.readyACMS.readyStates.readya-blog cms の JavaScript の初期化が完了した(サイト表示側・管理画面の両方)
acms.state.admin-readyACMS.readyStates.adminReady管理画面の初期化が完了した
acms.pending.readyACMS.pendingReadyState読み込み中表示の準備が完了した

ACMS.Ready() は従来どおり使えます(内部でこの仕組みを使っています)。

従来のイベントとの関係

a-blog cms はこれまで、DOM の CustomEvent(acms.media-updated など)と ACMS.dispatchEvent / ACMS.addListener でイベントを提供してきました。

  • 従来のイベントは今後も発火します。 既存のテーマ・プラグインの購読を書き換える必要はありません。
  • 新しく書く場合は ACMS.events を使ってください。中止・値の書き換え・非同期の待機は ACMS.events のゲートにしかありません。
  • 対応表は イベント一覧 の「従来のイベントとの対応」にあります。

独自のイベントを発火する

ACMS.events.gate() と ACMS.events.notify() は主に a-blog cms 本体が使う API ですが、プラグインが自分のイベントを発火することもできます。一覧に載っていない名前も使えます。

// 発火する側(中止できるイベント)
const result = await ACMS.events.gate('my-plugin.sync.before', { items });
if (result.canceled) {
  if (result.reason) {
    ACMS.Library.dialog.alert(result.reason);
  }
  return;
}

// 発火する側(知らせるだけのイベント)
await ACMS.events.notify('my-plugin.sync.success', { items: result.payload.items });

// 購読する側
ctx.events.on('my-plugin.sync.before', (event, gateCtx) => { /* ... */ });

gate() の戻り値は次の形です。

プロパティ説明
canceled中止されたかどうか
reasoncancel('理由') で中止された場合の理由
errorハンドラが例外を投げた場合の例外(この場合も canceled は true)
payload最終的な(書き換え後の)値

notify() は戻り値を返しません。

イベント名は {機能}.{操作}.{タイミング} の規約に合わせ、機能名にはプラグイン名を使うと衝突を避けられます。中止できるようにしたい場合は gate() で発火し、名前を .before で終わらせてください。

変更履歴

バージョン変更内容
Ver. 3.2.29新規追加(実験的機能)
Ver. 3.2.33発火とキャンセルの API を変更。ACMS.events.emit() と ACMS.events.cancel() を廃止し、gate() / notify() と gateCtx.cancel() に変更

イベント一覧


ACMS.events で購読できるイベントの一覧です。使い方は イベント(ACMS.events) を参照してください。

実験的機能

この機能は Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。

  • 変わりうる範囲: イベント名と受け取る値の構造は、マイナーバージョンアップで変更される可能性があります。
  • 変わらない範囲: 従来の DOM イベントと ACMS.dispatchEvent 経由のイベントは、今後も発火します(末尾の「従来のイベントとの対応」参照)。
  • 公開 API の線引き: このページに掲載しているイベントを公開 API として扱います。 掲載外のものも利用できますが、告知なく変更されることがあります。
  • サポート対象外: 管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。
  • 「種別」が 中止可 のイベントは、ハンドラの第2引数 gateCtx の cancel() で操作を中止できます。値の書き換えは、受け取った値のプロパティを直接書き換えて行います(イベント の「ゲートでできること」参照)。
  • 「通知」のイベントは、戻り値を返しても無視され、中止もできません。

メディア

イベント名種別発生タイミング受け取れる値変更できるもの効く画面
media.upload.before中止可ファイルを選択し、アップロードを開始する直前files(File の配列)files の除外のみ(新しい File への差し替えは反映されません)メディア管理・カスタムフィールド・ブロックエディターの画像/ファイル・リッチエディター・バナー・ナビゲーション・ユニットなど、メディア選択を使うすべての画面
media.upload.success通知アップロードが完了した後items(登録されたメディア)—同上
media.update.before中止可メディア詳細の「保存」直前item, formDataformData の書き換えメディア詳細モーダル(上記すべての画面から開けます)
media.update.success通知保存が成功した後item—同上
media.update-as-new.before中止可「別名で保存」の直前item, formDataformData の書き換え同上
media.update-as-new.success通知別名保存が成功した後item—同上
media.delete.before中止可メディア一覧の一括削除の直前(確認ダイアログの後)mediaIds絞り込みは不可(中止のみ)メディア管理の一覧
media.delete.success通知一括削除が成功した後mediaIds—同上

エントリー

イベント名種別発生タイミング受け取れる値変更できるもの効く画面
entry.trash.before中止可エントリーをゴミ箱へ移す直前(確認の後)entryentry の書き換え(書き換えた内容が実際の対象になります)エントリー一覧
entry.trash.success通知ゴミ箱へ移した後entry—同上
entry.duplicate.success通知エントリーを複製した後entry—同上
entry.bulk-status.before中止可複数選択して公開状態を変更する直前formDataformData の書き換えエントリー一覧(一括操作)
entry.bulk-status.success通知一括変更が成功した後formData—同上
entry.bulk-trash.success通知一括でゴミ箱へ移した後formData—同上
entry.bulk-duplicate.success通知一括で複製した後formData—同上

モジュール

イベント名種別発生タイミング受け取れる値変更できるもの効く画面
module.bulk-status.before中止可複数選択して公開状態を変更する直前formDataformData の書き換えモジュール一覧(一括操作)
module.bulk-status.success通知一括変更が成功した後formData—同上

プレビュー・タイムマシン

イベント名種別発生タイミング受け取れる値変更できるもの効く画面
preview.share.before中止可共有用プレビュー URL を発行する直前formDataformData の書き換えプレビュー画面
preview.share.success通知共有 URL の発行が成功した後shareUrl—同上
preview.mode.change通知プレビューモードのオン/オフが切り替わった後enabled—エントリー編集・プレビュー
timemachine.mode.change通知タイムマシンモードのオン/オフが切り替わった後enabled—エントリー編集

入力フィールド

イベント名種別発生タイミング受け取れる値効く画面
category.select.change通知カテゴリーの選択が変わった後target(対象の要素)エントリー編集・カスタムフィールド
sub-category.select.change通知サブカテゴリーの選択が変わった後target同上
tag.select.change通知タグの選択が変わった後target同上
related-entry.select.change通知関連エントリーが変わった後target, entries, type, title, moduleId, ctx, maxItemエントリー編集
entry.main-image.change通知メイン画像が設定された後target, mediaId, thumbnailブロックエディターの画像ブロック
media-field.change通知メディアフィールドの値が変わった後targetカスタムフィールド
media-unit.change通知メディアユニットの値が変わった後target, mediaItemsエントリー編集(ユニット)
field-group.add.after通知カスタムフィールドグループの行が追加された後element(追加された要素)カスタムフィールドを使う画面全般

同じ種類のフィールドが複数ある画面では、すべてのフィールドの変更が同じイベントで届きます。 どのフィールドかを判定するには target を確認してください。

画面共通の UI

イベント名種別発生タイミング受け取れる値効く画面
dialog.open.after通知ダイアログ・モーダル・ドロワーが開いた後element管理画面全般
tab.select.change通知タブが選択された後tab管理画面全般
tab.show.after通知タブのパネルが表示された後tab, panel(パネルがない場合は null)同上
tab.hide.after通知タブのパネルが非表示になった後tab, panel(パネルがない場合は null)同上
admin.delayed-contents.change通知非同期に読み込まれたコンテンツが差し込まれた後target, detail管理画面全般
custom-field-maker.preview.after通知カスタムフィールドメーカーのプレビューが再描画された後elementカスタムフィールドメーカー
geo.info-add.after通知地図に位置情報が追加された後element地図フィールド
lazy-load.load.after通知遅延読み込みの要素が読み込まれた後element管理画面・サイト表示側

フォームの検証

イベント名種別発生タイミング受け取れる値
validator.invalid.after通知検証に失敗した後results, element
validator.valid.after通知検証に成功した後results, element
validator.validated.after通知検証が完了した後(成功・失敗を問わず)results, element
validator.submit-fail.after通知検証エラーで送信が中止された後results, form

ユニットエディター

イベント名種別発生タイミング受け取れる値備考
unit-editor.create.after通知ユニットエディターが生成された後editor, settings従来の acmsUnitEditorCreate と同じタイミングで発火します
unit-editor.command.before通知(中止できません)ユニットの追加・削除・移動・複製・更新などの操作の直前commands, editor名前は .before ですが、観測専用です。値の書き換え・中止・非同期の待機はできません
unit-editor.command.success通知同じ操作が完了した後commands, editor—
unit-editor.inplace-dialog-open.after通知インライン編集のダイアログが開いた後element—

起動

購読より先に完了しているかどうかを確認してください(イベント の「起動時の処理を書く」参照)。

イベント名確認するプロパティ意味
acms.state.readyACMS.readyStates.readyJavaScript の初期化が完了した
acms.state.admin-readyACMS.readyStates.adminReady管理画面の初期化が完了した
acms.pending.readyACMS.pendingReadyState読み込み中表示の準備が完了した

従来のイベントとの対応

以下の DOM イベント(document.addEventListener で購読するもの)と ACMS.dispatchEvent 経由のイベントは、今後も発火します。既存の購読はそのままで動作します。新しく書く場合は右列のイベントを使ってください。

従来のイベント新しいイベント内容
acms.media-updatedmedia.update.successメディアの更新
acms.set-main-imageentry.main-image.changeメイン画像の設定
acms.category.changecategory.select.changeカテゴリー選択の変更
acms.sub-category.changesub-category.select.changeサブカテゴリー選択の変更
acms.tag.changetag.select.changeタグ選択の変更
acms.related-entry.changerelated-entry.select.change関連エントリーの変更
acms.media-field.changemedia-field.changeメディアフィールドの変更
acms.media-unit.changemedia-unit.changeメディアユニットの変更
acmsUnitEditorCreateunit-editor.create.afterユニットエディターの生成
acmsAddUnit(対応なし)サーバー側で描画されたユニットの追加
acmsCustomFieldMakerPreviewcustom-field-maker.preview.afterプレビューの再描画
acmsAdminDelayedContentsadmin.delayed-contents.change非同期コンテンツの差し込み
acmsDialogOpeneddialog.open.afterダイアログの表示
acmsAdminSelectTabtab.select.changeタブの選択
acmsAdminShowTabPaneltab.show.afterタブパネルの表示
acmsAdminHideTabPaneltab.hide.afterタブパネルの非表示
acmsAddCustomFieldGroupfield-group.add.afterフィールドグループの追加
acmsInplaceDialogOpenunit-editor.inplace-dialog-open.afterインライン編集ダイアログの表示
onGeoInfoAddedgeo.info-add.after位置情報の追加
acmsLazyLoadedlazy-load.load.after遅延読み込みの完了
acmsFormInvalidvalidator.invalid.after検証の失敗
acmsFormValidvalidator.valid.after検証の成功
acmsFormValidatedvalidator.validated.after検証の完了
acmsValidateFailedvalidator.submit-fail.after検証エラーによる送信中止
acmsReadyacms.state.ready初期化の完了
acmsAdminReadyacms.state.admin-ready管理画面の初期化完了

変更履歴

バージョン変更内容
Ver. 3.2.29新規追加(実験的機能)
Ver. 3.2.33media.* などの「中止可」イベントの中止方法を gateCtx.cancel() に変更

UI の差し込み(Slot / Fill)


管理画面のあらかじめ決められた位置に、独自のボタンやパネルを追加できます。

実験的機能

この機能は Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。

  • 変わりうる範囲: 差し込み位置の名前(Slot 名)と、そこで受け取れる値は、マイナーバージョンアップで変更される可能性があります。
  • 変わらない範囲: PHP 側のフック処理・テンプレート挿入・アセット API は、この実験的機能の対象外です。従来どおりの仕様として提供しています。
  • 公開 API の線引き: このページの一覧に掲載している Slot 名を公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。
  • サポート対象外: 管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。

差し込み位置(Slot)とは

管理画面の特定の場所に用意された、名前付きの差し込み口です。追加のみができます。 既存のボタンを消したり、置き換えたりはできません。

差し込みは ctx.ui.fill(差し込み位置の名前, 内容) で行います。

DOM で差し込む

React を使わない場合はこちらです。渡された要素に自由に DOM を追加できます。

ACMS.plugins.register('my-plugin', {
  setup(ctx) {
    ctx.ui.fill('media.edit-modal.footer', (el) => {
      const button = document.createElement('button');
      button.type = 'button';
      button.className = 'acms-admin-btn';
      button.textContent = '外部システムに送信';
      button.addEventListener('click', () => sendToExternal());
      el.append(button);

      // 画面が閉じられたときに呼ばれる(省略可)
      return () => button.remove();
    });
  },
});
  • 引数 el は、差し込み位置に用意された空の要素です。
  • この要素の中身は管理画面側から書き換えられません。 自分で追加した DOM がいつのまにか消えることはありません。
  • 戻り値の関数は、その画面が閉じられたときに呼ばれます。イベントリスナーの解除などに使ってください。

差し込み位置が渡す値(下の一覧の「受け取れる値」)を DOM 版で使うことはできません。値が必要な場合は次の React 版を使ってください。

React で差し込む

管理画面と同じ React を使えます。値を受け取らない場合は、引数のないコンポーネントをそのまま渡します。

ACMS.plugins.register('my-plugin', {
  setup(ctx) {
    ctx.ui.fill('preview.actions', function MyButton() {
      return ACMS.Library.React.createElement('button', { type: 'button', className: 'acms-admin-btn' }, '送信');
    });
  },
});

差し込み位置の値を受け取る

編集中のメディアやエディターの情報を受け取りたい場合は、ACMS.plugins.withFillProps() でラップします。

ACMS.plugins.register('my-plugin', {
  setup(ctx) {
    const { withFillProps } = ACMS.plugins;

    ctx.ui.fill(
      'media.edit-modal.field.alt',
      withFillProps(({ item, previewSrc, setAlt }) =>
        ACMS.Library.React.createElement(
          'button',
          {
            type: 'button',
            className: 'acms-admin-btn',
            onClick: async () => {
              const alt = await generateAlt(previewSrc);
              setAlt(alt);
            },
          },
          'alt を自動入力'
        )
      )
    );
  },
});

withFillProps を忘れると値が渡りません

値を受け取るコンポーネントをそのまま渡すと、DOM 版の書き方(要素を受け取る関数)と区別できないため、正しく動きません。値を受け取る場合は必ず withFillProps() でラップしてください。

JSX で書きたい場合は 開発環境と型定義 を参照してください。

差し込み位置の一覧

差し込み位置場所受け取れる値効く画面
unit-editor.unit-toolbarユニット共通のツールバー(各ユニットの操作ボタンが並ぶ場所)editor, unitエントリー編集・インライン編集・編集設定のユニット編集
unit-editor.topユニットエディターの上部(本文編集領域の直前)editor同上
unit-editor.bottomユニットエディターの下部(本文編集領域の直後)editor同上
block-editor.menusブロックエディターのメニュー群の直後editor, appendToブロックエディターを使うすべての画面
block-editor.block-menuブロックのツールバー(ブロックを選択したときに表示されるツールバー)の共通区画の直後。ブロックの種類を問わず表示editor, variantブロックエディターを使うすべての画面
block-editor.block-menu.textツールバーのテキスト系ブロック(段落・見出し・引用など)の区画の末尾editor, variant(常に 'text')同上
block-editor.block-menu.imageツールバーの画像ブロックの区画の末尾editor, variant(常に 'image')同上
block-editor.block-menu.fileツールバーのファイルブロックの区画の末尾editor, variant(常に 'file')同上
block-editor.block-menu.linkButtonツールバーのリンクボタンブロックの区画の末尾editor, variant(常に 'linkButton')同上
block-editor.block-menu.tableツールバーのテーブル(セル選択時)の区画の末尾editor, variant(常に 'table')同上
media.edit-modal.field.altメディア詳細の alt 入力欄の直後item, previewSrc, getAlt(), setAlt(値)メディア詳細モーダル(メディア管理・カスタムフィールド・ブロックエディター・リッチエディター・ユニットなどから開く画面すべて)
media.edit-modal.fieldsメディア詳細の編集タブ、項目テーブルの直後item同上
media.edit-modal.footerメディア詳細の保存ボタンの直後item, getFormData()同上
media.list.bulk-actionsメディア一覧の一括操作エリアselectedItems(選択中のメディア)メディア管理の一覧
preview.actionsプレビューの操作ボタン群の直後なしプレビューモーダル・インラインプレビュー

補足:

  • media.edit-modal.field.alt は、管理画面の設定で alt 入力欄を非表示にしている場合、この差し込み位置も一緒に非表示になります。
  • setAlt(値) を使うと、入力欄の表示・内部の値・高さの自動調整がまとめて更新されます。getAlt() は現在の値を返します。
  • getFormData() は、その時点で保存されようとしている内容を FormData として返します。
  • preview.actions は、プレビューのキャプチャまたは共有が有効なときだけ表示されます。

同じ位置に複数のプラグインが差し込んだとき

JS が読み込まれた順に並びます。 優先度の指定はありません。順序を制御したい場合は、アセット API の登録順で調整してください。

差し込む UI の見た目を合わせる

管理画面と同じ見た目にするには、管理画面の CSS クラスをそのまま使えます。

button.className = 'acms-admin-btn acms-admin-btn-primary';

変更履歴

バージョン変更内容
Ver. 3.2.29新規追加(実験的機能)

機能の登録(レジストリ)


「選べるものを増やす」拡張です。ユニットの種類、ブロックの種類、一覧画面のアクションやカラムの型などを追加できます。

実験的機能

この機能は Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。

  • 変わりうる範囲: 登録 API の名前と引数は、マイナーバージョンアップで変更される可能性があります。
  • 変わらない範囲: 従来の ACMS.Config.entryAdminConfig / moduleAdminConfig による一覧のカスタマイズは、今後も動作します。
  • 公開 API の線引き: このページの表に掲載している登録 API を公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。
  • サポート対象外: 管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。

イベントとの使い分け

やりたいこと使う仕組み
既存の操作の前後に処理を挟む・中止するイベント
画面の決まった位置に UI を足すSlot / Fill
選べる種類そのものを増やすレジストリ(このページ)

登録できるもの

すべて setup(ctx) の中で呼びます。

API増えるもの反映される画面
ctx.unitEditor.registerUnitDefinition(name, def)ユニットの種類エントリー編集・インライン編集・編集設定
ctx.blockEditor.registerBlockDefinition(name, factory)ブロックの種類ブロックエディター
ctx.blockEditor.registerExtension(name, factory)ブロックエディターの要素・機能ブロックエディター
ctx.dataview.registerColumnType(name, type)一覧画面のカラムの型エントリー一覧・モジュール一覧
ctx.dataview.registerAction(view, name, def)一覧画面の行アクション同上
ctx.dataview.registerBulkAction(view, name, def)一覧画面の一括アクション同上
ctx.dataview.registerMenu(view, name, def)一覧画面のメニュー項目同上
ctx.keyboardShortcuts.registerCategory(id, category) / registerShortcut(id, shortcut)キーボードショートカット一覧のカテゴリーと項目キーボードショートカットの一覧モーダル
ctx.i18n.addResources(lng, resources)翻訳リソース(プラグイン名の名前空間に追加されます)ACMS.i18n('プラグイン名:キー') で参照

ユニットとブロックの追加手順は、専用のガイドを参照してください。

名前の付け方

同じ名前で2回登録するとエラーになります。 他のプラグインと衝突しないよう、プラグイン名を接頭辞にした名前を付けてください。

ctx.dataview.registerAction('entry', 'acme-tools/export', {
  id: 'acme-tools/export',
  label: 'エクスポート',
  onAction: (entry) => {
    window.location.href = `/api/acme-tools/export/?eid=${entry.id}`;
  },
});

一覧画面の登録(registerAction / registerBulkAction / registerMenu)は、第1引数の view ごとに名前が独立しています。'entry' と 'module' で同じ名前を使っても衝突しません。

標準の機能との関係

登録するもの標準の定義と同じ名前を使った場合
ユニットの種類上書きされます(プラグイン側が優先)
ブロックの種類上書きされます(プラグイン側が優先)
一覧画面のカラム型上書きされます(プラグイン側が優先)
一覧画面のアクション・一括アクション・メニュー上書きされません。標準のものの後ろに追加されます

標準の機能を上書きすると、そのブログ全体に影響します。意図しない場所に影響しないよう、独自の名前を使うことを推奨します。

登録内容を確認する

ACMS.plugins.getAll();
// registrations に、そのプラグインが登録した内容が一覧で入っています

従来の方法との併用

エントリー一覧・モジュール一覧のカスタマイズには、従来から ACMS.Config.entryAdminConfig / moduleAdminConfig の getActions / getBulkActions / getMenus を使う方法があります。

  • 従来の方法も今後も動作します。 既存のコードを書き換える必要はありません。
  • レジストリで登録した内容は、標準の定義の後ろに追加された状態で従来の関数にも渡ります。そのため両方を併用できます。
  • 新しく書く場合はレジストリを推奨します。プラグインの登録解除時に自動で外れるためです。

一覧のカラムの並び替えや削除(getColumns)と表示値の加工(getValues)には、現時点でレジストリの代替がありません。従来の方法を使ってください。

変更履歴

バージョン変更内容
Ver. 3.2.29新規追加(実験的機能)