主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

動的Webページの作り方に関して2

                
tags:
動的にページ要素を追加していき、そのそれぞれにイベントを追加したかった。やり方に手間取ったのでメモ。

0から3までマウスイベントが設置されない。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Amazonの歩き方</title>
<link href="stylesheets/main.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/form.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="xml2json.js"></script>
<script type="text/javascript">
function showNumber(num){
alert(num);
}

function onLoad(){
var str = "";
var event = "";
for (var x=0; x<5; x++){
str = '<div id="camus'+x+'">'+x+'</div>';
document.getElementById("camus").innerHTML += str;
event = function(){showNumber(x);};
document.getElementById("camus"+x).onmousedown = event;
}
}

</script>
</head>
<body onload=onLoad()>
hell
<div id="camus"></div>
</body>
</html>


マウスイベントは設置されるが、すべて"5"が表示される。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Amazonの歩き方</title>
<link href="stylesheets/main.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/form.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="xml2json.js"></script>
<script type="text/javascript">
function showNumber(num){
alert(num);
}

function onLoad(){
var str = "";
var event = "";
for (var x=0; x<5; x++){
str = '<div id="camus'+x+'">'+x+'</div>';
document.getElementById("camus").innerHTML += str;
}
for (x=0; x<5;x++){
document.getElementById("camus"+x).onmousedown = function(){showNumber(x);};

}
}

</script>
</head>
<body onload=onLoad()>
hell
<div id="camus"></div>
</body>
</html>


解法1:HTMLタグ内にイベントを書く

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Amazonの歩き方</title>
<link href="stylesheets/main.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/form.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="xml2json.js"></script>
<script type="text/javascript">
function showNumber(num){
alert(num);
}

function onLoad(){
var str = "";
var event = "";
for (var x=0; x<5; x++){
str = '<div id="camus'+x+'" onmousedown=showNumber('+x+')>'+x+'</div>';
document.getElementById("camus").innerHTML += str;
}
}

</script>
</head>
<body onload=onLoad()>
hell
<div id="camus"></div>
</body>
</html>


解法2: クロージャを使う
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<link href="stylesheets/main.css" rel="stylesheet" type="text/css" />
<link href="stylesheets/form.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="xml2json.js"></script>
<script type="text/javascript">

function showNum(num){
function inner(){
alert(num);
}
return inner;
}

function onLoad(){
var str = "";
for (var x=0; x<5; x++){
str = '<div id="camus'+x+'">'+x+'</div>';
document.getElementById("camus").innerHTML += str;
}
for (x=0; x<5;x++){
//document.getElementById("camus"+x).onmousedown = showNum(x);
document.getElementById("camus"+x).addEventListener("click", showNum(x), false);
}
}

</script>
</head>
<body onload=onLoad()>
hell
<div id="camus"></div>
</body>
</html>



まとめ
ある関数を実行せず式のまま渡し、なんらかの条件が整ったときにその関数を実行しようということがぼちぼちある。たとえばXMLリクエストを送りなんらかのレスポンスを得たとき(XMLHttpRequest.onreadystatechange)。はたまた今回のようにマウスイベントをキャッチしてアラートウィンドウを表示するときなど(addEventListener)。

今回のケースで考える。ページ内のクリックした数字をアラートウィンドウで表示したい。じゃあaddEventListenerやエレメントのonclick要素に式を渡してやればいい。

たとえば、実行するとアラートウィンドウを表示するmyFuncという関数を宣言してあったとする。
function myFunc(){
alert("camus");
return false;
}

そしたらやるべきは、イベントを扱う要素に式を渡すということ。関数の実行結果ではない。つまり、
document.getElementById('00').onclick = myFunc();
document.getElementById('00').addEventListener("click", myFunc(), false)
上記は間違い。式を渡すので、
document.getElementById('00').onclick = myFunc;
document.getElementById('00').addEventListener("click", myFunc, false)
と表記すればいいわけだ。

そしたらそしたで引数を渡せない。そのときのためにまず関数リテラルがある。まずmyFuncを引数を取る形に宣言しなおす。
function myFunc(str){
alert(str);
return false;
}

であとは式として代入できるようにリテラルにする。
document.getElementById('00').onclick = function(){myFunc('camus');};
こうしておくと、myFuncに引数として文字列"camus"を与えた関数が、しかるべきイベントが発生したときに実行される。実行されるのはしかるべきイベントが発生したときだ。

このイベントが発生したときに実行される、というのが今回ネックになった。for文を使って引数を変えながらイベントを登録していくとしよう。
for(var x=0;x<5;x++)
だとする。
document.getElementById(x).onclick = function(){myFunc(x);};
わたしは最初、こう書いておけばタグのIDが0ならクリックすればアラートで0を表示、IDが1ならアラートで1、2なら2というふうにイベントが生成、登録されていくと思っていた。しかしあくまで、登録されているイベントはmyFunc(x)だった。xが評価されるのはイベント発生時であり、関数登録時ではない。だからどの要素をクリックしても5が表示された。

じゃあfor文を使ってイベントを登録していきたいときにはどうすればいいのか。ここでクロージャの出番だ。myFuncをまた書き換える。
function myFunc(str){
function inner(str){
alert(str);
}
return inner;
}

myFuncの変更にともなってイベント登録を書き直す。
document.getElementById(x).onclick = myFunc(x);
この状態は端的にいえば、引数にしたがって式をある程度まで実行していますという状態だ。ここでは引数xをstrという変数に入れておいて、innerという関数を中で宣言しましたよという状態。xはこのイベント登録の時点で評価されている。したがってfor文でのイベント生成にも対応できる。
            

コメントの投稿

非公開コメント

プロフィール

Matoba

Author:Matoba

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。