wpdb (12)

この投稿は2年半前の記事です。 情報が古くなっている可能性があるので、その点ご了承ください。
2014 年 12 月 24 日 912日前)
5,427文字 (読了時間13分)

SPONSORED LINK

前回まででフォロワーを出してみましたが、なんかいまいちスピードが上がらないので、今回はGithubのコミットログを貼り付けて、主に説明したいところまで端折ります。

  1. フォロワーとフォローしている人を取得する関数を修正して1つに
  2. the_contentにかけていたフックの関数をそのまま利用し、Ajaxで返す
  3. それぞれのフォロワーリストにボタンを表示
  4. ボタンにはユーザーIDを渡せるよう変更(指定しなければ現在の投稿の作者IDを利用)

わからないことがあったら、Githubのコミットログにコメントを残してもらえると答えられます。(※ Githubは行ごとにコメント残せるんですよ)

工夫したポイントを説明すると、Ajaxの部分ですかね。

Ajaxを実装する場合、「JSONを取得して云々かんぬん」という説明があるのですが、jsRenderとか、そういうJSテンプレートを使った実装していない限り、JSONで画面を作るのってめんどくさいんですよね。PHP側とJS側両方で似たような描画用関数を実装することになったりして。

WordPressでサイトを作っている場合、わざわざJSONで画面を作るようなWebアプリ的な作り方をしないと思うので、Ajax経由で渡すデータの利用方法が「DOMの操作」なのであれば、HTMLをサーバで作って、それをそのまま渡してしまった方がよいです。

Ruby on Railsの開発者であるDHHがブログでそんなこと(Server-generated JavaScript Responses)を書いていたので、それのしょぼい版ですね。

今回は「これ以上フォロワーが存在しない」という場合、pタグを渡すようにしていて、pタグが挿入された瞬間に「もっと読み込む」ボタンは消えるということをCSS上でやっています。

p.no-follower{
  & + a.fs-more-btn{
    display: none;
  }
}

で、こうなります。下にある「もっと見る」ボタンを押すとそれより古いフォロワーが読み込まれて……

以前と同じく、うまく表示されてます
以前と同じく、うまく表示されてます

あれー!!

読み込んだフォロワーはボタンがグレーのまま
読み込んだフォロワーはボタンがグレーのまま

フォローチェックのイベントを改善する

ページを表示した時点でフォロワーを取得できる機能を以前作りましたが、今回起きている事態は「フォローしているかチェック」機能がAjaxレスポンスでは働かないのが原因ですね。

これを避けるために次のような実装をしましょう。

  1. まず、「ボタンが画面に表示された」というイベントrendered.freundschaftを監視し、まだアップデートされていないボタン(=クラスがfs-disabledのまま)をアップデートする
  2. 「ログインしている/していない」は1回目のチェックでわかるので、1回しか確認しないようにする
  3. イベントが発生するのは、画面の表示(DOMREADY)とAjaxの更新の2回

ちなみに、rendered.freundschaftという書き方はjQueryにおけるイベントの名前空間ですね。clickイベントなんかはよく使いますが、このイベントの監視をやめたいなと思っても、他のJSがclickイベントを監視しているかもしれないんじゃないですか。そういうとき、click.takahashi.fumikiとかで登録しておけば、他のイベントリスナーをそのままに、自分のだけ削除できるんですね。

では、これを以前書いたfollower.jsに実装しましょう。

