JavaScriptでcookieを使う話(改訂版)
JavaScriptでcookieを使う話の改訂版である。
2年も昔に、JavaScriptのこともよくわからずに、様々な資料を引っ掻き回しながらプログラムを書いた。それはきちんと動作はしたし、そのときはそれで満足だった。
しかし、時間がたち、多少なりとも経験を積むと、昔書いたプログラムの変なところや無駄なところが目に付いてしょうがなくなってしまう。特に、このプログラムについては自分でもかなり納得のできないものになっているし、説明にも変なところがある。そこで、新たにコードと解説を書きなおしたというわけだ。
以前のものはもう削除したので比較することはできないのだが、ずいぶんとすっきりしたプログラムになっている。2年の間に、私がどう変わったか、なんてことはどうでもいいことだが、より新しくなったコードは有用ではないかと信じる次第である。
掲示板などのCGIでcookieを使う場合、たいていの場合はCGIが直接cookieを処理する。
誰かがそのCGIに書き込みなどをしたとき、名前やメールアドレスをcookieとして記録し、次にそのCGIにアクセスしたときに、そのcookieデータをCGIが取得して、フォームの初期値に「value="なんたらかんたら"」というように使用するのだ。
しかし、この形式でcookieを使う場合、フォームを呼び出されるときに必ずCGIが動かなければならない。
つまり、HTMLファイルを出力するタイプの掲示板では使用できないのだ。
すでに出力されたHTMLファイルからcookieを使う方法はないだろうか?
ある。
JavaScriptを使えばいいのだ。
では、理論編(なにがどーなってなにををどーするのか)と、実践編(具体例とその解説っぽいもの)にわけて、話を進めることにしよう。
理論編:なにがどーなってなにをどーするのか
1、cookieの書式とかなんとか。
cookieには、文字列以外にも情報が付加される。
cookieを保存する期間(通称:賞味期限)、cookieを記録したURL、cookieの名前、などがくっついてくるのだ。
実際のcookieを見たかったら、ブラウザの設定で、cookieを受け入れる前に警告するようにするといい。
ブラウジング中に、いろいろなcookieをもらうことができるはずだ。
また、ブラウザをインストールしてあるフォルダに、cookies.txtとかがあると思うので見てみるのもいいだろう。
なお、このファイルをエディタで修正しようとすると、cookieがすっきりなくなったりするので注意。
で、まあ、具体的には、
「name=文字列」「name2=文字列2」
などという形式でセーブされて、
それを呼び出してくると、
「name=文字列; name2=文字列2; name3=文字列3; name4=文字列4;」
とかいう形でロードされてくる。
というふうに理解しておけばいいんじゃないだろうか?
2、cookieで情報を保存したりする。
cookie使用の第1歩、とりあえずcookieで情報を保存する方法だ。
JavaScriptだから、
document.cookie="なんたらかんたら";
とか書いて保存する。
具体的な書式については後程ということで。
3、cookieで情報を呼び出したりする。
で、cookie使用の第2歩であり、もしかしたら最終目的、cookie情報を反映させる方法である。
基本的には、
string=document.cookie;
とか書いてやればいいのだが、こうやって書くとstringという変数にcookieの中身が全て代入される。
さっきの例でいうところの
「name=文字列; name2=文字列2; name3=文字列3; name4=文字列4;」
っていうのが全部代入されるのだ。
ここから、nameの値をつかって、必要な値を抽出する作業が君を待っている。
その具体的なやり方はやっぱしまた後程。
4、呼び出したりした文字列を使うとか。
ともかく、JavaScriptの変数に代入してしまえばこっちのものだ。
document.フォームの名前.要素の名前.value=string;
とか書いてテキストボックスにつっこんでやればいい。
まあ、あるいは、その文字列で分岐して違う処理をさせてみてもいいし、だいなみっくHTMLな気分で画面内を飛び回らせたりしても構わない。(飛び回らせてどうするかは知らないが・・・)
実践編:具体例とその解説っぽいもの
実際に動作するJavaScriptのプログラムを掲示して、それを解説してみよう。
とりあえず動作するものがこちら。
「記録」でテキストボックスの内容をクッキー情報として保存して。
「呼び出し」でそれを呼び出してテキストボックスに表示する。
「りせっと」はフォームのリセットボタン、type="reset"だ。
ブラウザの設定で、cookieを受け取る前に警告するようにしておいて、何か文字列を書いて記録ボタンを押す。
もちろん、JavaScriptも有効にしておく必要がある。
すると、cookieを送ってくる(完全にあなたのマシンローカルで行われているのだが)1日で消えてしまうようなものなので、とりあえず受け入れてもらいたい。
さて、りせっとボタンを押して、内容を消してから、
呼び出しボタンを押すと、さっきの内容がフォームに書き込まれる。
一度別のページを見たり、ブラウザを閉じてから、(1日以内に)
また同じページを開いても、やはり内容がフォームに書き込まれる。
さて、このプログラムについて解説していこう。
で、ソースと解説はこんな感じ。
<html>
<head>
<title>JavaScriptCookie</title>
<script language="JavaScript">
<!--
JavaScriptを使うときのお約束。
JavaScript非対応ブラウザのために、<!--と書いておく。
本当はブラウザのバージョンチェックなどもする方が無難だが。
ckary = new Array();
配列ckaryの宣言。
function setck(){
cookieを保存したりするfunction(関数):setck()の宣言。
ckary[0] = document.forms[0].usr.value;
ckary[1] = document.forms[0].eml.value;
ckary[2] = document.forms[0].url.value;
フォームに記入された値を配列ckaryに代入。
//alert('◎フォームの内容\n'+ckary[0]+' '+ckary[1]+' '+ckary[2]);
動作テスト用alert。//でコメントアウトしてるから、実際は動作しない。
exp=new Date();
新規Dateオブジェクトexpを作成。デフォルトでは現在時間を持つ。
exp.setTime(exp.getTime()+1000*60*60*24*1);
現在時間に、1日分(JavaScriptの時間単位は1/1000秒)足したものを、Dateオブジェクトexpに設定する。
ckstr = escape(ckary[0]);
変数ckstrに、配列ckaryの最初の値をESCAPEしたものを代入。
escape()は記号やマルチバイト文字などを%##(##は文字コード)というような形に置換した値を返す。
フォームを送信する場合などにブラウザが行う処理と同様である。
ちなみに、ブラウザによって返す値は異なるので注意。(NN4はS-JISのコード、IE5はUTF-16のコード、など)
文字コードの話を参照のこと。
for (i=1;i < ckary.length;i++){
ckstr += "%00" + escape(ckary[i]);
}
ckaryの全要素について、ループ内の処理を実行する。
このループで、変数ckstrに、%00とESCAPEされた配列ckaryの値を連結する。
%00はヌル文字をESCAPEしたものであり、
通常、フォームに入力された文字列をESCAPEしても出てくることはないので、
区切り記号として利用している。
結果として、
ckstr = escape(ckary[0]) + "%00" + escape(ckary[1]) + "%00" + escape(ckary[2]);
という処理を行ったことになるが、変数が配列なぶん、汎用性が高い。
//alert('◎ESCAPEされた文字列'+ckstr);
動作テスト用。
document.cookie = "ASH_jsc=" + ckstr + "; expires=" + exp.toGMTString();
クッキー情報を書き込む、ASH_jscというのは単なる名前、
呼び出す際に必要になる。勝手につけても問題ない。
expires=で、cookieの賞味期限を設定している。
ここではさっきexpに設定した現在の1日後になる。
標準形式に変換する必要があるのでtoGMTstring()を用いている。
}
setck()はここまで。
function getck(){
cookieを呼び出したりする関数getck()の宣言
//alert('◎cookie文字列全体\n'+document.cookie);
動作テスト用。
cklng = document.cookie.length;
cookie文字列全部の長さ。理論編の例で言うところの
「name=文字列; name2=文字列2; name3=文字列3; name4=文字列4;」
全部の長さ。
ckary = document.cookie.split("; ");
配列ckaryに、cookie文字列を"; "(セミコロン、スペース)で区切って配列に代入する。
これで『name=文字列』が配列の各要素に代入される。(ckaryは使いまわし)
ckstr = "";
ckstrの中身を空文字列に設定しておく。(ckstrも使いまわし)
下のループでckstrがちゃんと設定されていないと、
後でckstr.split("%00")するときエラーになるため、あらかじめ代入してある。
i = 0;
次のループのための準備。
while (ckary[i]){
if (ckary[i].substr(0,8) == "ASH_jsc="){
ckstr = ckary[i].substr(8,ckary[i].length);
break;
}
i++;
}
このループで、必要な文字列を抽出している。
ckaryの各要素(「name=文字列」)に対して、最初の8文字が「ASH_jsc=」かどうかをチェックし、
そうであれば残りの部分を取り出してckstrに代入する。
代入されたら、breakでループを直ちに終了する。
//alert('◎抽出された文字列\n'+ckary[i]);
おなじみ、動作テスト用。
ckary = ckstr.split("%00");
配列ckary(また使いまわし)に、抽出した文字列を%00で区切ったものを代入する。
ckstrがちゃんと定義されていないとエラーが発生する。
if (ckary[0]) document.forms[0].usr.value = unescape(ckary[0]);
if (ckary[1]) document.forms[0].eml.value = unescape(ckary[1]);
if (ckary[2]) document.forms[0].url.value = unescape(ckary[2]);
文字列をUNESCAPEしたものを、フォームに書き込む。unescape()は、escape()の逆の処理を行う。
各文字列が空だったらなにもしない。
}
getck()ここまで。
// -->
</script>
スクリプト終了。
</head>
<body bgcolor="#ffffff" onLoad="getck()">
ページが読み込まれたらcookie情報を呼び出す。
<form>
<input type="text" name="usr" size="40"><br>
<input type="text" name="eml" size="40"><br>
<input type="text" name="url" size="40"><br>
<input type="button" value="記録" onClick="setck()">
記録ボタンを押したときcookie情報を保存する。
<input type="button" value="呼び出し" onClick="getck()">
呼び出しボタンでcookie情報を呼び出す。
<input type="reset" value="りせっと">
フォームの中身を初期値(valueで指定した値)に戻す。
</form>
</body>
</html>
|
このソースを適当な名前をつけて保存してやれば、完全にローカルでも動作が可能だ。
サーバとやりとりをしなくてもいいことが、JavaScriptの最大のメリットの1つだからだ。
なお、動作試験はNetscapeNavigator4と、InternetExplorer5で行っている。残念ながら、古いバージョンのブラウザでテストするのは困難な現状になってしまっているので、動作チェックは不充分だ。もし、古いブラウザでテストし、エラーなどが出た場合は報告していただければ幸いである。
実験の際は、あちこちにある動作試験用のalert文を動かすのも手だ。//でコメントされているので、//を消去してやれば動作する。実際にどういう処理がされているのか、理解しやすくなると思う。
解説はこのくらいで終わり。理解できたひとも理解できてないひともごくろうさまでした。このページについての疑問質問意見その他はメールか掲示板でどうぞ。
理論よりも実践に偏っているので、cookieやJavaScriptについての詳しい仕様などは書いてない。探せばもっとちゃんとした解説ページもあるので、興味のある方は探してみるのがいいだろう。
なお、このスクリプトは「はしもと@ASH」の制作したものである。
ここまでソースを公開したら、これを参考にして(一部をコピー&ペーストで切り貼りしたりて)オリジナルのcookie処理スクリプトを作るのは簡単だと思う。
もし、このページが何かの参考になったのなら、感謝のメールでも出してくれると幸いである。
なお、お礼はカタチのあるものでも一向に構わない(笑) 送り先はこちらの通り。
では、また会う日まで。