のらねこの気まま暮らし

技術系だけど、Qiita向きではないポエムとかを書くめったに更新されないヤツ

mojoでpjaxを導入してみた with Text::Xslate

タグ機能が欲しい最近。

忘れないうちに書いてしまう。

pjax

説明面倒なのでハショる。Google先生に聞いて。

導入のアレコレ

jquery.pjax.jsをダウンロード

htmlに読み込み

<script type="text/javascript" src="/js/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="/js/jquery.pjax.js"></script>

pjaxを登録

(function($){
    // pjaxを登録
    $('a.pjax').pjax('#main', {"timeout": 36000});

    // pjaxイベントの登録
    $('#main')
        .bind('pjax:start', function(){ /* 開始時の処理 */})
        .bind('pjax:end',   function(){ /* 終了時の処理 */ });
});

server-sideでpjax用のレンダリングを設定

以下のどちらかを満たしていれば、pjaxのリクエストであると判定

  • リクエストヘッダに"X-PJAX"
  • GETパラメータに"_pjax=true"


テンプレートにText::Xslateを使っているため、以下のような仕組みを入れなければならない。

pjaxリクエストであある
コンテンツ部分である add-pjax.html.tx をレンダリング
pjaxリクエストでない
add-pjax.htmlをinclude, layout.txをcascadeした完全なhtmlをレンダリング
use HTML::FillInForm::Lite qw/fillinform/;
use Text::Xslate qw/html_builder/;

use Mojolicious::Lite;

my %template_options = (
    function    => {fillinform => html_builder(\&fillinform)},
);
plugin 'xslate_renderer' => {
    template_options => \%template_options,
};

my $tx = Text::Xslate->new({
    path => './templates/',
    %template_options,
});

get '/slide/add' => sub {
    my $self = shift;

    if ($self->param('_pjax')) {
        my $string = $tx->render('slide/add-pjax.html.tx');
        $self->render_text($string);
    } else {
        $self->render('slide/add');
    }
};


これで、<a class="pjax" herf="/slide/add">なリンクがpjaxとして動くようになった。

はまりどころ

  1. pjaxのデフォルトのtimeout時間が鬼畜
  2. うっかりhtmlタグを入れたままにすると、通常遷移

pjaxのデフォルトのtimeout時間が鬼畜

pjaxはajaxリクエストが(設定の)timeout時間を超えると location.href による遷移を行う。
なので、次のように自分でtimeoutを設定するが吉。

    $('a.pjax').pjax('#main', {"timeout": 36000});

うっかりhtmlタグを入れたままにすると、通常遷移

どうやらpjaxさんは、レスポンスコンテンツにhtmlタグがあるとコンテンツ全体を書き換えるために、 location.hrefを実行してくれるようだ。
とても親切。 :)

(add-pjax.html.tx の :cascade layout を消し忘れ、完全にhtmlをレンダリングしていた僕は長い時間この仕様にハマっていた。