かたつむりくんのWWW

jQueryAutoHeight.js をレスポンシブデザインで使う

細々と公開しているんですけれども意外と使われている「jQueryAutoHeight.js - 複数のカラムの高さを最大値にそろえるjQueryプラグイン」を、レスポンシブデザインのサイトで使いたいというご意見を頂きました。

PC版のときはカラムが横に並ぶので高さを揃えるといい感じになるのですが、スマホのときは1カラムになって縦に並ぶので、そこで高さを揃えてしまうと無駄に間延びしちゃうということですね。

そんなときは、jQueryAutoHeight.js を実行するところで、以下のように横幅の最小値を設定し、その最小値とウィンドウサイズを比較して実行するかリセットするかを分けてあげれば良いと思います。

<script type="text/javascript">
jQuery(function($){
    var minWidth = 450;
    $(window).resize(function(){
        if (minWidth <= $(this).width()) {
            $('div.box').autoHeight();
        }
        else {
            $('div.box').removeAttr('style');
        }
    }).trigger('resize');
});
</script>

minWidth の値を適宜設定してください。

このように .resize() を使えば、iPhone などを横に倒したりした時にも横幅をチェックして実行し直してくれると思います。

以上です。

Movable Type で n 個ずつ div で囲む場合の書き方

なんかいいタイトルが思いつかなかったのですが、要するに以下のような場合を想定したテンプレートの書き方です。

<div class="row">
    <div>hoge</div>
    <div>hoge</div>
</div>
<div class="row"> <div>hoge</div> <div>hoge</div> </div>
<div class="row"> <div>hoge</div> <div>hoge</div> </div>

この場合だと2個ずつの div を div.row で囲んでますね。Twitter Bootstrap を使ってるとちょくちょく直面したりするかも?

ここでは mt:Entries を例にしてやってみたいと思います。

続きを読む

今さらだけど Apache の gzip の設定をしてみた

gzip の説明や設定の仕方は @burnworks さんの下記の記事をどうぞ。

gzip 設定の前後でこのブログのトップページを計測してみました。

【設定前】

【設定後】

400ミリ秒くらい早くなりました。なんでもっと早く設定しなかったんだろうか・・・

RandomArray - Movable Typeの配列変数からランダムで値を取り出すプラグイン

Movable Type の配列変数からランダムで値を取り出せる MTRandomArray というファンクションタグを提供するプラグインです。

プラグインの詳細、ダウンロードは以下からお願いします。

日本語の使い方は以下に書いてあります。

使い方はシンプルですが、destructive モディファイアがノンプログラマ(俺もか)の方にはちょっと分かりにくいかもしれませんので、以下のサンプルテンプレートをインデックステンプレートに貼り付けて再構築してみたらいいかもしれません。

ダイナミックパブリッシングでこのサンプルを試したいときは、1行目の use_dynamic 変数に 1 をセットしてあげてください。

ランダムに記事を取り出すプラグインは他にもあるようですね。このプラグインは、事前に何かしらの配列をセットしないといけないですが、その分汎用性が高くなっていると思います。

以上です。

Movable Type の配列変数を MTUnless で判定するときのスタティックとダイナミックの違い

Movable Type のテンプレートで配列を変数に入れて扱っているときに、以下のような MTUnless の判定を入れてみます。

<mt:SetVar name="array">
<mt:SetVar name="array" function="push" value="soccer">

<mt:Unless name="array">
Stefan Edberg
<mt:Else>
Robert Baggio
</mt:Unless>

これをスタティックパブリッシングで再構築すると、変数 array には soccer という値が入っているので、 MTElse タグの方が評価されて「Robert Baggio」と表示されます。

しかし、これをそのままダイナミックパブリッシングにすると、

preg_match() expects parameter 2 to be string, array given

というエラーが表示されてしまいます。

これを回避するには、以下のようなテンプレートにして、一度配列の一番目の要素を array_exist 変数にセットして、その変数の有無をチェックするようにすればエラーはでなくなります。

<mt:SetVar name="array">
<mt:SetVar name="array" function="push" value="soccer">

<mt:Var name="array" index="0" setvar="array_exist">
<mt:Unless name="array_exist">
Stefan Edberg
<mt:Else>
Robert Baggio
</mt:Unless>

以上、豆知識として。

