Javascriptで、アコーディオン風のことをしたいと考えています。


そこで下記のコードを実行するとFirefoxだと、意図どおりクラス名の操作ができます。しかしIE系の場合thisの値がうまく渡せていないためエラーが起きてしまいます。

IEでも、うまくthisを渡す方法はありまでしょうか。

<html>
<body>

<ul class="test">
<li class="class_visible">リスト<span>追加領域</span></li>
<li>リスト<span>追加領域</span></li>
<li>リスト<span>追加領域</span></li>
</ul>


<script type="text/javascript" src="http://www.prototypejs.org/assets/2007/11/6/prototype.js"></script>
<script type="text/javascript"><!--

$$("ul.test li").invoke(
'observe',
'mouseover',
function (){
if( ! this.hasClassName("class_visible") ){
$A(this.parentNode.getElementsByTagName("li")).each( function(e){
e.removeClassName("class_visible");
});
}
this.addClassName("class_visible");
}
);

--></script>

<style type="text/css">
ul.test li span{
display: none;
}
ul.test li.class_visible span{
display: block;
}
</style>


</body>
</html>

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2008/05/14 16:10:32
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:openseed No.1

回答回数51ベストアンサー獲得回数6

ポイント60pt

こんな感じでいかがでしょう。



var page = this;
$$("ul.test li").invoke(
'observe',
'mouseover',
function (event){
var elem = event.srcElement ? event.srcElement : this;

if( ! elem.hasClassName("class_visible") ){
$A(elem.parentNode.getElementsByTagName("li")).each( function(e){
e.removeClassName("class_visible");
});
}
elem.addClassName("class_visible");
});

質問とは異なりますが、以下のサイトが参考になるかもしれません。

http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8...

http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8...

id:flar

ご回答ありがとうございます。なるほど。やはり回避策としては、eventが起きた要素を取得するという形になりますでしょうか。

私もひとまず、実装時は下記で回避しました。

var elem = Event.findElement(event, "li");

ご案内いただいたevent.srcElement、またはprototype.js的に言えば、Event.Element(event)だけですと、マウスのフォーカス位置によっては、liに内包されているspan等の要素がelemに返却されてしまうので、Event.findElementを使ってliまでさかのぼっています。


やはりthisの使い方、考え方としては、こういったイベントまわりでは使わずに、イベントが起きた要素を取得するというやり方が適切になるんでしょうか?

2008/05/10 10:30:55
  • id:openseed
    Event.findElement(event, "li");
    の方が、確かに良いですね。

    気になったので、調べてみました。
    今回の動作の相違(IE/FF)は、attachEventとaddEventListener の違いによるもののようです。

    <a href="#" id="a1" onclick="a();">a1</a>
    <a href="#" id="a2">a2</a>
    <a href="#" id="a3">a3</a>

    <script type="text/javascript"><!--
    function a(){
    alert(this.tagName ? this.tagName : (this == window ? "window" : this))
    }
    document.getElementById('a2').onclick = a;

    if(window.attachEvent){
    document.getElementById('a3').attachEvent('onclick', a);
    }else{
    document.getElementById('a3').addEventListener('click', a, false);
    }
    --></script>

    また、this についてですが、Event周りで利用するのが問題なのではなく、
    匿名メソッドの中で this の扱いに注意する必用があるかもしれません。
    ※ 基本的に、匿名メソッドの中では、混乱を防ぐために、this は、できる
    だけ使わないほうが良いかもしれません。

      var testThis = function(title){
        alert(title + " : " + this.name);
      };

      window.name = "window";
      var A = {name: 'A', testThis: testThis};
      var B = {name: 'B'};

      testThis("testThis()"); // window
      testThis.call(A, "testThis.call(A)"); // A
      A.testThis.call(B, "A['testThis'].call(B)"); // B

      B.testThis = testThis;
      B.testThis("B.testThis()"); // B


    参考になれば幸いです。
  • id:flar
    なるほどなるほど。attachEventとaddEventListener の仕様の違いですか。

    やはりprototype.jsを使うにしてもある程度、ライブラリーの中身を把握して置くとこういった場合検証ができますね。
    ありがとうございました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません