IMPOV::In My Point Of View

仕事、SEO、ウェブマーケティング、時事問題、健康、生き方などなど、書きたいことを勝手に書き倒しているブログです。とどのつまり「便所の落書き」

メニュー画像のロールオーバー (imgタグ、css background-image 両対応)をする jQuery JavaScript

機能

html の img タグの src もしくは css の background-image の url を読み込んで、ロールオーバー用の画像とハイライト用の画像の両方を自動的にセットします。

■追記(2014.05.06)
画像を事前読み込みして、初回読み込み時にマウスオーバーで画像がチラつくのを回避ししました。
なお、補足ですが、a タグで指定した URL がディレクトリの場合は、その配下のディレクトリ全てのページでハイライトが有効になります。

ソース

html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>メニューロールオーバー</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="js/jquery-1.11.0.min.js"></script>
<script src="js/jquery.menu.rollover.js"></script>
</head>

<body>
<div class="menu">
  <nav>
  <h3>CSS Background-imageを使用したメニュー</h3>
    <ul>
      <li><a href="index.html" class="menu1 rollover-bg"></a></li>
      <li><a href="page2.html" class="menu2 rollover-bg"></a></li>
      <li><a href="page3.html" class="menu3 rollover-bg"></a></li>
    </ul>
  </nav>
</div>

<div class="menu">
  <nav>
  <h3>イメージタグを使用したメニュー</h3>
    <ul>
      <li><a href="index.html"><img src="img/sample1.png" class="rollover-img"></a></li>
      <li><a href="page2.html"><img src="img/sample2.png" class="rollover-img"></a></li>
      <li><a href="page3.html"><img src="img/sample3.png" class="rollover-img"></a></li>
    </ul>
  </nav>
</div>
</body>
</html>
css
@charset "UTF-8";

.menu { overflow:hidden; }

.menu ul {
   margin:0;
   padding:0; }

.menu li {
   float:left;
   list-style:none; }

.menu li a {
   display:block;
   width:250px;
   height:50px; }


.menu1{ background:url(../img/sample1.png) 0px 0px no-repeat; }

.menu2{ background:url(../img/sample2.png) 0px 0px no-repeat; }

.menu3{ background:url(../img/sample3.png) 0px 0px no-repeat; }
JavaScript
// jquery.menu.rollover.js Ver. 0.0.2 as of 2014/05/06
$(function () {
	//init
	var imgSuffix = '_on'; //hover suffix
	var highlight = '_hl'; //highlight suffix

	//rollover-bg part CSSバックグラウンド画像のパート
	var re = /https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:@&=+$,%#]+[a-zA-Z]/g;

	$("a.rollover-bg").each(function () {
		var url = $(this).attr('href');
		var imgSrc = $(this).css("background-image");
		var sep = imgSrc.lastIndexOf('.');
		var onSrc = imgSrc.substr(0, sep) + imgSuffix + imgSrc.substr(sep);
		var highlightSrc = imgSrc.substr(0, sep) + highlight + imgSrc.substr(sep);
		if (imgSuffix) { $("<img>").attr("src", onSrc.match(re)); }
		if (highlight) { $("<img>").attr("src", highlightSrc.match(re)); }

		if(location.href.match(url)) {
			this.style.backgroundImage = highlightSrc;
		} else {
			$(this).hover(
				function() { this.style.backgroundImage = onSrc; },
				function() { this.style.backgroundImage = imgSrc; }
			);
		}
	}); 
	//end rollover-bg part ここまで
	
	//rollover-img part imgタグのパート
	$("img.rollover-img").each(function(){
		var url = $(this).parent('a').attr('href');
		var imgSrc = this.src;
		var sep = imgSrc.lastIndexOf('.');
		var onSrc = imgSrc.substr(0, sep) + imgSuffix + imgSrc.substr(sep);
		var highlightSrc = imgSrc.substr(0, sep) + highlight + imgSrc.substr(sep);
		if (imgSuffix) { $("<img>").attr("src", onSrc); }
		if (highlight) { $("<img>").attr("src", highlightSrc); }

		if(location.href.match(url)) {
			$(this).attr('src', highlightSrc);
		} else {
			$(this).hover(
				function() { this.src = onSrc; },
				function() { this.src = imgSrc; }
			);
		}
	}); 
	//end rollover-img partここまで
});

使い方

メニュー画像とハイライト用、ロールオーバー用の画像を同じディレクトリに置きます。

ハイライト用、ロールオーバー用の画像は、メニュー画像のファイル名の後ろに接尾語を付けたものにします。

デフォルトは、それぞれ、 _hl と _on としてあります。

たとえば、メニュー用の画像のファイル名が、"sample.png"であれば、それぞれ、"sample_hl.png"、"sample_on.png"となります。

画像の種類は、png、jpg、jpeggif など、なんでもOKです。

接尾語を変更する場合は、以下の部分を修正します。

	var imgSuffix = '_on'; //hover suffix
	var highlight = '_hl'; //highlight suffix

ハイライト用の接尾語の設定を、 _on にすれば、ロールオーバー用画像と同じものを使用することができます。

また、接尾語に何も設定しなければ(var highlight = '' とする)、ハイライトさせないこともできます。

2つのスクリプトを1つにまとめているだけなので、不要な方は消して使用してください。

余談

メニュー画像ロールオーバー再び

似たような案件は続くもので、今回もメニュー画像のロールオーバーが設定されたソースがコーダーさんから回ってきました。

前回は、img タグに rollover.js なる出所不明の javaScriptロールオーバーが実装されていたのですが、今回は素直に css で hover の background-image を設定してある方式です。

これなら、そのまま CMS(今回もMovableType) のモジュールに登録できるので「よしよし!」とそれぞれのページのソースを眺めていたのですが、メニューの a タグに現在ページをハイライトするクラスが、各ページそれぞれに設定されているではありませんか。

共通パーツで登録したい部分がページ毎に違っていると、私には技術力も根気も無いので CMS 対応が大変なんです。

この手の要望には CMS 側で分岐を組んで対応してもいいんですが、メンテナンス性も汎用性も悪くなってしまいます。

ということで、次に同じようなものが来てしまったときのために、前回の JavaScript をさらに改造してみることにしました。

img タグを使用したパターンと css background-image を使用したパターンの両方に対応し、ちょっと汎用性も高めてカンタンに設置できるように改造したので、後々使えるように Blog に公開し保存しておきます。

なお、両対応とほざいてはいますが、実態は両方のスクリプトをつくって1つにくっつけてるだけなので、使用する際には不要な方を削除したほうが良いです。

余談となりますが、実際に納めた方のソースは、もらったコードの css や html を書き直す手間が嫌だったので、addclass() を使って強引に対応しましたのでこのスクリプトは使用していません。