更新日: 2024年9月22日


I. 人生の余技として作成したプログラム(2)

4. Perl

自前のホームページを作って1年くらい経つと、アクセスカウンタを付けたくなります。1997年当時も出来合いのカウンタは色々出回っていましたが、「ページビュー」では水増しだと感じました。リロードしてもバックしてもカウントするというのでは、どう考えても実際の訪問者数とはかけ離れてしまいます。色々と考えた末、カウントの基準は何人目ですか?の冒頭に掲げた通りとしました。この運用は今も変えていませんが、グーグって目的のページに直接アクセスするのが当り前になったので、かなりのカウント漏れが発生していると思います。逆に検索エンジンのクローラーロボットが来訪してカウント数が急激に増えたこともあります。

この当時、CGIでカウンタを自作するとなればPerlの一択です。それが以下に示すプログラムで、これも作成した時のままです。上記の「何人目ですか?」の他にトップページにも累計来訪者数が記載されており、それぞれ英語と日本語のページがあるので合計4つのHTMLファイルをカウントする度に書換えるという力技です。6~80行目でcount.html、81~97行目でindex.html、98~140行目でcount_j.html、141~157行目でindex_j.htmlを書換えたワークファイルを作成し、158~161行目でオリジナルファイルに上書きコピーしています。

コードの表示にはPrism.jsを使用しています。
prism.cssの設定は団塊爺ちゃんの備忘録を参考にしました。

#!/usr/local/bin/perl4
$goto = $ENV{'QUERY_STRING'};
system("/bin/date >> counter");
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$flag = 0;
$in = 'count.html';
$out = 'work1';
if(open(IN,"$in") && open(OUT,">$out"))
	{
	while(<IN>)
		{
		if(?count =?)
			{
			($name, $count) = split(/ = /, $_);
			$count++;
			print OUT "count = $count\n";
			}
		elsif(?weeks =?)
			{
			($name, $weeks) = split(/ = /, $_);
			($sec1,$min1,$hour1,$mday1,$mon1,$year1,$wday1,$yday1,$isdst1) = localtime(856753200+$weeks*7*24*60*60);
			if(($year<$year1) || ($yday<$yday1))
				{
				print OUT "$_";
				}
			else
				{
				$flag = 1;
				$weeks++;
				print OUT "weeks = $weeks\n";
				}
			}
		elsif(?subcount =?)
			{
			($name, $subcount) = split(/ = /, $_);
			if($flag==0)
				{
				$subcount++;
				print OUT "subcount = $subcount\n";
				}
			else
				{
				$subcount = 1;
				print OUT "subcount = $subcount\n";
				}
			}
		elsif(?FINAL WEEK?)
			{
			if($flag==0)
				{
				print OUT "$_";
				$_ = <IN>;
				print OUT "$_";
				$_ = <IN>;
				}
			else
				{
				$_ = <IN>;
				print OUT "$_";
				$_ = <IN>;
				print OUT "$_";
				print OUT "<!--FINAL WEEK-->\n";
				($sec2,$min2,$hour2,$mday2,$mon2,$year2,$wday2,$yday2,$isdst2) = localtime(856753200+($weeks*7-1)*24*60*60);
				@mons_e = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul','Aug', 'Sep', 'Oct', 'Nov', 'Dec');
				$mon1_e = $mons_e[$mon1];
				$mon2_e = $mons_e[$mon2];
				$year2 = $year2+1900;
				print OUT "<TH>$mon1_e $mday1 - $mon2_e $mday2, $year2</TH>\n";
				}
			print OUT "<TH>$subcount</TH><TR>\n";
			$_ = <IN>;
			print OUT "<TH>Total</TH><TH>$count</TH>\n";
			}
		else
			{
			print OUT "$_";
			}
		}
	close(OUT);
	close(IN);
	$in = 'index.html';
	$out = 'work2';
	if(open(IN,"$in") && open(OUT,">$out"))
		{
		while(<IN>)
			{
			if(?var count?)
				{
				print OUT "var count = $count;\n";
				}
			else
				{
				print OUT "$_";
				}
			}
		close(OUT);
		close(IN);
		$in = 'count_j.html';
		$out = 'work3';
		if(open(IN,"$in") && open(OUT,">$out"))
			{
			while(<IN>)
				{
				if(?FINAL WEEK?)
					{
					if($flag==0)
						{
						print OUT "$_";
						$_ = <IN>;
						print OUT "$_";
						$_ = <IN>;
						}
					else
						{
						$_ = <IN>;
						print OUT "$_";
						$_ = <IN>;
						print OUT "$_";
						print OUT "<!--FINAL WEEK-->\n";
						$mon1++;
						$mon2++;
						$year1 = $year1+1900;
						$nen = '年';
						$gatsu = '月';
						$nichi = '日';
						$nichikara = '日~';
						print OUT "<TH>$year1$nen$mon1$gatsu$mday1$nichikara$mon2$gatsu$mday2$nichi</TH>\n";
						}
					print OUT "<TH>$subcount</TH><TR>\n";
					$_ = <IN>;
					$goukei = '合  計';
					print OUT "<TH>$goukei</TH><TH>$count</TH>\n";
					}
				else
					{
					print OUT "$_";
					}
				}
			close(OUT);
			close(IN);
			$in = 'index_j.html';
			$out = 'work4';
			if(open(IN,"$in") && open(OUT,">$out"))
				{
				while(<IN>)
					{
					 if(?var count?)
						{
						print OUT "var count = $count;\n";
						}
					else
						{
						print OUT "$_";
						}
					}
				close(OUT);
				close(IN);
				system("/bin/cp work1 count.html");
				system("/bin/cp work2 index.html");
				system("/bin/cp work3 count_j.html");
				system("/bin/cp work4 index_j.html");
				}
			}
		}
	}
