/**
 * core.js
 *
 * version:1.1.0
 * $Date:2009-9-29
 *
 * Release:
 *  addEventの実装 (0.1)
 *  domReadyの実装 (0.2)
 *  ブラウザ・バージョン取得 (0.3)
 *  オンラインショップ共通関数の設定 (0.4)
 *   showItemHistory:商品チェック履歴参照 (0.4)
 *   addFavorite:お気に入り追加 (0.4)
 *   showFavorite:お気に入り参照 (0.4)
 *   setCookie:クッキー登録 (0.4)
 *   getCookie:クッキー取得 (0.4)
 *   XtrimDivHeightの実装 (0.5)
 *   XtrimDivHeightの横列数が端数の時のバグをFIX (0.6)
 *   XtrimDivHeightを一新 (0.7)（しかしあまり速くなっていない）
 *   namespaceを作成 (0.8)
 *   オンラインショップ共通関数をpototypeに変更 (0.8)
 *   XtrimDivHeight（改名trimHeight）を再度、構造を書き換えてpototypeに変更（FIREFOXが高速に） (0.9)
 *   trimHeightの対応するIDのエレメントが無い時の処理を追加 (0.9.1)
 *   trimHeight内のaddCSSRuleがsafariで動いてないのを修正 (0.9.2)
 *   trimHeight内の高さ最大値のソートのバグを修正 (0.9.2)
 *   ロールオーバー・プロトタイプ関数を設定 (0.9.5)
 *   スムーススクロール・プロトタイプ関数を設定 (0.9.5)
 *   ＭＭＳお気に入りチェック機能追加 (0.9.6)
 *   debug関数を削除 (0.9.6)
 *   browser情報のオブジェクト名をXuaに変更し無名関数に変更 (0.9.7)
 *   ＭＭＳお気に入りチェック機能変更(0.9.8)
 *   ＭＭＳお気に入り追加機能変更(0.9.9.1)
 *   IE8対応(1.0)
 *   scroll-shopへの移行(1.1)
 */


/**windows IE documentへのアクセス高速化*/
/*@cc_on _d=document;eval('var document=_d')@*/



/**
 * 名前空間の作成
 *
 * @since 0.8
 *
 * @param {string} path namespaceのパス
 * @returns {object}
 */
var jsSetupPackage = function(path){
  var a = path.split('.');
  var o = window;
  for (var i = 0, l = a.length; i < l; i++){
      var name = a[i];
	  if (typeof(o[name]) == 'undefined') o[name] = {};
      o = o[name];
  }
  return o;
};


/**
 * ブラウザ情報
 *
 * @since 0.3
 * @config {srting} version ブラウザバージョン
 * @config {boolean} safari safariか否か
 * @config {boolean} opera operaか否か
 * @config {boolean} msie IEか否か
 * @config {boolean} mozilla mozillaか否か
 * @config {boolean} win windowsOSか否か
 * @config {boolean} mac macOSか否か
 */
var Xua = (function(){
	var userAgent = navigator.userAgent.toLowerCase();
	return {
		version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
		safari: /webkit/.test(userAgent),
		opera: /opera/.test(userAgent),
		msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
		mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent),
		win: /windows/.test(userAgent),
		mac: /macintosh/.test(userAgent)
	}
})();

/**
 * イベントリスナーに関数を登録する
 *
 * @since 0.1
 * @param {object} object (domReady時はobjectは無効)
 * @param {string} type イベント名
 * @param {function} function 関数名または関数式
 *
 * @example
 *  abc = function(){...};
 *  addEvent(window, 'load', imgSwap);
 *  addEvent(window, 'domReady', imgSwap);
 */
var addEvent = function(obj, type, fn) {
	if ('function' != typeof fn) return false;
	if(type == "domReady") {
		addDomReadyEventListener(fn);
		return false;
	}
	if (obj.attachEvent) {
		obj['e'+type+fn] = fn;
		obj[type+fn] = function(){obj['e'+type+fn](window.event);}
		obj.attachEvent('on'+type, obj[type+fn]);
	} else {
		obj.addEventListener(type, fn, false);
	}
};

