javascriptは,PC上のブラウザ内で,html文書を操作するクライアントサイドスクリプト(クライアントサイドプログラム)である。これはPHPなどがWebサーバ内で動作するサーバサイドスクリプトとは異なる概念である。
ブラウザ内のみで動作するので.htmlファイル内に記述できる。javascriptのライブラリであるjQueryを使うと,短いスクリプトの記述で済むため,またブラウザの種類の差を吸収できるようになるため,多く使用されている。
デモページではjquery-2.1.3.min.jsを必要とし,(バージョンによる動作の違いがあるかもしれないのでバージョンまで指定,おそらく,他のバージョンでもOK)それがサーバのドキュメントルート内のディレクトリjquery中に置いてあるものとする。
例えばドキュメントルートがc:\apache2.2\htpdocなら次のところに置く。
c:\apache2.2\htpdoc\jquery/jquery-2.1.3.min.js
これはphpファイル中の
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
に書いてあることに対応している。
もし,phpファイルに
<script type="text/javascript" src="/js/jquery-2.1.10.min.js"></script>
と書いてあるなら,(jqueryのバージョンが2.1.10になったことを想定)
c:\apache2.2\htpdoc\js/jquery-2.1.10.min.js
のように置けば良い。
jqueryはネット検索で見つけてダウンロードすればよい。 https://code.jquery.com/jquery/
追記
インターネット回線が高速になっており,キャッシュメモリも大きくなっているため,ページ表示の時に,jqueryを元のサイトから読み出す方が手間がなくなっていて,主流になっている。
次のように記述するとよい。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
デモファイル
jscriptに関する説明からスタートしたい場合はこちらへ
jQueryは,html内の指定したタグ(<div></div>,<p></p>など)に対して,値や状態,動作を取得したり,値(文字列も含む)を設定することができる。まずは最初のデモを見てみよう。
テキスト入力ボックスに何かの文字列を入力し,echoボタンを押すと,その下に入力した文字列が表示されるデモである。
pagedisplay 1.1 echoデモ echo_click.html
ここで動作します。
(リセットボタンでもとに戻ります)
なにか文字列を入力して,echoボタンを押してください。
list 1.1 echoデモ echo_click.html <html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
$(function () {
$("#btnecho").click( function() {
var text= "「" + $("#texthello").val() + "」と書きましたね。"
$("#mytextarea").html(text);
});
});
</script>
</head>
<body>
なにか文字列を入力して,echoボタンを押してください。<br>
<input type="text" id="texthello"><br>
<input type="button" id="btnecho" name="hoge" value="echo">
<div id="mytextarea"></div>
</body>
</html>
上記のList1.1について細部を見てみよう。
$("#btnecho").click : id="btnecho"を持つもの(ここではボタン)がクリックされた時に呼び出される関数名
$("#texthello").val() : id="texthello"を持つもの(ここではテキストボックス)の値(すなわち入力文字列)
$("#mytextarea").html(text) : id="mytextarea"を持つもの(ここでは領域)にtextを入れる。
例えば,テキストボックスに「hello」が書かれて,echoボタンが押されると,次のように動作する。
(1)「hello」は<input type="text" id="texthello">に取り込まれているので,
$("#texthello").val()で取り出すことが出来,var textには,
"「" + $("#texthello").val() + "」と書きましたね。",すなわち,
"「" + "hello" + "」と書きましたね。",すなわち,
"「hello」と書きましたね。"が代入されることになる。
(2)そして,<div id="mytextarea"></div>に挿入されるので,これは
<div id="mytextarea">「hello」と書きましたね。</div>
と書かれている状態になる。
ところで,
jQueryはjavascriptのライブラリなので,javascriptの記述方法と同じで,
<head></head>内の<script>と</script>の間に記述される。
jQueryでは
「 $(function () { 」と「 }); 」 の間に記述した内容は,html文書を読み込んだ後に実行あるいは定義される。
もし,「 $(function () { 」と「 }); 」を読み込んだ時点で実行あるいは定義されると,その時点ではまだ $("#texthello") などは読み込まれていないので,未定義状態エラーとなってしまう。
$("#btnecho").click() は関数定義で,()内には引数を書くのだが,引数として関数を渡すことになっている。
そこで,引数として渡される関数を
function() {
var text= "「" + $("#texthello").val() + "」と書きましたね。"
$("#mytextarea").html(text);
}
と定義している。
関数定義は
function myfunc() {
}
の形(myfuncが関数名)のはずだが,ここでの関数定義は名前を持たないため,このような表記になる。
$("#btnecho"),$("#texthello")などは,html文書の部品タグを指定するので,セレクタと呼ばれている。
ここで使用したセレクタはidを使って選択していたが非常に多くの指定のしかたがあるので,詳しくは「jQuery,セレクタ」でWeb検索して欲しい。
ここまでの説明を読んで,???だった場合はこちらを先に読むこと
jscriptに関する説明からスタートしたい場合はこちらへ
list1.1と同じ意味をjQueryを使わずに書くと次のようになる。
list 1.1-atl echoデモ echo_clickJS.html <html>
<head>
<script>
function myecho() {
mytext=document.getElementById('texthello').value;
document.getElementById('mytextarea').innerHTML='「'+mytext+'」と書きましたね。';
}
</script>
</head>
<body>
なにか文字列を入力して,echoボタンを押してください。<br>
<input type="text" id="texthello"><br>
<input type="button" id="btnecho" name="hoge" value="echo" onclick="myecho()">
<div id="mytextarea"></div>
</body>
</html>
次の例はclassで選択したものである。同じclassを持つタグは複数作れるので,それら全てへの操作が可能となっている。
>pagedisplay 1.2 echoデモ echo_click_multi.html
ここで動作します。
(リセットボタンでもとに戻ります)
なにか文字列を入力して,echoボタンを押してください。
list 1.2 echoデモ echo_click_multi.html <html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
$(function () {
$("#btnecho").click( function() {
var text= "「" + $("#texthello").val() + "」と書きましたね。"
$("div.mytextarea").css('background-color','yellow');
$("div.mytextarea").html(text);
//$('*[class*="mytex"]').html(text);
});
});
</script>
</head>
<body>
なにか文字列を入力して,echoボタンを押してください。<br>
<input type="text" id="texthello"><br>
<input type="button" id="btnecho" name="hoge" value="echo">
<div class="mytextarea"></div>
<div class="mytextarea"></div>
<div class="mytextarea"></div>
<div class="mytextarea"></div>
</body>
</html>
すべての<div class="mytextarea"></div>に対して,背景色を黄色にし,入力された文字列を表示している。
次の例はボタンがクリック(click)された時に動作が起こるのではなく,テキストボックスの内容が変化(change)したら動作が起こるようになっている。
(入力中はまだ確定したことになっていないので,入力終了時にはエンターキー押す)
(ブラウザによっては,テキストボックス以外をクリックすることで確定する)
pagedisplay 1.3 echoデモ echo_change.html
ここで動作します。
(リセットボタンでもとに戻ります)
なにか文字列を入力してください。
(入力の最後にenterキーで確定させてください)
(ブラウザによっては,テキストボックス以外をクリック)
list 1.3 echoデモ echo_change.html <html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
$(function () {
$("#texthello").change( function() {
var text= "「" + $("#texthello").val() + "」と書きましたね。"
$("#mytextarea").html(text);
});
});
</script>
</head>
<body>
なにか文字列を入力してください。<br>
(最後にenterキーで確定させてください)<br>
<input type="text" id="texthello"><br>
<div id="mytextarea"></div>
</body>
</html>
次の例は指定したタブを隠したり見せたりして,表示に変化を持たせるものである。
ここではプログレスバーを見せたり隠したりしている。
「使い方説明」を通常は隠しておき,ユーザの求めに応じて表示するなどの応用例がある。
pagedisplay 1.4 show-hideデモ showhide.html
ここで動作します。
show, hideボタンを押してください。
list 1.4 show-hideデモ showhide.html <html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
$(function () {
$("#btn_hide").click( function() {
$("#myimagearea").hide();
});
$("#btn_show").click( function() {
$("#myimagearea").show();
});
$("#myimagearea").hide();
});
</script>
</head>
<body>
show, hideボタンを押してください。<br>
<input type="button" id="btn_hide" value="かくす">
<input type="button" id="btn_show" value="見せる">
<div id="myimagearea"><img src="./progressbar.gif" alt="プログレスバー"> </div>
</body>
</html>
「 $(function () { 」と「 }); 」 の間に,関数定義が2つと,実行命令が1つある。
$("#myimagearea").hide();
によって,起動時にはイメージを見えないようにしている。
list 1.4 と同じ意味をjQueryを用いずにjavascriptだけを使って書くと次のようになる。
list 1.4-alt show-hideデモ showhideJS.html <html>
<head>
<script>
function hidearea() {
area=document.getElementById('myimagearea');
area.style.display='none';
}
function showarea() {
area=document.getElementById('myimagearea');
area.style.display='';
}
</script>
</head>
<body onload="hidearea()">
show, hideボタンを押してください。<br>
<input type="button" id="btn_hide" value="かくす" onclick="hidearea()">
<input type="button" id="btn_show" value="見せる" onclick="showarea()">
<div id="myimagearea"><img src="./progressbar.gif" alt="プログレスバー"> </div>
</body>
</html>
PHPはサーバサイドスクリプトなので,PC側ブラウザの求めに応じて,htmlを生成して,ブラウザに送り,送ったものを表示している。
次の例では,ブラウザ側で文字列をユーザが入力し,送信ボタンを押すことでWebサーバに送り,Webサーバは受け取った文字列を埋め込んだhtmlを生成し,ブラウザに送り,それを表示している。PHPプログラムのサンプルとしてよく取り上げられるものである。
pagedisplay 2.1 送信デモ confirmless.php
(ここでは操作できますが,送信はしません)
あなたのお名前は?
list 2.1 送信デモ confirmless.php <?php
if(isset($_POST['username']) == true) {
//「usernameという箱に入った変数を受け取れたら」というわけだから
//1回目の呼び出しでは,ここには入らない。
$yourname = htmlspecialchars($_POST['username'], ENT_QUOTES);
$firsttime = false;
} else {
//一回目の呼び出しではこちらに入る
$firsttime = true;
}
?>
<html>
<body>
<?php
if ($firsttime == true) {
print "あなたのお名前は?<br>\n";
print "<form method=\"post\">\n";
print "<input type=\"text\" size=\"30\" name=\"username\"><br>\n";
print "<input type=\"submit\" name=\"soshin\" value=\"送信\">\n";
print "</form>\n";
} else {
print $yourname . " さん,こんにちは<br><br>";
print "もう一度試しますか?<br>\n";
print "<form method=\"post\">\n";
print "<input type=\"submit\" name=\"soshin\" value=\"もう一度\">\n";
print "</form>\n";
}
?>
</body>
</html>
ここまでは純粋なPHPプログラムである。
ところで,送信ボタンを押した後に,本当に送信してよいかどうかユーザに問い合わせるためにはどうしたら良いだろう。
PHPのプログラムはWebサーバ側で動作しているので,そちらでチェックするとすれば,送信後になってしまう。
送信前にブラウザ側がユーザに問い合わせなければならないので,javascriptで書く必要がある。
送信ボタンが押されたら,confirm()で問い合わせて,ユーザが「OK」ボタンを押したら送信(submit)するように作ればよい。
pagedisplay 2.2 送信デモ confirm.php
(ここでは確認表示まで動作しますが,送信はしません)
あなたのお名前は?
list 2.2 送信デモ confirm.php <?php
if(isset($_POST['username']) == true) {
//「usernameという箱に入った変数を受け取れたら」というわけだから
//1回目の呼び出しでは,ここには入らない。
$yourname = htmlspecialchars($_POST['username'], ENT_QUOTES);
$firsttime = false;
} else {
//一回目の呼び出しではこちらに入る
$firsttime = true;
}
?>
<html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
$(function () {
$("#btnsend").click( function() {
var text ="「" + $("#txtusername").val() + "」を送信します。\n";
text += "よろしいですか?";
ok = confirm(text);
if (ok) {
$("#frmname").submit();
}
return false; //falseを返さないとデフォルト動作で送信してしまう。
});
});
</script>
</head>
<body>
<?php
if ($firsttime == true) {
print "あなたのお名前は?<br>\n";
print "<form method=\"post\" id=\"frmname\">\n";
print "<input type=\"text\" id=\"txtusername\" size=\"30\" name=\"username\"><br>\n";
print "<input type=\"submit\" id=\"btnsend\" value=\"送信\">\n"; //はOK
//print "<input type=\"button\" id=\"btnsend\" value=\"送信\">\n"; //はOK
//print "<button id=\"btnsend\">送信</button>\n"; //はOK
print "</form>\n";
} else {
print $yourname . " さん,こんにちは<br><br>";
print "もう一度試しますか?<br>\n";
print "<form method=\"post\">\n";
print "<input type=\"submit\" name=\"soshin\" value=\"もう一度\">\n";
print "</form>\n";
}
?>
</body>
</html>
上記のプログラムは,PHPプログラムが生成するhtml文書中にjavascriptが埋め込まれているものである。
WebブラウザがWebサーバにWebページを要求すると,Web サーバは要求されたhtmlファイルを送信し,Webブラウザは受信したhtmlファイルを解釈して表示する。Webブラウザが同じページのリロード要求したり,別のページを要求したりしても,同じ手順で表示が行われる。このような通信は同期通信である。
これに対して,javascriptは非同期通信の手段を与えている。表示中のWebページ中に書かれたjavascriptが,Webサーバに対して データを要求し,Webサーバが返信したデータによって,表示中のWebページの一部分を書き換えるという手順が非同期通信である。jQueryライブラ リを用いると記述が少なくて済む。非同期通信を用いると,通信量を押さえたり,htmlを解釈して表示する(レンダリング)の時間を低減させることができ る。(GoogleMapはこの手法で動作しているため,ページの再描画することなしに地図を更新できるようになっている。)
ここのデモでは,ブラウザページを表示後,次のような事を行う。
(1)送信ボタンによりjavascriptで3つのデータをWebサーバに送る。
3つのデータはID,名前,パスワードを模したもので,
s12345,Tokyo Taro,HelloPass
とする。
(2)Webサーバ側ではPHPプログラムにより3つのデータを受け取る。
(3)Webサーバ側では3つのデータをまとめて受信したことを示すために,文字列
「you sent [ s12345, Tokyo Taro, HelloPass ].」をブラウザ側に送る。
(4)ブラウザは受け取った文字列をページ中の「<div id="target"></div>」に表示する。
ページ全体が書き換わったわけではない。
最初の表示
TEXT TEST
送信ボタンを押した後
TEXT TEST
you sent [ s12345, Tokyo Taro, HelloPass ].
List 3.1 デモページ textupdown0.php <?php
if (isset( $_POST["id"] )) {
$id=isset( $_POST["id"] ) ? $_POST["id"]:"";
$name=isset( $_POST["name"] ) ? $_POST["name"]:"";
$passwd=isset( $_POST["passwd"] ) ? $_POST["passwd"]:"";
print "you sent [ ".$id.", ".$name.", ".$passwd." ].";
exit;
}
?>
<html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
var datatosend = {
"id": "s12345",
"name": "Tokyo Taro",
"passwd": "HelloPass"
}
$(function () {
//これ以降はロード直後に設定されるだけ
//$("#target"),$("#sendjson")はロード後でないと未定義なので,ロード後でないと設定できない
var sendandreseive = function () {
// XHR で送信
$.ajax({
type: "POST",
data: datatosend, //送信するデータ
dataType:'text', //これは返信受け取り形式の指定
success: function(res){
text=res + "<br>";
$("#target").html(text); //id="target"の場所に書き込む
}
});
};
//送信ボタン
//$("#sendjson").click( function (e) {
//$("#sendjson").bind("click", function (e) {
$("#sendjson").on("click", function (e) {
// 送信処理
sendandreseive();
});
});
</script>
</head>
<body>
<h2>TEXT TEST</h2>
<div id="target"></div>
<br>
<input id="sendjson" type="button" value="送信">
</body>
</html>
上記のList3.1について細部を見てみよう。
(1)このphpが呼び出されると,最初のPHP部分はif (isset( $_POST["id"] ))で実行されずにそれ以外の部分がブラウザに送られる。最初に表示されるのは表題部「TEXT TEST」と空の<div>と送信ボタンのみである。
(2)次に送信ボタンを押すと,送信ボタンが押されたらjavascriptが動作して関数sendandreceive()が実行されることになっており,sendandreceive()ではあらかじめdatatosendで定義されたデータ配列を,$.ajax()が自分のURLにPOST送信する。
(3)Webサーバでは再度このphpファイルがPOST付きで要求されるため,PHP部分で
if (isset( $_POST["id"] ))内が実行される。受け取った3つのデータをまとめてブラウザにprintで送信し,exitでそれ以降は送信しないで送信終了する。
(4)ブラウザ側は$.ajax()のsuccess部分でresとしてWebサーバからのデータを受け取る。そして,受け取ったデータを<div id="target">部に表示する。
このデモでは,ブラウザページを表示後,次のような事を行う。
(1)送信ボタンによりjavascriptで3つのデータをWebサーバに送る。
3つのデータはID,名前,パスワードを模したもので,
s12345,Tokyo Taro,HelloPass
とする。
(2)Webサーバ側ではPHPプログラムにより3つのデータを受け取る。
(3)Webサーバ側では3つのデータの一部を変更してブラウザ側に送る。
変更方法は各文字列の末尾に「_1」をつける。
(4)ブラウザは受け取った3つのデータをページ中の「<div id="target"></div>」に表示する。
最初の表示
JSON TEST
送信ボタンを押した後
JSON TEST
s12345_1
Tokyo Taro_1
HelloPass_1
List 3.2 デモページ jsonupdown0.php <?php
if (isset( $_POST["id"] )) {
$id=isset( $_POST["id"] ) ? $_POST["id"]:"";
$name=isset( $_POST["name"] ) ? $_POST["name"]:"";
$passwd=isset( $_POST["passwd"] ) ? $_POST["passwd"]:"";
$reply=array();
$reply["id"]=$id."_1";
$reply["name"]=$name."_1";
$reply["passwd"]=$passwd."_1";
header("Content-Type: application/json");
print json_encode($reply);
exit;
}
?>
<html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
var datatosend = {
"id": "s12345",
"name": "Tokyo Taro",
"passwd": "HelloPass"
}
$(function () {
//これ以降はロード直後に設定されるだけ
//$("#target"),$("#sendjson")はロード後でないと未定義なので,ロード後でないと設定できない
var sendandreceive = function () {
// XHR で送信
$.ajax({
type: "POST",
data: datatosend, //送信するデータ
dataType:'json', //これは返信受け取り形式の指定
success: function(res){
text=res.id + "<br>" + res.name + "<br>" + res.passwd +"<br>";
$("#target").html(text); //id="target"の場所に書き込む
}
});
};
//送信ボタン
$("#sendjson").bind("click", function (e) {
// 送信処理
sendandreceive();
});
});
</script>
</head>
<body>
<h2>JSON TEST</h2>
<div id="target"></div>
<br>
<input id="sendjson" type="button" value="送信">
</body>
</html>
上記のList3.2について細部を見てみよう。
(1)このphpが呼び出されると,最初のPHP部分はif (isset( $_POST["id"] ))で実行されずにそれ以外の部分がブラウザに送られる。最初に表示されるのは表題部「JSON TEST」と空の<div>と送信ボタンのみである。
(2)次に送信ボタンを押すと,送信ボタンが押されたらjavascriptが動作して関数sendandreceive()が実行されることになっており,sendandreceive()ではあらかじめdatatosendで定義されたデータ配列を,$.ajax()が自分のURLにPOST送信する。
(3)Webサーバでは再度このphpファイルがPOST付きで要求されるため,PHP部分で
if (isset( $_POST["id"] ))内が実行される。受け取った3つのデータにそれぞれ「_1」を付けて,json_encodeしてブラウザにprintで送信し,exitでそれ以降は送信しないで送信終了する。
(4)ブラウザ側は$.ajax()のsuccess部分でresとしてWebサーバからのデータを受け取る。そして,受け取ったデータを<div id="target">部に表示する。
次のList 3.3は,いろいろな条件で試してみた時のものである。
List 3.3 デモ2 <?php
if (isset( $_POST["id"] )) {
$id=isset( $_POST["id"] ) ? $_POST["id"]:"";
$name=isset( $_POST["name"] ) ? $_POST["name"]:"";
$passwd=isset( $_POST["passwd"] ) ? $_POST["passwd"]:"";
$reply=array();
$reply["id"]=$id."_1";
$reply["name"]=$name."_1";
$reply["passwd"]=$passwd."_1";
header("Content-Type: application/json");
print json_encode($reply);
/*
file_put_contents("zzzzzzlog.txt",json_encode($reply));
こうするとlogがサーバ内の"zzzzzzlog.txt"に次のように残される
{"id":"s12345_1","name":"Tokyo Taro \u6771\u4eac\u592a\u90ce_1","passwd":"HelloPass_1"}
{"id":"s12345_1","name":"Tokyo Taro \u6771\u4eac\u592a\u90ce_1","passwd":"<script>alert(111)<\/script>_1"}
*/
exit;
}
?>
<html>
<head>
<script type="text/javascript" src="/jquery/jquery-2.1.3.min.js"></script>
<script>
//PHPでいうhtmlspecialchars
function escapeHTML(str) {
return jQuery('<div>').text(str).html();
}
var datatosend = {
"id": "s12345",
"name": "Tokyo Taro 東京太郎",
"passwd": "HelloPass" //通常の例
//"passwd": "\<script\>alert(111)\</script\>" //攻撃の例
}
$(function () {/*すべて読み込み後に動作あるいは設定される*/
//alert('はじめの一歩');//意味はないが,ロード直後に実行されることを確認
//これ以降はロード直後に設定されるだけ
//$("#target"),$("#sendjson")はロード後でないと未定義なので,ロード後でないと設定できない
var sendandreceive = function () {
// XHR で送信
$.ajax({
type: "POST",
//url: "xxx", //not found エラーを起こすために実在しないものでテストしたなごり
//urlを省略すると自分自身に送信する
data: datatosend, //送信するデータ
//data: JSON.stringify(datatosend), //これはダメ,すでに変換されている
dataType:'json', //これは返信受け取り形式の指定
success: function(res){
//text=res.id+ "<br>" + res.name + "<br>" res.passwd +"<br>";
//これは無防備
text=escapeHTML(res.id)+ "<br>"
+ escapeHTML(res.name) + "<br>"
+ escapeHTML(res.passwd) +"<br>";
//ここまでやるとscriptを潜り込ませる事はできない
$("#target").html(text); //id="target"の場所に書き込む
//$("div#target").html(text); //このようにも書ける
//$("target").html(text); //これはダメ
//$("div").html(text); //<div>が1つだけなのでこれでもOK
// 複数の<div>があると全てに表示される
//alert("success");
},
complete: function(){
//alert("completed");
//ここではresは受け取れない
},
error: function(XMLHttpRequest, textStatus, errorThrown){
err=XMLHttpRequest.status+"\n"+XMLHttpRequest.statusText;
alert(err);
//urlが不正など通信以上の場合は 404 not found などが表示される
//urlが正しいが返信内容が不正の場合は 200 OK が返されるが
//errorが呼び出されると,successは呼び出されない
}
})
.done(function( res ) {
//作業が終わった時,Webサーバからメッセージデータの受信と表示
//dataにWebサーバからの受信メッセージ文字列を受け取っている
//表示先は「<div id="resulttxt"></div>」
//$("#target").html("sample text");
//ここではresも受け取ることができる
//呼び出される順は,success,done,completeの順である
});
};
//送信ボタン
$("#sendjson").bind("click", function (e) {
// 送信処理
sendandreceive();
});
});
</script>
</head>
<body>
<h2>JSON TEST</h2>
<div id="target"></div>
<br>
<input id="sendjson" type="button" value="送信">
</body>
</html>