print "Content-type: text/html\n\n";
if(open(IN,"$goto"))
	{
	while(<IN>)
		{    
		print "$_"; 
		}
	close(IN);
	}
exit(0);

4つのifブロックを並置せずに入れ子にしているのは、どれかが失敗したらオリジナルファイルの上書きをしないようにという配慮だったと記憶しています。書換えが無事終ったら(終らなくても)、167~174行目で本来のジャンプ先$gotoを読込んで書出します。今にしてif(?count =?)って何のことと思ったのですが、/pattern/が前方検索の正規表現なのに対して?pattern?は後方検索の正規表現でした。この辺がPerlの真骨頂だと思うのですが、作成当時は検索だから"?"なのか、ワイルドカードなのかと訳も分からず書いていたと思います。何れにせよ、while(<IN>)で順次読出した各行に"count ="が含まれるかどうかをチェックします。

一方、count.htmlは下記のようになっていて、9~11行にコメントとして合計人数 (count)、カウント開始からの経過週数 (weeks)、最終週の人数 (subcount)を記載しています。count.cgiの12~46行でこれらの数値をカウントアップしますが、その日の日付(4行目で算出)が最終週の終了日(21行目で算出)より前か後かで処理が異ります。104行目で最終週のラベル<!--FINAL WEEK-->を見つけ、後の場合は58~68行で新しい週を追加します。21行目と63行目に出てくる856753200という数字はカウントを開始した1997年2月24日12:00:00に対応するUNIX時間で、経過週数に対応する秒数を足すことで最終日の日付が分ります。


<HTML>
<HEAD>
<TITLE>
How many people?
</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFB0" LINK="#0000FF" VLINK="#FF4000" ALINK="#FF4000" TEXT="#000000">
<!--
count = 217022
weeks = 738
subcount = 357
-->
<CENTER>
<H1>
<FONT COLOR="#008000">
How many people have visited?
</FONT>
</H1>
</CENTER>
<P>
<HR ALIGN=center WIDTH=100% SIZE=4>
<P>
The number of guests is counted up when a guest jumps from the title page in English or in Japanese to some page included in the Tomo-chan Home Page. Therefore, if someone returns to the title page during her/his visiting, the system counts her/him as a new guest . However, only looking at the title page is not counted as a guest.
<P>
<B>
Since February 24, 1997, the number of guests in each week is as follows:
</B>
<P>
<CENTER>
<TABLE BORDER=1>
<TH></TH><TH>Number of Guests</TH><TR>
<TH>Feb 24 - Mar 2, 1997</TH>
<TH>36</TH><TR>
<TH>Mar 3 - Mar 9, 1997</TH>
<TH>36</TH><TR>
<TH colspan="2">--- Omitted ---</TH><TR>
<TH>Apr 4 - Apr 10, 2011</TH>
<TH>441</TH><TR>
<!--FINAL WEEK-->
<TH>Apr 11 - Apr 17, 2011</TH>
<TH>357</TH><TR>
<TH>Total</TH><TH>217022</TH>
</TABLE>
</CENTER>
<P>
<HR ALIGN=center WIDTD=100% SIZE=2>
<P>
</BODY>
</HTML>

