// ===== namespace =====
if( window.info === undefined ) { info = {}; }
if( ! info.vividcode ) { info.vividcode = {}; }
if( ! info.vividcode.ipm ) { info.vividcode.ipm = {}; }
if( ! info.vividcode.em ) { info.vividcode.em = {}; }

/**
 * 読み込まれたら即時実行
 * body タグの直前に入れること
 */

/**
 * info.vividcode.ipm
 *   画像へのリンクを、新しいページに遷移せず、現在のページ内で開くための
 *   JavaScript モジュールです.
 *
var info.vividcode.ipm = function() {
	this.version = "beta6";
};*/

//------------------------------
// 設定項目
//------------------------------

/** 背景画像の設定 */
info.vividcode.ipm.bgImage = "http://www.vividcode.info/_lib/ipm_bg.png";
/** カーソル画像の設定 */
info.vividcode.ipm.cursorImage = "http://www.vividcode.info/_lib/ipm_cursor.png";


//------------------------------
// Event 処理関連
//------------------------------

/**
 * イベントリスナを追加する関数
 * 基本的には IE でも Firefox でも Safari でも Opera でも同じように使えるようにしてある. 
 * IE ではイベントリスナが受け取る引数のプロパティに currentTarget がないが, 
 * この関数を使うと自動的に追加してくれる. 
 * イベントリスナ内での this による参照は IE とその他で互換性を保っていないので, 
 * イベントリスナ内で現在のイベントターゲットを取得するときは, this を使うのではなく
 * 引数の currentTarget プロパティを使用すること. 
 *
 * 使い方:
 *     var return = addListener( target, type, func );
 * パラメータ等:
 *     @param target イベントリスナを追加する対象. window オブジェクトや element オブジェクト.
 *     @param type イベントリスナが受け取るイベントのタイプ. "click" や "load" など. 
 *     @param func イベントリスナそのもの. 普通は関数. 
 *     @return 戻り値は boolean. addEventListener か attachEvent が実装されていれば true が返り, 
 *             それ以外の場合は false.
 */
if( ! info.vividcode.em.addListener )
info.vividcode.em.addListener = (function() {
	if ( window.addEventListener ) {
		// DOM Event 実装ブラウザ用
		return function(target, type, func) {
			target.addEventListener(type, func, false);
			return true;
		};
	} else if ( window.attachEvent ) {        // IE 用
		/**
		 * IE 用の, イベント伝播を停止させる関数
		 */
		if( ! info.vividcode.em.preventDefaultIE )
		info.vividcode.em.preventDefaultIE = function() {
			window.event.returnValue = false;
		};
		return function(target, type, func) {
			// ----- 局所変数の宣言 -----
			var i = 0;
			var hasBeenAdded = false;
			// ----- 処理 -----
			// target のプロパティに管理用配列を追加
			if( ! target._vividcode_el ) {
				target._vividcode_el = new Array(0);
                // unload 時に解体
                var cleanupTarget = function(evt) {
                    // 配列の中身を null に
                    for( i = 0; i < target._vividcode_el.length; i++ ) {
                        target._vividcode_el[i][0] = null;
                        target._vividcode_el[i][1] = null;
                        target._vividcode_el[i] = null;
                    }
                    // 配列への参照をなくす
                    target._vividcode_el = null;
                    // 自分自身を detachEvent
                    window.detachEvent("onunload", cleanupTarget);
                };
                window.attachEvent("onunload", cleanupTarget);
            }
            // 既に登録済みかどうかチェックする
            hasBeenAdded = false;
            for( i = 0; i < target._vividcode_el.length; i++ ) {
                if( target._vividcode_el[i][0] === func ) {
                    hasBeenAdded = true;
                    break;
                }
            }
            // 未登録の場合, 登録する
            if( ! hasBeenAdded ) {
                i = target._vividcode_el.length;
                target._vividcode_el[i] = new Array(func, function(evt) {
                    // evt.currentTarget を追加
                    if( ! evt.currentTarget ) { evt.currentTarget = target; }
                    // evt.preventDefault を追加
                    if( ! evt.preventDefault ) { evt.preventDefault = info.vividcode.em.preventDefaultIE; }
                    // EventListener 起動
                    func(evt);
                }, {});
            }
            // addEventListener の方では, 同じ関数を二重に登録しようとすると 2 個目は破棄される. 
            // attachEvent の方だと 2 個目は破棄されない. 同一の動作になるようにする. 
            if( ! target._vividcode_el[i][2][type] ) {
				target.attachEvent("on"+type, target._vividcode_el[i][1]);
	            // unload 時に detachEvent しなければメモリリークを起こすとどこかで読んだので念のため. 
	            // 必要以上に detachEvent する場合もあるが実害はないと思う 
	            // (さすがに動作時間はそんなに変わらないでしょう) ので気にしないことにする.
	            var cleanupListener = (function () {
	                // target._vividcode_el も onunload イベントで解体するので, 
	                // 下手すると参照前に解体されている可能性もある. 
	                // よって, あらかじめ局所変数に読み込んでおく.
	                var func = target._vividcode_el[i][1];
	                return function(evt) {
	                    target.detachEvent("on"+type, func);
	                    window.detachEvent("onunload", cleanupListener);
	                    // なぜか IE では下の方法だとちゃんと detachEvent できない
	                    // cleanupListener === myself がなぜか true じゃないため
	                    //window.detachEvent("onunload", myself);
	                    //window.alert("cleanup listener");
	                };
	            })();
	            target._vividcode_el[i][2][type] = cleanupListener;
	            window.attachEvent("onunload", target._vividcode_el[i][2][type]);
	        }
            return true;
        };
	} else {
		// addEventListener も attachEvent も持ってないブラウザ用
		return function(elem, type, func) {
			return false;
		};
	}
})();