/**
 * イベントリスナーに登録された関数を解除する
 *
 * @since 0.1
 * @param {object} object
 * @param {string} type イベント名
 * @param {function} function 関数名または関数式
 */
var removeEvent = function(obj, type, fn) {
	if (obj.detachEvent) {
		obj.detachEvent('on'+type, obj[type+fn]);
		obj[type+fn] = null;
	} else {
		obj.removeEventListener(type, fn, false);
	}
};

var onDomReady,onLoadAll;

/**
 * addDomReadyEventListener
 * DOMがロードされて操作・解析が可能になったタイミングで登録された関数を実行します。
 *
 * @since 0.1
 * @param {function} 関数名または関数式
 *
 * @example
 *  function something() {
 *     // do something
 *  }
 *  addDomReadyEventListener(something);
 *  //or
 *  addDomReadyEventListener(function(){
 *    // do other stuff
 *  });
 */

var addDomReadyEventListener = (function(){
	// create event function stack
	var load_events = [],
		load_timer,
		script,
		done,
		exec,
		old_onload,
		init = function () {
			done = true;

			// kill the timer
			clearInterval(load_timer);

			// execute each function in the stack in the order they were added
			while (exec = load_events.shift())
				exec();

			if (script) script.onreadystatechange = '';
		};

	return function (func) {
		// if the init function was already ran, just run this function now and stop
		if (done) return func();

		if (!load_events[0]) {
			// for Mozilla/Opera9
			if (document.addEventListener)
				document.addEventListener("DOMContentLoaded", init, false);

			// for Internet Explorer
			/*@cc_on @*/
			/*@if (@_win32)
				document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");
				script = document.getElementById("__ie_onload");
				script.onreadystatechange = function(){
					if (this.readyState == "complete")
						init(); 
				};
			/*@end @*/

			// for Safari
			if (/WebKit/i.test(navigator.userAgent)) { // sniff
				load_timer = setInterval(function(){
					if (/loaded|complete/.test(document.readyState))
						init(); // call the onload handler
				}, 10);
			}

			// for other browsers set the window.onload, but also execute the old window.onload
			old_onload = window.onload;
			window.onload = function(){
				init();
				if (old_onload) old_onload();
			};
		}
		load_events.push(func);
	}
})();







/**
 *	@namespace スクロールショップの名前空間
 */
jsSetupPackage('jp.co.mutow');

/**
 * スクロールショップのお買い物機能の共通機能
 *
 * @since 0.8
 * @constructor
 * @param {function} func 関数名または関数式
 * @returns {function}
 */
jp.co.mutow.commonSystem = function(func){
	var t = this;
	return function(){
		return func.apply(t, arguments);
	}
};

jp.co.mutow.commonSystem.prototype = {
	/**
	 * ウインドウを開く
	 * 
	 * @since 0.8
	 * @param {string} buildUrl ウインドウで開くURL
	 * @param {string} windowName ウインドウ名
	 * @param {string} window.open パラメータ
	 */
	cookieWindow:function(buildUrl, windowName, param){
		this.setCookie("checkCookie", "true");
		if(this.getCookie("checkCookie") == "true"){
			var win = window.open(buildUrl, windowName, param);
			win.focus();
		}else{
			alert("Cookieの設定を「使用する」に変更してください。");
		}
	},
	/**
	 * クッキーを登録する
	 *
	 * @since 0.8
	 * @private
	 * @param {string} key クッキーオブジェクトのキー
	 * @param {string} val 値
	 */
	setCookie:function(key, val) {
		var tmp = key + "=" + escape(val) + ";path=/;";
		document.cookie = tmp;
	},
	/**
	 * クッキーを取得する
	 *
	 * @since 0.8
	 * @private
	 * @param {string} key クッキーオブジェクトのキー
	 * @param {string} tmp1 
	 * @param {string} tmp2 
	 * @param {string} xx1 
	 * @param {string} xx2 
	 * @param {string} xx3 
	 * @returns {string}
	 */
	getCookie:function(key, tmp1, tmp2, xx1, xx2, xx3) {
		tmp1 = " " + document.cookie + ";";
		xx1 = xx2 = 0;
		var len = tmp1.length;
		while (xx1 < len) {
			xx2 = tmp1.indexOf(";", xx1);
			tmp2 = tmp1.substring(xx1 + 1, xx2);
			xx3 = tmp2.indexOf("=");
			if (tmp2.substring(0, xx3) == key) {
				return(unescape(tmp2.substring(xx3 + 1, xx2 - xx1 - 1)));
			}
			xx1 = xx2 + 1;
		}
		return("");
	}
};