カウントする度に4つのHTMLファイルを書換えるというのはやはり荒業で、よくファイルの中身が消えてしまうというトラブルが発生しました。もちろんローカルにバックアップファイルがあるのでそれを再度アップロードすればいいのですが、それでは前回アップロードしてからの来訪者数がカウントされません。そこを担保するために入れてあるのが3行目で、カウントアップに対応する日時のみをcounterというファイルに追記していくようにしています。このcounterにトラブルが発生したことはないのですが、counterをExcelで開いて前回アップロードしてからの来訪者数を数え、手作業で4つのファイルを修正するというのは面倒なことでした。

年表の丸印を一つ飛ばした「特許活用システム」がこの情けない状況を打開する契機となりました。詳細は飛ばした丸印と一緒に「IV. DBを使って人事評価から特許活用まで」で説明しますが、会社で知財戦略を担当していた時に余技で構築したデータベースシステムです。最初はPerlを使ってTSVファイルを読み書きしていたのですが、「まだそんなことをやってるの。これからはLAMPだよ」と笑われたのをきっかけにPHPとMySQLを勉強しました。WAMPを何とか使いこなせるようになった2011年にもう一つの契機がありました。

それまでプライベートのwebサーバにはリムネットを利用していましたが、さくらインターネットに変更したのです。変更の理由は、データ容量に対して従量課金だったリムネットの月額利用料がどんどん高くなっていったことですが、さくらのレンタルサーバはMySQLを手軽に利用できるというおまけが付きました。これでお膳立てができたので、従来のcount(_j).htmlの中身はMySQLにデータとして保存し、count(_j).phpとindex(_j).phpでそのデータを表示するようにしました。データの書込みもPHPにしてもよかったのですが、これはPerlのままにしました。書込みプログラムは以下の通りです。


#!/usr/bin/perl
use strict;
use warnings;
use DBI qw(:sql_types);

# MySQLと接続
my $dbh = DBI->connect(
	"DBI:mysql:データベース名:ホスト名", "ユーザ名", "パスワード");