/**
 * イベントリスナを削除する関数
 *
 * 使い方:
 *     var return = removeListener( target, type, func );
 * パラメータ等:
 *     @param target イベントリスナを取り除く対象. window オブジェクトや element オブジェクト.
 *     @param type イベントリスナが受け取るイベントのタイプ. "click" や "load" など. 
 *     @param func イベントリスナそのもの. 普通は関数. 
 *     @return 戻り値は boolean. removeEventListener か detachEvent が実装されていれば true が返り, 
 *             それ以外の場合は false.
 */
if( ! info.vividcode.em.removeListener )
info.vividcode.em.removeListener = (function() {
	if( window.removeEventListener ) {
		// DOM Event 実装ブラウザ用
		return function(target, type, func) {
			target.removeEventListener(type, func, false);
			return true;
		};
	} else if( window.detachEvent ) {        // IE 用
        return function(target, type, func) {
            // ----- 局所変数の宣言 -----
            var i = 0;
            var hasBeenAdded = false;
            // ----- 処理 -----
            // func が登録されているかどうかチェックする
            hasBeenAdded = false;
            for( i = 0; i < target._vividcode_el.length; i++ ) {
                if( target._vividcode_el[i][0] === func ) {
                    hasBeenAdded = true;
                    break;
                }
            }
            // 登録されている場合, detachEvent
            if( hasBeenAdded ) {
            	if( target._vividcode_el[i][2][type] ) {
					target._vividcode_el[i][2][type]();
					delete target._vividcode_el[i][2][type];
	            }
                //target.detachEvent("on"+type, target._vividcode_el[i][1]);
            }
            return true;
        };
	} else {
		// addEventListener も attachEvent も持ってないブラウザ用
		return function(elem, type, func) {
			return false;
		}
	}
})();

if( ! info.vividcode.em.preventDefault )
info.vividcode.em.preventDefault = function() {
	window.event.returnValue = false;
};

info.vividcode.ipm.targetTable = new Array(0);
// class が "illust" である node を取得する
info.vividcode.ipm.searchByClass = function(aNode, aClassName) {
	//alert(node);
	var resNodes = new Array(0);
	if( aNode.nodeType != 1 ) {
		return resNodes;
	}
	// var className = aNode.getAttribute("class"); // IE6,7 で不可
	var classNames = aNode.className.split(" "); // 複数の class 名が記述してある場合用
	for( var i = 0; i < classNames.length; i++ ) {
		if( classNames[i] == aClassName ) {
			resNodes.push(aNode);
			break;
		}
	}
	var children = aNode.childNodes; // NodeList
	for( var i = 0; i < children.length; i++ ) {
		var retNodes = info.vividcode.ipm.searchByClass( children.item(i), aClassName );
		resNodes = resNodes.concat(retNodes);
	}
	return resNodes;
}