/**
 * お気に入り登録
 *
 * @since 0.8
 * @augments jp.co.mutow.commonSystem
 * @param {string} hincd 品番
 * @param {string} catecd カテゴリーコード
 * @param {string} sitecd サイトコード
 * @param {string} limtdt 有効期限
 * @param {string} outletsw アウトレットフラグ
 * @param {string} [categoryCd] 一覧・詳細ページコード
 * @param {string} [rtnURL] 表示するURL
 */
var addFavorite = new jp.co.mutow.commonSystem(function(hincd, catecd, sitecd, limtdt, outletsw, categoryCd, rtnURL){

	//rtnURLが無ければ、location.href
	var rtnURL = rtnURL || location.href,
	
	//categoryCdが無い場合は'xxxxxx'を代入
	categoryCd = categoryCd || 'xxxxxx',

	buildUrl = "http://www.scroll-shop.com/plaza/apl/SV?md=jump&dst=checklistentry&rtnURL=" + encodeURIComponent(rtnURL);
	buildUrl += "&hinCD=" + hincd + "&ctgryCD=" + categoryCd + "&siteCD=" + sitecd + "&limit=" + limtdt + "&entryFlg=2";
	buildUrl += (outletsw != '') ? "&outletFlg=1" :"&outletFlg=0";
		
	var x = (screen.width  - 300) / 2;
	var y = (screen.height - 150) / 2;
	var param = "width=300,height=150,scrollbars=0,resizable=1,location=0,status=0,titlebar=0,top=" + x + ",left=" + y;
	this.cookieWindow(buildUrl,"checklistentry", param);
});

/**
 * お気に入り参照
 * 
 * @since 0.8
 * @augments jp.co.mutow.commonSystem
 */
var showFavorite = new jp.co.mutow.commonSystem(function(){
	var x = screen.width - 250;
	var buildUrl = "http://www.scroll-shop.com/plaza/apl/SV?md=jump&dst=checklist&rtnURL=" + encodeURIComponent(location.href);
	var param = "width=250,height=800,scrollbars=1,resizable=1,location=0,top=1,left=" + x;
	this.cookieWindow(buildUrl,"checklist", param);
});

/**
 * 商品チェック履歴参照
 * 
 * @since 0.8
 * @augments jp.co.mutow.commonSystem
*/
var showItemHistory = new jp.co.mutow.commonSystem(function(){
	var x = screen.width - 250;
	var buildUrl = "http://www.scroll-shop.com/plaza/apl/SV?md=jump&dst=readinglist";
	var param = "width=250,height=800,scrollbars=1,resizable=1,location=0,top=1,left=" + x;
	this.cookieWindow(buildUrl,"readinglist", param);
});

/**
 * チェックリスト画面をリロードするか否かの判定
 *
 * @since 0.9.8
 * @param {object} data フラグが格納されているオブジェクト
 */
var checkListReLoad = function(data) {
	if (data.checkListFlg == 'true') showItemHistory();
	if (data.favoriteFlg == 'true') showFavorite();
};