MTSetVarにpushする前に変数を初期化するときのスタティックとダイナミックの違い

Movable Type で MTSetVar に function="push" して配列を作っていくとき、事前に変数を初期化というか宣言しておくことがあります。

ことのき、以下のように書くと、スタティックパブリッシングだと問題ありませんが、ダイナミックパブリッシングだと「'mtlover' is not an array.」のようなメッセージでエラーになります。

<mt:SetVar name="mtlover" value="">
<mt:SetVar name="mtlover" function="push" value="bit">
<mt:SetVar name="mtlover" function="push" value="part"> <mt:Loop name="mtlover" glue="-"><mt:Var name="__value__"></mt:Loop>

これは1行目の value="" で文字列として初期化してるのが原因なので、value="" を削除して、

<mt:SetVar name="mtlover">
<mt:SetVar name="mtlover" function="push" value="bit">
<mt:SetVar name="mtlover" function="push" value="part"> <mt:Loop name="mtlover" glue="-"><mt:Var name="__value__"></mt:Loop>

というようにすればエラーはでなくなります。

まあ、変数を初期化しなくても良いのですが、「この後こういう変数を使うよ」というのは宣言しておいた方がテンプレートが見やすくなると思います。

2015/10/14 追記:ダイナミックの場合は初期化しないで function="push" するとエラーになりました。なので、最初の

<mt:SetVar name="mtlover">

は必須のようです。

以上、豆知識として。

DisableRebasename - 記事の編集画面で出力ファイル名が自動で変更されるのを無効にするプラグイン

Movable Type の記事編集画面で、タイトル欄に文字を入力すると自動で出力ファイル名が設定・変更されるのを無効にするプラグインです。

自動で設定してくれるのは嬉しいんですけど、(1) タイトル 入力 → (2) 出力ファイル名入力 → (3) タイトル修正、とやると、せっかく(2)で入れた出力ファイル名が変更されてしまうんですよね。

プラグインの詳細、ダウンロードは以下からお願いします。

なお、万が一出力ファイル名を設定しないで保存しても、MT が勝手に入れてくれるので大丈夫です。

また、一度保存された出力ファイル名欄は「編集」ボタンが付きます。

DesableRebasename01 DesableRebasename02

【2014/02/04 23:58 追記】