$dbh->do("set names utf8");
# 先頭レコード(合計)のnumberを+1
my $sth0 = $dbh->prepare("UPDATE count SET number=number+1 WHERE id = 1");
$sth0->execute;
$sth0->finish();
# 新規週開始日が今日より先になるまで繰返す
my $i = 0;
while($i++ < 1000){
	# 最終レコードの選択
	my $sth1 = $dbh->prepare(
		"SELECT * FROM count WHERE id = (SELECT max(id) FROM count)");
	$sth1->execute;
	# 最終レコードのフィールド値取得
	my @final = $sth1->fetchrow_array;
	$sth1->finish();
	# 今日のyear(-1900), mon(-1), mday
	my ($sec0, $min0, $hour0, $mday0, $mon0, $year0, $wday0, $yday0,
		$isdst0) = localtime(time);
	# 新規週開始日ymd
	my ($sec1, $min1, $hour1, $mday1, $mon1, $year1, $wday1, $yday1,
		$isdst1) = localtime(856753200+($final[0]-1)*7*24*60*60);
	# 新規週開始日が今日より先になったらwhileループを終了
	if($year0 < $year1 || $year0 == $year1 && $yday0 < $yday1){
		# 最終レコードのnumberを+1
		my $sth2 = $dbh->prepare(
			"UPDATE count SET number=number+1 WHERE id = $final[0]");
		$sth2->execute;
		$sth2->finish();
		last;
	}else{
		# 新規週終了日ymd
		my ($sec2, $min2, $hour2, $mday2, $mon2, $year2, $wday2, $yday2,
			$isdst2) = localtime(856753200+($final[0]*7-1)*24*60*60);
		# 英語新規週
		my @mons_e = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
					  'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
		my $mon1_e = $mons_e[$mon1];
		my $mon2_e = $mons_e[$mon2];
		$year2 += 1900;
		my $e_week_new
			= ($mon1_e.' '.$mday1.' - '.$mon2_e.' '.$mday2.', '.$year2);
		# 日本語新規週
		$year1 += 1900;
		$mon1++;
		$mon2++;
		my $j_week_new
			= ($year1.'年'.$mon1.'月'.$mday1.'日~'.$mon2.'月'.$mday2.'日');
		# 新規週を追加
		my $sth3 = $dbh->prepare(
			"INSERT INTO count (e_week, J_week, number) VALUES (?, ?, 0)");
		$sth3->bind_param(1, $e_week_new, SQL_VARCHAR);
		$sth3->bind_param(2, $j_week_new, SQL_VARCHAR);
		$sth3->execute;
		$sth3->finish();
	}
}
# MySQLと切断
$dbh->disconnect();

# 最終ジャンプ先の取得
my $goto = ('/'.$ENV{'QUERY_STRING'});
print "Content-Type: text/html\n\n";
print "<HTML><HEAD>";
if($goto =~ /_j/){
	print"<META http-equiv=\"Content-Type\" content=\"text/html;
		charset=UTF-8\">";
    print "<META http-equiv=\"REFRESH\" CONTENT=\"1;URL=$goto\">";
	print "<TITLE>カウントしてジャンプ</TITLE></HEAD>";
	print "<BODY BGCOLOR=#3FB6BF>";
	print "ちょっと待ってね・・・";
}else{
	print"<META http-equiv=\"Content-Type\" content=\"text/html;
		charset=UTF-8\">";
	print "<META http-equiv=\"REFRESH\" CONTENT=\"1;URL=$goto\">";
	print "<TITLE>Count and Jump</TITLE></HEAD>";
	print "<BODY BGCOLOR=#3FB6BF>";
	print "Wait a moment.....";
}
print "</BODY></HTML>";
exit(0);

count.cgi (old)ではその日の日付が最終週の終了日より後の場合には新しい週を追加しますが、ここで新たな問題に気付きました。もしアクセスが全くない週(ブランク週)があったとすると、アクセスがあった時点でブランク週に1人のアクセスがあったと登録されます。ブランク週が複数あると、それらの週をアクセス数1で順次埋めた後に本来の週のカウントがスタートします。ブランク週は未だかつて発生したことはありませんが、未来永劫発生しないとは言えません。その対策として、count.cgi (new)では16行目からのwhileループで新規週開始日が今日より先にならない間は38行目のelseブロックでアクセス数0の週を追加します。

5. Java

年表でPerl、Java、Javascriptの左端の丸印は全て1997年になっています。この3つのプログラミング言語は駄待ち狐にとってホームページを動的なものにするための3種の神器でした。今やwebサイトで動画を見るのは当り前ですが、黎明期のインターネットは驚くほどの低速で動画など送れるはずもなく、写真でも高精細のものを送ると徐々にページ上に現れるという状況でした。駄待ち狐が初めてwebサイトにアクセスしたのは1994年9月30日です。なぜそんなに正確な日付が分かるかと言うと、以下のメールが残っているからです。

To: adachi, kamiyama, kidoguci, kito, kubo, matsuda, matsui, nshinji,
      otsuka, takamori, uno, uemura, yokogawa
