JAVAスクリプト活用法

 今回は、JAVAスクリプトの「外から見えない」使い方を解説します。目立つためじゃない、ホームページを管理しやすくするためのスクリプトです。

「JAVAスクリプト」ってなに?
 って、CGI使っている人でこれを知らない人はいないと思いますが、簡単に説明しておきましょう。

 「JAVAスクリプト」。分ければ「JAVA」と「スクリプト」。
 「JAVA」は知っての通り、泣く子も黙るマルチプラットフォームプログラミング言語。ですが、JAVAスクリプトの言語としての性質はJAVAと大きく違います。このことには十分注意してください。似てはいるんですがね。
 「スクリプト」は、ほぼ「プログラミング」と同義語です。ただ、いわゆる「インタープリタ系」プログラムのことを示すことが多いです。JAVAスクリプトもそうで、実行するのにコンパイルなどを必要としません。この辺も「JAVA」と違う部分ですね。
 とゆーわけで「JAVAスクリプト」とは「JAVAに似たプログラミング言語」ということです。

 さて。
 JAVAスクリプトはCGIと違って、クライアント、つまりあなたの目の前にあるパソコンで実行されます。これには結構大きな問題があります。
 CGIの場合、どんなブラウザで見ようと実行されるのはサーバーのコンピューターです。ということは、安定しているというわけです。実行結果は常に一定というわけです。
 ところがJAVAスクリプトはそうはいきません。よーするにブラウザに依存するということです! ホームページを作っていればイヤというほど分かると思いますが(分かってないとまずいです)、ブラウザによってHTMLの解釈や見え方が変わってきます。これが、JAVAスクリプトにもあるということです

 と言っても、実際にはあまり差はないと思っていいでしょう。特別変なものを使わない限り動くはずです。でも、できるだけ、どのブラウザでも動くかどうかチェックするようにしましょう。
 ちなみにここから解説するすべてのスクリプトは「ネットスケープナビゲーター3.01」「ネットスケープコミュニケーター4.03」「インターネットエクスプローラー3.02」でちゃんと動くのを確認しています。え? ひとつ抜けてないかって? いやー、あれはちょっと、ねぇ(汗)。誰か代わりに試してくださるとうれしいです、はい。