(function ($) {
    'use strict';

    // いろんなイベントを渡って使う変数を記録
    var nonce = '',
        loggedIn;

    // documentオブジェクトを監視
    $(document).on('rendered.freundschaft', function(){
        var $btns = $('.fs-disabled'), // disabledが未確認のボタンをこの時点で取得
            authorIds = [];
        // ログインしていないことをすでに確認済みだったら、
        // ログインボタンに変更
        if( false === loggedIn ){
            $btns.removeClass('fs-disabled').addClass('fs-login');
        }
        // ボタン全部の投稿者IDを取得して、ログイン判定
        $btns.each(function(index, btn){
            authorIds.push($(btn).attr('data-author-id'));
        });
        // 投稿者IDがあればAjax
        if( authorIds.length ){
            $.post(FreundschaftFollow.endpoint, {
                action: FreundschaftFollow.actions.fs_status,
                author_ids: authorIds
            }).done(function(result){
                if( result.logged_in ){
                    // ログインしているので、ユーザーに応じたボタンを出力
                    for( var prop in result.users ){
                        if( result.users.hasOwnProperty(prop) ){
                            var userId = prop.replace(/user_/, '');
                            if( result.users[prop] ){
                                // フォローしている
                                $('.fs-btn[data-author-id=' + userId + ']').removeClass('fs-disabled').addClass('fs-following');
                            }else{
                                // フォローしていない
                                $('.fs-btn[data-author-id=' + userId + ']').removeClass('fs-disabled').addClass('fs-follow');
                            }
                        }
                    }
                    // nonceを保存
                    nonce = result.nonce;
                }else{
                    // ログインしていないので、
                    // ボタンをログインに
                    $btns.removeClass('fs-disabled').addClass('fs-login');
                    // ログインチェックを記録
                    loggedIn = false;
                }
            }).fail(function(xhr, status, message){
                alert(message);
            });
        }
    });

    // DOMREADYでイベント発行
    $(window).ready(function(){
        $(document).trigger('rendered.freundschaft');
    });

    $(document).on('click', '.fs-btn', function(e){
        // ここは変更なしなので中略
    });

    // フォロワーをもっと読み込むボタン
    $(document).on('click', '.fs-more-btn', function(e){
        e.preventDefault();
        var $btn = $(this),
            endpoint = $btn.attr('href') + '&offset=' + $btn.attr('data-offset');
        // 読み込み中は何もしない
        if( !$btn.hasClass('loading') ){
            // 読み込み中に変更
            $btn.addClass('loading');
            $.get(endpoint).done(function(result){
                // HTMLを挿入
                $btn.before(result.html);
                // オフセットを更新
                $btn.attr('data-offset', result.offset);
                // ボタンの更新イベント
                $(document).trigger('rendered.freundschaft');
            }).fail(function(xhr, status, error){
                alert(error);
            }).always(function(){
                // 読み込み中を解除
                $btn.removeClass('loading');
            });
        }
    });

})(jQuery);

変わったところだけハイライトしようかと思いましたが、大変なのでGithubのコミットdiffを見てください。こんだけコード量が多くなってくると、githubの方が見やすいですね……。

こんな感じになりました
こんな感じになりました

まとめ

  • Ajaxでどんどん読み込んだ
  • Ajaxで返すJSONにHTMLぶっこんじゃいなよ!
  • DOMREADY以外でも画面を更新した

さて、というわけで、色々とやってきましたが、他の細部を(フォロワー数が出てない)とか、そいういう問題もありつつ、本来の目的は$wpdbに詳しくなることなので、次回以降、細部の調整をしつつ、メッセージ機能の仕様を固めてみましょう。

シングルページWebアプリケーション ―Node.js、MongoDBを活用したJavaScript SPA

シングルページWebアプリケーション ―Node.js、MongoDBを活用したJavaScript SPA [書籍]

著者Michael S. Mikowski, Josh C. Powell

クリエーター佐藤 直生, 木下 哲也

出版社オライリージャパン

出版日2014 年 5 月 24 日

商品カテゴリー大型本

ページ数498

ISBN4873116732

Supported by amazon Product Advertising API

 

フォローしてください

ここで会ったのもなにかの縁。
高橋文樹.comの最新情報を見逃さないためにもフォローをお願いします。
めったに送らないメルマガもあります。

SPONSORED LINK

この記事について

この記事はが2014 年 12 月 24 日にプログラミングの記事として公開しました。

高橋先生の電子書籍

高橋先生の電子書籍

Amazonで電子書籍も買えます。

好きな言葉

『ザナドゥへの道』と『フィネガンズ・ウェイク』との両方について言えるただ一つの特徴は、こういう本は一冊でたくさんだということだ。

— T・S・エリオット

高橋先生の処女作

『途中下車』高橋文樹

2001年幻冬舎NET学生文学大賞受賞作です。

Web制作やります

Web制作やります

Web制作のご依頼は株式会社破滅派へ

不定期メルマガ

高橋文樹.comでは、不定期でニュースレターを配信しています。滅多に送らないので是非購読してください。

高橋文樹.comではプライバシーポリシーに準じて登録情報を取り扱います。