Subject: MacWeb, WWW browser
Date: Fri, 30 Sep 1994 14:17:54 +0900
Sender: tohmon
かねてからの皆様の要望であったWWW browserのMacintosh 版がようやく動くよう
になりました。MacWebと言うソフトです。
喜びさんで松田SNGに見せたところ、「遅いね。。。」と反響はいまいとつでしたが、
つかいたかったらトウモンにご一報ください。
現在はunoマシンとkamiyamaマシンにMacWebが入ってます。松下内のWWWを見
るにはMacWeb Internal, また、松下外はMacWeb external を使ってください。
自分のマシンに入れたかったら、トウモンに連絡ください。
--------------------------------------------------------------------------------
        Genji Tohmon                               Panasonic/Matsushita Electric

これはMac Quadra上のEudoraというメールソフトで受信したものですが、データはテキストベースで保存されているので今でも読むことができます。万が一にも文中の宛先の方がこのサイトを訪問されることがあれば「懐かしさに涙があふれる」かもしれませんが、それ以外の方には誰のことだか分かりませんよね。因みに送信者の東門元二さんはキャンプ中に倒木の下敷きになるという不運な事故で鬼籍に入られています。東門さんはアメリカ育ちの日本人で日本語よりも英語が得意という方だったので「喜びいさんで」の「い」が抜けています。

「松田SNG」は駄待ち狐のことですが、東門さんに言われるがままにアクセスしたのはグリニッジ天文台で、惑星の画像が見られるとのこと。天体望遠鏡で見た動画でも出るのかと思ったら、30分ほどかかってやっと現れたのは切手大の静止写真。「遅いね。。。」と言ってもバチは当たらないと思います。この時は自分でホームページ(HP)を作ることになるとは夢にも思いませんでしたが、この原体験がHP上で動画を公開したいという強い思いに繋がりました。この願いが叶ったのはHPを開設した2年半後の1998年9月27日です。HPの開設当初は動画を公開するのは無理だったので、Javaアプレットでアニメーションをとなった訳です。

「プログラミング環境の自分史」で示したOS-言語一覧表にもある通り、PerlのCGIはサーバ上のApacheで動くので、リムネットであれ、さくらインターネットであれ、サーバがPerlに対応していればユーザは*.cgiのソースコードをアップロードするだけです。また、Javaと似た名称ですが全く異なるプログラミング言語であるJavaScriptはブラウザ上で動作しますが、閲覧者が使っているブラウザがJavaScript対応であれば、*.html内にソースコードを書くか、コードが書かれた*.jsファイルにリンクを張るだけです。これは両者がインタープリタ言語であるためです。

Javaもブラウザ上で動作しますが、コンパイル言語なので事前にソースコードをビルドした上でサーバにアップロードする必要があります。Cもコンパイル言語ですが、先程紹介したような簡単なプログラムであればシェル上でccコマンドを実行すればビルドできます。これらに対し、Javaアプレットのプログラミングではビルドのための開発環境が必要になってきます。さらにJavaは駄待ち狐にとって初めてのオブジェクト指向言語だったため、「クラスって何なの? 継承ってどういうこと?」状態です。Cの「プログラムは関数だ!」はいいですが、そもそもクラスが分からないのにJavaで「プログラムはクラスだ!」と言われてはもうお手上げです。

そこでまたJavaの教科書を買って勉強したのですが、オブジェクト指向やJavaのコンセプトは丁寧に説明されているものの、具体的なコードの書き方については書かれていません。一方、開発環境として使い始めたMRJSDK (Macintosh OS runtime for Java software developer kit)には、コーヒー豆が踊ってJavaという文字になるものを始めアプレットのサンプルコードが色々と収録されていました。HP上でやりたいことに一番近い(といってもかなり違う)サンプルコードを試行錯誤でひねくり回して、何とか所望の動きをするアプレットをビルドしました。これについては「V. JavaアプレットをJavaScriptで代替」で紹介します。

こんなに苦労して作ったJavaアプレットですが、セキュリティ上の問題で提供元のOracle自身が2015年にJavaプラグインを完全に非推奨にすると発表しました。Javaアプレットに対応するブラウザはどんどん減って行き、最後に残ったIE11もEdgeに取って代られました。そこで致し方なくプライベートHP上のJavaアプレットをJavaScriptに書換えていきました。厄介そうなので削除していたページも2024年に復活しました。駄待ち狐にとってのJavaは哀れな末路を迎えたかに見えましたが、2021年に仕事の余技でAnyLogicをいじり出した時に奇跡の復活を遂げます。これが年表右端の丸印で、「VII. AMRのモデリングシミュレーション」で紹介します。

