2006年5月21日日曜日

OOなJavaScriptの勉強がてら、ボタンの2度押し禁止機能を簡単に実現するライブラリを作ってみました

ちょっと時代に乗り遅れている気もしますが、最近prototype.jsをつかったOOなJavaScriptを書くのにはまっています。

今日はbindとbindAsEbentListenerの勉強がてら、これまたかなり昔話題になった「2度押し禁止ボタン」を実現するコードを書いてみました。

input.js

使い方はこんな感じです。

>

 // prototype.jsとinput.jsをロードします。
 <script type="text/javascript" src="/path/to/prototype.js"></script>
 <script type="text/javascript" src="/path/to/input.js"></script>
 <script type="text/javascript"><!--
 // windoのロード時に2度押し禁止機能を有効にします。
 Event.observe(window, 'load', function(){
  // ボタンのIDか要素のオブジェクトを渡せばクリックすると押せなくなります。
  new Input.DisableAfterClick('myButton');
 }, false);
  --></script>
<

ボタンのテキストを変えたい場合は2番目の引数に代替テキストを渡します。
画像の場合は代替画像のURLを渡します。
>

new Input.DisableAfterClick('mySubmitButton2', '送信中です');
new Input.DisableAfterClick('myImageButton2', '/path/to/image2.gif');
<

一定時間経過後にボタンを再度有効にしたい場合は、3番目の引数に有効にするまでの時間をミリ秒単位で渡します。
>

new Input.DisableAfterClick('myButton', '1秒後にまた有効になります', 1000);
<

サンプルページにサンプルがあります。

また、input.jsの中身はこんな感じです。画像ボタンの扱いはもっといい方法があるのかなーとも思うんですが、おかしなところがあったら突っ込んでください。

>

var Input = new Object();
Input.DisableAfterClick = Class.create();
Input.DisableAfterClick.prototype = {
initialize : function(input, alt, timer){
this.input = $(input);
this.alt = alt;
this.timer = timer;
this.org = this.input.type == 'image'
? this.input.src
this.stopEvent = this._stopEvent.bindAsEventListener(this);

Event.observe(this.input, 'click', this.disable.bind(this));
},
disable : function() {
this.input.blur();
if (this.input.type == 'image'){
if ( this.alt )
this.input.src = this.alt;
Event.observe(this.input, 'click', this.stopEvent);
} else {
if ( this.alt )
this.input.value = this.alt;
this.input.disabled = true;
}
if (this.timer)
setTimeout(this.enable.bind(this), this.timer);
},
enable : function() {
if (this.input.type == 'image'){
if ( this.alt )
this.input.src = this.org;
Event.stopObserving(this.input, 'click', this.stopEvent);
} else {
if ( this.alt )
this.input.value = this.org;
this.input.disabled = '';
}
},
_stopEvent : function (evt) {
evt.stop();
return false;
}
};

<

2006年5月18日木曜日

CentOS4.3なローカル開発環境がでけた

もう2週間も前になりますが、なかなか時間がなくて作れなかったローカルな開発環境をゴールデンウィークを利用して構築しました。Vmware Player上でCentOS4.3を動かしてます。
CentOSのデフォルトのロケールがja_JP.UTF-8なので、UTF-8な環境の構築も行いました。
さらに、今までbashを使ってたんですが、zshに変更しました。

それにしても環境構築まで長かった。。

最初、colinuxにCentOS4.3を入れようと思って「coLinux 用 インストーラ」を使って、はじめたんですが、OSのインストールに時間がかかるかかる。。最初はスムースに行くんですが、ちょっとすると、真っ青な画面になって、まったく動かなくなりました。固まっちゃったのかなと、何度かインストールをやり直してみましたが、やっぱり、青い画面でとまるので、そのまま放置して寝てみることに。
8時間くらい寝て、起きた後、画面を見てみると、ちょっとインストールが進んでいました。とまっているわけではないのだなと、さらに放置しておいたのですが、なかなか終わる気配がありません。。結局インストール完了するまでに、2日くらいかかりました。。ここまで我慢してがんばってきたんですが、起動してみるとネットワークカードを認識しない。。いろいろ試してみたんですが、うまくいかなかったので、Vmwareでも試してみるかとなりました。

Vmwareへのインストールはすんなりいって、今までの苦労はナンだったんだという感じですが現在が快適なのでよしとします。



2006年4月29日土曜日

Apache::RequestからPOSTデータがとれない!?