/**
 * 商品チェック履歴追加
 *
 * @since 0.9.8
 * @param {String} hinmokucd 品目コード
 * @param {String} sitecd サイトコード
 * @param {String} limit カタログ有効期限
 * @param {String} outletflg アウトレットフラグ
 */
var addReadingHistory = function(In_hinCD, In_siteCD, In_limit, In_outletFlg){
	var sendParam = 'hinCD=' + In_hinCD + '&ctgryCD=xxxxxx&siteCD=' + In_siteCD + '&limit=' + In_limit;
	if (In_outletFlg == '1') {
		sendParam = sendParam + '&outletFlg=' + In_outletFlg;
	}
	var sendUrl = 'http://www.scroll-shop.com/plaza/apl/jsp/MACReadingHistry2.jsp?' + sendParam;
	var scriptTag = document.createElement("script");
	scriptTag.setAttribute("type", "text/javascript");
	scriptTag.setAttribute("src", sendUrl);
	document.getElementsByTagName("head").item(0).appendChild(scriptTag);
};



/**
 * 要素の高さをそろえる
 *
 * @since 0.9
 * @constructor
 * @returns {function} update関数を走らせる
 * @config {object} cache IDごとのエレメントとクラスを登録するオブジェクト
 * @config {function} addCSSRule スタイルルールを追加する
 */
jp.co.mutow.trimHeight = function(){
	var t = this;
	this.cache = {};
	this.addCSSRule = (/*@cc_on!@*/false)
		? (function(sheet){
				return function(selector, declaration){
					sheet.addRule(selector, declaration);
				};
			})(document.createStyleSheet())
		: (function(sheet){
				return function(selector, declaration){
					sheet.insertRule(selector + '{' + declaration + '}', sheet.cssRules.length);
				};
			})((function(e){
				e.appendChild(document.createTextNode(''));
				(document.getElementsByTagName('head')[0] || (function(h){
					document.documentElement.insertBefore(h, this.firstChild);
					return h;
				})(document.createElement('head'))).appendChild(e);
				return e.sheet;
			})(document.createElement('style')))
		;
	
	return function(){
		return t.update.apply(t, arguments);
	}
};