Javaとは関係ありませんが、脆弱性の問題で使えなくなったもう一つの技術について触れておきます。2016年に米国コンピューター緊急事態対策チームがQuickTime(QT) for Windowsのアンインストールを推奨したのです。駄待ち狐はHP上で動画やスライドショーを公開するのにずっとQTムービーを使っていました。1998年9月27日に最初にアップロードした動画もそうですし、その半年後には字幕、MIDIで自作したBGM、Macの音声読上げソフトによるナレーションを入れた「ネットが低速だった時代の名作」を制作しました。しかし、Windows上で見られなくなっては困るので、HP上のQTムービーは全てMPEG4に変換しました。

6. JavaScript

今やHP作成の3種の神器と言えばHTML、CSS、JavaScriptですが、Javaと同時に登場した当初、JavaScriptには「バッタもん」感がありました。駄待ち狐の個人的な見解ですが、FORTRANは難しいのでBASICを使う、Cは難しいのでPerlを使う、Javaは難しいのでJavaScriptを使うといった印象です。それがJavaアプレットの敵失を受けてスポットライトを浴びると、表舞台で歌って踊ってと大活躍です。年表の蛍光緑「アプレット代替」と「イベントリスナー」はスポットライトが当ってからの話ですが、ここではそれ以前の話をします。

年表の左端「HP日数カウント」はともちゃんHPから削除されていますが、今でも問題なく動くのでたここに再掲します。元々は、HP冒頭の「今日は○○日目なので」の「○○日目」からリンクを張っていました。なぜこんなページを作ったかというと、HP開設当時はパソコンに日時を設定していないユーザがたまにいたのです。そんな人からメールを貰うと日付の降順ソートで一番最後になってしまいますし、ともちゃんHPの「○○日目」にも間違った数字が表示されます。「それはあなたのコンピュータのせいですよ」ということを明示するためにこのページを作ったのです。JavaScriptを埋込んだHTMLは以下の通りです。


<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=iso-2022-jp">
<TITLE>
何日目?
</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function calc1(year1,mon1,date1,year2,mon2,date2)
	{
	var time1 = Date.UTC(year1,mon1,date1);
	var time2 = Date.UTC(year2,mon2,date2);
	return Math.round((time2-time1)/(1000*60*60*24));
	}
function calc2(form)
	{
	form.days2.value = calc1(eval(form.year3.value),eval(form.month3.selectedIndex),eval(form.date3.value),eval(form.year4.value),eval(form.month4.selectedIndex),eval(form.date4.value));
	}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFB0" LINK="#0000FF" VLINK="#FF4000" ALINK="#FF4000" TEXT="#000000">
<CENTER>
<H1>
<FONT COLOR="#008000">
何日目ですか?
</FONT>
</H1>
</CENTER>
<P>
<HR ALIGN=center WIDTH=100% SIZE=4>
<P>
<SCRIPT LANGUAGE="JavaScript">
<!--
var date1 = 24;
var mon1 = 1;
var month1 = 2;
var year1 = 1997;
var today = new Date();
var date2 = today.getDate();
var mon2 = today.getMonth();
var month2 = mon2 + 1;
var year2 = today.getYear();
if(year2 < 2000)
	year2 += 1900;
