2006年09月24日 16:00 [Edit]

javascript + perl - yubin2jsonp

どうせなら、JSONPを使ってどこにでも設置できたらいいじゃんと思ったのでこんなのこさえました。

[Ajax] CGI不要の郵便番号→住所変換フォーム  Kawa.net Blog /ウェブリブログ
JavaScript のみで稼動するため、サーバサイドで稼動するCGIプログラムは不要です。

こんな感じです。


〒(7けた)
都道府県
市区町村
町域以降

HTMLまで含めたsourceはこんな感じです。

<script>
function Yubin2JSONP(root){
  this.root = root;
  this.parse = function(yubin){
    if (! yubin.match(/[0-9]{7}/) ) return;
    var yubin3 = yubin.substr(0,3);
    var script = document.createElement('script'); 
    script.id = this.root + yubin3 + '/' + yubin + '.js';
    script.charset = 'UTF-8';
    script.src = script.id; 
    document.lastChild.appendChild(script); // jsonp is invoked here
    // document.lastChild.removeChild(script); // cleanup; not mendatory
  };
  return this;
}
var yubin2jsonp = new Yubin2JSONP('http://www.dan.co.jp/~dankogai/yubin2jsonp/');

function $(id){ return document.getElementById(id) }
function _(evt){ return evt.target || evt.srcElement }
function parse_yubin2jsonp(json){
  $('addresses').innerHTML = '';
  for (var i = 0; i < json.length; i++){
    $('addresses').innerHTML += '<option value="' + json[i].join(",") + '">'
      + json[i].join("") + '</option>';
  }
  
  select_address(json[0]);
}
function select_address(arg){
  var a = arg.join ? arg : arg.split(',');
  $('todofuken').value   = a[0];
  $('shikuchoson').value = a[1];
  $('choiki').value      = a[2];
}
</script>
<div style="border: dotted 1px; padding: 0.25em">
<br>
<table>
<tr><th>〒(7けた)</th><td>
<input id="yubin" type="text" size="7" maxlength="7"
 onkeyup="yubin2jsonp.parse($('yubin').value)">
<select id="addresses" onchange="select_address(_(event).value)"></select>
</td>
<tr><th>都道府県</th><td><input id="todofuken"   type="text"></td></tr>
<tr><th>市区町村</th><td><input id="shikuchoson" type="text"></td></tr>
<tr><th>町域以降</th><td><input id="choiki" type="text"></td></tr>
<tr></tr>
</table>
</div>

要は、http://www.example.com/yubin2jsonp/100/1000001.jsをJSONPで取ってきてparse_yubin2jsonp()でparseすると。parse_yubin2jsonp()の中身を書き換えればカスタマイズできるというわけです。Ajaxと違って、jsとhtmlが違うドメインにあっても問題ありません。

送られてくるjsonpはこんな風になっています。

parse_yubin2jsonp([['東京都','千代田区','千代田']]);

なんとこれ、全部静的コンテンツです。サーバー側の準備は、これを置いとくだけ。

以下が、郵政省の「読み仮名データの促音・拗音を小書きで表記したもの」にあるCSVファイルから静的jsonpを自動生成するためのperl scriptです。Perl 5.8があれば、外部モジュールなしで利用できるはずです。

これを使うのもめんどいという方は、

から持ってきて好きな所に転がしておいてもかまわないですが、なるべく生成scriptで適宜生成することをお薦めします。

make_yubin2jsonp.pl
#!/usr/local/bin/perluse strict;
use File::Path;

my $root = 'yubin2jsonp';
$|=1;
my $csv = shift;
my %yubin2jsonp;

open my $rfh, "<:crlf:encoding(sjis)", $csv or die "usage: $0 ken_all.csv";
while(<$rfh>){
    chomp;
    my @field = map {s/\A\"//; s/\"\z//; $_ } split /,/, $_;
    my $yubin7 = @field[2];
    $yubin2jsonp{$yubin7} ||= [];
    push @{ $yubin2jsonp{$yubin7} }, [ @field[6..8] ];
    print "read: $yubin7\r";
}
close $rfh;

-d $root or mkpath $root or die "$root : $!";
open my $wfh, ">", "$root/.htaccess" or die "$root/.htaccess : $!";
print $wfh qq(AddType "application/x-javascript; charset=UTF-8" .js\n);
close $wfh;

for my $yubin7 (sort keys %yubin2jsonp){
    my $yubin3 = substr($yubin7,0,3);
    my $d = "$root/$yubin3";
    unless (-d $d){
        print "making $d/\r";
        mkpath $d or die "$d : $!";
    }
    my $f = "$d/$yubin7.js";
    open my $wfh, ">:utf8", $f or die "$f : $!";
    my @items;
    for my $item ( @{ $yubin2jsonp{$yubin7} } ){
        push @items, join ",", map { qq('$_') } @$item;
    }
    my $rhs = join ",", map { qq([$_]) } @items;
    print $wfh qq(parse_yubin2jsonp([$rhs]);\n);
    close $wfh;
}
print "\n";
__END__

Enjoy!

Dan the Javascripting Perl Monger


この記事へのトラックバックURL

この記事へのトラックバック
http://jsonp.yatena.com/ 実際のJSONPデータをご覧頂ければわかりますが、callbackの関数名はkakaku_wsとなっております。 http://blog.livedoor.jp/dankogai/archives/50639200.html 送られてくるjsonpはこんな風になっています。 parse_yubin2jsonp(’東京都’,’千代田
[jsonp] 関数名固定のコールバックをJSONPと言うことについて【snippets from shinichitomita’s journal】at 2006年10月01日 13:07
AjaxZip 2.0 - Ajax郵便番号→住所自動入力フォーム(CGI不要版) これ見て勉強しよっと (tags: ajax zip address library) 404 Blog Not Found:javascript + perl - yubin2jsonp こんなのもありました。 (tags: ajax zipcode jsonp) ...
links for 2006-09-25【オラオラ】at 2006年09月26日 06:22
この記事へのコメント
ありがとうございます。
JSONPとみせかけて、実は form の action 属性を書き換えるスクリプトを忍ばせておくとか。
郵便番号だけでなくてフォーム内の全情報を引っこ抜けそう。(悪知恵)
Posted by ゆうすけ at 2006年09月24日 17:43