jp.co.mutow.trimHeight.prototype = {
	/**
	 * 高さの値を更新する
	 *
	 * @param {string} ID 揃える要素を包括するID
	 * @param {integer} cols 揃える要素の横列数
	 * @param {string} [cellTag="div"] 揃える要素のタグ名 
	 * @param {string} [cellClass="X_ITEM_CELL"] 揃える要素のクラス名
	 */
	update:function(ID, cols, cellTag, cellClass){
		//IDかcolsの引数が無いか該当するIDがなければ終了
		if(!ID || !cols || !document.getElementById(ID)) return false;
		
		var	
		cellTag = cellTag || 'div',
		cellClass = cellClass || 'X_ITEM_CELL',
		items,
		heights,
		pad;

		//すでにクラスが設定されていたら、指定を解除
		if(this.cache[ID + 'class']) this.resetClass(ID, this.cache[ID + 'class']);
		
		//揃える要素の配列を取得
		items = this.cache[ID] || this.getItems(ID, cellTag, cellClass);
		
		//揃える要素の高さを取得
		heights = this.getHeight(items);
		
		//揃える要素の縦に設定させているcssの値の合計を取得
		pad = this.cache[ID + 'pad'] || this.getPad(ID, items[0]);
		
		//揃える要素の横並びの固まりごとにクラス名を付加
		//一度だけ実行
		if(!this.cache[ID + 'class']) this.setClass(ID, items, cols);
		
		//クラスの適応
		this.setRule(ID, cols, heights.h, pad);
		
	},
	/**
	 * 対象要素を取得する
	 *
	 * @private
	 * @param {string} ID 取得するエリアID
	 * @param {string} cellTag 対象要素のタグ名
	 * @param {string} cellClass 対象要素のクラス名
	 * @returns {array} 対象要素配列
	 */
	getItems:function(ID, cellTag, cellClass){
		var list = document.getElementById(ID),
		divs = list.getElementsByTagName(cellTag),
		items = [];
		for(var i = 0, len = divs.length; i < len; i++){
				if(cellClass == divs[i].className){
					items[items.length] = divs[i];
				}
			}
		return this.cache[ID] = items;
	},
	/**
	 * 対象要素の高さ取得する
	 *
	 * @private
	 * @param {array} items 対象要素配列
	 * @returns {object} 高さ配列と最大値のオブジェクト
	 */
	getHeight:function(items){
		for(var i = 0, len = items.length, h = [], maxh = 0; i < len; i++){
			var itemh = parseInt(items[i].offsetHeight);
			h[h.length] = itemh;
			if(maxh < itemh) maxh = itemh;
		}
		return {h:h, maxh:maxh};
	},
	/**
	 * 1つのサンプル要素からCSSのボーダー、マージン、パディングの高さ要素の合計値を取得
	 *
	 * @private
	 * @param {string} ID 取得するエリアID
	 * @param {object} sample 1つのサンプル要素
	 * @returns {integer} 要素のCSSのボーダー、マージン、パディングの高さ要素の合計値
	 */
	getPad:function(ID, sample){
		//互換モードは0を返す
		if(Xua.msie && (document.compatMode != "CSS1Compat" || Xua.version < 6)) return this.cache[ID + 'pad'] = 0;
		var pad = 0, sty, props = ['paddingTop','paddingBottom','borderTopWidth','borderBottomWidth'];
		(sample.currentStyle) ? sty = sample.currentStyle : sty = document.defaultView.getComputedStyle(sample,'');
		for(var i = 0, len = props.length; i < len; i++){
			pad += parseInt(sty[props[i]].replace("px",""));
		}
		return this.cache[ID + 'pad'] = pad;
	},
	/**
	 *	横並びの要素ごとに同一のクラス属性を追加する
	 *
	 * @private
	 * @param {string} ID 取得するエリアID
	 * @param {array} items 対象要素配列
	 * @param {integer} cols 揃える要素の横列数
	 */
	setClass:function(ID, items, cols){
		var num = 0, temp, tempArr = [],
		attr = (Xua.msie && Xua.version<9) ? 'className' : 'class';	//IE8は取得方法変更
		for(var i = 0, len = items.length; i < len; i++){
			var defClass = items[i].getAttribute(attr),
			arr = defClass.split(' '),
			cname = 'X_TRIM_CLASS' + num;
			if(temp != cname){
				temp = cname;
				tempArr[tempArr.length] = temp;
			}
			arr[arr.length] = cname;
			items[i].setAttribute(attr, arr.join(' '));
			if(i%cols == (cols-1)) num++;
		}
		this.cache[ID + 'class'] = tempArr;
	},
	/**
	 *	クラスルールの高さをautoにする
	 *
	 * @param {string} ID 取得するエリアID
	 * @param {array} classes 対象クラス名配列
	 */
	resetClass:function(ID, classes){
		for(var i = 0, len = classes.length; i < len; i++){
			this.addCSSRule('#' + ID + ' .' + classes[i], 'height:auto;');
		}
	},
	/**
	 *	クラスルールに高さを登録する
	 *
	 * @private
	 * @param {string} ID 取得するエリアID
	 * @param {integer} cols 揃える要素の横列数
	 * @param {array} heights 揃える要素の高さ配列
	 * @param {integer} pad 要素のCSSのボーダー、マージン、パディングの高さ要素の合計値
	 */
	setRule:function(ID, cols, heights, pad){
		var tempArr = [];
		var count = Math.ceil(heights.length/cols);
		var s = function(a,b){return a - b;}
		for (var i = 0; i < count; i++) {
			tempArr[tempArr.length] = heights.slice(i * cols, i * cols + cols);
		}
		for (var i = 0, len = tempArr.length; i < len; i++) {
			var maxH = tempArr[i].sort(s).pop();
			this.addCSSRule('#' + ID + ' .X_TRIM_CLASS' + i, 'height:'+ (maxH - pad) + "px;");
		}
	}
};


