prototype.jsを利用したイベントの登録について

このQ&Aのポイント
  • prototype.jsを使ったイベントの登録方法について困っています
  • イベントの登録で動的に生成した要素の背景色がうまく変更されません
  • コードを確認したところ、リスナー関数で最後に生成された要素のみが変更されてしまっています
回答を見る
  • ベストアンサー

prototype.jsを利用したイベントの登録について

はじめまして。 現在 prototype.js 1.4.0 を利用して、Web ページの作成を行っているのですが、イベントの登録 (Event.observe)でやりたいことと、異なる動作になってしまい困っているところです。 [ やりたいこと ] javascript側で動的に生成した各要素 (div) に対して moueover & mouseout のイベントを割り当てる。mouseover 時には background の値を変え mouseout 時には background の値を元(transparent)に戻す。 [ 困っていること ] 各要素のmouseover & mouseout 時には各要素の背景色が変更されるはずなのに、一番最後に生成した要素の背景が変更されてしまう。 [ コード ] <html> <head> <script type="text/javascript" src="prototype.js" ></script> <script type="text/javascript"> view = new Class.create(); view.prototype = { initialize:function() { var view = $('viewContents'); var idName = 'test'; for (var i=0; i<10; i++) { var id = idName + i; var d = document.createElement('div'); d.id = id; d.innerHTML = id; view.appendChild(d); Event.observe(d,'mouseover',function() {d.style.background='#aaa';}.bind(this),false); Event.observe(d,'mouseout' ,function() {d.style.background='transparent';}.bind(this),false); Event.observe(d,'click' ,function() {alert(d.id);}.bind(this),false); } } } </script> </head> <body> <p><input type="button" onclick="new view();" value="取得"></p> <div id="viewContents"></div> </body> </html> となります。 なにか基本的なところが間違っているのでしょうか? よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

#1>…ということでよろしいのでしょうか? 私の理解している処(なので、間違っているかも知れません、話半分で聴いて下さい)では、 コールバック関数にbind(this)すると言うことは、this(この場合は、view)の中でその関数を呼び出すことです。 ここで呼び出される関数は、定義された時の(dの)値を中味として実行されるのではなくて、呼び出された時にその(dの)中味を実行するので、ループが終了した最後のd(ループで置き換えられるから)が使われるのだと思います。(つまり変数名でアクセスされその定義した時の中味にアクセスされるのではない) なので、この場合、dを1つの変数でアクセスするのでなく、それぞれのオブジェクトでアクセスできた方がいいとわかります。 それで、this.div にしてみました。 view のままでも配列にして保持するとか Event.observe を使わないで d.onclick=function(){alert(this.id)}; のようにもできると思います。 また、 click:function(){ alert(this.div.id); } のようにメソッド定義をして Event.observe(this.div,'click', this.click.bind(this),false); のようにもできると思います。(どちらかというと、こちらの方がbindしてるという感じになるような)

maxfactor
質問者

お礼

丁寧なご説明ありがとうございます。 >呼び出された時にその(dの)中味を実行するので、ループが終了した最後のd(ループで置き換えられるから)が使われるのだと思います。 で、何とかですが理解することができました。 ありがとうございました。

その他の回答 (1)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

