Javascriptに関する質問です。

ゆっくり開閉するプルダウンメニューに関する解説サイトを教えてください。
「prototype」や「script.aculo.us」を組み合わせて、なんとか実現できそうな所までは分かったのですが、何故かうまく稼動しなくて困っております。

なお、メニューはOnClickではなく、OnMouseやOutMouseでイベント判定をし、プルダウンするメニューを作りたいと考えております。

どなたかお心当たりの方がいらっしゃいましたら、よろしくお願い致します。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:
  • 終了:2006/11/25 11:30:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:meenie No.1

回答回数2ベストアンサー獲得回数0

ポイント60pt

スムーズに開閉するタイプのサンプルページです。

ソースもダウンロードできますよ。

http://www.dynamicdrive.com/dynamicindex1/switchmenu2.htm

id:susie-t No.2

回答回数99ベストアンサー獲得回数18

ポイント10pt

解説サイトは分からないのですが、参考までに。

私もやってみましたが、script.aculo.usのEffect.BlindUp/Effect.BlindDownはこの件に向いていない気がします。アニメーション途中に更にイベントが発生することは想定していないような。。。

onmouseover、onmouseoutで動作させる場合、メニューのタイトル(最初から見えている部分)と、メニューの内容部分(スクロールする部分)を同一要素に入れ、その親要素のイベントを設定するのがやりやすいと思います。(別にするとタイトル部分からないよう部分へマウスカーソルを動かす度にイベントが発生する)

以下は私が自作したものです。prototype.jsは使用してます。親要素にタイトル、内容の要素をその順番で記述してください(直の子要素は2つだけになります)。その親要素を第一引数にして(ID、要素指定どちらでも可)scrollMenuクラスのインスタンスを作成してください。第二引数で0.01秒ごとにスクロールするpx値を指定できます。無指定時はデフォルトで2になります。

<html>
<head>
<title></title>
<style>
<!--
a{
  color:red;
}
#menu1{
  float:left;
}
.title{
  border:solid blue 2px;
  width:100px;
}
-->
</style>
<script language="javascript" src="prototype.js" charset="utf-8"></script>
<script>
<!--
//scrollMenuクラス
var scrollMenu = Class.create();
scrollMenu.prototype = {
  initialize: function(obj, speed){
    this.obj = $(obj);
    this.speed = speed || 2;
    Element.cleanWhitespace(this.obj);
    this.title = this.obj.childNodes[0];
    this.menu = this.obj.childNodes[1];
    Element.setStyle(this.menu, {
      visibility:'hidden',
      position:'absolute',
      overflow:'hidden',
      display:'block'
    });
    var bkp = Element.getStyle(this.menu, 'height');
    Element.setStyle(this.menu, {height:''});
    this.height = Element.getHeight(this.menu);
    var value = Position.cumulativeOffset(this.title);
    var left = value[0];
    var top  = value[1] + Element.getHeight(this.title);
    Element.setStyle(this.menu, {
      height:'1px',
      left:left,
      top:top
    });
    Event.observe(this.obj, 'mouseover', this.start.bind(this), false);
    Event.observe(this.obj, 'mouseout', this.stop.bind(this), false);
  },

  start: function(){
    Element.setStyle(this.menu, {
      visibility:'visible'
    });
    if(this.tid) clearTimeout(this.tid);
    this.tid = setInterval(this.show.bind(this), 10);
  },

  show: function(){
    var height = parseInt(Element.getStyle(this.menu, 'height'));
    height += this.speed;
    if(height >= this.height){
      height = this.height;
      clearTimeout(this.tid);
    }
    Element.setStyle(this.menu, {height:height + 'px'});
  },

  stop: function(){
    if(this.tid) clearTimeout(this.tid);
    this.tid = setInterval(this.hide.bind(this), 10);
  },

  hide: function(){
    var height = parseInt(Element.getStyle(this.menu, 'height'));
    height -= this.speed;
    if(height <= 1){
      height = 1;
      Element.setStyle(this.menu, {
        visibility:'hidden'
      });
      clearTimeout(this.tid);
    }
    Element.setStyle(this.menu, {height:height + 'px'});
  }
}
//onloadイベントでインスタンス作成
Event.observe(window, 'load', function(){
  new scrollMenu('menu1');
  new scrollMenu('menu2');
}, false);
//-->
</script>
</head>
<body>

<div id="menu1">
<div class="title">MENU 1</div>
<div>
┣ <a href="リンク先URL">MENU1-1</a><BR>
┣ <a href="リンク先URL">MENU1-2</a><BR>
┗ <a href="リンク先URL">MENU1-3</a><BR>
</div>
</div>