/**
 * swap img
 *
 * タグのclassに引数"class"が指定されているタグ(引数"tag")に
 * ロールオーバーイベントで、引数"suffix"をファイル名に付加したファイルを表示する命令を追加する
 * 引数"suffix"ファイルが存在しない場合は、イベントを付加しない。
 * プリロード付き
 *
 * @since 0.9.5
 * @constructor
 * @returns {function} init関数を走らせる
 *
 * @example
 *  imgSwapObject = new jp.co.mutow.imgSwap();
 *  imgSwapObject('img', 'swap', '-o');
 *  以下は、上と同等
 *  imgSwapObject('img');
 *
 */
jp.co.mutow.imgSwap = function(){
	var t = this;
	return function(){
		return t.init.apply(t, arguments);
	}
};

jp.co.mutow.imgSwap.prototype = {
	/**
	 * 要素に設定する
	 * @param {string} tag 置き換え処理をするタグ
	 * @param {string} [targetClass="swap"] ロールオーバー時に置き換えするタグに設定しているclass名
	 * @param {string} [suffix="-o"] ロールオーバー時に置き換えするsrcの接尾語
	 */
	init:function(tag, targetClass, suffix){
		if(!tag) return false;
		var 
		targetClass = targetClass || 'swap',
		suffix = suffix || '-o',
		elm = document.getElementsByTagName(tag),
		preLoader = new Array();
		for(var i=0,len = elm.length; i < len; i++) {
			if(elm[i].className == targetClass){
				preLoader[i] = new Image();
				var fileName = elm[i].originalImg = elm[i].getAttribute("src");
				preLoader[i].src = elm[i].hoverImg = fileName.replace(/^(.+)(\.[a-z]+)$/, "$1-o$2");
				preLoader[i].elm = elm[i];
				preLoader[i].onload = function(){
					this.elm.onmouseover = function(){
						this.setAttribute("src", this.hoverImg);
					};
					this.elm.onmouseout = function(){
						this.setAttribute("src", this.originalImg);
					};
				};
			}
		}
	}
};


/**
 * scroller
 * <a>タグのhref属性に引数"ID"が含まれていたら、クリックイベントにスムーススクロール機能を追加する
 *
 * @since 0.9.5
 * @constructor
 * @returns {function} init関数を走らせる
 *
 */

jp.co.mutow.scroller = function(){
	this.init.apply(this, arguments);
};

jp.co.mutow.scroller.prototype = {
	/**
	 * 初期化
	 *
	 * @param {string} [ID="#header"] キーとなるhrefに指定してあるアンカー名
	 * @param {number} [speed=1.5] スクロールの早さ[1.0以上]
	 */
	init:function(ID, speed){
		this.speed = (speed<=1) ? 1.5 : speed || 1.5;
		var 
		ID = ID || '#header',
		self = this,
		elm = document.getElementsByTagName('A');
		for(var i=0,len = elm.length; i < len; i++) {
			var hrf = (Xua.msie) ? elm[i].getAttribute("href", 2) : elm[i].getAttribute("href");
			if(hrf && hrf.indexOf(ID) > -1){
				elm[i].onclick = function(){
					self.scrlTo();
					return false;
				}
			}
		}
	},
	/**
	 * ウインドウをスクロールする
	 *
	 * @private
	 * @throws 目的地まで達していない場合は再帰する
	 */
	scrlTo:function(){
		var t = this,
		y1 = y2 = y3 = 0;
		if (document.documentElement) y1 = document.documentElement.scrollTop || 0;
		if (document.body) y2 = document.body.scrollTop || 0;
		y3 = window.scrollY || 0;
		var y = Math.max(y1, Math.max(y2, y3));
		window.scrollTo(0, Math.floor(y / this.speed));
		if (y > 0) {
			window.setTimeout(function(){t.scrlTo()}, 30);
		}
	}
};



