WordPress プラグイン「Reaction Buttons」をカスタマイズしてみた

最近の制作案件で「コラム系のコンテンツへユーザからのリアクションを表示させたい」というご要望があり、既成のプラグインであったりするのかな?と探していたところ「Reaction Buttons」の存在を知りました。

デザインの都合上、プラグインで出力されるマークアップ自体を調整する必要があったため、その際のカスタマイズについてまとめてみます。

Reaction Buttons プラグインとは?

プラグインの概要は、LIG さんのブログ記事が判りやすいです。
2年くらい前の情報ではありますが、最新版でも大差はありませんでした。

サイトに独自のいいね!ボタンを設置できるWordPressプラグイン「Reaction Buttons」 | 株式会社LIG:
http://liginc.co.jp/programmer/archives/3497

CSS を調整すれば、雰囲気も変わって「いい感じ」にできそうです。
実際にプラグインを導入されている kyotokoto さんは、写真もあわせてステキですよね。

kyotokoto / 日常の小さなきろく:
http://www.kyotokoto.jp

大事なことなので...

BUN が WordPress のカスタマイズをする際、デフォルト(または、一般に配布されているような)テーマを利用していないため、wp_head や wp_footer などの関数をテーマファイルに記述していない前提です。

Reaction Buttons プラグインは、ボタンを出力するページの wp_head へ JavaScript を追加する仕組みのため、お使いのテーマによってはここで解説している通りにしても上手く動かないかもしれません。

また、WordPress アドレスとサイトアドレスが異なる場合に二重投稿防止機能が動作しませんので、参考サイトもご紹介しておきます。

Wordpressプラグイン「Reaction Buttons」のCookieによる二重投稿防止が効かない場合の対処 | Yuta Ihara.com:
http://yutaihara.com/archives/62

集計数と投票ボタンのマークアップ

デフォルトのボタンではデザインに沿ったレイアウトを表現できなかったため、プラグイン設定の「Position in the post:」のチェックをすべて外しておきました。

また、「いいね!」ボタンだけあればよいため「Reaction Buttons:」には「like」と入力し、シングルページのテンプレートへ集計数と cookie をチェックするためのコードを追加しました。

<?php
    if(have_posts()){
        while(have_posts()){
            the_post();

            // いいね!数の取得
            $_btn_label = 'like';
            $_cnt       = get_post_meta($post->ID, '_reaction_buttons_' . $_btn_label, true);
            $_cnt       = (!$_cnt) ? 0 : $_cnt;
            $_cnt_arr   = str_split($_cnt);

            // 二重投稿防止の場合は cookie の値をチェック
            $_cookie    = "";
            $_json      = stripslashes($_COOKIE["reaction_buttons_" . $post->ID]);
            $_cookie    = json_decode($_json, true);
            if(!is_array($_cookie)) $_cookie = array();

            // 投票済みであれば true
            $_voted     = array_key_exists(addslashes($_btn_label), $_cookie) && $_cookie[addslashes($_btn_label)];
        }
    }
?>

集計数の表示はセットしておいた $_cnt_arr を利用して、桁ごとに span 要素を付加しました。
.num0 〜 .num9 のスタイルを定義すれば、数字部分の画像置換も可能です。

<div id="reaction-counts">
    <span class="counts">
    <?php
        $_html = null;

        // いいね!数を桁ごとに出力
        foreach($_cnt_arr as $_num){
            $_html .= '<span class="num' . $_num . '">' . $_num . '</span>' . PHP_EOL;
        }

        echo $_html;
    ?>
    </span><!-- /.counts -->
    <span class="unit">いいね!</span>
</div><!-- /#reaction-counts -->

投票ボタンも CSS で画像に置換するため、シンプルなテキストリンクに。
class 属性に書いてある PHP コードは、プラグイン設定の「Use cookies:」がオンの場合に二重投稿を防止するための記述です。

<p id="btn-reaction">
    <a class="btn<?php if($_voted){ echo ' voted'; } ?>" href="#">いいね!</a>
</p>

カウントアップの処理

投票ボタンをクリックした際のカウントアップ処理として、JavaScript を記述します。
サンプルでは、非同期通信後の集計数もCSSで画像置換できるように調整してあります。

<script>
$(function(){
    var already_voted_text  = '';
    var buttons             = ['like'];

    // 投票ボタン
    _reaction_btn = $('#btn-reaction').find('.btn');

    // クリックイベント
    _reaction_btn.on('click', function(){
        if($(this).hasClass('voted')){
            // 「投稿済み」であれば、処理を終了
            return false;
        }

        jQuery.ajax({
            type: 'post',url: '<?php bloginfo('wpurl'); ?>/wp-admin/admin-ajax.php', dataType: 'json',
            data: { action: 'reaction_buttons_increment_button_php', post_id: <?php echo $_post_id; ?>, button: 'like', _ajax_nonce: '<?php echo wp_create_nonce('reaction_buttons'); ?>' },
            success: function(data){
                // カウントアップ後の集計数
                var _cnt        = String(data['count']);
                var _cnt_arr    = _cnt.split('');
                var _tmpl       = '';

                // 桁ごとに span 要素をセット
                for(var _i = 0; _i < _cnt_arr.length; _i ++){
                    _tmpl += '<span class="num' + _cnt_arr[_i] + '">' + _cnt_arr[_i] + '</span>\n';
                }

                // 集計数をアップデート
                $("#reaction-counts").find('.counts').html(_tmpl);

                // 「投稿済み」の class を追加
                _reaction_btn.addClass('voted');
            }
        });
    });
});
</script>

動作を確認して、問題がなければ完成です。

デフォルトの出力コードから不要な部分を取り除くなど自分なりに最適化しただけですが、reaction_buttons.php に目を通しておけば、カスタマイズの参考になります。

やってみて気づいたこと

「専用のカスタムフィールドを追加しつつ、非同期通信の際に関数を渡してデータをアップデートする」というシンプルな構造だったので、同じような仕組みを自前でも用意できそうな雰囲気です。

そして、それができるのであれば wp-admin/admin-ajax.php を DataAPI のそれに置き換えつつゴニョゴニョしたら、MT でもなんとかなるかも?と妄想してみたり(。-_-。)