var days1 = calc1(year1,mon1,date1,year2,mon2,date2);
document.write("<B>お客様のカウントは<FONT COLOR=E000C0>",year1,"年",month1,"月",date1,"日</FONT>に開始しました。<P>");
document.write("今日は<FONT COLOR=E000C0>",year2,"年",month2,"月",date2,"日</FONT>です。(この日付はあなたのコンピュータが教えてくれました。)<P>");
document.write("お客様のカウントを始めてから<FONT COLOR=E000C0>",days1,"日目</FONT>になりました!</B><P>");
//-->
</SCRIPT>
<HR ALIGN=center WIDTH=100% SIZE=2>
<P>
上記の日数計算をどんな日付に対しても行えるようにしたのが、この下の入力フォームです。これで、計算が正しいことをご確認下さい。
<BR>
開始日と最終日にはお好きな日を入力して下さい。その後、「計算」ボタンをクリックすると、最後のテキストボックスにこの間の日数が表示されます。
<BR>
間違った日付を入力しても、次の考え方で計算が行われます。4月31日=5月1日、4月35日=5月5日、4月0日=3月31日・・・
<FORM>
<B>
開始日は 
<INPUT TYPE="text" NAME="year3" SIZE=5 VALUE=1997>
年
<SELECT NAME="month3">
<OPTION>
1
<OPTION SELECTED>
2
<OPTION>
3
<OPTION>
4
<OPTION>
5
<OPTION>
6
<OPTION>
7
<OPTION>
8
<OPTION>
9
<OPTION>
10
<OPTION>
11
<OPTION>
12
</SELECT>
月
<INPUT TYPE="text" NAME="date3" SIZE=3 VALUE=24>
日です。
</B>
(お好きな日を入力して下さい。)
<P>
<B>
最終日は
<INPUT TYPE="text" NAME="year4" SIZE=5 VALUE=1997>
年
<SELECT NAME="month4">
<OPTION>
1
<OPTION SELECTED>
2
<OPTION>
3
<OPTION>
4
<OPTION>
5
<OPTION>
6
<OPTION>
7
<OPTION>
8
<OPTION>
9
<OPTION>
10
<OPTION>
11
<OPTION>
12
</SELECT>
月
<INPUT TYPE="text" NAME="date4" SIZE=3 VALUE=25>
日です。
</B>
(お好きな日を入力して下さい。)
<P>
<B>
<INPUT TYPE="button" VALUE="計算" onClick="calc2(this.form)">
</B>
(このボタンをクリックすると結果が表示されます。)
<P>
<B>
開始日から数えて、最終日は
<INPUT TYPE="text" NAME="days2" SIZE=6 VALUE="1">
日目です。
</B>
</FORM>
<P>
<HR ALIGN=center WIDTH=100% SIZE=2>
<P>
<CENTER>
<APPLET CODE="Pusher.class" WIDTH=113 HEIGHT=20>
<PARAM NAME="bname" VALUE="gohome_j">
<PARAM NAME="href" VALUE="index_j">
<PARAM NAME="bgcolor" VALUE="1">
</APPLET>
</CENTER>
</BODY>
</HTML>

<HEAD>の7~19行目で関数の定義を行い、<BODY>の33~50行目でこの関数を使ってHTMLを出力する。133行目のボタンのonClickでは<SCRIPT LANGUAGE="JavaScript">とも書かずに定義した関数を引用するといった破茶滅茶なところが最初はなかなか理解できませんでした。ただ、もっと自由奔放な書式が可能なPHPを学ぶと「これはインビジブルコンピュータならぬインビジブルコードへの道なのかもしれない」と思えるようになりました。一方で歌って踊れる大スターになると「コードはコードらしくしなさい」とお説教する人も出てきます。この辺りは「V. JavaアプレットをJavaScriptで代替」で書かせていただきます。

年表の次の丸印「ウィンドウ制御」は以下の4行のコードです。この4行をHTMLなり、PHPなりに埋込んでおくと、ウィンドウサイズを最大にして表示してくれます。年表に垂直の破線がある通り、これはPatent Portfolio Manager(PPM)を作る時に使った小技です。PPMはPHPながらクラスを駆使した本格的なDBシステムですが、PHPではウィンドウサイズを最大にするという制御が見つけられなかったので、この部分にだけJavaScriptを使いました。詳細は「IV. DBを使って人事評価から特許活用まで」の「8.1 index.php」で説明します。JavaScriptはブラウザそのものを制御する名脇役でもあることが言いたくて、年表に上げました。


var scrnx = screen.availWidth; 
var scrny = screen.availHeight;
window.moveTo(0, 0);
window.resizeTo(scrnx, scrny);

人生の余技として作成したプログラム(3)へ続く