<div id="menu2">
<div class="title">MENU 2</div>
<div>
┣ <a href="リンク先URL">MENU2-1</a><BR>
┣ <a href="リンク先URL">MENU2-2</a><BR>
┗ <a href="リンク先URL">MENU2-3</a><BR>
</div>
</div>

</body>
</html>

参考になりますでしょうか。

ダミーURL:http://q.hatena.ne.jp/

id:susie-t No.3

回答回数99ベストアンサー獲得回数18

ポイント10pt

コメントしたとおり、2の回答だとレイアウトが崩れる場合があります。改善したものを提示します。注意として、メニュータイトルと内容の幅をスタイル指定するようにしてください(下ではtitleクラスとcontentsクラスのwidth)。

バタバタしてしまってすみません・・・。

<html>
<head>
<title></title>
<style>
<!--
a{
  color:red;
}
.menu{
  float:left;
}
.title{
  border:solid blue 2px;
  width:100px;
}
.contents{
  width:100px;
}
-->
</style>
<script language="javascript" src="prototype.js" charset="utf-8"></script>
<script>
<!--
//scrollMenuクラス
var scrollMenu = Class.create();
scrollMenu.prototype = {
  initialize: function(obj, speed){
    this.obj = $(obj);
    this.speed = speed || 2;
    Element.cleanWhitespace(this.obj);
    this.title = this.obj.childNodes[0];
    this.menu = this.obj.childNodes[1];
    Element.setStyle(this.menu, {
      visibility:'hidden',
      position:'absolute',
      overflow:'hidden',
      display:'block',
      height:'1px'
    });
    Event.observe(this.obj, 'mouseover', this.start.bind(this), false);
    Event.observe(this.obj, 'mouseout', this.stop.bind(this), false);
  },

  start: function(){
    var bkp = Element.getStyle(this.menu, 'height');
    Element.setStyle(this.menu, {height:''});
    this.height = Element.getHeight(this.menu);
    var value = Position.cumulativeOffset(this.title);
    var left = value[0];
    var top  = value[1] + Element.getHeight(this.title);
    Element.setStyle(this.menu, {
      left:left,
      top:top,
      visibility:'visible',
      height:bkp
    });
    if(this.tid) clearTimeout(this.tid);
    this.tid = setInterval(this.show.bind(this), 10);
  },

  show: function(){
    var height = parseInt(Element.getStyle(this.menu, 'height'));
    height += this.speed;
    if(height >= this.height){
      height = this.height;
      clearTimeout(this.tid);
    }
    Element.setStyle(this.menu, {height:height + 'px'});
  },

  stop: function(){
    if(this.tid) clearTimeout(this.tid);
    this.tid = setInterval(this.hide.bind(this), 10);
  },

  hide: function(){
    var height = parseInt(Element.getStyle(this.menu, 'height'));
    height -= this.speed;
    if(height <= 1){
      height = 1;
      Element.setStyle(this.menu, {
        visibility:'hidden'
      });
      clearTimeout(this.tid);
    }
    Element.setStyle(this.menu, {height:height + 'px'});
  }
}
//onloadイベントでインスタンス作成
Event.observe(window, 'load', function(){
  new scrollMenu('menu1');
  new scrollMenu('menu2');
  new scrollMenu('menu3');

}, false);
//-->
</script>
</head>
<body>

<div id="menu1" class="menu">
<div class="title">MENU 1</div>
<div class="contents">
┣ <a href="リンク先URL">MENU1-1</a><BR>
┣ <a href="リンク先URL">MENU1-2</a><BR>
┗ <a href="リンク先URL">MENU1-3</a><BR>
</div>
</div>

<div id="menu2" class="menu">
<div class="title">MENU 2</div>
<div class="contents">
┣ <a href="リンク先URL">MENU2-1</a><BR>
┣ <a href="リンク先URL">MENU2-2</a><BR>
┗ <a href="リンク先URL">MENU2-3</a><BR>
</div>
</div>

<div id="menu3" class="menu">
<div class="title">MENU 3</div>
<div class="contents">
┣ <a href="リンク先URL">MENU3-1</a><BR>
┣ <a href="リンク先URL">MENU3-2</a><BR>
┗ <a href="リンク先URL">MENU3-3</a><BR>
</div>
</div>

</body>
</html>

ダミーURL:http://q.hatena.ne.jp/

  • id:susie-t
    すみません、2の回答だとレイアウトが崩れる場合があります。改善案を考えてみます。
  • id:lg-tsp
    ご回答ありがとうございます。かなり参考になりそうです。

    何パターンか試してみたのですが、おっしゃるとおりscript.aculo.usのEffect.BlindUp/Effect.BlindDownでは実現することができそうにありませんでした。

    足元、mootoolsを利用したりしながら組んでおりました。

    ご回答いただいた内容を参考にしつつ、メニューを作成してみたいと思います。
    どうもありがとうございました。

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

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

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

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