/**
 * 画像を新しく画面の中央に配置する.
 * @param aNode event が発生した node
 * @param aEL この関数を呼び出す eventListner. 関数呼出し後に eventListener は取り除く
 */
info.vividcode.ipm.showIllust = function( aNode ) {
	//info.vividcode.em.removeListener( aNode, "click", aEL );
	
	var width  = null;
	var height = null;
	var style     = null;
	var boxStyle  = null;
	var src = aNode.getAttribute("href");
	if( src.indexOf("?") >= 0 ) {
		var tmp = src.split("?");
		src = tmp[0];
		tmp = tmp[1].split("&");
		for( var i = 0; i < tmp.length; i++ ) {
			if( tmp[i].match(/^width=\d+/) != null ) {
				width = "width: " + tmp[i].substr(6) + "px;";
			}
			if( tmp[i].match(/^height=\d+/) != null ) {
				var h = tmp[i].substr(7);
				h /= 2;
				height = "height: " + tmp[i].substr(7) + "px;";
			}
		}
		style = width + height;
	}
	
	var isIE6 = true;
	if( typeof document.body.style.maxHeight != "undefined" ) {
		isIE6 = false;
	}
	
	if( isIE6 ) { // IE 6
		var node = document.documentElement;
		node = node.getElementsByTagName("body");
		node = node[0];
	} else { // mozilla, safari, opera, ie7, ...
		var node = aNode.parentNode;
	}
	
	var box   = document.createElement("div");
	//box.className = "popupIllust";
	if( isIE6 ) {
		box.style.cssText = "position: absolute;" + 
			"filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + info.vividcode.ipm.bgImage + "',sizingMethod='scale');" + 
			"width: expression(document.documentElement.clientWidth);" + 
			"height: expression(document.documentElement.clientHeight);" + 
			"top: expression(document.documentElement && document.documentElement.scrollTop || document.body && body.scrollTop || 0 + 0 + 'px' );" + 
			"left:expression( document.documentElement && document.documentElement.scrollLeft || document.body && body.scrollLeft || 0 + 0 + 'px' );";
	} else {
		box.style.cssText = "position: fixed; top: 0px; left: 0px; width: 100%; height: 100%; " + 
			"background-image: url(\"" + info.vividcode.ipm.bgImage + "\");" + 
			"text-align: center; line-height: 100%;";
	}
	var t1 = document.createElement("table");
	t1.style.cssText = "width: 100%; height: 100%;";
	if( boxStyle != null ) {
		box2.style.cssText = boxStyle;
	}
	var t2 = document.createElement("tbody");
	var t3 = document.createElement("tr");
	var box2 = document.createElement("td");
	var box3 = document.createElement("div");
	box3.style.cssText = "border: solid 3px #999999; margin: auto; " + width + height;
	var image = document.createElement("img");
	image.setAttribute("src", aNode.getAttribute("href"));
	image.setAttribute("alt", "");
	if( style != null ) {
		image.style.cssText = style;
	}
	box.appendChild(t1);
	t1.appendChild(t2);
	t2.appendChild(t3);
	t3.appendChild(box2);
	box2.appendChild(box3);
	box3.appendChild(image);
	node.appendChild(box);
	// 登録
	box.popupRelation = aNode;
	var i = 0;
	while( i < info.vividcode.ipm.targetTable.length ){
		if( info.vividcode.ipm.targetTable[i][0] == aNode ) {
			info.vividcode.ipm.targetTable[i][1] = box;
			break;
		}
		i++;
	}
	//info.vividcode.ipm.targetTable[i][1] = box;
	info.vividcode.em.removeListener( aNode, "click", info.vividcode.ipm.showEventListener );
	info.vividcode.em.addListener( box,   "click", info.vividcode.ipm.delEventListener );
	info.vividcode.em.addListener( aNode, "click", info.vividcode.ipm.delEventListener );
}
info.vividcode.ipm.showEventListener = function(evt) {
	//alert( e.type + " " + this.getAttribute("href") );
	info.vividcode.ipm.showIllust(evt.currentTarget);
	// ページ遷移 (本来のイベント) の停止
	evt.preventDefault();
};

