kinalog

自称フロントエンドエンジニアが何か喚いています。

投稿前に確認ダイアログを出す

Wordpressで投稿をする時、通常は日時を変えなければ投稿と同時に即時公開状態になる。

が、予約投稿がメインで、なおかつ公開と同時にSNSに共有するというようなサイトの場合、「日付を変え忘れて即時投稿になっちゃった☆彡」はちょっと困る。(特に企業向けのサイトの場合)

デフォルトの投稿時刻設定を現在時刻+1時間とかにできないかなあとも考えたけれど、例えば投稿画面を1時間放置してたら意味ないし...ってことで、色々考えた結果、

・投稿ボタンを押した時に確認ダイアログを表示
・確認ダイアログに公開予定時刻を表示

という感じにしてみることにした。

ブラウザの確認ダイアログを出す

同じことをやろうとしている先人がいたので、とりあえずそのまま実装。

お手軽で、もうこれでいいかなーと思っていたんだけど、このダイアログ、表示時にフォーカスされているボタンが「OK」ボタンのため、勢い余ってEnterキーとか押しちゃうと、さらっとスルーできてしまう。それじゃあ意味ない。

ちょっと調べてみたけどこのフォーカスを変更する術は無い模様。
となると、自前でキャンセルボタンがフォーカスされているウィンドウを作るしかない。

jQuery UIのdialogを使う

どうせ管理画面だから、デザインなんかも気にする必要は無い。
ってなわけで、Wordpressには標準でjQuery UIが同梱されているので、それを使う。

dialogウィジェットを有効にするには、functions.phpに下記の呪文を追加。

wp_enqueue_script('jquery-ui-dialog');
wp_enqueue_style("wp-jquery-ui-dialog");


で、ウィンドウの表示は先人の知恵を借りつつ、下記のように書いてみた。

function pre_post_dialog () {
echo <<< EOF
<script>
jQuery(document).ready(function($) {
    var dialog_box = $('<div>'),
        publish_btn = $('#publish'),
        dialog_id = 'confirm_dialog';

    dialog_box.attr('id', dialog_id);
    dialog_box.appendTo('body');

    $('#' + dialog_id).hide();
    
    function show_confirm_dialog() {
        var msg = '<strong style="font-size:15px;">' + $('#aa').val() + '年' + $('#mm').val() + '月' + $('#jj').val() + '日 ' + $('#hh').val() + '時' + $('#mn').val() + '分</strong><br>' + '記事を<strong>「' + $('#publish').val() + '」</strong>しても宜しいですか?';

        $('#' + dialog_id).html(msg);
        $('#' + dialog_id).dialog({
            modal: true,
            title: '投稿確認',
            buttons: {
                'キャンセル': function() {
                    $(this).dialog('close');
                    return false;
                },
                'OK': function() {
                    $('#post').trigger('submit');
                    $(this).dialog('close');
                }
            }
        });

        return false;
    }

    publish_btn.on('click', show_confirm_dialog);
});
</script>
EOF;
}

add_action('admin_head-post.php', 'pre_post_dialog');
add_action('admin_head-post-new.php', 'pre_post_dialog');


上記で動いて完成!・・・かと思いきや、思わぬ罠があった。
「公開」ボタンを押しても、何故か「下書き」状態にしかならない。

「公開」状態にできないのを修正

推測ですが、恐らく公開ボタンをreturn falseしているせいで、イベントが消失。
しかし消失したイベントの中に、記事の状態を「公開」にするための設定があったんでしょう。

というわけで、確認画面表示用の別の投稿ボタンを用意して、ダイアログ内のOKを押されたら元の#publishボタンが押される、という処理に変えてみた。

jQuery(document).ready(function($) {
    var dialog_box = $('<div>'),
        publish_btn = $('#publish'),
        dialog_id = 'confirm_dialog',
        confirm_btn = publish_btn.clone();

    // 投稿ボタンの設定。元のボタンは隠しておく
    confirm_btn.attr('id', 'confirm_btn');
    publish_btn.hide();
    publish_btn.after(confirm_btn);

    dialog_box.attr('id', dialog_id);
    dialog_box.appendTo('body');
    $('#' + dialog_id).hide();
    
    function show_confirm_dialog() {
        var msg = '<strong style="font-size:15px;">' + $('#aa').val() + '年' + $('#mm').val() + '月' + $('#jj').val() + '日 ' + $('#hh').val() + '時' + $('#mn').val() + '分</strong><br>' + '記事を<strong>「' + $('#publish').val() + '」</strong>しても宜しいですか?';

        $('#' + dialog_id).html(msg);
        $('#' + dialog_id).dialog({
            modal: true,
            title: '投稿確認',
            buttons: {
                'キャンセル': function() {
                    $(this).dialog('close');
                    return false;
                },
                'OK': function() {
                    publish_btn.trigger('click');
                    $(this).dialog('close');
                }
            }
        });

        return false;
    }

    confirm_btn.click(show_confirm_dialog);

    // 日付や記事の状態を変えた時に、ボタンのvalueが変わるように。
    // setTimeoutしないとうまく切り変わらない。。。
    $('#submitdiv a.button').on('click', function() {
        setTimeout(function() {
            confirm_btn.val($('#publish').val());
        }, 1);
    });

});

まとめ

「公開」状態にできないバグはかなり悩んだので、管理画面のボタンをいじるときは細心の注意が必要(当たり前
デフォルトのイベントは殺してはいけない。

これもうちょっと頑張れば、投稿前のプレビューウィンドウとかにできそう。

おまけ - 今回つかったアクションフック

admin_head-(ファイル名)

管理画面内の特定のページだけで実行するという、超絶便利なアクションフック。
今回は「post.php」と「post-new.php」だけに有効にしてある。