周期的に画像とリンクを更新

prototype.js1.6を使い、周期的に画像とリンクを更新するクラスを実装してみました。

属性を保持するクラス

一組の画像とリンク先のurlを保持するクラスを以下のように定義。

var ImageLink = Class.create( {
	initialize: function(imageUrl, linkUrl) {
		this.imageUrl = imageUrl;
		this.linkUrl = linkUrl;
	}
});

周期的に画像とリンクを更新するクラスを以下のように定義。

上で定義したImageLinkのオブジェクトのArrayを指定し、そのImageLinkの属性である画像とリンク先のurlでHtmlのタグを周期的に更新していくかたちとなります。

var ImageRotator = Class.create( {
	initialize: function(imageLinks) {
		this.current = 0;
		images = new Array();
		imageLinks.each( function(imageLink) {
			var image = new Image();
			image.src = imageLink.imageUrl;
			images[images.length] = image;
		}
		);
		this.imageLinks = imageLinks;
		this.images = images;
	},
	
	execute: function( imageElement, hrefElement, period, instance) {
		this.imageElement = imageElement;
		this.hrefElement = hrefElement;
		callback = function() {
			this.current += 1;
			if(this.current >= this.images.length)
				this.current = 0;
			if(this.imageElement) {
				this.imageElement.src = this.imageLinks[this.current].imageUrl;
			}
			if(this.hrefElement) {
				this.hrefElement.href = this.imageLinks[this.current].linkUrl;
			}
		}.bind(this);
		if(instance)
			callback();
		this.executer = new PeriodicalExecuter(
			callback,
			period
		);
	},
	
	
	stop: function() {
		this.executer.stop();
	}
});
    1. コンストラクタには周期的に表示することになる画像、リンク先のurlを含むImageLinkオブジェクトのArrayを引数として指定します。
    2. executeメソッドで周期的な表示更新処理を開始します。引数は、Imageタグ、リンク先となるaタグ、周期、1回目は即時に画像とリンク先を更新するかどうかのフラグとなります。
    3. 画像とリンク先を更新するコールバック関数は、bindメソッドを呼び出して、このImageRotatorのオブジェクトにバインディングしておく必要があります。そうしないとデフォルトのWindowオブジェクトにバインディングされてこの関数が実行されてしまいます。
    4. コンストラクタ中で各画像に対してImageオブジェクトを生成していますが、これは最初に画像を読み込んでキャッシュしておこうという意図です。ただ、その意図どおりキャッシュされているか未確認です。

テストのHtmlは以下のものです。

<!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="en" lang="en">
  <head>
    <script type="text/javascript" src="javascripts/prototype.js"></script>
    <script type="text/javascript" src="javascripts/my.js"></script>
  <script language="JavaScript" type="text/javascript">
  <!--
		function rotateImage() {
        	new Ajax.Request('images.xml', {
	       method: "get",
			  onComplete: function(res) {
			 	  rotator = new ImageRotator(createImageListsFromXml(res.responseXML));
				  rotator.execute($('img'),$('img_link'), 2, true);
				
			}
		} );
		
		function createImageListsFromXml(xml) {
			imageLinks = new Array();
			root = xml;
			imageLinksTag = root.getElementsByTagName("ImageLinks");
			if(imageLinksTag.length >= 1) {
				imageLinkArray = imageLinksTag[0].getElementsByTagName("ImageLink");
				for(var i = 0; i < imageLinkArray.length; ++i) {
					imageLinkTag = imageLinkArray[i];
					imageUrl = imageLinkTag.getAttribute("imageUrl");
					linkUrl = imageLinkTag.getAttribute("linkUrl");
					imageLink = new ImageLink(imageUrl, linkUrl);
					imageLinks[imageLinks.length] = imageLink;
				}
			}
			return imageLinks;
		}
	}
  //-->
  </script>
    <title></title>
   </head>
  <body onload="rotateImage();">
	<span id="images" >
	    <a id="img_link" href="" target="_blank">
		    <image id="img"  src="">
	    </a>
	</span>
  </body>

</html>
    1. 画像とリンク先のタグは、最初からHtml上の存在、周期的のその内容だけを更新していくかたちとなっています。
    2. 画像とリンク先の情報はxmlから読み込むことにしました。Ajax.Requestによりxmlを取得、完了時のハンドラ(OnComplete)で画像、リンク先の組(ImageLink)の配列を生成して、周期処理の起動(execute)を行っています。

テスト用のxml

対象画像、リンク先を定義したxml(images.xml)は以下の内容のものでテストしました。

<?xml version="1.0" encoding="UTF-8"?>
<ImageLinks>
    <ImageLink imageUrl="images/moomin1.jpg" linkUrl="images/moomin1.jpg"/>
    <ImageLink imageUrl="images/moomin2.jpg" linkUrl="images/moomin2.jpg"/>
    <ImageLink imageUrl="images/moomin3.jpg" linkUrl="images/moomin3.jpg"/>
</ImageLinks>