2011-09-26

[jquery] 複数の $.get が全部終わるまで待つには

jQuery を使って、リクエストを並列に送った後、すべてのレスポンスが出そろうまで待って処理をする、ということをやりたい場合は、jQuery.when() を使います。この関数を使うと、引数に与えた複数の Deferred オブジェクトから、新しく Deferred オブジェクトを作ってくれます。

jQuery 1.5 (2011/1/31リリース) 以降で利用可能です。

jQuery.get() の返り値 jqXHR は jQuery 1.5 以降では都合の良いことに Deferred になっているので、jQuery.when() にこれをそのまま渡せばよいです。

以下の例において、arg_a, arg_b は、もともとの Deferred の done の引数リストになっているので、jQuery.get() の、success(data, textStatus, jqXHR) の data を得るためには arg_a[0] 等とする必要があることに注意します。

$.when($.get('/path_a'), $.get('/path_b')).done(function(arg_a, arg_b) {
    var a_data = arg_a[0],
        b_data = arg_b[0];

    console.log([a_data, b_data]);
});

さらに、制限時間以内にレスポンスがそろわなかった場合に失敗とするには、以下のようにすれば良いです。

var timerDeferred = $.Deferred();

setTimeout(timerDeferred.reject, 1000);

$.when($.get('/path_a'), $.get('/path_b'), timerDeferred)
    .done(function(arg_a, arg_b) {
        var a_data = arg_a[0],
            b_data = arg_b[0];

        console.log([a_data, b_data]);
    })
    .fail(function() {
        console.log('fail');
    });

2011-09-19

Yahoo!ローカルサーチAPIで最速マクドナルド案内


Fastest fastfood

Yahoo!ローカルサーチAPI で最速マクドナルド案内を作ってみました。開くだけでGeolocation APIで取得した現在位置に基づいて、最寄りの結果を表示します。

結果の表示には最近リリースされた 経路地図API を使っています。

[javascript] Google 日本語入力 API を使って郵便番号から住所を取得

Google CGI API for Japanese Input を使うと JavaScript から Google 日本語入力の変換結果を取得できるようです。

NETBUFFALO さんの記事 によると、クロスドメイン対応は JSONP 形式のレスポンスに対応しているようなのでそれを用いました。jsonpというパラメータでコールバック関数名を指定します。

var postalcode = '150-0031';

$.get('http://www.google.com/transliterate?jsonp=?&' + $.param({
    langpair: 'ja-Hira|ja',
    text: postalcode
}), function (data) {
    if (data.length === 1) {
        var address = data[0][1][0];
        console.log(['solved', address]);
    } else {
        console.log('not found');
    }
}, 'jsonp');

参考
NETBUFFALO:Google日本語入力APIでAjax IME

関連情報
郵便番号から場所と関連情報を取得する「郵便番号API」公開しました! - お知らせ - Yahoo! Open Local Platform (YOLP)

2011-09-18

[python] urllib.urlencode の引数を全て encode('utf-8') する

リスト内包表現と、urllib.urlencode が2要素のタプルのシーケンスを受け入れることを利用しました。

#coding=utf-8
import urllib

param = {
    'name': u'なまえ',
    'msg': u'こんにちは!'
}
urllib.urlencode([ (k, v.encode('utf-8')) for k, v in param.iteritems() ])

[javascript] 一日後の Date オブジェクト

現在時刻から一定時間ずれた Date オブジェクトを作るには、以下のようにコンストラクタにミリ秒を与える方法で作れば簡単です。

new Date();
// Sun Sep 18 2011 12:40:50 GMT+0900 (Japan Standard Time)

new Date(+new Date() + 24 * 3600 * 1000);
// Mon Sep 19 2011 12:40:50 GMT+0900 (Japan Standard Time)

2011-09-16

[jquery] Google Chart Tools の QR Code機能を使う

簡単に使えて便利な、Google Visualization API の Google Chart Tools: Infographics: QR Code をjQueryを活用して楽しく使う方法についての記事です。

パラメータを静的に与えれば済む場合は、このサイト ChartTool で作ると便利です。

動的に与えたい場合、foo=bar&buzz=123&...と長々と手動で書くのはしんどいですが、以下のように、jQuery.param() を活用すれば楽しく使えます。

相対プロトコル指定にしてあるので、httpsのページでもいい感じに対応できます。

$('body').append($('<img />', {
    width: 80,
    height: 80,
    src: '//chart.googleapis.com/chart?' + $.param({
        cht: 'qr',
        chs: '80x80',
        choe: 'Shift_JIS',
        chl: 'あなたの予想に反してこのQR Codeが読み取れますか?'
    })
}));

表示例 (外枠はBloggerの側のスタイルです)

[jquery] append をもっと活用する

jQueryを使っているとわりと良くある状況:例えば、$.getで持ってきた情報に基づいて div#container にJavaScriptでp要素を追加する方法についてもっと考えてみます。

リストのそれぞれについてp要素を作って追加したい場合、ループ中でひとつひとつちまちまと append や appendTo で追記していく方法もありますが、配列演算と組み合わせられるようにするため、一気にやる方法について考えてみました。

appendのドキュメント を読むと、複数の引数をとることができるようなので、これを活用します。

// 1. よくあるコード
$('#container').append($('<p />').text('foo'));

// 2. jQuery(html, props) を使う
$('#container').append($('<p />', {text: 'foo'}));

// 3. append(content, content, ...) appendは複数個の引数をとることができます
$('#container').append(
    $('<p />', {text: 'foo'}),
    $('<p />', {text: 'bar'})
);

// 3a. 関数オブジェクトのメソッドapply(context, [arg1, arg2, ...]) を使って、配列でappendします。
// $.fn.append = $.prototype.appendです。
$.fn.append.apply($('#container'), [
    $('<p />', {text: 'foo'}),
    $('<p />', {text: 'bar'})
]);

// 3b. 配列を作る部分を $.map(list, fn)に置き換えます
$.fn.append.apply($('#container'), $.map(['foo', 'bar'], function (item) {
    return $('<p />', {text: item});
}));

// 4. もしくは、appendにelementArrayを与える方法
$('#container').append($.map(['foo', 'bar'], function (item) {
    return $('<p />', {text: item})[0];
}));

この方法を使えば、良くあるデータ構造(ハッシュのリスト) からの table の動的生成も以下のように簡単に書くことができます。

var $table = $('<table />'),
    list = [
        {
            name: '佐藤一郎',
            address: '東京都新宿区',
            tel: '0312341234'
        },
        {
            name: '山田太郎',
            address: '大阪府大阪市北区',
            tel: '0612341234'
        }
    ];

$table.append($('<tr />').append(
    $.map(['名前', '住所', '電話番号'], function (item) {
        return $('<th />', {text: item})[0];
    })
));

$table.append($.map(list, function (r) {
    return $('<tr />').append($.map([r.name, r.address, r.tel], function (item) {
        return $('<td />', {text: item})[0];
    }))[0];
}));

$('#container').append($table);

/*
<table>
<tr><th>名前</th> <th>住所</th> <th>電話番号</th></tr>
<tr><td>佐藤一郎</td> <td>東京都新宿区</td> <td>0312341234</td></tr>
<tr><td>山田太郎</td> <td>大阪府大阪市北区</td> <td>0612341234</td></tr>
</table>
*/

出力例
名前 住所 電話番号
佐藤一郎 東京都新宿区 0312341234
山田太郎 大阪府大阪市北区 0612341234
前回の jQuery の記事 [jquery] jQuery(html, props)が便利 もぜひ併せてご参照ください。