イベントハンドラの取り付け

onclick=を設定する

次のimg1などはspan要素です。下の[ボタンにする]ボタンで、イベントハンドラが取り付けられてボタンになり、画像を切り替えられるようになります。

img1 img2 img3

説明図

属性の取得と変更で述べたようにonclick="hoge"などのイベントハンドラも src=, class=, style=,... の様に属性なのでsetAttribute()メソッドを使って操作が可能です。

プログラム

<p id="ev01" class="btns">
<span>img1</span>
<span>img2</span>
<span>img3</span>
</p>
<p>
<img src="images/npkamo.jpg" id="area1">
</p>
<p><button type="button" onclick="setevent01()">ボタンにする</button>
<button type="button" onclick="resetevent01()">元に戻す</button>
</p>
<script>
function setevent01(){
   var elmev01 = document.getElementById("ev01");
   var spans = elmev01.getElementsByTagName("span");
   spans[0].setAttribute("onclick","showimg1()");
   spans[1].setAttribute("onclick","showimg2()");
   spans[2].setAttribute("onclick","showimg3()");
}
function resetevent01(){
   var elmev01 = document.getElementById("ev01");
   var spans = elmev01.getElementsByTagName("span");
   spans[0].removeAttribute("onclick");
   spans[1].removeAttribute("onclick");
   spans[2].removeAttribute("onclick");
}
function showimg1(){
   document.getElementById("area1").src = "images/npbellflow.jpg";
}
function showimg2(){
   document.getElementById("area1").src = "images/nptombo2.jpg";
}
function showimg3(){
   document.getElementById("area1").src = "images/npnanakamado.jpg";
}
</script>

ここで大切なのは、setAttribute()の引数が2つの文字列であることです。引数や、thisキーワードについても理解しやすくなります。.onclickなどのプロパティの設定を使うと、いろいろ厄介ですので、授業用にはsetAttribute()を使っていました。

授業で使ったページをウェブに公開するときに、当時まだ IE ver6 が多く残っていて、これがsetAttribute()に対応しなので .onclickを使う様に変更しようとして苦労しました。今時のIEは ver9以上であると考えられますから、setAttribute()を使えばよいでしょう。src, class, styleなど他の属性と統一的に考えられることもメリットと言えます。

ちなみにボタン化されたときに視覚的にもボタンに見えるのは予め設定されたcssによります。cssのセレクタに詳しくない場合は、プログラムでclass属性も変更するほうがわかりやすいかもしれません。

span[onclick]{
  border:outset 2px #999;
  background:#eee;
  margin:4px;
  padding:2px 4px 2px 4px;
  cursor: pointer;
}
span[onclick]:active{
  background:#ee0;
  border:inset 2px #999;;
}

関数に引数をつける時

上記の例のように、閲覧者が操作することでイベントハンドラの設定を変更するのは面白い仕掛けではありますが、実際にはページを読み込んだ時点で自動的にイベントハンドラを設定するプログラムにすると思います。onclickの代わりにonloadで行います。

ただそれでは、あらかじめ onclick="hogehoge()" と書く場合と使用感が変わらないので、閲覧者の操作で動くようにしました。

onloadの場合、イベントハンドラを取り外す必要は少ないと思いますから、removeAttribute()ボタンは今後省略します。

上記の例では、画像ごとにfunctionを作っていますが、引数を使うのがスマートです。つまり次のようにしたいのです。

<p class="btns">
<span onclick="showimg('hoo02.jpg')">img1</span>
<span onclick="showimg('hoo03.jpg')">img2</span>
<span onclick="showimg('hoo04.jpg')">img3</span>
</p>
<p>
<img src="images/hoo01.jpg" id="area2">
</p>
<script>
function showimg(filename){
   document.getElementById("area2").src = "images/"+filename;
}
</script>

ファイル名が連番でついていることが多いでしょう。こんなときはプログラムで取り付けたくなります。

というわけで、

img1 img2 img3

朴の木の花

プログラム

<p id="ev02" class="btns">
<span>img1</span>
<span>img2</span>
<span>img3</span>
</p>
<p>
<img src="images/hoo01.jpg" id="area2">
</p>
<p><button type="button" onclick="setevent02()">ボタンにする</button>
</p>
<script>
function setevent02(){
   var elmev01 = document.getElementById("ev02");
   var spans = elmev01.getElementsByTagName("span");
   for(var i=0;spans.length>i;i++){
      spans[i].setAttribute("onclick","showhoonoki("+(i+2)+")");
   }
}
function showhoonoki(n){
   document.getElementById("area2").src = "images/hoo0"+n+".jpg";
}
</script>

