riina-k.net

音楽・小説・プログラミングを手がけるリイナの拠点。

遅延ロードのライブラリをクロスブラウザ対応

先日の記事「遅延ロードをライブラリ化してみた」がIEで動作しなかった原因が分かったので、一部書き直し。

delayload.js

変更点は2箇所。ひとつは「オブジェクトのプロパティとして class という名前は使用できない」という制約があるため、これを「target」というプロパティ名に変更。
もう一つは、img要素を生成する際、先にwidth, heightを設定してからsrcを設定してしまうと、IEでは先に設定したサイズを無視してオリジナルサイズでwidth, heightを上書きしてしまうため、srcを設定してからwidth, heightを設定という順番に変更。

var DelayLoad = {
	target: "delay",
	error: "error",
	retry: 1,
	init: function(params)
	{
		if ( params && params.hasOwnProperty("target") ) {
			this.target = params.target;
		}
		if ( params && params.hasOwnProperty("retry") ) {
			this.retry = params.retry;
		}
		if ( params && params.hasOwnProperty("error") ) {
			this.error = params.error;
		}
		
		// 対象のjQueryオブジェクトにパラメータを設定
		var jqTarget = jQuery( "*[class^='" + this.target + "']" );
		for ( i=0; i<jqTarget.length; ++i ) {
			jQuery.data( jqTarget.get(i), "retry", this.retry );
			jQuery.data( jqTarget.get(i), "error", this.error );
		}
		jqTarget.each(function(){
			// 引数をパース
			var paramsString = this.className.split(";")[1];
			var arrParams = paramsString.match(/^params=\{(.*?)\}$/)[1].match(/([a-z]+):('(.*?)'|[0-9]+)/g);
			var objParams = {};
			for ( i=0; i<arrParams.length; ++i ) {
				var tmp = arrParams[i].split(":");
				if ( tmp[1].match(/^'(.*?)'$/) ) {
					objParams[ tmp[0] ] = RegExp.$1;
				} else {
					objParams[ tmp[0] ] = tmp[1];
				}
			}
			if ( !objParams.hasOwnProperty("url") ) {
				throw "DelayLoad: url required";
			}
			if ( !objParams.hasOwnProperty("title") ) {
				objParams.title = "";
			}
			if ( !objParams.hasOwnProperty("retry") ) {
				objParams.retry = jQuery.data( this, "retry" );
			}
			objParams.error = jQuery.data( this, "error" );
			
			var jqImg = jQuery("<img />");
			// エラー時のイベントハンドラ
			jqImg.bind("error", function(e){
				// 再試行回数だけリロード
				var retry = jQuery.data( this, "retry" );
				if ( --retry > 0 ) {
					jQuery.data( this, "retry", retry );
					this.src = this.src;
				} else {
					// 試行回数切れ
					var target = jQuery.data( this, "target" );
					var error = jQuery.data( this, "error" );
					target.replaceWith(error);
					// 後始末
					jQuery.removeData( this, "retry" );
					jQuery.removeData( this, "error" );
					jQuery.removeData( this, "target" );
				}
			});
			// ロード時のイベントハンドラ
			jqImg.bind("load", function(e){
				var target = jQuery.data( this, "target" );
				target.replaceWith( jQuery(this) );
				// 後始末
				jQuery.removeData( this, "retry" );
				jQuery.removeData( this, "error" );
				jQuery.removeData( this, "target" );
			});
			// 再試行回数を設定
			jQuery.data( jqImg.get(0), "retry", objParams.retry );
			// エラーHTMLを設定
			jQuery.data( jqImg.get(0), "error", objParams.error );
			// 画像置換対象
			jQuery.data( jqImg.get(0), "target", jQuery(this) );
			// 読み込み
			jqImg.attr("src", objParams.url);
			if ( objParams.hasOwnProperty("width") ) {
				jqImg.attr("width", objParams.width);
			}
			if ( objParams.hasOwnProperty("height") ) {
				jqImg.attr("height", objParams.height);
			}
			if ( objParams.hasOwnProperty("title") ) {
				jqImg.attr("alt", objParams.title);
			}
		});
	}
};

DelayLoad デモ

現時点では、以下のブラウザで動作を確認。

  • [Windows XP] IE 8.0
  • [Windows XP] Firefox 13.0.1
  • [Windows XP] Opera 11.64
  • [Windows 7] Opera 23.0

クロスブラウザ対応がとりあえずできたということで、今回をもって「DelayLoad ver 1.0」としますか。
前回書いたものはβ版ってことで。

デモファイルは http://riina-k.net/delayload/1.0/ 以下にあるので、欲しい人はソース漁ってください 要望があればzipにまとめてDLできるようにしますかねー。

  1. コメント 0

  1. トラックバック 0

return top