バグってました、ごめんなさい。Sublime Text 2 でカーソルを複数にしたまま他の作業して思わぬところにコードが入っちゃってることってありますよね・・・(言い訳

MTAppjQuery v1.2.0 リリース - $.MTAppOtherTypeCategories() を追加ほか

MTAppjQuery v1.2.0 を公開しました。

今回のリリースでは、次のような新機能の追加と変更があります。

  • カテゴリ選択欄をラジオボタンまたはドロップダウンリストに変更できる $.MTAppOtherTypeCategories() を追加
  • MTAppMultiCheckbox() でチェックボックスの順番通りに値が保存されるように変更
  • 変数の型を文字列で返す $.varType() を追加

ここでは、新機能の $.MTAppOtherTypeCategories() をご紹介します。

続きを読む

SetDefaultCategory - Movable Type の記事にデフォルトカテゴリを設定するプラグイン

Movable Type の記事にデフォルトカテゴリを設定するプラグインを作りました。

プラグインの詳細、ダウンロードは GitHub の以下のページからお願いします。

使い方は以下のページに書いてあります。

JavaScriptで値が空文字のcookieを取得したときのブラウザ間の違い

JavaScript で値が空文字のcookieを取得したとき、Chrome や Safari、Firefox では空文字("")が返ってきますが、Internet Explorer (テストしたのは IE8)では undefined が返ってきます。

例えば、次のような setCookie 関数で "testcookie" という名前で空文字をセットします。

setCookie("testcookie", "", 1);
function setCookie(key, val, days){
    var cookie = encodeURIComponent(key) + "=" + encodeURIComponent(val);
    if(days != null){
        var expires = new Date();
        expires.setDate(expires.getDate() + days);
        cookie += ";expires=" + expires.toGMTString() + '; path=/;';
    }
    document.cookie = cookie;
}

これを次のような getCookie 関数で取得して alert で表示してみると、Chrome や Safari、Firefox では空文字となりますが、IE では undefined という文字列が表示されます。

getCookie1 を試す

function getCookie1(key) {
    if(document.cookie){
        var cookies = document.cookie.split(";");
        for(var i = 0; i < cookies.length; i++){
            var cookie = cookies[i].replace(/\s/g,"").split("=");
            if(cookie[0] == encodeURIComponent(key)){
                return decodeURIComponent(cookie[1]);
            }
        }
    }
    return "";
}

なので、IEでもちゃんと空文字になるようにするには、以下のように変更すれば良いと思います。

getCookie2 を試す

function getCookie2(key) {
    if(document.cookie){
        var cookies = document.cookie.split(";");
        for(var i = 0; i < cookies.length; i++){
            var cookie = cookies[i].replace(/\s/g,"").split("=");
            if(cookie[0] == encodeURIComponent(key)){
                var value = "" + decodeURIComponent(cookie[1]);
                return (value == "undefined" || value == "null" || value == "") ? "": value;
            }
        }
    }
    return "";
}

Data API Extend Search - ユーザー名でのフィルタに対応しました

Data API Extend Search プラグインは、Data API での記事(entries)の検索を拡張するプラグインです。

このプラグインをインストールすると「タグ」「カテゴリ」「日時」で記事を絞り込むことができます。

今回はこのプラグインに「ユーザー名」フィルタを追加しました。author_name=tinybeans というような感じで指定出来ます。

プラグインのダウンロード、使い方は以下のページからお願いします。

今後、もう少し拡張していく予定です。

Data API を PHP の file_get_contents で取得するときに注意した方がいいかもしれないこと

Movable Type 6 で注目されている Data API を PHP で扱うときの Tips というか、ハマったところが解決したのでシェアします。

まず、インデックステンプレートにシンプルな PHP ファイルを作り、file_get_contents を利用して Data API で JSON を取得して表示してみます。

<?php
$url = '<mt:CGIPath><mt:Var name= "config.DataAPIScript">/v1/sites/<mt:BlogID>/entries';
echo file_get_contents($url);
?>

問題なく表示されますね。

file_get_contents01

次に、リクエスト URL に「?status=Draft」を付けてみます。このパラメータを付けると、下書き状態の記事を取得することになるので認証を通さないと取得できません。

試しにブラウザで URL を直接叩くと、以下のような JSON が返ってきます。

{
"error":{
"code":403,
"message":"Do not have permission to retrieve the requested entries."
}
}

では、先程の PHP の $url にもこのパラメータを付けてみます。

<?php
$url = '<mt:CGIPath><mt:Var name= "config.DataAPIScript">/v1/sites/<mt:BlogID>/entries?status=Draft';
echo file_get_contents($url);
?>

ページにアクセスしてみると、、、真っ白です。

PHP エラーを表示するようにファイルの先頭に「ini_set('display_errors', 1);」を入れて見ると、次のようなエラーが出ます。

Warning: file_get_contents(http://your-host/mt-data-api.cgi/v1/sites/15/entries?status=Draft): failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden in /var/www/your-path/file_get_contents.php on line 11

さてどうしたものかとここでハマり、とりあえずは代替案で対応していましたが、以下のページを参考に解決しました。

このサイトの説明にあるように、file_get_contents の第三引数に渡すコンテキストリソースを作成して渡してみます。

<?php
ini_set('display_errors', 1);
$url = '<mt:CGIPath><mt:Var name= "config.DataAPIScript">/v1/sites/<mt:BlogID>/entries?status=Draft';
$context = stream_context_create(array(
'http' => array('ignore_errors' => true)
));
echo file_get_contents($url, false, $context);
?>

無事、この PHP ファイルを通してでもブラウザでアクセスしたときと同様の JSON が表示されました。良かった良かった。

file_get_contents02

なお、この部分の file_get_contents では PHP の Warning とかのエラーを出さないようにするのは、file_get_contents の頭に「@」を付けて「@file_get_contents」にすれば、Warning とかの PHP エラーは出なくなります。

以上です。

上記のページが分かりやすいよと教えてくださった宮澤さん、同じように原因をアドバイスしてくださった松崎さん、ありがとうございます!

Data API PHP Cache - Data API のレスポンス結果をPHPキャッシュするプラグイン

この記事は Movable Type Advent Calendar 2013 の6日目の記事です。

毎年恒例、自分の誕生日に記事を書くノルマを課して、1歳分大きくなろう企画です(謎

Data API

Movable Type 6 の目玉機能である「Data API」は、Movable Type の楽しさをより深くしてくれる存在になるかもしれません。

先日、この Data API での記事の検索を少し拡張するプラグイン(Data API Extend Search)を公開しました。

Data API に関するプラグインは、だいぶ早い段階からいくつか公開されています。KING Junnama さんが MT タグで Data API から情報を取得するプラグインを公開していたり、プロフェッサー藤本さんがエンドポイントを拡張するプラグインを公開していたりします。

今後も、Data API に関するプラグインはたくさん出てくるでしょう。

Data API の結果をキャッシュする

さて、Data API は夢が広がる反面、気を付けなければいけないこともあります。

アクセスの多いサイトで頻繁に Data API を叩く必要のある使い方をすると、スペックの低いレンタルサーバーでは 500 エラーになる可能性があるでしょう。また、CGI のオーバーヘッドによりレスポンスが遅いということも考えられます。Data API を快適に使うには、やはり VPS で PSGI での環境が必要かもしれません。

そうなってくると、重要なのがレスポンス結果のキャッシュですね。

そんな中で、このアドベントカレンダーの3日目の記事で、MT界きっての発明家、Toi企画の天野さんが「.htaccess を利用して Data API のキャッシュの仕組みをつくる - blog.taaas.jp」という記事を書いてくださいました。なかなか難しい内容ですがとても興味深いですね。

この天野さんのキャッシュは Apache レベルでキャッシュの処理をするものですが、PHPで処理するものに関しては野田さんが8月の時点で既に公開しています。先に紹介したプラグインがそれですね。PHP の軽量版もあります。

さすが KING。

自分でも作ってみたくなった

さて、そんなわけで、PHP 版のキャッシュ機能のプラグインはすでにあるのは知っていましたが、先程の天野さんの記事の中で「パラメータを MD5 でハッシュ化して readfile するような簡単な PHP を追加して、」というさらっとした文章を読んで、猛烈に自分で作ってみたくなったのでした。勉強のために。

それがこれです。

このプラグインのコンセプトは以下のようになっております。

  • Data API の書き方と同じように書きたい。
  • キャッシュの削除のタイミングとかプラグイン側で適切にやって欲しい。
  • 主要なエンドポイントだけキャッシュする(MT側で削除側を細かく制御したいと思ったりしたので...)。
  • 認証が必要なやつはキャッシュしないで無視してほしい。

使い方

まずは、「data-api-cache.php」というインデックステンプレートを作ります。ウェブサイト、ブログ、どこでもいいです。

上記のコンセプトから、キャッシュの対象は以下のエンドポイントに限定されています。

https://your-host/mt-data-api.cgi/v1/sites/{blog_id}
https://your-host/mt-data-api.cgi/v1/sites/{blog_id}/categories
https://your-host/mt-data-api.cgi/v1/sites/{blog_id}/entries/{entry_id}/comments
https://your-host/mt-data-api.cgi/v1/sites/{blog_id}/comments
https://your-host/mt-data-api.cgi/v1/sites/{blog_id}/comments/{comment_id}
https://your-host/mt-data-api.cgi/v1/sites/{blog_id}/entries
https://your-host/mt-data-api.cgi/v1/sites/{blog_id}/entries/{entry_id}

これらにアクセするときに上記 URL の「mt-data-api.cgi」の部分を「data-api-cache.php」にすればOKです。あとは勝手にキャッシュしてくれます。

キャッシュのファイル名は、パラメータを MD5 でハッシュ可し、mt-static/support/data-api-php-cache というディレクトリの中に、上記URL通りのディレクトリ構造で保存されます。

そして、「ウェブサイト、ブログ、記事、コメント、カテゴリ」の保存と削除のタイミングで、該当するファイルやディレクトリだけが勝手に削除されます。

もし、認証の必要な URL を叩いた場合は、そのままエラー結果が返ってきます。

簡単なテストをした結果、やっぱり CGI を叩くよりも5倍くらい速いです。

その他

ツッコミどころは満載かもしれませんが、やっぱり何でも自分で作ってみると勉強になりますね。

そんな感じのプラグインですが、興味があれば「テスト環境」で使ってみてください。

明日は Masa Osugi さんで、テーマは「Movable Type × Amazon Web Service」が予定されています。楽しみですね!

Data API Extend Search - Data API での記事の検索を拡張するプラグイン

「Data API Extend Search」というプラグインを公開します。Data API での記事(entries)の検索を拡張するプラグインです。

このプラグインをインストールすると「タグ」「カテゴリ」「日時」で記事を絞り込むことができます。

日時は「公開日」「作成日」「更新日」「公開終了日」での絞り込みが可能です。タグとカテゴリについては、指定した値を「含む」検索になります。

プラグインのダウンロード、使い方は以下のページからお願いします。

今後、もう少し拡張していく予定です。

MTAppjQueryを使って記事ごとに表示するカスタムフィールドを変える

Movable Type ユーザーコミュニティの MTQ に「ブログ記事編集画面のカスタムフィールの項目をカスタマイズしたい。」という投稿を見つけました。藤本さんも MTAppjQuery プラグイン の出番だとおっしゃってるので、その方法を紹介します。

MTAppjQuery プラグインのインストールはこちらのページ(ちょっと古いです)をご覧ください。最新の情報はドキュメントも販売しております。

続きを読む

MTAppjQueryを使ってMTEntriesが使えるドロップダウンリストのカスタムフィールドを疑似的に作る

Movable Type ユーザーコミュニティの MTQ に「カスタムフィールド作成(編集)画面のMTタグ使用について」という投稿を見つけました。

MTAppjQuery プラグインを利用すれば疑似的に実現することができるので、その方法を紹介します。

MTAppjQuery プラグインのインストールはこちらのページ(ちょっと古いです(>_<))をご覧ください。最新の情報はドキュメントも販売しております。

続きを読む

jQueryでtitle要素を変更しようとするとIE8でエラーになる

HTML の <head> 内の <title> の中身を jQuery で以下のように変更しようとすると、IE8 でエラーになります(IE9, IE10 は大丈夫)。

jQuery("title").text("タイトルを変更");

このようなときは、jQuery を使わずに、

document.title = "タイトルを変更";

とすれば大丈夫です。

jQueryAutoHeight.js v0.04 - jQuery 1.9 以降に対応

当ブログで3年くらい前から公開している「jQueryAutoHeight.js - 複数のカラムの高さを最大値にそろえるjQueryプラグイン」を、jQuery 1.9 以降(1.x系)に対応させました。

動作や機能に変更はありません。

jQuery では、だいぶ前から非推奨だった「jQuery.browser」が、1.9 からとうとう使えなくなりました。

jQueryAutoHeight.js においても、IE6 を判定するのに jQuery.browser.version を使っていましたので、jQuery 1.9 以降の環境で利用するとエラーが出てしまっていました。その部分を修正しました。

あと、リポジトリを Github に変更しました。

jQueryAutoHeight.js にご興味のある方は以下のページをご覧下さい。

まだ使って頂いている方がいるようで、感謝です m(_ _)m

MTAppjQuery v1.1.0 リリース

Movable Type 6 Beta に対応した MTAppjQuery v1.1.0 を公開しました。

今回のリリースでは、

  • MTAppLineBreakField を1つの画面内で複数のフィールドに適用させたときの不具合の修正
  • MT6 でのユーザーダッシュボードの表示が崩れる不具合の修正

の2つの修正と、

  • mtappVars.status(ブログ記事やウェブページの公開・非公開のステータスを取得)の追加

を行いました。

さあ、MT6 の管理画面も MTAppjQuery でカスタマイズしましょー!

Movable Type 6 の Data API を使ってその場で記事を更新できる拡張機能を作ってみた

今日の Movable Type ハッカソンに行って刺激を受けて、Movable Type 6 の Data API を使って、管理画面に入らずにその場で記事を更新できる拡張機能を作ってみました。

いろいろ楽しみですね、Data API。(動画は音声付きです)

今まで MT に対して「なんか難しそう」とか「もう古くね?」とかいうイメージを持ってるフロントエンド・エンジニアの方、ぜひ今後は横目で Movable Type のことも見ておいてくださいね。きっと触りたくなりますよ(笑

「管理画面重いんでしょ?」っていってる方、軽い管理画面を作っちゃってください!(ちなみに PSGI にすれば速いです)

まだベータ版ですが、今後が楽しみな MT6 です!