数値引数の説明

上の例は引数が数値です。javascriptは変数が数値であるか文字列であるかは状況によります。

forの中のsetAttribute内でi+2を括弧でくくって先に処理しています。iはもともとforの制御変数ですから数値です。2を足すのは数値として扱われます。その後"showhoonoki("という文字列と"+"演算子で文字列に変換されて結合されます。結果としてここでは"showhoonoki(2)"などの文字列になります。

ちなみに(i+2)に括弧がないと+2する前にiが文字列に変換されて結合され、"showhoonoki(02)"から始まって 02,12,22,となって行きます。

これで onclick="showhoonoki(2)" などと設定されるのですが、クリックされると、括弧内は数値と解釈されます。

function showhoonoki(n) ではnには数値が代入されます。

images/hoo0"+n+".jpg" でnが再び文字列に変換されて "hoo02.jpg" などのファイル名となりうまく働きます。

もしも、01,02,から09,10,11と頭が0でない数値が出てくるような場合には、

   document.getElementById("area2").src ="images/hoo"+('00'+n).slice(-2)+".jpg";

のようにします。

thisキーワード

画像に直接onclick属性を設定できます。この時thisキーワードを使うとクリックした要素を引数で渡すことができます。

flagflagflagflagflagflag

プログラム

<p class="reds" id="ev03">
<img src="images/redof.png"><img src="images/redof.png">....繰り返し(省略).....
</p>
<p><button type="button" onclick="setevent03()">ボタンにする</button>
</p>
<script>
function setevent03(){
   var elmev01 = document.getElementById("ev03");
   var imgs = elmev01.getElementsByTagName("img");
   for(var i=0;imgs.length>i;i++){
      imgs[i].setAttribute("onclick","changeimg(this)"); 
      imgs[i].setAttribute("class","clickable"); 
   }
}
function changeimg(koko){
   if(koko.getAttribute("src")=="images/redof.png"){
      koko.setAttribute("src","images/redon.png");
   }else{
      koko.setAttribute("src","images/redof.png");
   }
}
</script>

onclick属性の設定はsetAttribute()の方が都合が良いので、src, class も合わせてsetAttribute()を使っています。

changeimg(koko)のkokoはthisを受ける引数ですが、数値でも文字列でもなく、クリックされた要素を表すオブジェクトです。

onmouseover

thisを使い、onmouseoverを設定してみます。画像の変化を比較(jpg品質)で紹介したものと同じですがsetAttribute()を使っているところが異なります。向こうはプロパティを使っています。

圧縮後の品質
下の数字で品質を選択
品質100908070605040302010 0

マウスで品質の数字なぞると、それに合わせた画像に変わります。クロガネモチの花の写真を拡大したものです。

プログラム

<div class="table">
<table class="comp">
<tr>
<td><img src="images/kuroge100.png" id="ev04" alt="圧縮後の品質"></td>
</tr>
<tr><td id="text04">下の数字で品質を選択</td></tr>
<tr><td id="spans04" class="comp">品質<span>100</span><span>90</span><span>80</span><span>70</span><span>60</span><span>50</span><span>40</span><span>30</span><span>20</span><span>10</span> <span>0</span>
</td></tr>
</table>
</div>
<p><button type="button" onclick="setevent04()">ボタンにする</button>
</p>
<script>
var imgnm = "kuroge";
var ext   = ".png";
var lasttxt = null;
var imgtarget;
var txtnode;
function setevent04(){ 
    imgtarget = document.getElementById("ev04");
    txtnode = document.getElementById("text04").firstChild;
    var tmp = document.getElementById("spans04");
    var spans = tmp.getElementsByTagName("span");
    for (var i=0;spans.length>i;i++){
       spans[i].setAttribute("onmouseover","msover(this)"); 
    }
}
function msover(koko){
    if (lasttxt) lasttxt.setAttribute("style","background-color:transparent");
    koko.setAttribute("style","background-color:#00ffff");
    var code = koko.firstChild.nodeValue;
    txtnode.nodeValue = "品質 " + code + "%";
    imgtarget.setAttribute("src","images/"+imgnm+code+ext);
    lasttxt= koko;
}
</script>