「ローカル」かどうかのチェック
 ブラウザの中には「オフライン」モードを備え付けていないものがあります。これだけではそれほど問題はありません。そこで、以前に保存したホームページを見たとします。これも問題はありません。ところが、このページに「URL直接指定(http://なんたら)」のイメージやCGIがあると、その都度ダイヤルアップのダイアログが出たりします。これが問題で、特に「保存されることが高いホームページ」はまずいことになる可能性があります。
 そういうブラウザで使われることを考えて、そのページがローカルか否かをチェックするJAVAスクリプトを使うのがいいでしょう。スクリプトは次のようなものです。
 



// ローカルかどうかチェックします。
function IsLocal( p_strLocate )
{
	strTemp = new String( p_strLocate );
	strTemp = strTemp.substring( 0, 4 );
	if( strTemp == "http" )
		return 0;		//ローカルファイルでないなら0を返します。

	 return 1;
}

	if( IsLocal( document.location ) == 1 )	//ローカルファイルなら……
		document.write( 'Not display image.' );
	else
		document.write( '<IMG SRC="http://www.kab-studio.biz/KABLogo.gif" WIDTH="140" HEIGHT="135" ALIGN="RIGHT">' );

	

 システムとしては簡単なもので、まずdocumentオブジェクトlocationプロパティから「そのドキュメントのURL」を取得します。そのあと最初の4文字を取得して、それがhttpでないならローカルということにしています。ローカルの場合、たいがいはfileとなっているので、これでローカルかどうかばっちり分かります。
 実際に実行すると、次のような感じになります。  ホームページ上で見てるときにはイメージが表示されるでしょう。で、このホームページを保存してローカルで見れば、「Not display image.」なる文章が表示されることでしょう。
 このスクリプトの中で使われているいくつかのメソッドはこれからもよく使います。特にStringオブジェクトとそのsubstringメソッドは活躍します。憶えておいてください。
 それに、この関数自体も、これから紹介するスクリプトと組み合わせて使ってください。

「アクセスログ」との連携
 前回紹介した「アクセスログ」ですが、実際にそのページのURLを書き込んでCGIを呼び出すと、はっきり言って大変です。当然のことですが、すべてのページにおいてURLは異なります。とゆーことはページを作るごとに変えていかなければならないということです。これは大変です。
 これを簡単に処理しましょう。

// アクセスログを読み込みます。
function LoadAccessLog( strLocate )
{
	strLocate = new String( p_strLocate );
	Len = strLocate.length;
	strTemp = "";
	strUrl = "";

	for( i = 0; i < Len; i++ )
	{
		strTemp = strLocate.charAt( i );
		if( strTemp == "+" )
			strUrl += "0x2b";
		else
			strUrl += strTemp;
	}

	strRet = '<IMG SRC="cgi-bin/AccessLog/AccessLog.cgi?';
	strRet += strUrl;
	strRet += '" WIDTH="1" HEIGHT="1">';

	 return strRet;
}

	document.write( LoadAccessLog( document.location ) );
	

 先ほど出てきたdocument.locationをそのままCGIに渡してます。このコードなら、すべてのページにそのまま貼り付けるだけでちゃんと実行されます。

 このスクリプトでは、まず「+(プラス記号)」を他の文字(ここでは0x2b)に置き換えています。これは、通常+はCGIに渡されるパラメーターの分割という意味になってしまうからです。
 例えばC++Prog.htmlなるファイルのログを取る場合には、この通りのファイル名が渡されません。それを処理するというわけです。当然ログの方には変更されたあとのファイル名が渡されるので、もし気になるのなら、CGIの方で元に戻させてください。

 また、ここでちょっと注意して欲しいのが、document.write()です。これは「HTMLに書き込むメソッド」ですが、このメソッドを関数の中で使うとその関数の置かれた部分に直接書き込んでしまうという問題点があります。
 例えば、関数をヘッダーの中に入れてある場合には、そのヘッダーの中で無理矢理文字を表示しようとしてしまうのです。そこで、このように文字列を返して、それを表示するというふうにしてるわけです。

 基本的に「スクリプトを書き換えられるスクリプト」なんて少ないんで、これがフツーと言われればそうかもなーとか思ってしまいますが、まぁでもめんどくさいことには変わりないでしょう。この辺は注意してください。

リファレンスログ、そしてクッキー
 上の関数にはdocument.locationを渡していますが、これをdocument.referrerにすると直前にどのページを見ていたかが分かります。このログを組み込むことで、どこからリンクが張られているのか、どのリンクページが人気があるのかといったことが分かります。
 ただ、これははっきり言って思ったように動きません。まずIE3以下では機能しません。直前のページではなく、そのページのURL(つまりlocationプロパティと同じ)が入っています。また、リンクが張られていなくても直前のページが渡されることもあります。さらに、実はローカルファイルも……ということもあるので、あまり期待しない方がいいと思います。

 あと、バリエーションとしてクッキーを使う方法もあります。クッキーを使うことで誰が何回来てるかということをチェックすることができます。ただ、クッキーは個人的にあまり好きでないので、使いたい人は自分で調べてください。

NEXT & BACK
 今度は「前へ」と「戻る」リンクの作製です。
 Front Pageなどを使わない限り、リンクの管理は大変です。特にページが増えていくとどんどん大変になっていきます。そこで、ホームページのファイル名を簡単にして、自動的にリンク先を算出させるようにします。

 まず、ファイル名がCool07.htmlのように、文字数字2桁.htmlとなるようにしてください。もちろんスクリプトを書き換えればもっとフレキシブルになります。
 で、スクリプトは次のようになります。

//	ページのインデックスナンバーを取得します。
function GetThisIndex( locStr )
{
	//	ピリオド直前の2文字をインデックスナンバーと見なして取得します。
	FullURL = "";
	FullURL = new String( locStr );
	FullURL = FullURL.substring( FullURL.length - 7, FullURL.length - 5 );

	return eval( FullURL );
}

// ファイル名を作製します。
function GetFileName( Add, locStr )
{
	ChkStr = "";
	Chapter = new String( locStr );
	IndexNo = 0;

	//	スラッシュまで検索してファイル名を取得します。
	for( iF1 = Chapter.length; iF1 != 0; iF1-- )
	{
		ChkStr = Chapter.substring( iF1 + 1, iF1 );
		if( ChkStr == "/" || ChkStr == "\\" )
			break;
	}

	//	ファイル名のインデックスより手前を取得します。
	Chapter = Chapter.substring( iF1 + 1, Chapter.length - 7 );

	IndexNo = GetThisIndex( locStr ) + Add;
	if( IndexNo < 10 )
		Chapter = Chapter + "0" + IndexNo;
	else
		Chapter = Chapter + IndexNo;
	return Chapter;
}

// hrefタグを作製します。
function MakeRef( Add, locStr )
{
	FullURL = GetFileName( Add, locStr );	
	return '<A HREF="' + FullURL + '.html">';
}

// リンクを作製します(Codian、C+CGI用)
function MakeFB( Direct, strLocate )
{
	strRet = "";
	if( Direct <= 0 )
		strRet += MakeRef( -1, strLocate ) + "<前へ</A>";
	
	if( Direct == 0 )	
		strRet += "|";

	if( 0 <= Direct )
		strRet += MakeRef( 1, strLocate ) + "次へ></A><BR>";
		
	return strRet;
}

	MakeFB( 0, document.location );
	

 やたら長いですが、中身的には特に難しいことをしてません。
 まずGetThisIndex()で数字部分だけ抜き出して、eval()でその数字部分の文字列を整数値化します(C言語的に言えばcharからint、つまりatoi()ってことやね)。
 その値を元に、GetFileName()ではリンク先のファイルを作製します。渡されてくる文字列はURLなので最初のファイル名だけを取り出し、そのファイル名の整数値部分以下を取り除きます(つまりCool07.htmlならCoolだけにするということ)。そこに、先ほど取得した整数値を増減させ、無理矢理2桁にしてくっつけます(Cool08とかCool06とかになります)。
 くっつけたものにMakeRef()でリンク形式にし、MakeFB()で使える形に成型して返します。で、それを出力するというわけです。

 結果は……いいですね。このページの一番最後とか、Codianのページとかはすべてこれにしてあります。

他フレームの関数を呼び出す
 でも、このスクリプトをすべてのページに埋め込むのはかなり大変です。そして何より、メンテナンスが大変になります。
 プログラムの基本は同じコードを書かないことです。同じことをするプログラムが至る所にあると、ひとつ修正を加える度にすべて変更しなければならなくなります。手間と時間が掛かり、さらにバグの出る可能性が無茶苦茶アップします。
 それを防ぐため、コードはパッケージ化するのが基本です。ですが、JAVAスクリプトでは外部ファイルを読み込むことができません。そこで、フレームを利用します

 JAVAスクリプトの関数は、そのフレームのメソッドのように振る舞います。それを利用して、次のようなスクリプトを書くことができます。

	if( window.parent.frames.length != 0 )
		if( window.parent.frames[0].document.title == "menubar" )
			document.write( window.parent.frames[0].MakeFB( 0, document.location ) );
	

 まずwindow.parent.frames.lengthプロパティで、今表示されているページの親フレームがいくつフレームを持っているかチェックします。これで「今フレームとして表示されているかどうか」を調べることができます。ローカルに保存して一枚のページとして表示しているときには何も処理させないようにするというわけです。
 次にwindow.parent.frames[0].document.titleプロパティで、関数本体があるページのタイトルをチェックします。ここでは上のメニューバーページのタイトルをチェックしています。これは「他のページが読み込まれていないか」をチェックすると同時に、「そのページがすでに読み込まれているかどうか」もチェックします。

 良くあることですが、ちゃんとファイルはあるのにブラウザにページが送信されない場合があります。今回のように「他のページに関数がある」場合、当然関数本体のあるページは先に読み込まれている必要があります。そのためのチェックを怠らないようにしてください。

 最後に、他フレームの関数(ここでは「<前へ|次へ>」リンクを作製するMakeFB())を呼び出しています。このように、あっけなく他フレームの関数を呼び出すことができるというわけです。
 ここで、document.locationプロパティを渡していることに注目してください。ここまでに紹介してきた関数は、すべてこのプロパティを受け取る形にしています。そういった関数設計なのは、すべてこういった使い方をするためというわけでした。

 さて、実はこのシステムにはいくつか問題があります
 まず、この機能はスクリプトが実行されない可能性があるということです。「関数本体のあるページがまだ読み込まれていない場合」や「ローカルで見る場合」には、スクリプトが実行されません。
 実は、前者の場合にはあまり問題はありません。エラーが発生するのは最初に開くページだけですから。ところが、後者はちょっと気を付ける必要があります。

 このシステムを使うと、実はホームページ作りがかなり楽になります。ホームページのタイトルやテーブル部分など、「多くのページで共通する部分」というのは結構あります。通常はすべてのページにそれを書き込むわけですが、このシステムを使うとすべて自動で共通化できるようになります。「ちょっとテーブルの背景色を変えたいなー」とか思った時にも、関数本体の数値をちょっと変えるだけですべてのページが変更されます。
 ところが、これは結構まずいことになります。というのも、ローカルで見るとスクリプトが実行されないからです。多くのブラウザは、JAVAスクリプトもそのまま保存します。つまり結果だけを残すようなことはしないのです。そのため、最悪の場合、とても見れたものじゃないページになる可能性が大になるというわけです。

 これの問題に対する対処法は3つあります。ひとつはこのシステムを使わないことです。単に手間が掛かるだけ、と割り切ってしまうわけです。ふたつめは併設することです。つまりどちらの場合にも対処する、というわけです。でもこれはあんまり意味がありませんね。「JAVAスクリプトを使うときれいに見える、使わなくても一応見える」くらいに差を付ければ、それほど大変じゃないかもしれませんが。最後に無理矢理使う、乱暴な方法ですが実はこのページはそういうポリシーにしています。といっても最後の「<前へ|次へ>」リンクだけです。これにする場合には「スクリプトが実行されなくてもさして問題ない」、もしくは「保存される可能性が無茶苦茶低い」と考える時のみにしましょう。
 実際、この辺の兼ね合いは難しいので、TPOに合わせて自分で書き換えてください。

 また、実はこの機能、明確にドキュメントとして読んだわけではありません。もしかしたら使っちゃいけない機能なのかもしれませんが、多分英文のちゃんとしたリファレンスには載っている……と願いますし、まーIEでもねすけでも動くんですから大丈夫でしょう。

全部組み合わせると……?
 以上の機能すべてを組み込んだのが、KAB−studioのホームページです。実際にどんな使われ方をしているのかは、各ページを保存してチェックしてみてください(「ソースを見る」だと、スクリプトの中身が表示されない場合があります)。
 はっきり言ってちょっと怖いです。JAVAスクリプトの場合、ホントに動いているのか、チェックするのには限界があるのできついものがあります。「まぁ動くだろう」という余裕、「動く状態かチェック」というエラー回避の充実、「動かなくても大丈夫」というあまり重要な部分を任せないこと、といった部分が重要になってくるのではないでしょうか。

 
(C)KAB-studio 1998 ALL RIGHTS RESERVED.