prototype.js って普段使っていないのでオオボケかましてたらすみません。 >基本的なところが間違っているのでしょうか? 質問にあるソースでbind(this) されている'this' は、何かということを勘違いされているのだと思います。 なるべく、元の形を活かして書き直してみました。 ---------------------------------------------------------------- <script type="text/javascript"> cDiv = new Class.create(); cDiv.prototype = { initialize:function(id, html){ this.div = document.createElement('div'); this.div.id = id; this.div.innerHTML = html; //better? : bind -> bindAsEventListener Event.observe(this.div,'mouseover', function(){this.div.style.background='#aaa';}.bind(this),false); Event.observe(this.div,'mouseout', function(){this.div.style.background='transparent';}.bind(this),false); Event.observe(this.div,'click', function(){alert(this.div.id);}.bind(this),false); } }; view = new Class.create(); view.prototype = { initialize:function() { var view = $('viewContents'); var idName = 'test'; for (var i=0; i<10; i++) { var id = idName + i; var div = new cDiv(id, id).div; view.appendChild(div); } } }; </script>

maxfactor
質問者

お礼

書き直していただいたコードで実行することにより、期待した動作になりました。ありがとうございます。 >bind(this) されている'this' は、何かということを勘違いされているのだと思います。 ですが、動的に生成した要素の Class オブジェクト一つ一つにイベントを登録しないといけないのに、ひとつしか生成していない View オブジェクトにイベントを割り当てたために、おかしな動作になってしまった。 ということでよろしいのでしょうか?

関連するQ&A

  • Event.observeで、入れ子divタグでのmouseoutイベントについて

    box1の中にbox2、box2の中にbox3と入れ子になったDIVタグがあります。 box1の外側へカーソルが外れた際にイベント発生させたくて以下のような コードを用意しましたが、box1の内側へカーソルを移動し、box2へカーソルが重なった時にもイベントが発生してしまいます。 box1の外側に外れたときだけイベントが発生するようにしたいのですが、どのように記述したらよいのでしょうか? また、入れ子になったbox2、3でイベントが発生しないよう、イベントを発生させたいオブジェクトとイベントが発生したオブジェクトを比較していますが、もっとスマートな方法はあるのでしょうか? ご助力お願いいたします。 <html> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8"> <title>mouseout</title> <script type="text/javascript" src="/js/prototype.js"></script> <script type="text/javascript"> <!-- window.onload = function () { Event.observe( $("box1"), "mouseout",out,true ); } function out(event) { var p = Event.findElement(event,'div.parent'); var e = Event.element(event); if(p!=e) return; $("tt").innerHTML = e.id+"からmouseout<br />"+$("tt").innerHTML; Event.stop(e) } // --></script> <style> #box1{ background: #ccc; padding: 10px; } #box2{ background: #ddd; padding: 10px; } #box3{ background: #eee; padding: 10px; } </style> </head> <body> <h1>mouseout</h1> <div id="box1" class="parent">ボックス1 <div id="box2">ボックス2 <div id="box3">ボックス3</div> </div> </div> </div> </body> <div id="tt"></div> </html>

  • Ajax.Updaterで読み込んだ先の要素にイベントを設定したい

    Ajaxの勉強をしているのですが、非同期通信で要素を書き換えた後の処理について困っています。 現在、prototype.jsのAjax.Updaterを利用して下記のようなソースを書き、動作の検証を行っているのですが、読み込み元のファイル(test.1html)から読み込んだ先(test2.html)の要素を取得することは出来ても、その要素に対してイベントを設定することが出来ません。 具体的に言うと、 targ2の要素をクリックすると、test2.html内のtarg3の要素を取得出来てアラートが走りますが、targ3の要素をクリックしてもイベントが実行されないという状況です。 このtarg3の要素に対してイベントを設定するにはどのようにすれば良いでしょうか? ○test1.html <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Ajaxtest</title> <script src="prototype.js"></script> <script> window.onload=function(){ Event.observe('targ1', 'click', handler1); Event.observe('targ2', 'click', handler2); Event.observe('targ3', 'click', handler3); } function handler1() { var myajax = new Ajax.Updater(      {success : "targetString"},      "test2.html",      {evalScripts:true}); } function handler2() { alert($('targ3').innerHTML); } function handler3() { alert($('targ3').innerHTML); } </script> </head> <body> <div id="targ1">押して非同期通信開始</div> <div id="targ2">非同期通信終了後に押す</div> <div id="targetString"></div> </body> </html> ○test2.html <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Ajaxtest</title> </head> <body> <div id="targ3">非同期通信で呼ばれた要素</div> </body> </html>

    • ベストアンサー
    • AJAX
  • jQueryで指定された要素のIDに触れた時イベントを起こしたいのです

    jQueryで指定された要素のIDに触れた時イベントを起こしたいのですがうまくいかずに困っています。 jQuery(document).ready(function($) { var msg = ""; $("#Div11").mouseover(function() { msg = "おはよ" alert(msg); }); $("#Div2").mouseover(function() { msg = "こんにちは" alert(msg); }); $("#Div3").mouseover(function() { msg = "うっすー" alert(msg); }); $("#Div4").mouseover(function() { msg = "お疲れ様でした" alert(msg); }); $("#Div5").mouseover(function() { msg = "こんばんは" alert(msg); }); }); このような記述をしているのですがIDに触れた時、値を代入してメッセージを表示させたいのですが出来ません。 どなたかご教示願います!

  • prototype.js で $ is not defined になってしまう!

    JSバージョン:prototype1.6 ブラウザ:Firefox2.0、IE7.0 OS:WinXPpro でシンプルに <html> <head> <title>$ - 指定idのエレメントを取得</title> </head> <script type="text/javascript" src="/js/prototype.js?aaads"></script> <script type="text/javascript"> function test1() { var element = $('div1'); alert(element.innerHTML); } </script> <body> <div id="div1">DIV1の中身</div> </body> </html> を実行したところ、$ is not defined と エラーになってしまいます。 あるレンタルサーバにUPして動かすと問題なく、 ローカルPCで実行するとエラーになってしまうようです。 どなたか教えて下さい!!!

  • 【javascript 文法】値渡し?参照渡し?

    以下実行すると、AAAをクリックしてもBBBをクリックしても「BBB」とアラートされます。 <html> <head> <script type="text/javascript" src="prototype.js"></script> </head> <body> <script type="text/javascript"><!-- var gDown= false; var div = document.createElement('div'); div.id = 'AAA'; div.innerHTML = 'AAA'; document.body.appendChild(div); Event.observe(div, 'mousedown',function(){ gDown = div; }); var div = document.createElement('div'); div.id = 'BBB'; div.innerHTML = 'BBB'; document.body.appendChild(div); Event.observe(div, 'mousedown',function(){ gDown = div; }); Event.observe(document, 'mouseup',function(){ alert(gDown.id); gDown=false; }); //--></script> </body> </html> javascriptって値渡しだと思っていたので、期待した動作と異なります。参照渡しだと考えると納得できるのですが、javascriptって 参照渡し?それとも値渡し? と混乱しています。 この辺のところを、教えてください。お願いいたします。

  • prototype.jsのコード

    の中に分からないものがあります。 var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x} } ・・・・・・・・・ のなかの '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)' 特に (?:<script.*?>)と(?:<\/script>) の部分です。 これらは正規表現だと思うのですが (?: の意味を教えてください。

  • Prototypeを使っていて困ったことがあります。

    Prototypeを使っていて困ったことがあります。 以下のようなソースでprototypeでtest.htmlを読み込みました。 そしたら困った事が2点出てきました。 (1)test.html内のjavascriptが動かない test.html内で使用しているprototypeやjquery等が全く動きません。 何か解決策はあるのでしょうか? (2)test.htmlからtest1.htmlのdiv idに対して更新が行えない 読み込んだ先でも読み込み元のdiv idにファイルで更新が出来ると思い込んでおり これが出来ない為、かなり致命的な事になってしまいました。。 何とかできないでしょうか? [test1.html] <html> <head> <script type="text/javascript" src="./js/prototype.js"></script> <script type="text/javascript"> function test() { new Ajax.Updater('title','test.html',{method: 'get'}); } </script> </head> <body> <div id="title"> ここにファイルを読み込む。 </div> <input type="button" value="操作" onclick="test()"/> </body> </html> 以上、よろしくお願いします。

  • js プロトタイプ

    javascriptソースコード <!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> </head> <body> <script type="text/javascript" src="jquery-1.7.2.min.js"></script> <script src="fastclick.js"></script> <script> function print(str){ document.write(str + "<br />"); } function Car(manufact, name){ this.manufact = manufact; this.name = name; } Car.prototype.info = function(){return this.manufact + " " + this.name;}; document.write("<p>"); var car1 = new Car("Toyota", "PRIUS"); print(car1.info()); var car2 = new Car("Honda", "INSIGHT"); print(car2.info()); document.write("</p>"); </script> </body> </html> 23行目なのですが「 Car.prototype.info 」とありますがjsにおいてプロトタイプはオブジェクトだという事は認識しておりますがプロトタイプを宣言する意味は何があるのでしょうか? 参考urlです。 http://www.ajaxtower.jp/js/function_class/index3.html

  • 複数のイベントリスナーを設置するのは正しい?

    クリック時、マウスオーバー時、マウスアウト時の処理を作るとき、 イベントリスナーの使い方はこのようなやり方でよいでしょうか。 var d = document.getElement.ById("id"); d.addEventListener('click', function(e){ var tar=e.target; tar.style.backgroundColor ="#000000"; },false); d.addEventListener('mouseover', function(e){ var tar=e.target; tar.style.backgroundColor ="#aaaaaa"; },false); d.addEventListener('mouseout', function(e){ var tar=e.target; tar.style.backgroundColor ="#555555"; },false);

  • prototype.jsを利用して

    よろしくお願いします。prototype.jsを使い、 データバインドを利用せず、csvファイルを読込ませ、safariで 表示できるようにサンプルを利用して作成しました。 csvのレコードは400くらいあります。このレコードデータを テーブル3列の繰り返しで表示したいのですが、以下のソースで 行うようにするとどうしても3列表示したら繰り返しせず 終了してしまいます。 3列表示させる部分の値を変数へ渡してループにすれば出来るような感じがするのですが、そのように想定したものを記述してもどうしても 3列で終了してしまいます。 データバインドで散々質問したのですが、再度お知恵をお借りしたいです。どうかよろしくお願いします。 --------------------------------------------------------------- <script type="text/javascript" src="prototype.js"></script> <script type="text/javascript"> <!-- window.onload = function(){ var msec = (new Date()).getTime(); new Ajax.Request("list2.csv", { method: "get", parameters: "cache="+msec, onSuccess:function(httpObj){ var text = httpObj.responseText; var LF = String.fromCharCode(10); var tabText = text.split(LF); var color= "red"; var leng=tabText.length; var retu=0; var cnt=0; var m=0; var tbl = "<table border='1'>"; var tbb = "<td><table border='1'>"; while(cnt<3){ //試しに3回ループさせてみる tbl += "<tr>"; var w=m; var a=w; var s=w+1; var f=0; while(retu<3){ //3列分表示 tbl += "<td><table border='1'>"; for (var i=a; i<s; i++){  var cText = tabText[i].split(","); tbl += "<tr><td><img src="+cText[0]+"></td></tr>"; tbl += "<tr><td>"+cText[1]+"</td></tr>"; tbl += "<tr><td>"+cText[2]+"</td></tr>"; tbl += "<tr><td>"+cText[3]+"</td></tr>"; tbl += "<tr><td>"+cText[4]+"</td></tr>"; tbl += "<tr><td>"+cText[5]+"</td></tr>"; } a=a+1; s=s+1; retu++; tbl += "</table></td>"; } tbl += "</tr></table>"; cnt++; m=m+3; } $("tableData").innerHTML = tbl+color+leng+a; //変数で表示させたいものをここで宣言 }, onFailure:function(httpObj){ $("tableData").innerHTML = "エラーで読み込めませんでした"; } }); } //--> </script>

専門家に質問してみよう