情報学部 菅沼ホーム

JavaScript によるプレゼンテーションシステム

      1. 教師用ページ
      2. 学生用ページ
      3. 使用方法
  まず,教師用のページと学生用のページに別の Window を使用して入り,このページにあるシステム例を使用してみて下さい.その後,以下の説明を読んで貰うと理解しやすいと思います.

  1. 教師用ページ

      下に示すのが,教師用のページです.

      このページは,3 つのインラインフレームから構成されています.左上(左側の細長い部分のほとんど),左下(左側の細長い部分の下の一部),及び,右です.左上において,学生のパソコンに表示させたいページを選択すると,右の画面に学生のパソコンと同じ内容が表示されます.指定 URL の下のテキストフィールドに URLを入力し,「 OK 」ボタンをクリックすれば,その URL が表示されます.また,「白板」を選択すると,白板が表示されます(後述).

      「第1章」,「第2章」の部分をクリックすると,その内容が展開され,もう一度クリックすると,内容が見えなくなります.図は,「第1章」をクリックした状態を表しています.展開された内容(「sheet001」,「sheet002」)が具体的に表示する HTML ファイル等を表しています.上の図は,「sheet001」をクリックした状態を示しています.表示するファイルの実体は,「第1章」の場合は,ディレクトリ sheet/s1 にあります.同様に,「第2章」の場合は,ディレクトリ sheet/s2 にあります.

      左下の部分は,サーバからの応答であり,指定したページをサーバが受け取ったことを意味しています.ここに,クリックしたページと同じ内容が表示されれば,システムが正しく動作していることになります.

      下に示すのが,白板を選択したときの画面です.白板上にマウスで図を描いたり,下のテキストエリアで文字を入力し(テキストエリアへのフォーカスが失われたときに白板上に文字が表示される),「送信」ボタンをクリックすると,学生のパソコンに白板が表示されます.学生側のパソコンには,テキストエリアは表示されず,白板だけが表示されます.白板には,教師が白板の表示を選択したときの内容が表示されるため,白板上のその後の変更を見るためには,学生は,適宜,「更新」ボタンをクリックする必要があります.

      次に,以上のことを実現しているプログラムについて見てみます.まず,教師側のトップページ control.htm は以下のようになっています.IFRAME 要素のうち,一番上が右,2 番目が左上,さらに,3 番目が左下に対応しています.右及び左下に関しては,そのソースファイルについて何も指定してありませんが,右は左上の list.htm の指示により,また,左下はサーバからの返信によって表示されます.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>JavaScript プレゼンテーションシステム</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    
    </HEAD>
    
    <BODY CLASS="white">
    	<IFRAME ID="sheet" NAME="sheet" SRC="" WIDTH="79%" HEIGHT="700px" STYLE="margin: 0px; padding: 0px; float: right"></IFRAME>
    	<IFRAME ID="list" NAME="list" SRC="list.htm" WIDTH="20%" HEIGHT="650px" STYLE="margin: 0px; padding: 0px; float: left"></IFRAME>
    	<IFRAME ID="message" NAME="message" SRC="" WIDTH="20%" HEIGHT="50px" STYLE="margin: 0px; padding: 0px; float: left"></IFRAME>
    </BODY>
    
    </HTML>
    			
      以下に示すのが,list.htm の内容です.なお,行番号は,説明のために付加しました.
    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>プレゼンテーションシステム</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    07		<SCRIPT TYPE="text/javascript">
    08			function disp(part)
    09			{
    10				var str = eval('document.getElementById("' + part + '").style');
    11				if (str.display)
    12					str.display = "";
    13				else
    14					str.display = "none";
    15			}
    16	
    17			function disp_p(sw, page)
    18			{
    19				if (sw == 0) {
    20					document.set.number.value = page;
    21					document.set.submit();
    22				}
    23				else {
    24					var str = document.getElementById("URL").value;
    25					parent.sheet.location.replace(str);
    26					document.set.number.value = str;
    27					document.set.submit();
    28				}
    29			}
    30		</SCRIPT>
    31	</HEAD>
    32	<BODY STYLE="font-size:90%; background-color:#ffffcc">
    33		<P CLASS="center"><B>プレゼンテーション・システム</B></P>
    34	
    35		<P CLASS="center">
    36			<B>指定 URL</B> 
    37			<INPUT TYPE="button" VALUE="OK" STYLE="font-size: 80%" onClick="disp_p(1, '')"><BR>
    38			<INPUT ID="URL" TYPE="text" NAME="url" SIZE="25" VALUE="">
    39		</P>
    40	
    41		<A HREF="white.php" TARGET="sheet" onClick="disp_p(0, 'white/white.php')">白板</A>
    42	
    43		<P>
    44		<SPAN onClick="disp('1_sho')" TITLE="クリックによって,表示/非表示の切り替え" CLASS="link">1.第1章</SPAN>
    45		<DIV ID="1_sho" STYLE="display: none">
    46			 <A HREF="../sheet/s1/sheet001.htm" TARGET="sheet" onClick="disp_p(0, 's1/sheet001.htm')">sheet001</A><BR>
    47			 <A HREF="../sheet/s1/sheet002.htm" TARGET="sheet" onClick="disp_p(0, 's1/sheet002.htm')">sheet002</A>
    48		</DIV>
    49		<P>
    50		<SPAN onClick="disp('2_sho')" TITLE="クリックによって,表示/非表示の切り替え" CLASS="link">2.第2章</SPAN>
    51		<DIV ID="2_sho" STYLE="display: none">
    52			 <A HREF="../sheet/s2/sheet001.htm" TARGET="sheet" onClick="disp_p(0, 's2/sheet001.htm')">sheet001</A><BR>
    53			 <A HREF="../sheet/s2/sheet002.htm" TARGET="sheet" onClick="disp_p(0, 's2/sheet002.htm')">sheet002</A>
    54		</DIV>
    55		<FORM ACTION="control.php" NAME="set" METHOD="post" TARGET="message">
    56			<INPUT TYPE="hidden" NAME="number" VALUE="-1">
    57		</FORM>
    58	</BODY>
    59	</HTML>
    			
    36 行目~ 38 行目

      表示したい URL を処理する箇所である.URL を入力し,「 OK 」ボタンをクリックすると,関数 disp_p が呼ばれ,24 行目~ 27 行目でその処理が行われる.右画面にそのページを表示し( 25 行目),次に,URL を 56 行目の INPUT 要素に設定し( 26 行目),その後,55 行目~ 56 行目のフォームを control.php に送信する( 27 行目).

    41 行目

      白板を処理する部分である.クリックすると,右画面に白板( white.php )を表示すると共に,関数 disp_p が呼ばれ,20,21 行目でその処理が行われる.2 番目の引数(右画面に表示したページの URL )を 56 行目の INPUT 要素に設定し( 20 行目),その後,55 行目~ 56 行目のフォームを control.php に送信する( 21 行目).

    44 行目,50 行目

      クリックすると,関数 disp が呼ばれ,各章の内容に対する表示・非表示を切り替える.

    46 行目,47 行目,52 行目,53 行目

      クリックすると,右画面に指定したページを表示すると共に,関数 disp_p が呼ばれ,20,21 行目でその処理が行われる.2 番目の引数(右画面に表示したページの URL )を 56 行目の INPUT 要素に設定し( 20 行目),その後,55 行目~ 56 行目のフォームを control.php に送信する( 21 行目).
      フォームデータを送信する control.php の内容は以下に示すとおりです.
    01	<?php
    02		$num = $_POST['number'];
    03		$out = fopen("../sheet/number", "wb");
    04		fwrite($out, $num);
    05		fclose($out);
    06	?>
    07	<!DOCTYPE HTML>
    08	<HTML>
    09		<HEAD>
    10			<TITLE>結果</TITLE>
    11			<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    12		</HEAD>
    13		<BODY>
    14			<H3><?php echo $num; ?> を受け取りました</H3>
    15		</BODY>
    16	</HTML>
    			
    02 行目~ 05 行目

      送信されてきたページアドレスを,ディレクトリ sheet にあるファイル number に保存する.この結果,number には,現在,右画面に表示しているページアドレスが保存されることになる.

    14 行目

      送信されてきたページを受け取ったことを示している.control.php の内容は,list.htm の 55 行目において TARGET="message" を指定しているため,教師用画面の左下に表示されることになる.
      教師用画面において,あと一つ説明しておかなければならないのは,白板です.白板は,遠隔地に対する講義など,黒板を使用しにくい環境を考えて作成したものであり,普通の講義室における講義ではあまり必要ないと思いますので,教師用及び学生用の環境から削除しておいて構わないと思います.従って,ここでの説明も最小限にとどめたいと思います.

      今まで述べてきた内容は,「Java と PHP によるプレゼンテーションシステム」とほとんど同じですが(白板を表す URL アドレスが異なっているだけ),白板の内容に関しては,大きく異なっています.教師用の白板は,描画する領域とテキストを入力する領域の 2 つに分かれていますが,描画は CANVAS 要素内で JavaScript を使用して行われ,テキストは TEXTAREA 要素内に入力されます.これらを実行するファイル white.php の内容は,以下に示すとおりです.
    001	<!DOCTYPE HTML>
    002	
    003	<HTML>
    004	
    005	<HEAD>
    006	
    007		<TITLE>白板</TITLE>
    008		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    009		<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    010	
    011	<?php   // 保存してある状態を呼び出し
    012		$n = "0";
    013		$x = "";
    014		$y = "";
    015		$tx = "";
    016		$in = fopen("../sheet/white/data", "rb");
    017		if (filesize("../sheet/white/data") > 0) {
    018			$str = fread($in, filesize("../sheet/white/data"));
    019			$n = strtok($str, ",");
    020			if (intval($n) > 0) {
    021				$x = strtok(",");
    022				for ($i1 = 1; $i1 < intval($n); $i1++)
    023					$x = $x.",".strtok(",");
    024				$y = strtok(",");
    025				for ($i1 = 1; $i1 < intval($n); $i1++)
    026					$y = $y.",".strtok(",");
    027			}
    028			$tok = strtok(",");
    029			if ($tok) {
    030				$i1 = 0;
    031				$tt = strtok($tok, "\n\r");
    032				while ($tt) {
    033					if ($i1 == 0)
    034						$tx = $tt;
    035					else
    036						$tx = $tx."\\n".$tt;
    037					$i1++;
    038					$tt = strtok("\n\r");
    039				}
    040			}
    041		}
    042		fclose($in);
    043	?>
    044	
    045		<SCRIPT TYPE="text/javascript">
    046			blush  = false;   // お絵かき用ブラシの状態(絵を描けない状態)
    047			x_old  = -1;
    048			y_old  = -1;
    049			x_base = -1;
    050			y_base = -1;
    051			canvas = null;
    052			ctx    = null;
    053			x = new Array();
    054			y = new Array();
    055			n = 0;
    056						// 初期設定
    057			function draw() {
    058				canvas = document.getElementById('canvas_e');
    059				canvas.width  = 800;   // キャンバス要素の幅
    060				canvas.height = 500;   // キャンバス要素の高さ
    061				x_base = canvas.offsetLeft;   // キャンバスの左上のx座標
    062				y_base = canvas.offsetTop;   // キャンバスの左上のy座標
    063				ctx = canvas.getContext('2d');   // キャンバスからコンテキストを取得
    064				ctx.lineWidth = 3;   // 線の太さ
    065								// 描画
    066				n = parseInt(<?php echo $n; ?>);
    067				if (n > 0) {
    068					var str = "<?php echo $x; ?>";
    069					x = str.split(",");
    070					str = "<?php echo $y; ?>";
    071					y = str.split(",");
    072					blush = false;
    073					ctx.beginPath();
    074					ctx.moveTo(x[0], y[0]);
    075					for (var i1 = 1; i1 < n; i1++) {
    076						if (x[i1] >= 0)
    077							ctx.lineTo(x[i1], y[i1]);
    078						else {
    079							ctx.stroke();
    080							i1++;
    081							if (i1 < n) {
    082								ctx.beginPath();
    083								ctx.moveTo(x[i1], y[i1]);
    084							}
    085						}
    086					}
    087					ctx.stroke();
    088				}
    089								// テキスト
    090				var text = "<?php echo $tx; ?>";
    091				var tt = text.replace(/\\n/g, "\n");
    092				if (text.length > 0) {
    093					document.getElementById("text").value = tt;
    094					var str = tt.split("\n");
    095					if (str.length > 0) {
    096						ctx.font = "20px 'MS ゴシック'";
    097						var ph = 20;
    098						for (var i1 = 0; i1 < str.length; i1++) {
    099							ctx.fillText(str[i1], 10, ph);
    100							ph += 20;
    101						}
    102					}
    103				}
    104			}
    105						// イベント処理
    106			function m_move(event) {   // マウス移動イベント
    107				if (blush) {
    108					if (navigator.appName.indexOf("Explorer") >= 0) {
    109						x_now = event.x - x_base;
    110						y_now = event.y - y_base;
    111					}
    112					else {
    113						x_now = event.pageX - x_base;
    114						y_now = event.pageY - y_base;
    115					}
    116					x[n] = x_now;
    117					y[n] = y_now;
    118					ctx.beginPath();
    119					ctx.moveTo(x_old, y_old);
    120					ctx.lineTo(x_now, y_now);
    121					ctx.stroke();
    122					n++;
    123					x_old = x_now;
    124					y_old = y_now;
    125				}
    126			}
    127	
    128			function m_down(event) {   // マウスボタン押下イベント
    129				if (!blush) {
    130					if (navigator.appName.indexOf("Explorer") >= 0) {
    131						x_old = event.x - x_base;
    132						y_old = event.y - y_base;
    133					}
    134					else {
    135						x_old = event.pageX - x_base;
    136						y_old = event.pageY - y_base;
    137					}
    138					x[n] = x_old;
    139					y[n] = y_old;
    140					n++;
    141					blush = true;   // 描ける状態
    142				}
    143			}
    144	
    145			function m_up(event) {   // マウスボタン離されたイベント
    146				if (blush) {
    147					if (n == 0 || x[n-1] >= 0) {
    148						x[n] = -1;
    149						y[n] = -1;
    150						n++;
    151					}
    152					blush = false;   // 描けない状態
    153				}
    154			}
    155						// 領域のクリア
    156			function clear_text()   // 文字
    157			{
    158				document.getElementById("text").value = "";
    159				ctx.clearRect(0, 0, canvas.width, canvas.height);
    160				if (n > 0) {
    161					blush = false;
    162					ctx.beginPath();
    163					ctx.moveTo(x[0], y[0]);
    164					for (var i1 = 1; i1 < n; i1++) {
    165						if (x[i1] >= 0)
    166							ctx.lineTo(x[i1], y[i1]);
    167						else {
    168							ctx.stroke();
    169							i1++;
    170							if (i1 < n) {
    171								ctx.beginPath();
    172								ctx.moveTo(x[i1], y[i1]);
    173							}
    174						}
    175					}
    176					ctx.stroke();
    177				}
    178				return false;
    179			}
    180	
    181			function clear_fig()   // 画像
    182			{
    183				ctx.clearRect(0, 0, canvas.width, canvas.height);
    184				n = 0;
    185				str = (document.getElementById("text").value).split("\n");
    186				if (str.length > 0) {
    187					ctx.font = "20px 'MS ゴシック'";
    188					var ph = 20;
    189					for (var i1 = 0; i1 < str.length; i1++) {
    190						ctx.fillText(str[i1], 10, ph);
    191						ph += 20;
    192					}
    193				}
    194				return false;
    195			}
    196	
    197			function clear_all()   // すべて
    198			{
    199				document.getElementById("text").value = "";
    200				ctx.clearRect(0, 0, canvas.width, canvas.height);
    201				n = 0;
    202				return false;
    203			}
    204						// 描画領域へテキストエリアの文字列を設定
    205			function set_text(str)
    206			{
    207				if (str == "")
    208					str = (document.getElementById("text").value).split("\n");
    209				ctx.font = "20px 'MS ゴシック'";
    210				var ph = 20;
    211				for (var i1 = 0; i1 < str.length; i1++) {
    212					ctx.fillText(str[i1], 10, ph);
    213					ph += 20;
    214				}
    215				return false;
    216			}
    217						// データを送信し保存
    218			function trans(form)
    219			{
    220				form.n.value = n;
    221				var xx = new Array();
    222				var yy = new Array();
    223				for (var i1 = 0; i1 < n; i1++) {
    224					xx[i1] = x[i1];
    225					yy[i1] = y[i1];
    226				}
    227				form.x.value = xx;
    228				form.y.value = yy;
    229				form.t.value = document.getElementById("text").value;
    230				form.submit();
    231			}
    232		</SCRIPT>
    233	
    234	</HEAD>
    235	
    236	<BODY CLASS="color" onLoad="draw()">
    237	
    238		<FORM ACTION="keep.php" METHOD="post" TARGET="message">
    239			<P CLASS="center">
    240				<BUTTON STYLE="font-size: 90%; background-color: yellow" onClick="return clear_fig()">画像削除</BUTTON> 
    241				<BUTTON STYLE="font-size: 90%; background-color: yellow" onClick="return clear_text()">テキスト削除</BUTTON> 
    242				<BUTTON STYLE="font-size: 90%; background-color: yellow" onClick="return clear_all()">すべて削除</BUTTON>
    243				<BUTTON STYLE="font-size: 90%; background-color: pink" onClick="trans(this.form)">送信</BUTTON>
    244				<INPUT TYPE="hidden" NAME="n" ID="n" VALUE="">
    245				<INPUT TYPE="hidden" NAME="x" ID="x" VALUE="">
    246				<INPUT TYPE="hidden" NAME="y" ID="y" VALUE="">
    247				<INPUT TYPE="hidden" NAME="t" ID="t" VALUE="">
    248			</P>
    249		</FORM>
    250		<DIV CLASS="center">
    251			<CANVAS ID="canvas_e" STYLE="background-color: #ffffff;" WIDTH="800" HEIGHT="500" onMouseMove="m_move(event)" onMouseDown="m_down(event)" onMouseUp="m_up(event)"></CANVAS><BR><BR>
    252			<TEXTAREA ID="text" COLS="65" ROWS="10" STYLE="font-size: 100%" onBlur="set_text('')"></TEXTAREA>
    253		</DIV>
    254	
    255	</BODY>
    256	
    257	</HTML>
    			
    012 行目~ 042 行目

      ディレクトリ sheet/white にあるファイル data から,描画データ(自由曲線を構成する点データ)と文字列データを読み込んでいる.

    067 行目~ 088 行目

      描画データに基づき,自由曲線を描画している.

    090 行目~ 103 行目

      文字列データに基づき,文字列を描画している.

    106 行目~ 154 行目

      描画を行い,描画データに追加している

    218 行目~ 231 行目

      描画データ及び文字列データを保存するため,それらのデータを keep.php に送信している.

    244 行目~ 247 行目

      各々,描画データを構成する点の数,各点の x 座標,各点の y 座標,及び,文字列データが設定され,keep.php に送信される.

    252 行目

      このテキストエリアからフォーカスが離れると,関数 set_text ( 205 行目~ 216 行目)が呼ばれ,描画領域にテキストエリアの内容が描画される.

  2. 学生用ページ(学籍番号あり)
    学生用ページ(学籍番号なし)

      「学籍番号あり」のページに入ると,以下に示すようなページが表示されます.

      このページを表示する presentation.htm の内容は以下に示すとおりであり,2 つのインラインフレーム( control.php と gakuseki.htm )から構成されていますが,上のインラインフレーム( control.php )の高さが 0 px であるため,画面上には表示されません.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>プレゼンテーション</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    
    </HEAD>
    
    <BODY CLASS="white">
    	<IFRAME ID="control" NAME="control" SRC="control.php" WIDTH="100%" HEIGHT="0px" STYLE="margin: 0px; padding: 0px"></IFRAME>
    	<IFRAME ID="page" NAME="page" SRC="gakuseki.htm" WIDTH="100%" HEIGHT="700px" STYLE="margin: 0px; padding: 0px"></IFRAME>
    </BODY>
    
    </HTML>
    			
      gakuseki.htm の内容は以下に示すとおりであり,学籍番号を入力し,「送信」ボタンをクリックすると,gakuseki.htm 及び control.php のフォームを引数として,11 行目以降に記述されている関数 gaku_no_set が呼ばれます( 51 行目).関数 gaku_no_set においては,学籍番号が正しく設定されていることを確認後,control.php のフォームに対し,学籍番号の設定( 33 行目),下の画面に表示されている URL アドレスの設定( 34 行目)を行い,そのページ wait.htm を下の画面に表示します( 35 行目).なお,wait.htm は,下に見るように,「しばらくお待ち下さい!」と表示するだけです.

    gakuseki.htm
    01	<!DOCTYPE HTML>
    02	
    03	<HTML>
    04	
    05	<HEAD>
    06	
    07		<TITLE>学籍番号</TITLE>
    08		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    09		<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    10		<SCRIPT TYPE="text/javascript">
    11			function gaku_no_set(form1, form2)
    12			{
    13				var sw = 0;
    14				if (form1.no.value.length < 7) {
    15					sw = 1;
    16					alert("学籍番号,または,メールアドレスを「正しく」入力して下さい!");
    17				}
    18				else {
    19					if (form1.no.value.length != 7) {
    20						if (form1.no.value.indexOf("@") <= 0 || form1.no.value.indexOf(".") <= 0) {
    21							sw = 1;
    22							alert("メールアドレスを 「正しく」 入力して下さい!");
    23						}
    24					}
    25					else {
    26						if (isNaN(form1.no.value)) {
    27							sw = 1;
    28							alert("学籍番号を「正しく」入力して下さい!");
    29						}
    30					}
    31				}
    32				if (sw == 0) {
    33					form2.no.value = form1.no.value;
    34					form2.now.value = "wait.htm";
    35					parent.page.location.replace("wait.htm");
    36				}
    37			}
    38		</SCRIPT>
    39	
    40	</HEAD>
    41	
    42	<BODY CLASS="color">
    43		<P CLASS="center">
    44			<SPAN CLASS="font15">学籍番号を半角で入力してください</SPAN><BR>
    45			<SPAN CLASS="font15">(外部の方は,E-mailアドレスを入力してください)</SPAN>
    46		</P>
    47		<FORM>
    48			<P CLASS="center">
    49				<LABEL FOR="id_no">学籍番号: </LABEL>
    50				<INPUT TYPE="text" NAME="no" ID="id_no" SIZE="20" STYLE="font-size: 100%"> 
    51				<INPUT TYPE="button" VALUE="送信" STYLE="font-size: 90%" onClick="gaku_no_set(this.form, parent.control.document.gakuseki_no)"><BR><BR>
    52				<INPUT TYPE="reset" VALUE="リセット" STYLE="font-size: 90%">
    53			</P>
    54		</FORM>
    55	</BODY>
    56	
    57	</HTML>
    			

    wait.htm
    <!DOCTYPE HTML>
    
    <HTML>
    
    	<HEAD>
    
    		<TITLE>プレゼンテーション</TITLE>
    		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    		<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    
    	</HEAD>
    
    	<BODY CLASS="color">
    
    		<H1>しばらくお待ち下さい!</H1>
    
    	</BODY>
    
    </HTML>
    			
      control.php の内容は以下に示すとおりです.基本的には,このページを上のインラインフレームに常駐させ,学籍番号等の情報をキープしたいのですが,Java を使用したバージョンと同じ方法は利用できません.そこで,一定時間毎に,キープしたい情報をパラメータとして,control.php を再呼び出しするといった方法を採用しています.いずれにしろ,学籍番号等の情報は,このインラインフレームにキープされますので,下の画面で演習問題を行うような場合に,その結果を control.php に引き渡すような利用方法も可能です.

    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>プログラミング</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    07	</HEAD>
    08	<BODY CLASS="white">
    09		<form name="gakuseki_no">
    10			<input type="text" name="no" value="">
    11			<input type="text" name="now" value="wait.htm">
    12			<input type="text" name="target" value="wait.htm">
    13		</form>
    14	<?php
    15		if (strlen($_GET['no']) > 0) {
    16			$in = fopen("number", "rb");
    17			$target = fread($in, filesize("number"));
    18			fclose($in);
    19	?>
    20		<SCRIPT TYPE="text/javascript">
    21			gakuseki_no.no.value = <?php echo "'".$_GET['no']."'"; ?>;
    22			gakuseki_no.now.value = <?php echo "'".$_GET['now']."'"; ?>;
    23			gakuseki_no.target.value = <?php echo "'".$target."'"; ?>;
    24			if (gakuseki_no.target.value != "" && (gakuseki_no.now.value != gakuseki_no.target.value)) {
    25				gakuseki_no.now.value = gakuseki_no.target.value;
    26				parent.page.location.replace(gakuseki_no.target.value);
    27			}
    28		</SCRIPT>
    29	<?php
    30		}
    31	?>
    32		<SCRIPT TYPE="text/javascript">
    33			timerID = setInterval("timer()", 10000);
    34			function timer()
    35			{
    36				if (gakuseki_no.no.value != "") {
    37					clearInterval(timerID);
    38					location.replace("control.php?no="+gakuseki_no.no.value+"&now="+gakuseki_no.now.value);
    39				}
    40			}
    41		</SCRIPT>
    42	</BODY>
    43	</HTML>
    			
    09 行目~ 13 行目

      学籍番号( 10 行目),下のインラインフレームに現在表示している URL アドレス( 11 行目),及び,下のインラインフレームに表示すべき URL アドレス( 12 行目)からなるフォームである.

    15 行目~ 31 行目

      学籍番号が設定されている場合は( 15 行目),16 行目~ 27 行目が実行される.16 行目~ 18 行目においては,ファイル number(教師が指示した URL アドレス)を読み込んでいる.送信されてきたパラメータ及び読み込んだデータをフォームに設定し( 21 行目~ 23 行目),インラインフレームに現在表示している URL アドレスと表示すべき URL アドレスが異なっていた場合は( 24 行目),表示すべき URL アドレスを記憶した後( 25 行目),表示すべき URL アドレスが表すページを下のインラインフレームに表示している( 26 行目).

    33 行目~ 40 行目

      10 秒ごとに関数 timer が呼ばれ( 33 行目),学籍番号が入力されている場合は( 36 行目),学籍番号と現在表示している URL アドレスをパラメータとして,control.php を呼んでいる.このため,学生のパソコンに表示された内容が切り替わるには,教師が指示してから,最大 10 秒かかる.もっと短くしたい場合は,33 行目の値を修正してやる必要がある.ただし,時間を短くすると,サーバへの負担が大きくなる.
      以上述べた処理により,学籍番号が正しく入力されると,例えば,以下に示すようなページが表示されます.

      また,白板の場合は,例えば,以下に示すようなページが表示されます.

      ただし,白板の場合は,通常のページとは表示方法が異なります.それは,単に指定された URL アドレスを表示するといった方法が利用できないからです.そこで,下に示すような内容の white.php が表示さます.white.php においては,描画に必要なデータ(ディレクトリ sheet/white にあるファイル data )を読み込み,そのデータに基づき,CANVAS 要素上に描画しています.この描画は,最初に白板が選択されたときだけ行われるため,教師が白板の内容を変更してもそれが反映されません.そのため,学生は,適宜,「更新」ボタンをクリックしてやる必要があります(教師が,白板を再選択しても可能).
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>白板</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<LINK REL="stylesheet" TYPE="text/css" HREF="../../master.css">
    
    <?php   // 保存してある状態を呼び出し
    	$n = "0";
    	$x = "";
    	$y = "";
    	$tx = "";
    	$in = fopen("data", "rb");
    	if (filesize("data") > 0) {
    		$str = fread($in, filesize("data"));
    		$n = strtok($str, ",");
    		if (intval($n) > 0) {
    			$x = strtok(",");
    			for ($i1 = 1; $i1 < intval($n); $i1++)
    				$x = $x.",".strtok(",");
    			$y = strtok(",");
    			for ($i1 = 1; $i1 < intval($n); $i1++)
    				$y = $y.",".strtok(",");
    		}
    		$tok = strtok(",");
    		if ($tok) {
    			$i1 = 0;
    			$tt = strtok($tok, "\n\r");
    			while ($tt) {
    				if ($i1 == 0)
    					$tx = $tt;
    				else
    					$tx = $tx."\\n".$tt;
    				$i1++;
    				$tt = strtok("\n\r");
    			}
    		}
    	}
    	fclose($in);
    ?>
    
    	<SCRIPT TYPE="text/javascript">
    		blush  = false;   // お絵かき用ブラシの状態(絵を描けない状態)
    		x_old  = -1;
    		y_old  = -1;
    		x_base = -1;
    		y_base = -1;
    		canvas = null;
    		ctx    = null;
    		x = new Array();
    		y = new Array();
    		n = 0;
    					// 初期設定
    		function draw() {
    			canvas = document.getElementById('canvas_e');
    			canvas.width  = 800;   // キャンバス要素の幅
    			canvas.height = 500;   // キャンバス要素の高さ
    			x_base = canvas.offsetLeft;   // キャンバスの左上のx座標
    			y_base = canvas.offsetTop;   // キャンバスの左上のy座標
    			ctx = canvas.getContext('2d');   // キャンバスからコンテキストを取得
    			ctx.lineWidth = 3;   // 線の太さ
    							// 描画
    			n = parseInt(<?php echo $n; ?>);
    			if (n > 0) {
    				var str = "<?php echo $x; ?>";
    				x = str.split(",");
    				str = "<?php echo $y; ?>";
    				y = str.split(",");
    				blush = false;
    				ctx.beginPath();
    				ctx.moveTo(x[0], y[0]);
    				for (var i1 = 1; i1 < n; i1++) {
    					if (x[i1] >= 0)
    						ctx.lineTo(x[i1], y[i1]);
    					else {
    						ctx.stroke();
    						i1++;
    						if (i1 < n) {
    							ctx.beginPath();
    							ctx.moveTo(x[i1], y[i1]);
    						}
    					}
    				}
    				ctx.stroke();
    			}
    							// テキスト
    			var text = "<?php echo $tx; ?>";
    			var tt = text.replace(/\\n/g, "\n");
    			if (text.length > 0) {
    				var str = tt.split("\n");
    				if (str.length > 0) {
    					ctx.font = "20px 'MS ゴシック'";
    					var ph = 20;
    					for (var i1 = 0; i1 < str.length; i1++) {
    						ctx.fillText(str[i1], 10, ph);
    						ph += 20;
    					}
    				}
    			}
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY CLASS="color" onLoad="draw()">
    
    	<DIV CLASS="center">
    		<BUTTON STYLE="font-size: 90%; background-color: pink" onClick="JavaScript: location.reload();">更新</BUTTON><BR>
    		<CANVAS ID="canvas_e" STYLE="background-color: #ffffff;" WIDTH="800" HEIGHT="500"></CANVAS>
    	</DIV>
    
    </BODY>
    
    </HTML>
    			
      最後に,「学籍番号なし」のページを利用する場合について説明します.このページに入ると,学籍番号を入力するページを経由せず,教師が指示したページがすぐに表示されます.「学籍番号なし」のページ presentation_n.htm の内容は以下に示すとおりです.「学籍番号あり」のページ presentation.htm と同様,2 つのインラインフレームから構成されています.ただし,下のインラインフレームには,「しばらくお待ち下さい!」と表示する wait.htm が設定されています.また,control_n.php は,学籍番号のチェックを行っていない点を除けば,control.php とほとんど同じです.

    presentation_n.htm
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>プレゼンテーション</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    
    </HEAD>
    
    <BODY CLASS="white">
    	<IFRAME ID="control" NAME="control" SRC="control_n.php" WIDTH="100%" HEIGHT="0px" STYLE="margin: 0px; padding: 0px"></IFRAME>
    	<IFRAME ID="page" NAME="page" SRC="wait.htm" WIDTH="100%" HEIGHT="700px" STYLE="margin: 0px; padding: 0px"></IFRAME>
    </BODY>
    
    </HTML>
    			

    control_n.php
    <!DOCTYPE HTML>
    <HTML>
    <HEAD>
    	<TITLE>プログラミング</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
    </HEAD>
    <BODY CLASS="white">
    	<form name="gakuseki_no">
    		<input type="text" name="now" value="wait.htm">
    		<input type="text" name="target" value="wait.htm">
    	</form>
    <?php
    	$in = fopen("number", "rb");
    	$target = fread($in, filesize("number"));
    	fclose($in);
    ?>
    	<SCRIPT TYPE="text/javascript">
    		gakuseki_no.now.value = <?php echo "'".$_GET['now']."'"; ?>;
    		gakuseki_no.target.value = <?php echo "'".$target."'"; ?>;
    		if (gakuseki_no.target.value != "" && (gakuseki_no.now.value != gakuseki_no.target.value)) {
    			gakuseki_no.now.value = gakuseki_no.target.value;
    			parent.page.location.replace(gakuseki_no.target.value);
    		}
    
    		timerID = setInterval("timer()", 10000);
    
    		function timer()
    		{
    			clearInterval(timerID);
    			location.replace("control_n.php?now="+gakuseki_no.now.value);
    		}
    	</SCRIPT>
    </BODY>
    </HTML>
    			

  3. 使用方法

      上で示したようなシステムを作成するには,最初のページにおいて,プレゼンテーションシステムのページ全体(「 Java と PHP によるシステム」及び「 JavaScriput と PHP によるシステム」の両方を含む)をダウンロードして解凍した後,以下に示す手順に従って必要なファイルを修正することによって可能です.ここでは,ディレクトリ example_JavaScriput 以下を対象としています.なお,このページのシステム例は,「教師用ページ」からも明らかなように,白板と 2 つの章からなる講義資料(各章は 2 ページで構成)となっています.

    1. ディレクトリ sheet の下に,ディレクトリ s1,s2,・・・ を作成する(各章に対応する).以下においても同様であるが,名称を変更した場合は,それに対応して,list.htm の内容も修正する必要がある.なお,白板を使用する場合は,ディレクトリ white 以下はシステム例のものをそのまま使用したほうが便利である.

    2. 各ディレクトリ s1,s2,・・・ の下に必要な html ファイル,または,pdf ファイルを必要な数だけ作成する(例においては,2 つずつ作成してある).

    3. ディレクトリ control の下にある list.htm を章と資料の数に合わせて修正する.

    4. ディレクトリ example_JavaScript 以下にあるファイル及びディレクトリをアップロードする.なお,ディレクトリ名 example_JavaScript は任意の名前に変更して良い.

    5. ディレクトリ sheet の下にあるファイル number,及び,ディレクトリ sheet/white の下にあるファイル data のモードを以下のようにして変更する.

      chmod a+w number
      chmod a+w data

    6. 実行して,チェックする.

情報学部 菅沼ホーム