/**
 * product_list.js
 *
 * @version:0.9.7
 * $Date:2008-7-25
 */


/**
 * @namespace 商品一覧ページで使用する機能群
 */
var XlistContorller = {
	
	/**
	 * 設定オブジェクト
	 */
	options:{
		/**
		 * ソートの種類
		 * (ソートのデータ、ソートのX_と全てのキーになる)
		 * @type string[]
		 */
		sortArray:['recom', 'lowPrice', 'highPrice', 'popular', 'new'],
		
		/**
		 * 表示方法の種類
		 * @type object[]
		 * @desc [{ {string} mode getクエリー対応のmode値, {string} ID DOMID対応のmode値 (X_DISPLAY_がコントローラー部のname、X_LIST_がリストのdivのID) ,{integer} cols 表組みの横列数 },{}]
		 */
		modeArray:[{mode:'l', ID:'MODE_A', cols:4}, {mode:'s', ID:'MODE_B',cols:2}],
		//
		/**
		 * コントロール部のID
		 * @type string
		 */
		controllerID:'X_CONTROLLER_TOP',
		
		/**
		 * ソートのデフォルト値
		 * @type string
		 */
		defaultSort:"recom",
		
		/**
		 * 表示のデフォルト値
		 * @type string
		 */
		defaultMode:"l",
		
		/**
		 * ソートのカレント値
		 * @type string
		 */
		currentSort:"",
		
		/**
		 * 表示のカレント値
		 * @type string
		 */
		currentMode:"",
		
		/**
		 * 表示しているURL
		 * @type string
		 */
		currentURL:"",
		
		/**
		 * X_オブジェクト格納オブジェクト
		 * @type object
		 */
		X_Obj:{},
		
		/**
		 * 商品情報タグ置換形式連想配列
		 * タグ名の重複は不可
		 * innerHTMLよりinnerTextの方が早いので、データにタグが含まれていないものは、innerTextを設定する
		 * @type object[]
		 * @desc {タグname属性名: [ 置換モード("innerHTML" | 属性名 ) , データのプロパティ名]}
		 */
		replTagNamesItem : {
			/** 商品名を囲んでいる<a>タグの商品詳細へのリンク */
			X_PDLINK : ["href", "detailURL"],
			/** 商品画像を囲んでいる<a>タグの商品詳細へのリンク */
			X_PDLINKIMG : ["href", "detailURL"],
			/** 商品詳細へボタンのリンク */
			X_PDLINKBTN : ["href", "detailURL"],
			/** 価格 */
			X_PRICE : ["innerHTML", "price"],
			/** 旧価格 */
			X_OLDPRICE :[ "innerHTML", "oldPrice"],
			/** 色情報（短縮型） */
			X_COLORVARIATION : ["innerText", "colors"],
			/** 色情報（全表示） */
			X_COLORVARIATIONFULL : ["innerText", "colorInfo"],
			/** サイズ情報 */
			X_SIZEINFO : ["innerText", "sizeInfo"],
			/** 商品名 */
			X_PDNAME : ["innerText", "itemName"],
			/** 販促コピー */
			X_PRCOPY : ["innerHTML", "copyText"],
			/** 販促マーク */
			X_PRMARK : ["src", "topIcon"],
			/** お気に入りに入れるボタンのリンク */
			X_SETFAVORITE : ["onclick", "addFavorite"],
			/** 特長コピー */
			X_SPCOPY : ["innerHTML", "prText"],
			/** 特長マーク1 */
			X_SPMARK1 : ["src", "bottomIcon1"],
			/** 特長マーク2 */
			X_SPMARK2 : ["src", "bottomIcon2"],
			/** 特長マーク3 */
			X_SPMARK3 : ["src", "bottomIcon3"],
			/** 商品画像（小） */
			X_PDIMAGE100 : ["src", "imageSmallURL"],
			/** 商品画像（大） */
			X_PDIMAGE : ["src", "imageLargeURL"]
		}
	},
	/**
	 * 設定オブジェクトを取得
	 *
	 * @private
	 * @param {string} key 設定オブジェクトのキー
	 * @returns {array|string|object} 設定オブジェクトの内容
	 */
	getOption:function(key){
		return this.options[key];
	},
	/**
	 * 設定オブジェクトに登録
	 *
	 * @private
	 * @param {string} key 設定オブジェクトのキー
	 * @param {array|string|object} param 設定オブジェクトの登録内容
	 */
	setOption:function(key, param){
		this.options[key] = param;
	},
	
	/**
	 * 設定オブジェクトを置き換え
	 * 商品繰り返し置換タグオブジェクトの置き換えモードを書き換え
	 *（firefoxは、innerTextが無いので同等のtextContentに書き換える為の関数）
	 *
	 * @private
	 * @param {string} key 設定オブジェクトのキー（replTagNamesItemのみ対応）
	 * @param {string} find 検索文字列
	 * @param {string} str 置き換え文字列
	 */
	replaceOption:function(key, find, str){
		var o = this.getOption(key);
		for(var p in o){
			o[p][0] = o[p][0].replace(find,str);
		}
		this.setOption(key, o);
	},
	
	/**
	 * 初期化
	 */
	setup:function(){
		
		/**
		 * 要素の高さを揃える関数を作成
		 *
		 * @scope XlistContorller
		 * @function
		 */
		this.XtrimDivHeight = new jp.co.mutow.trimHeight();
		
		//オプションの書き換え
		//innerHTMLよりinnerTextの方が早いが、firefoxは、innerTextが無いので同等のtextContentに設定する
		if(Xua.mozilla) this.replaceOption('replTagNamesItem', 'innerText', 'textContent');
		
		//X_オブジェクトを取得
		this.setOption('X_Obj',this.getXObjects());
		
		//表示しているURLを登録
		this.setOption('currentURL', location.href.split("?")[0]);
		
		//テンプレートの初期ソートを取得
		var defSort = this.getDefaultSort();
		
		//表示方法のデフォルト値を取得
		var defMode = this.getOption('defaultMode');
		
		//getクエリーからソートと表示方法を取得
		var qSort = this.getRequestParameter('sort');
		var qMode = this.getRequestParameter("mode");
		
		//getクエリーに値があれば登録
		if(qSort) defSort = qSort;
		if(qMode) defMode = qMode;
		
		//デフォルト値の登録
		this.setOption('defaultSort', defSort);
		this.setOption('defaultMode', defMode);
		
		//ページの更新
		this.update(defSort, defMode);
	},

	/**
	 * 操作パネルのクリック
	 *
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 */
	onControllerClick:function(sort, mode){
		
		//URLのgetクエリーを作成
		var currentURL = this.getOption('currentURL'),
		pageURL = currentURL + '?sort=' + sort + '&mode='+mode;
		
		//Urchinに送信
		urchinTracker(pageURL);
		
		//サーバーに非同期送信
		this.AjaxRequest(pageURL);
		
		//更新
		this.update(sort, mode);
	},
	
	/**
	 * ページの更新
	 *
	 * @private
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 */
	update:function(sort, mode){
		
		//変更があったかチェック
		var currentSort = this.getOption('currentSort'),
		currentMode = this.getOption('currentMode');
		if(sort == currentSort && mode == currentMode) return false;
		
		//変更があれば現在値を登録
		this.setOption('currentSort', sort);
		this.setOption('currentMode', mode);
		
		//コントローラー部の更新
		this.setController(sort, mode);
		
		//コンテンツ部の更新
		this.setContents(sort, mode);
		
	},

	/**
	 * コントローラー部を設定
	 *
	 * @private
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 */
	setController:function(sort, mode){
		
		var currentURL = this.getOption('currentURL'),
		controllerID = this.getOption('controllerID'),
		X_Obj = this.getOption('X_Obj')[controllerID];
		
		//ソート順を設定
		this.setSortController(sort, mode, currentURL, X_Obj);
		
		//表示方法を設定
		this.setModeController(sort, mode, currentURL, X_Obj);
	
	},

	/**
	 * ソート順コントローラー部を設定
	 *
	 * @private
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 * @param {string} currentURL 現在のURL
	 * @param {object} X_objコントローラー部のX_オブジェクト
	 */
	setSortController:function(sort, mode, currentURL,X_obj ){

		var self = this,
		sortArray = this.getOption('sortArray');
		for(var i = 0, len = sortArray.length; i < len; i++){
			var h = null; 
			var elm = X_obj['X_ORDER_' + sortArray[i].toUpperCase()];
			if(sortArray[i] != sort){
				h = './p1.html?sort=' + sortArray[i] + '&mode=' + mode;
				this.hrefReplace(elm, h);
				this.wrapStrong(elm,false);
				elm.sort = sortArray[i];
				elm.mode = mode;
				elm.onclick = function(){
					self.onControllerClick(this.sort , this.mode);
					return false;
				};
			}else{
				this.hrefReplace(elm, h);
				this.wrapStrong(elm,true);
				elm.onclick = null;
			}
		}
	},

	/**
	 * 表示方法コントローラー部を設定
	 *
	 * @private
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 * @param {string} currentURL 現在のURL
	 * @param {object} X_objコントローラー部のX_オブジェクト
	 */
	setModeController:function(sort, mode, currentURL, X_obj ){
		var self = this,
		modeArray = this.getOption('modeArray'),
		replaceMode,modeID;
		
		if(mode == "l"){
				replaceMode = "s";
				modeID = modeArray[0].ID;
			}else{
				replaceMode = "l";
				modeID = modeArray[1].ID;
		}
		
		for( var i = 0, len = modeArray.length; i < len; i++){
			var h = null,
			elm = X_obj['X_DISPLAY_' + modeArray[i].ID];
			if(modeArray[i].ID != modeID){
				h = currentURL + '?sort=' + sort + '&mode=' + replaceMode ;
				this.hrefReplace(elm, h);
				this.wrapStrong(elm,false);
				elm.sort = sort;
				elm.mode = replaceMode;
				elm.onclick = function(){
					self.onControllerClick(this.sort , this.mode);
					return false;
				};
			}else{
				this.hrefReplace(elm, h);
				this.wrapStrong(elm,true);
				elm.onclick = null;
			}
		}
	},

	/**
	 * コンテンツ部を更新
	 *
	 * @private
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 */
	setContents:function(sort, mode){
		
		var modeArray = this.getOption('modeArray'),
		len = modeArray.length,
		modeID;
		
		//表示モードのIDと列数を取得
		for( var i = 0; i < len; i++){
			if(modeArray[i].mode == mode){
				modeID = 'X_LIST_' +modeArray[i].ID;
				modeCols = modeArray[i].cols;
			}
		}
		var X_Obj = this.getOption('X_Obj')[modeID];
		
		//ソートデータの取得
		var data = this.getSortData(sort);
		
		//コンテンツ部の書き換え
		this.setContentsHTML(data, sort, mode, modeID, X_Obj);
		
		//表示
		var list;
		
		for( var i = 0; i < len; i++){
			if(modeArray[i].mode == mode){
				list = document.getElementById('X_LIST_' + modeArray[i].ID);
				list.style.display = "block";
			}else{
				list = document.getElementById('X_LIST_' + modeArray[i].ID);
				list.style.display = "none";
			}
		}
		
		//cellの高さをそろえる
		this.XtrimDivHeight(modeID, modeCols);
	},
	
	/**
	 * ソートデータの取得
	 *
	 * @private
	 * @param {string} sort ソート順
	 * @returns {object} data ソート済み商品データ
	 */
	 getSortData:function(sort){
		var data = eval(sort + "Data");
		return data;
	},

	/**
	 * コンテンツ部を書き換え
	 *
	 * @private
	 * @param {object} data ソート済み商品データ
	 * @param {string} sort ソート順
	 * @param {string} mode 表示モード
	 * @param {string} modeID 書き換えるリストのdivID
	 * @param {object} X_Obj 書き換えるリスト内のX_オブジェクト
	 */
	setContentsHTML:function(data, sort, mode, modeID, X_Obj){
		var Xconf = this.getOption('replTagNamesItem'),
		rtnURL = this.getOption('currentURL') + '?sort=' + sort + '&mode='+mode;
		
		//書き換えるXオブジェクトでLoop
		for(var name in X_Obj){
			
			var Xelm = X_Obj[name],	//HTMLエレメント
			Xobjs = name.split('_'),
			Xtag = Xobjs[0] + '_' + Xobjs[1],	//タグ名（番号なし）
			Xindex = parseInt(Xobjs[2]) - 1;	//商品の順番
			
			//NEWアイコン処理
			if(Xtag == "X_NEWMARK"){
				var d = new Date();
				var ds = new Date(data[Xindex]['startDate']);
				//現在の日付との差が14日間以下ならNEWマーク画像を表示
				if (d.getTime() < ds.getTime() + (14 * 86400000)) {
					Xelm.style.display = "block";
				} else {
					Xelm.style.display = "none";
				}
				continue;
			}
			
			//データの取得
			var dType = Xconf[Xtag][0],	//dataの置き換えタイプ
			dName = Xconf[Xtag][1],	//dataのオブジェクト名
			dData = data[Xindex][dName];
			if(dData == "") dData = null;
			
			
			//価格処理
			if(Xtag == "X_PRICE" || Xtag == "X_OLDPRICE"){
				var flgOutletPrice =  data[Xindex]['flgOutletPrice'];
				if(!flgOutletPrice){
					if(Xtag == "X_PRICE") dData = data[Xindex]['normalPrice'];
					if(Xtag == "X_OLDPRICE") dData = null;
				}else{
					if(Xtag == "X_PRICE") dData = data[Xindex]['outletPrice'];
					if(Xtag == "X_OLDPRICE") dData = data[Xindex]['outletOldPrice'];
				}
			}
			
			//サイズ処理
			if(Xtag == "X_SIZEINFO"){
				var flgZaccaSize = data[Xindex]['flgZaccaSize'];
				if(flgZaccaSize){
					dData = data[Xindex]['zaccaSizeInfo'];
				}else{
					dData = data[Xindex]['raptySizeInfo'];
				}
			}
			
			//お気に入りに入れる機能に戻りURLを追加する(0.9.6)
			if(Xtag == "X_SETFAVORITE"){
				dData = dData.replace(");", ",'"+rtnURL+"');");
			}
			
			//置き換え処理
			//if文でなく関数を文字列で直接走らせることで高速に。
			this[dType + 'Replace'](Xelm, dData);
			
			//画像はaltも
			if(Xtag=="X_PDIMAGE") this.altReplace(Xelm, data[Xindex]['itemName']);
		}
	},

	
	/**
	 * X_をname属性に含むタグをオブジェクトに格納し返す
	 *
	 * @private
	 * @returns {object}
	 */
	getXObjects:function(){
		var obj = {};
		var modeArray = this.getOption('modeArray');
		var IDs = ['X_LIST_' + modeArray[0].ID, "X_LIST_" + modeArray[1].ID, this.getOption('controllerID')];
		
		var strSearchWord = "X_";
		var strAttrName = "name";
			
		var getObjs = function(ID){
			var elm;
			var list = {};
			
			(!ID) ?	elm = document.body: elm = document.getElementById(ID);
		
			var parse = function(elm){
				if(elm.nodeType !== 1){
					return;
				}
				var name = elm.getAttribute(strAttrName);
				if (name && name.indexOf(strSearchWord) !== -1){
					list[name] = elm;
				}
				var len = elm.childNodes.length;
				for(var i = 0; i < len; i++){
					parse(elm.childNodes[i]);
				}
				return list;
			}
			obj[ID] = parse(elm);
		};
		
		for (var i = 0; i < 3; i++) {
			getObjs(IDs[i])
		}
		return obj;
		
	},
	
	/**
	 * タグalt属性を書き換え
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} value
	 */
	altReplace: function( elm, value ) {
		if(value == undefined ){
			elm.removeAttribute("alt");
		}else{
			elm.setAttribute("alt", value);
		}
	},
	
	/**
	 * タグhref属性を書き換え
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} URL
	 */
	hrefReplace: function( elm, value ) {
		if(value == null ){
			elm.removeAttribute("href");
		}else{
			elm.setAttribute("href", value);
		}
	},
	
	/**
	 * タグonclick属性を書き換え
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} URL
	 */
	onclickReplace: function( elm, value ) {
		if(value == null ){
			elm.removeAttribute("onclick");
		}else{
			(Xua.msie) 
				? elm.setAttribute("onclick", new Function(value + 'return false;') )
				: elm.setAttribute("onclick", value + 'return false;');
		}
	},
	/**
	 * タグsrc属性を書き換え
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} URL
	 */
	srcReplace: function( elm, value ) {
		if(value == null ){
			elm.removeAttribute("src");
			elm.style.display = 'none';
		}else{
			elm.setAttribute("src", value);
			elm.style.display = 'block';
		}
	},
	/**
	 * タグ内を書き換え(HTML)
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} value
	 */
	innerHTMLReplace: function( elm, value ) {
		if(value == null ){
			elm.innerHTML = '';
			elm.style.display = 'none';
		}else{
			elm.innerHTML = value;
			elm.style.display = 'block';
		}
	},
	/**
	 * タグ内を書き換え(TEXT)
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} value
	 */
	innerTextReplace: function( elm, value ) {
		if(value == null ){
			elm.innerText = '';
			elm.style.display = 'none';
		}else{
			elm.innerText = value;
			elm.style.display = 'block';
		}
	},
	/**
	 * タグ内を書き換え(TEXT)（FireFox用）
	 *
	 * @private
	 * @param {object} elm
	 * @param {string} value
	 */
	textContentReplace: function( elm, value ) {
		if(value == null ){
			elm.textContent = '';
			elm.style.display = 'none';
		}else{
			elm.textContent = value;
			elm.style.display = 'block';
		}
	},
	
	/**
	 * <strong>タグの付加・削除
	 *
	 * @private
	 * @param {object} elm
	 * @param {boolean} 
	 */
	wrapStrong:function(elm, bool) {
		var html = elm.innerHTML.replace(/<strong>/i, "").replace(/<\/strong>/i, "");
		if(bool) html = '<strong>'+ html + '</strong>';
		elm.innerHTML = html;
	},
	
	/**
	 * テンプレートの初期ソートを取得
	 *
	 * @private
	 * @returns {string} ソート名
	 */
	getDefaultSort:function(){
		var defSort = this.getOption('defaultSort');
		var arr = this.getOption('sortArray');
		var len = arr.length;
		for(var i = 0;i<len; i++){
			var ID = 'X_SORT_' + arr[i].toUpperCase();
			if(document.getElementById(ID)){
				defSort = arr[i];
				break;
			}
		}
		return defSort;
	},
	
	/**
	 * URLクエリーを取得
	 *
	 * @private
	 * @param {string} param パラメータのキー
	 * @return {string} 値
	 */
	getRequestParameter: function(param) {
		var q = document.location.search || document.location.hash;
		if (param == null) { return q; }
		if(q) {
			var pairs = q.substring(1).split("&");
			for (var i=0; i < pairs.length; i++) {
				if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
					return pairs[i].substring((pairs[i].indexOf("=")+1));
				}
			}
		}
		return "";
	},
	/**
	 * サーバーにURLをAjax送信
	 *
	 * @private
	 * @param {string} URL 
	 */
	AjaxRequest:function(URL){
		var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
		xmlhttp.open("GET", URL, true);
		xmlhttp.send(null);
		var response = xmlhttp.responseXML;
	},
	
	/**
	 * ページ繰りの処理
	 *
	 * @param e イベントが発生したオブジェクト
	 */
	onChangePage:function(e){
		var strHref = (e.getAttribute("href"));
		location.href = strHref + "?sort=" + this.getOption('currentSort') + "&mode=" + this.getOption('currentMode') ;
	}
};


/**
 * ページ繰りのクリックイベント
 *
 * cmsのページ繰り部分の書き出しがタグを含むため、そのタグの互換用グローバル関数
 * 全てのサイトのテンプレートが更新されたら、cmsの書き出しを更新して、このグローバル関数は廃止する。
 *
 * @param e イベントが発生したオブジェクト
 */
var changePage = function(e){
	XlistContorller.onChangePage(e);
	return false;
}






/** DOM解析終了後のイベント*/
addEvent(window, 'domReady', function(){
	XlistContorller.setup();
});