うおーーーーー、Apache::RequestからPOSTデータがとれない!!なぜだーと小一時間悩んでいたら、こんなコード書いてました。

>

sub handler {
my $r = Apache::Request->new(shift)
my @keys = qw(foo bar baz);
for my $key ( @keys) {
my $val = $r->param($_);
warn "$val\n";
}
}
<

原因に気づいて愕然としました。。。

2006年4月20日木曜日

livedoor Reader いい!

先日ベータ版がリリースされたlivedoor Readerを使ってみました。

恐ろしく快適です。
記事をバックグラウンドで先読みしてくれていて、動作が軽快です。
さらに、キーボードショートカットが超便利。
s,a,j,k,spaceを使えば記事を次々読んでいけるし、気になる記事はpでピンをうっておいて、oで別ウィンドウで表示できる機能は恐ろしく便利です。
まら、oで別ウィンドウを開く際、ブラウザのポップアップブロックで別ウィンドウが開けないと、その旨をメッセージ欄で教えてくれたり、IMEがオンになっている状態でショートカットキーを使おうとすると、ショートカットを使うにはIMEをOFFにしてくださいと親切に教えてくれます。すごく細かいところまで作りこまれているなーと感動しました。

なんてことをやっていたら、午前中が終わってしまった。。



LWPのバージョンあげたらファイルアップロードが遅くなった

ここ最近AtomPPを使ったサービスを作っているんですが、そのためにXML::Atomをインストールしたら、LWPを使って10MBくらいの大きいファイルをアップロードすると異常に時間がかかるようになってしまいました。
アップロード時のサーバの様子を見ているとメモリとCPUをやたらと消費しているようです。

LWPのドキュメントを読んでいるとHTTP::Request::Commonのドキュメントに$DYNAMIC_FILE_UPLOADをTRUEにセットすれば大きなファイルをメモリをあまり使わずにアップロードできるよと書いてあったので、これをTRUEにしたところ、劇的にアップロードの時間が短縮されました。

めでたしめでたし。





2006年4月15日土曜日

Sledge::Plugin::FormValidator::Simple-0.02

Sledge::Plugin::FormValidator::Simpleを0.02にバージョンアップしました。



Sledge::Plugin::FormValidator::Simple-0.02



0.01ではリダイレクト先やプロファイルをメソッドを定義することで変更できるようにしていましたが、あんまりかっこよくない気がしたので、メンバ変数として定義するようにしよう変更しました。

それと、valid_before_foo, valid_after_fooを定義することができるようにしました。
使い方はこんな感じです。

>

sub valid_before_foo {
my $self = shift;

# change profile by query param.
if ( $self->r->param('step') == 2 ) {
$self->validator->profile_name($self->profile_name . ".step2");
}else {
$self->validator->profile_name($self->profile_name . ".step1");
}

# change redirection when error is found.
$self->validator->redirect_url('/');
}

sub valid_after_foo {
my $self = shift;
my $results = $self->validator->results;
if ( found some error... ) {
$results->set_invalid('param3' => 'MY_ERROR');
}
}

<

JavaScriptでのバリデーションはまた後日対応したいです。

2006年4月13日木曜日

WSSE認証で使用するパスワードにハッシュ化した文字列を使うのはどうか?

ここ最近APIの認証について、考えてます。

AtomAPIの認証として事実上標準的に使われているWSSE認証ですが、APIを提供しているサービスにログインするためのパスワードとAPIの認証用パスワードを共通にした場合、APIを利用するクライアント側に生のパスワードを持たせる必要があるので、APIを利用したサービスでパスワードがもれた場合、そのパスワードを使って、提供側のサービスにもログインできてしまうということになりえてしまいます。

かといってサービスログイン用のパスワードと、API認証用のパスワードを別々に設定するようにすると、ユーザはパスワードを二つ覚えておく必要があるので、ちょっと、めんどくさーとか、わすれたーとなってしまいそうです。

そこで、パスワードは1つで済んで、APIを利用する側のアプリでパスワードがもれたりした場合も、本サービスではそのパスワードを使ってログインできないようにする方法として、APIで使用するパスワードは生のパスワードをハッシュ化したものを使うというのはどうだろうかと考えています。

こうしておけば、APIを利用するアプリ側も生パスワードを持たなくて済むので、なんとなく気持ちが楽になるのかなと。結局ハッシュ化した文字列がパスワードのかわりになるだけなので、これがもれるとAPIの認証はできてしまうんですが、APIで触れる範囲はログインしてできる範囲より小さいと考えられるので、被害は小さくなるのかなと思いました。