Qitailang's HP > webtech

UL画像メニューのマウスオーバー画像を切り替える2

2015/06/28

2014/11/16に記録したメモの改訂版。以前のものは下のような段取りだったが、jquery.rollover.jsを使うなどしてより汎用性のある方法が(中途半端ですが)分かったので忘れないうちにメモメモ。

とりあえず以前の方法

<ul id="menu">
  <li class=active><a href="#"><img src="images/menu_01_off.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_02_off.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_03_off.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_04_off.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_05_off.gif" width=360 height=40 /></a></li>
</ul>

リンク用の画像をマウスオーバーで切り替え、その際現在開いているページのメニュー画像はマウスオーバー時の画像にするというもの。

現在開いているページかどうかは<li>要素に class=active をつけることで処理していた。

すべてのメニュー項目について、非マウスオーバー時の画像(〜_off.gif)とマウスオーバー時の画像(〜_on.gif)を用意しておき、マークアップでは初期値として、すべての画像を非マウスオーバー時の画像にしておく、あとをjQueryで処理。

ul#menu{
  list-style:none;
}
ul#menu li{
  margin-bottom:10px;
}
img{
  border:none;
}
a:focus { /*FireFox用*/
  outline: none;
}
a img{ /*FireFox用*/
  border: none;
}
<script type = "text/javascript" src = "js/jquery-1.10.2.min.js"></script>
<script type = "text/javascript">
$(document).ready(function() {
  $('#menu li.active img').each(function(){
    $(this).attr('src', $(this).attr('src').replace('_off', '_on'));
  });
  $('#menu img').hover(function(){
    $(this).attr('src', $(this).attr('src').replace('_off', '_on'));
    }, function(){
    if (!$(this).parents("li").hasClass('active')) {
      $(this).attr('src', $(this).attr('src').replace('_on', '_off'));
    }
  });
});
</script>

jQueryのコードの意味は、

  1. <li class=active>で括られているimgはマウスオーバー時の画像に切り替えておく。
  2. マウスオーバーしたとき、〜_on.gifに切り替える。
  3. マウスが離れるとき、親要素の li が active クラスでなければ、〜_off.gifに切り替える。
であった。

sample1

改良版

今回は下のように改良した。

  1. 現在開いているページかどうかを自動で判断し、もしそうなら<a>タグに class=activeを追加する。(重要ではないが以前は<li class=active>だった)
  2. マウスオーバー時の画像を〜_off.gifでなく単に〜.gifにした。また.png、.jpgでも使えるように。

class=activeを自動で追加するするのでHTMLソースはより単純になった。

<ul id="menu">
  <li><a href="sample2.html"><img src="images/menu_01.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_02.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_03.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_04.gif" width=360 height=40 /></a></li>
  <li><a href="#"><img src="images/menu_05.gif" width=360 height=40 /></a></li>
</ul>

画像切り替えはjquery.rollover.jsにおまかせ。

<script type = "text/javascript" src = "js/jquery-1.10.2.min.js"></script>
<script type = "text/javascript" src = "js/jquery.rollover.js"></script>
<script type = "text/javascript">
$(document).ready(function() {
  //aタグのリンクページと現在開いているファイルと同じならactiveクラスを追加
  $('ul#menu li a').each(function(){
    var url = $(this).attr('href');
    if(location.href.match(url)) {
      $(this).addClass('active');
    }
  });
  //activeクラスのsrcを 〜.拡張子 => 〜_on.拡張子に変える。_onはsuffixの値で指定する。
  $('ul#menu a.active img').each(function(){
    var suffix="_on";
    var extension=$(this).attr('src').split(".").pop();
    $(this).attr('src', $(this).attr('src').replace('.'+extension, suffix + '.' + extension));
  });
  //マウスオーバー画像を切替える
  $('ul#menu img').rollover("_on");/*"_on"はデフォルトなので省略加*
});
</script>

sample2

追記:汎用化できて便利そうだが、index.htmlなどの場合ファイル名指定なし、つまりhttp://~/~/のようにアクセスされた場合はうまくいかないかもしれない。

$('ul#menu li a').each(function(){
		var url = $(this).attr('href');
		var loc=location.href.split('/').pop();  //ファイル名を取得
		if(loc ==''){  //もし空なら
			loc='index.html'; //index.htmlとする
		}
		if(loc.match(url)) {
			$(this).addClass('active');
		}
	});

などと一応やってみたりするのだが、どうだろう?でも今度はリンクの方が<a href="./index.html">などとなっている場合はうまくいくのだろうか?あまり汎用化してもまずいのかな?

参照サイト:
http://www.coolwebwindow.com/weblife_column/coolweb/000317.php
http://rewish.jp/blog/releases/jquery_rollover

jquery.rollover.js