info.vividcode.ipm.delIllust = function(aNode) {
	var ancNode;
	var boxNode;
	var parent;
	if( aNode.popupRelation != undefined ) {
		ancNode = aNode.popupRelation;
		boxNode = aNode;
	} else {
		ancNode = aNode;
		var i = 0;
		while( i < info.vividcode.ipm.targetTable.length ){
			if( info.vividcode.ipm.targetTable[i][0] == aNode ) {
				boxNode = info.vividcode.ipm.targetTable[i][1];
				break;
			}
			i++;
		}
		info.vividcode.ipm.targetTable[i][1] = null;
	}
	parent = boxNode.parentNode;
	// opera だとそのまま削除すると部分的にしか再描画されない
	// よって、まずは "display: none" に設定して、1ms 後に DOM 木から取り除く
	boxNode.style.display = 'none';
	setTimeout( function() {parent.removeChild(boxNode);}, 1);
	// set the popup event to the element "a"
	/*
	var eventListener = function(e) {
		//alert( e.type + " " + this.getAttribute("href") );
		// stop the default event (=moving the page)
		alert("event show");
		info.vividcode.ipm.showIllust(aNode, eventListener);
		if(e.preventDefault) { e.preventDefault(); }
		else { event.returnValue = false; } // IE 用
	};
	*/
	info.vividcode.em.removeListener( ancNode, "click", info.vividcode.ipm.delEventListener );
	info.vividcode.em.removeListener( boxNode, "click", info.vividcode.ipm.delEventListener );
	info.vividcode.em.addListener( ancNode, "click", info.vividcode.ipm.showEventListener );
};
info.vividcode.ipm.delEventListener = function(evt) {
	info.vividcode.ipm.delIllust(evt.currentTarget);
	// イベント伝播の停止
	evt.preventDefault();
};

info.vividcode.ipm.setCursor = function() {
	var selector = "a.popup";
	var property = "cursor: url(\"" + info.vividcode.ipm.cursorImage + "\"), pointer;";
	
	var sheet = null;
	//var property = "cursor: move;";
	if( document.styleSheets ) {
		if( document.styleSheets.length >= 1 ) {
			sheet = document.styleSheets[0];
		} else {
			return false;
		}
		//sheet = document.styleSheets[0];
		if( sheet.addRule ) { //IE
			sheet.addRule( selector, "{" + property + "}" );
		} else if( sheet.insertRule ) { //Mozilla
			sheet.insertRule( selector + "{" + property + "}", sheet.cssRules.length );
		} else {
			return false;
		}
	}
}


// a function which is executed when the page have been loaded
info.vividcode.ipm.init = function(evt) {
	var i = 0;
	var node = null;
	var root = document.documentElement; // get the root element
	var list = info.vividcode.ipm.searchByClass(root, "popup"); // search target nodes
	
	for( i = 0; i < list.length; i++ ) {
		//var nodes = list[i].getElementsByTagName("a");
		//var node = nodes[0];
		node = list[i];
		node.style.cursor = "url(\"" + info.vividcode.ipm.cursorImage + "\"), pointer";
		info.vividcode.ipm.targetTable[i] = new Array(2);
		info.vividcode.ipm.targetTable[i][0] = node;
		info.vividcode.ipm.targetTable[i][1] = null;
		info.vividcode.em.addListener( node, "click", info.vividcode.ipm.showEventListener );
	}
	
	// cursor の設定
	//info.vividcode.ipm.setCursor();
	
	/*
	var imifu = null;
	var test = (function () {
		// target._vividcode_el も onunload イベントで解体するので, 
		// 下手すると参照前に解体されている可能性もある. 
		// よって, あらかじめ局所変数に読み込んでおく.
		var func = "aaa";
		imifu = function myself(f) {
			window.alert(f === myself ? "一緒" : "違う");
		};
		return imifu;
	})();
	test(test);
	window.alert(test === imifu ? "一緒" : "違う");
	*/
};
// window オブジェクトに EventListener として init 関数を追加
//info.vividcode.em.addListener(window, "load", info.vividcode.ipm.init);
info.vividcode.ipm.init();
