MTAppjQuery で Movable Type 8 の記事編集画面に表示するフィールドを選択されたカテゴリごとに切り替えたい

MTAppjQuery で Movable Type 8 の記事編集画面に表示するフィールドを選択されたカテゴリごとに切り替える方法をご紹介します。

この記事は弊社 bit part 合同会社が提供している Movable Type プラグイン「MTAppjQuery」の利用を前提としております。MTAppjQuery って何?という方は弊社の「MTAppjQuery」の製品ページをご覧ください。

MTAppjQuery で Movable Type 8 の記事編集画面に表示するフィールドを選択されたカテゴリごとに切り替える方法をご紹介します。

仕様

以下の表のように、各フィールドについて、特定のカテゴリが選択されたり選択が解除されたりしたときに、フィールドを表示したり非表示にしたりするようにします。

言い換えると、「◯」となっているフィールドは常に表示で、それ以外のフィールドは「表示するカテゴリ」の列で指定したカテゴリが選択されているときだけ表示されるようになります。

フィールド名 ベースネーム 表示するカテゴリ
タイトル title
本文 text 当社限定物件
概要 excerpt
担当者名 staff_name 当社限定物件
郵便番号 post_code 公開物件
都道府県 prefecture 公開物件
市区町村 city 公開物件
番地等 street 公開物件
最寄駅 stations

キャプチャで見ると下図のようになります。

新規作成時

Clean Shot 2024 04 05 at 17 00 02 2x

「当社限定物件」カテゴリ選択時

Clean Shot 2024 04 05 at 17 01 22 2x

「公開物件」カテゴリ選択時

Clean Shot 2024 04 05 at 17 02 05 2x

「当社限定物件」と「公開物件」カテゴリ選択時

Clean Shot 2024 04 05 at 17 03 12 2x

フィールドの並べ替えとドラッグ&ドロップの無効化

はじめに、mtapp.sortDisabled() を使ってフィールドのドラッグ&ドロップによる並べ替え機能を無効化し、mtapp.fieldSort() を使ってフィールドを指定通りに並べます。

(function () {
    // 記事編集画面のみ動くようにする
    if (mtappVars.screen_id === 'edit-entry') {
        // ドラッグ&ドロップの並べ替えを無効化
        mtapp.sortDisabled();
        document.getElementById('display-options').style.display = 'none';
        // ベースとなるフィールドの並べ替えと使わないフィールドを非表示
        mtapp.fieldSort({
            sort: 'title,text,excerpt,customfield_staff_name,customfield_post_code,customfield_prefecture,customfield_city,customfield_street,customfield_stations',
            otherFieldHide: true
        });
    }
})();

カテゴリ選択時にフィールドの表示状態を切り替える関数を作成

続いて下記のようにカテゴリ選択時にフィールドの表示状態を切り替える categoryChanged 関数を作ります。

(function ($) {
    /**
     * 選択されたカテゴリに基づいてフィールドの表示・非表示を切り替える。
     * @param {HTMLElement[]} fields - 表示または非表示にするDOM要素の配列。
     * @param {string} ids - 選択されたカテゴリIDのカンマ区切り文字列。
     */
    const categoryChanged = (fields, ids) => {
        // 選択されたカンマ区切りのカテゴリIDを配列に変換
        const selectedIds = ids.split(',');

        // 選択されたカテゴリIDからカテゴリ名の配列を取得
        const selectedCategories = [];
        for (const id of selectedIds) {
            const category = window.MT.App.categoryList.find((category) => Number(category.id) === Number(id));
            if (category) {
                selectedCategories.push(category.label);
            }
        }

        // すべてのフィールドをループして表示・非表示を切り替え
        fields.forEach((field) => {
            // div.field の id 属性を取得して customfield_ と -field を削除
            const basename = field.getAttribute('id').replace(/^customfield_|-field$/g, '');
            // フィールドのベースネームと選択されたカテゴリによって表示・非表示を切り替え
            // ベースネームが text または staff_name の場合は、当社限定物件のカテゴリが選択されている場合のみ表示
            if (['text', 'staff_name'].includes(basename)) {
                field.style.display = selectedCategories.includes('当社限定物件') ? 'block' : 'none';
            }
            // ベースネームが post_code, prefecture, city, street の場合は、公開物件のカテゴリが選択されている場合のみ表示
            else if (['post_code', 'prefecture', 'city', 'street'].includes(basename)) {
                field.style.display = selectedCategories.includes('公開物件') ? 'block' : 'none';
            }
            // それ以外のフィールドは常に表示
            else {
                field.style.display = 'block';
            }
        });
    };

    // 記事編集画面のみ動くようにする
    if (mtappVars.screen_id === 'edit-entry') {
        // 省略
    }
})(jQuery);

この関数の第一引数には、表示または非表示を切り替えるフィールド(DOM要素)の配列を渡します。

第二引数には、選択されたカテゴリのIDをカンマ区切りにした文字列を渡します。

フィールドの表示・非表示の切り替えは下記の部分で行なっていますので、この部分( ['text', 'staff_name']['post_code', 'prefecture', 'city', 'street'] など)を適宜環境に合わせて変更してください。

// すべてのフィールドをループして表示・非表示を切り替え
        fields.forEach((field) => {
            // div.field の id 属性を取得して customfield_ と -field を削除
            const basename = field.getAttribute('id').replace(/^customfield_|-field$/g, '');

            // フィールドのベースネームと選択されたカテゴリによって表示・非表示を切り替え
            // ベースネームが text または staff_name の場合は、当社限定物件のカテゴリが選択されている場合のみ表示
            if (['text', 'staff_name'].includes(basename)) {
                field.style.display = selectedCategories.includes('当社限定物件') ? 'block' : 'none';
            }
            // ベースネームが post_code, prefecture, city, street の場合は、公開物件のカテゴリが選択されている場合のみ表示
            else if (['post_code', 'prefecture', 'city', 'street'].includes(basename)) {
                field.style.display = selectedCategories.includes('公開物件') ? 'block' : 'none';
            }
            // それ以外のフィールドは常に表示
            else {
                field.style.display = 'block';
            }
        });

カテゴリ変更時と初回実行

最後に mtapp.fieldSort() を使ってフィールドを並べ替えた後でイベントをセットします。

カテゴリが変更されると、#category-ids の要素で mtappCategoryChanged イベントが発火されます。なので、そのイベントにバインドする関数の中で categoryChanged 関数が動くようにします。

mtappCategoryChanged イベントでは、変更後のカテゴリID(カンマ区切り)がイベントオブジェクトから event.detail.newValue のようにして取得できます。それを categoryChanged 関数の第二引数に渡すようにします。

また、ページを表示した時にも一度 categoryChanged 関数を動かす必要があります。その時は、mtappVars.selectedCategories という変数に選択されているカテゴリIDがセットされていますので、それを categoryChanged 関数の第二引数に渡します。

(function ($) {
    const categoryChanged = (fields, ids) => {
        // 省略
    };

    // 記事編集画面のみ動くようにする
    if (mtappVars.screen_id === 'edit-entry') {
        // ドラッグ&ドロップの並べ替えを無効化
        mtapp.sortDisabled();
        document.getElementById('display-options').style.display = 'none';
        // ベースとなるフィールドの並べ替えと使わないフィールドを非表示
        mtapp.fieldSort({
            sort: 'title,text,excerpt,customfield_staff_name,customfield_post_code,customfield_prefecture,customfield_city,customfield_street,customfield_stations',
            otherFieldHide: true
        });

        // メインカラムのフィールドをすべて取得
        const fields = document.querySelectorAll('#sortable > .field');
        // カテゴリの変更を検知するリスナーを設定
        document.getElementById('category-ids').addEventListener('mtappCategoryChanged', function (event) {
            categoryChanged(fields, event.detail.newValue);
        });
        // ページを表示した時に実行
        categoryChanged(fields, mtappVars.selectedCategories);
    }
})(jQuery);

完成したコード

まとめると下記のようなコードになりました。これを user.js に書いてください。また、カテゴリの部分は適宜変更してください。

(function () {
    /**
     * 選択されたカテゴリに基づいてフィールドの表示・非表示を切り替える。
     * @param {HTMLElement[]} fields - 表示または非表示にするDOM要素の配列。
     * @param {string} ids - 選択されたカテゴリIDのカンマ区切り文字列。
     */
    const categoryChanged = (fields, ids) => {
        // 選択されたカンマ区切りのカテゴリIDを配列に変換
        const selectedIds = ids.split(',');

        // 選択されたカテゴリIDからカテゴリ名の配列を取得
        const selectedCategories = [];
        for (const id of selectedIds) {
            const category = window.MT.App.categoryList.find((category) => Number(category.id) === Number(id));
            if (category) {
                selectedCategories.push(category.label);
            }
        }

        // すべてのフィールドをループして表示・非表示を切り替え
        fields.forEach((field) => {
            // div.field の id 属性を取得して customfield_ と -field を削除
            const basename = field.getAttribute('id').replace(/^customfield_|-field$/g, '');
            // フィールドのベースネームと選択されたカテゴリによって表示・非表示を切り替え
            switch (basename) {
                case 'text':
                case 'staff_name':
                    field.style.display = selectedCategories.includes('当社限定物件') ? 'block' : 'none';
                    break;
                case 'post_code':
                case 'prefecture':
                case 'city':
                case 'street':
                    field.style.display = selectedCategories.includes('公開物件') ? 'block' : 'none';
                    break;
                default:
                    field.style.display = 'block';
            }
        });
    };

    // 記事編集画面のみ動くようにする
    if (mtappVars.screen_id === 'edit-entry') {
        // ドラッグ&ドロップの並べ替えを無効化
        mtapp.sortDisabled();
        document.getElementById('display-options').style.display = 'none';
        // ベースとなるフィールドの並べ替えと使わないフィールドを非表示
        mtapp.fieldSort({
            sort: 'title,text,excerpt,customfield_staff_name,customfield_post_code,customfield_prefecture,customfield_city,customfield_street,customfield_stations',
            otherFieldHide: true
        });

        // メインカラムのフィールドをすべて取得
        const fields = document.querySelectorAll('#sortable > .field');
        // カテゴリの変更を検知するリスナーを設定
        document.getElementById('category-ids').addEventListener('mtappCategoryChanged', function (event) {
            categoryChanged(fields, event.detail.newValue);
        });
        // ページを表示した時に実行
        categoryChanged(fields, mtappVars.selectedCategories);
    }
})();
Published 2024-04-05
Updated 2024-04-08

「MTAppjQuery」カテゴリの記事一覧