/**
 * 定数一覧
 * 
 */
var Constants =
{
	// 配送種別
	SHIPPING_TYPE: {
		STANDARD: 0, // 通常配送
		MAIL: 1 // メール便
	},
	
	DELIVERY_METHOD_ID: {
		STANDARD: 1,
		MAIL: 2
	},
	
	DELIVERY_DATE_RANGE: {
		FROM: 7, // 7日以降
		TO: 26 // 7日以降で26日間
	},
	
	// 配送日時
	DELIVERY_TIME_ID: {
		0: '指定なし',
		1: '午前中',
		2: '12時～14時',
		3: '14時～16時',
		4: '16時～18時',
		5: '18時～20時',
		6: '20時～21時'
	},
	
	PAYMENT_METHOD: {
		CREDIT_CARD: 1, // 'クレジットカード',
		BANK_TRANSFER: 2, // '銀行振込',
		CASH_ON_DELIVERY: 3, // '代金引換',
		TRANSFER: 4 // '郵便振替・コンビニ振替'
	},
	
	PAYMENT_METHOD_TRANSFER_LIMIT: 30000, // 郵便振替／コンビニ決済は、3万円まで
	
	// クーポン利用不可catalogSpecId群
	DISAPPROVE_OF_COUPON: [5,8,9,12,13,16,17,20,23,24,25,35,37,38,43,45,47,49,108,109,112,123,124,135,117,137,53,153,54],
	
	// ギフト商品catalogSpecId群
	GIFT_ITEMS: [55]
	
	// TODO 送料無料金額追加する
};


/**
 * DOMツリー構築後に呼ばれます。
 * 
 */
$(function(){
	// グローバルな処理をここで行う
	APIManager.initialize();
	
	$('<img />').attr('src', '/img/common/loader.gif');
	$('<img />').attr('src', '/img/cart/bg_org_box.gif');
	$('<img />').attr('src', '/img/cart/bg_org_box.png');
	
	// カート情報更新
	Cart.reload(function(){
		// サイドメニューのログイン表示非表示切替
		if(Cart.isLoggedIn()){
			$('.box_lohas-member').hide();
		}else{
			$('.box_lohas-member').show();
			
			// サイドメニュー「ログイン」ボタンのクリック時
			$('#login_button').live('click', function(event){
				event.preventDefault();
				location.replace('https://' + location.host + '/login/');
				return false;
			});
			
			// サイドメニュー「会員登録」ボタンのクリック時
			$('#entry_button').live('click', function(event){
				event.preventDefault();
				location.replace('https://' + location.host + '/entry/kiyaku.html');
				return false;
			});
			
			// サイドメニュー「パスワードを忘れた方はこちら」リンク
			$('#go_forgot_button').live('click', function(event){
				event.preventDefault();
				location.replace('https://' + location.host + '/forgot/');
				return false;
			});
		}
		
		$.preloadRollover();
		
		_direct_add_cart();
	});
	
	// 「カートに入れる」ボタンを拾う
	// class属性に
	// add_cart_カタログスペックID
	// が指定してあるものが対象
	// 
	// トップページなど、サイズや数量の選択なしで
	// ダイレクトにカートに入れるタイプ
	// 
	$(':regex(class,add_cart_[0-9]+)').live('click', function(event){
		event.preventDefault();
		
		var catalogSpecId = $(this).attr('class').replace(/^.*add_cart_([0-9]+).*$/, '$1');
		// カート追加
		APIManager.CT002(catalogSpecId, 1, function(response){
			if(!response.result){
				$.each(response.errors, function(){
					if(this.errorCode == 'ECT002_001'){
						// ECT002_001	catalog_spec_id	商品が売り切れ（sold_out=1の状態）	
						alert('売り切れました');
						
					}else if(this.errorCode == 'ECT002_002'){
						// ECT002_002	catalog_spec_id	商品が終売（end_of_sale=1の状態）	
						alert('取り扱い終了いたしました');
						
					}else if(this.errorCode == 'ECT002_003'){
						// ECT002_003	quantity	数量の入力が不正	
						alert('数量が不正です');
					}else{
						alert('エラーが発生しました');
					}
				});
				
				return false;
			}
			
			Cart.reload(function(){
				PopUpManager.createPopUp(Cart.view, function(){
					Cart.addItemGlow(catalogSpecId);
				});
			});
		});
		
		return false;
	});
	
	// 「カートに入れる」ボタンを拾う
	// class属性に
	// add_cart
	// が指定してあり、name属性がsizeのプルダウンで
	// optionのvalueがcatalogSpecIdになっており、
	// name属性がquantityの数量入力項目があり、
	// それらがformでくくられているタイプ
	// 主に商品詳細ページなど
	// 
	$('.add_cart').live('click', function(event){
		event.preventDefault();
		var form = $(this).closest('form');
		var selected = $('[name=size] option:selected', form);
		var catalogSpecId = selected.val();
		if(catalogSpecId){
			var quantity = $('[name=quantity]', form).val();
			
			if(!quantity){
				alert('数量が入力されておりません');
				return false;
			}
			
			quantity = quantity.zenkakuNumeric2HankakuNumeric();
			if(!quantity.match(/^[0-9]+$/)){
				alert('数量を数字で入力してください');
				return false;
			}
			
			quantity = Number(quantity);
			
			//if(!quantity){
			//	quantity = 1;
			//}
			
			// カート追加
			APIManager.CT002(catalogSpecId, quantity, function(response){
				if(!response.result){
					$.each(response.errors, function(){
						if(this.errorCode == 'ECT002_001'){
							// ECT002_001	catalog_spec_id	商品が売り切れ（sold_out=1の状態）	
							alert('売り切れました');
							
						}else if(this.errorCode == 'ECT002_002'){
							// ECT002_002	catalog_spec_id	商品が終売（end_of_sale=1の状態）	
							alert('取り扱い終了いたしました');
							
						}else if(this.errorCode == 'ECT002_003'){
							// ECT002_003	quantity	数量の入力が不正	
							alert('数量が不正です');
						}else{
							alert('エラーが発生しました');
						}
					});
					
					return false;
				}
				
				Cart.reload(function(){
					PopUpManager.createPopUp(Cart.view);
					Cart.addItemGlow(catalogSpecId);
				});
			});
		}else{
			alert('サイズを選択してください');
		}
		
		return false;
	});

	// 「カートに入れる」リクエストを拾う
	// 外部サイトなどからダイレクトにカートに入れる
	function _direct_add_cart(){
		var matches = location.search.match(/^\?_hv_direct_cart\=(.+)$/);
		if(matches){
			var catalogSpecId = matches[1];
			// カート追加
			APIManager.CT002(catalogSpecId, 1, function(response){
				if(!response.result){
					$.each(response.errors, function(){
						if(this.errorCode == 'ECT002_001'){
							// ECT002_001	catalog_spec_id	商品が売り切れ（sold_out=1の状態）	
							alert('売り切れました');
							
						}else if(this.errorCode == 'ECT002_002'){
							// ECT002_002	catalog_spec_id	商品が終売（end_of_sale=1の状態）	
							alert('取り扱い終了いたしました');
							
						}else if(this.errorCode == 'ECT002_003'){
							// ECT002_003	quantity	数量の入力が不正	
							alert('数量が不正です');
						}else{
							alert('エラーが発生しました');
						}
					});
					
					return false;
				}
				
				Cart.reload(function(){
					PopUpManager.createPopUp(Cart.view, function(){
						Cart.addItemGlow(catalogSpecId);
					});
				});
			});
		}
	}
});

Date.__formats = {
	yyyy: function(){
		if(this instanceof Date){
			return this.getFullYear();
		}else{
			return Number(this); // format関数用
		}
	},
	mm: function(){
		if(this instanceof Date){
			return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1);
		}else{
			return Number(this);
		}
	},
	m: function(){
		if(this instanceof Date){
			return this.getMonth() + 1;
		}else{
			return Number(this);
		}
	},
	dd: function(){
		if(this instanceof Date){
			return (this.getDate() < 10 ? '0' : '') + this.getDate();
		}else{
			return Number(this);
		}
	},
	d: function(){
		if(this instanceof Date){
			return this.getDate();
		}else{
			return Number(this);
		}
	}
};

Date.parse = function(dateString, format){
	var _defaultFormat = 'yyyy/mm/dd';
		
	var patternString = '';
	for(var key in Date.__formats){
		patternString += ('|' + key);
	}
	patternString = patternString.slice(1);
	var pattern = new RegExp(patternString, 'g');
		
	var _year;
	var _month;
	var _day;
	(format || _defaultFormat).replace(pattern, function(match, position, format){
		var dateStringPart = dateString.substr(position, match.length);
		var replaceFunction = Date.__formats[match];
		if(replaceFunction){
			var result = replaceFunction.call(dateStringPart);
			if(match.toString().match(/yyyy/)){ // TODO
				_year = result;
			}else if(match.toString().match(/mm?/)){ // TODO
				_month = result;
				
			}else if(match.toString().match(/dd?/)){ // TODO
				_day = result;
			}
		}
	});
		
	return new Date(_year, _month - 1, _day, 0, 0, 0);
};

Date.prototype.addDay = function(addDay){
	var newDate = new Date(this.getFullYear(), this.getMonth(), this.getDate());
	var now = newDate.getTime();
	var add = addDay * 86400000;
	newDate.setTime(now + add);
	
	return newDate;
};

Date.prototype.format = function(format){
	var _self = this;
	
	var patternString = '';
	for(var key in Date.__formats){
		patternString += ('|' + key);
	}
	patternString = patternString.slice(1);
	var pattern = new RegExp(patternString, 'g');
	
	return format.replace(pattern, function(match){
		var replaceFunction = Date.__formats[match];
		return replaceFunction.call(_self);
	});
};


String.prototype.hiragana2Katakana = function(){
	var result = new Array();
	for(var i = 0; i < this.length; i++){
		var character = this.charCodeAt(i);
		result.push((0x3041 <= character && character <= 0x3096) ? character + 0x0060 : character);
	}
	
	return String.fromCharCode.apply(null, result);
};


String.prototype.hankakuKatakana2ZenkakuKatakana = function(){
	var mapping = {\uff76\uff9e: '\u30ac', \uff77\uff9e: '\u30ae', \uff78\uff9e: '\u30b0', \uff79\uff9e: '\u30b2', \uff7a\uff9e: '\u30b4', \uff7b\uff9e: '\u30b6', \uff7c\uff9e: '\u30b8', \uff7d\uff9e: '\u30ba', \uff7e\uff9e: '\u30bc', \uff7f\uff9e: '\u30be', \uff80\uff9e: '\u30c0', \uff81\uff9e: '\u30c2', \uff82\uff9e: '\u30c5', \uff83\uff9e: '\u30c7', \uff84\uff9e: '\u30c9', \uff8a\uff9e: '\u30d0', \uff8b\uff9e: '\u30d3', \uff8c\uff9e: '\u30d6', \uff8d\uff9e: '\u30d9', \uff8e\uff9e: '\u30dc', \uff8a\uff9f: '\u30d1', \uff8b\uff9f: '\u30d4', \uff8c\uff9f: '\u30d7', \uff8d\uff9f: '\u30da', \uff8e\uff9f: '\u30dd', \uff71: '\u30a2', \uff72: '\u30a4', \uff73: '\u30a6', \uff74: '\u30a8', \uff75: '\u30aa', \uff76: '\u30ab', \uff77: '\u30ad', \uff78: '\u30af', \uff79: '\u30b1', \uff7a: '\u30b3', \uff7b: '\u30b5', \uff7c: '\u30b7', \uff7d: '\u30b9', \uff7e: '\u30bb', \uff7f: '\u30bd', \uff80: '\u30bf', \uff81: '\u30c1', \uff82: '\u30c4', \uff83: '\u30c6', \uff84: '\u30c8', \uff85: '\u30ca', \uff86: '\u30cb', \uff87: '\u30cc', \uff88: '\u30cd', \uff89: '\u30ce', \uff8a: '\u30cf', \uff8b: '\u30d2', \uff8c: '\u30d5', \uff8d: '\u30d8', \uff8e: '\u30db', \uff8f: '\u30de', \uff90: '\u30df', \uff91: '\u30e0', \uff92: '\u30e1', \uff93: '\u30e2', \uff94: '\u30e4', \uff95: '\u30e6', \uff96: '\u30e8', \uff97: '\u30e9', \uff98: '\u30ea', \uff99: '\u30eb', \uff9a: '\u30ec', \uff9b: '\u30ed', \uff9c: '\u30ef', \uff66: '\u30f2', \uff9d: '\u30f3', \uff67: '\u30a1', \uff68: '\u30a3', \uff69: '\u30a5', \uff6a: '\u30a7', \uff6b: '\u30a9', \uff6c: '\u30e3', \uff6d: '\u30e5', \uff6e: '\u30e7', \uff6f: '\u30c3', \uff70: '\u30fc'};
	var result = this;
	for(var key in mapping){
		var pattern = new RegExp(key, "g");
		result = result.replace(pattern, mapping[key]);
	}
	
	return result;
};


String.prototype.zenkakuNumeric2HankakuNumeric = function(){
	return this.replace(/[０-９]/g, function(value){
		return String.fromCharCode(value.charCodeAt(0) - 65248);
	});
};


/**
 * jQuery拡張
 * セレクタに正規表現を使える
 * 
 */
jQuery.expr[':'].regex = function(element, index, match) {
	var matchParams = match[3].split(','),
		validLabels = /^(data|css):/,
		attr = {
			method: matchParams[0].match(validLabels) ? matchParams[0].split(':')[0] : 'attr',
			property: matchParams.shift().replace(validLabels,'')
		},
		regexFlags = 'ig',
		regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
	
	return regex.test(jQuery(element)[attr.method](attr.property));
};


/**
 * jQuery拡張
 * outerHTML実装
 * 
 */
jQuery.fn.outerHTML = function() {
	try{
	    return $('<div />').append(this.eq(0).clone()).html();
	}catch(error){
		return error;
	}
};

/**
 * jQuery拡張
 * ￥表記(3桁ごとのカンマ)で返します
 * 
 */
jQuery.extend({
	currency: function(n){
		var result;
		var str = '' + n;
		var ary;
		if(!(ary = str.match(/^([\+-]|)(\d+)(\.\d+|)$/))){
			return '';
		}
		var int_part = ary[2];
		var len = int_part.length;
		var mod = (len - 1) % 3 + 1;
		result = int_part.substr(0, mod);
		for(var i = mod; i < len; i += 3){
			result += "," + int_part.substr(i, 3);
		}
		result = ary[1] + result + ary[3];
		
		return result;
	}
});

jQuery.extend({
	isEmpty: function(hash){
		for(var key in hash){
			return false;
		}
		return true;
	}
});


/**
 * jQuery拡張
 * form値をjsonに
 * 
 */
jQuery.fn.form2json = function(){
	var serialize = this.serializeArray();
	
	if(serialize.constructor != Array){
		return serialize;
	};
	
	var data = {};
	for(var i = 0; i < serialize.length; i++){
		if(typeof data[serialize[i].name] != 'undefined'){
			if(data[serialize[i].name].constructor!= Array){
			    data[serialize[i].name] = [data[serialize[i].name],serialize[i].value];
			}else{
			    data[serialize[i].name].push(serialize[i].value);
			}
		}else{
			data[serialize[i].name] = serialize[i].value;
		}
	}
	
	return data;
};

// rollover.js依存
jQuery.extend({
	preloadRollover: function(){
		var rolloverSuffix = '_on';
		
		$('img.imgover,input.imgover').each(function(i){
			var element = $(this);
			
			if(element.attr('hsrc')){ // rollover.jsでプリロード済みなら何もしない
				return true;
			}
			
			if($.data(element.get(0), 'hsrc')){ // 自身でプリロード済みなら何もしない
				element.attr('src', $.data(element.get(0), 'src'));
				return true;
			}
			
			var src = element.attr('src');
			var rolloverImageSrc = src.replace(/^(.+)\.(jpg|gif|png)$/, '$1' + rolloverSuffix + '.$2');
			
			$('<img />').attr('src', rolloverImageSrc);

			$.data(element.get(0), 'src', src);
			$.data(element.get(0), 'hsrc', rolloverImageSrc);
			
			element.unbind('mouseover.preload');
			element.bind('mouseover.preload', function(){
				element.attr('src', $.data(element.get(0), 'hsrc'));
			});
			
			element.unbind('mouseout.preload');
			element.bind('mouseout.preload', function(){
				element.attr('src', $.data(element.get(0), 'src'));
			});
			
			element.unbind('mousedown.preload');
			element.bind('mousedown.preload', function(){
				element.attr('src', $.data(element.get(0), 'src'));
			});
		});
	}
});


/**
 * 入力値バリデーター
 * 
 * jQuery依存
 * jQuery regex拡張依存
 * 
 */
(function($){
	/**
	 * jQuery名前空間に新たなメソッドを追加
	 * 
	 */
	$.validator = {};

	/**
	 * jQueryオブジェクトに対して
	 * バリデーションを有効にするにために最初に実行する
	 * 
	 */ 
	$.fn.loadValidation = function(settings){
		// デフォルト設定と引数に渡された設定をマージ
		var settings = $.extend({
			allrules: messages,
			triggers: 'blur',
			//triggers: 'keyup blur',
			//triggers: 'focusout',
			inlineValidation: true,
			returnIsValid: false,
			animateSubmit: true,
			unbindEngine: true,
			ajaxSubmit: false,
			position: "topRight", // topLeft, topRight, bottomLeft, centerRight, bottomRight
			success : false,
			failure : function() {}
		}, settings);
		
		// 設定反映
		$.validator.settings = settings;
		
		// インラインバリデーション(リアルタイムバリデーション)の場合は
		// 入力項目のイベントハンドルする
		if(settings.inlineValidation){
			if(!settings.returnIsValid){
				
				// 入力項目のイベントをハンドル
				var _triggers = '';
				$.each(settings.triggers.split(' '), function(){
					// unbindのための名前空間を付加
					_triggers += this + '.validate ';
				});
				_triggers = $.trim(_triggers);
				
				// 条件付バリデーションの場合はパースしておく
//				$(this).find(':enabled:regex(class,v\\[c\\[)').each(function(){
				$(this).find(':regex(class,v\\[c\\[)').each(function(){
					var element = $(this);
					var condition = element.attr('class').match(/v\[c\[(.+?)\]/)[1];
					var matches = condition.match(/(.+)=(.+)/);
					var targetName = matches[1];
					var targetValue = matches[2];
					var targets = $('[name=' + targetName + ']');
					
					// TODO とりあえず条件ターゲットはラジオボタンのみ
					
					// 現時点で条件を満たしてるかどうかのチェック
					if($('[name=' + targetName + ']:checked').val() == targetValue){
						_updatePrompt(element, _validate(element));
						element.bind(_triggers, function(){
							_updatePrompt(element, _validate(element));
						});
					}
					
					// 値が変更されるイベントをハンドル
					targets.click(function(event){
						element.unbind(_triggers);
						if($(this).val() == targetValue){
							if(element.val()){
								_updatePrompt(element, _validate(element));
							}
							element.bind(_triggers, function(){
								_updatePrompt(element, _validate(element));
							});
						}else{
							_updatePrompt(element, null);
						}
					});
				});
				
				$(this).find(':regex(class,v\\[[^c])').not('[type=checkbox]').bind(_triggers, function(){
					var element = $(this);
					
					var name = element.attr('name');
					if(name.match(/^(.+)_part[1-9]$/)){ // グループバリデーションの場合
						var namePrefix = name.replace(/(.+)_part[1-9]/, '$1');
						
						if($('#gv_' + namePrefix).size() == 1){ // グループバリデーションの指定がある
							var elements = $(':regex(name,' + namePrefix + '_part[0-9])');
							// ソート？
							//for(var i = 0; i < elements.length; i++){
							//	var element = elements.find(':regex(name,^.+_part' + (i + 1) + '$)');
							//}
							var errorMessages = _validateGroup(elements);
							if(errorMessages){
//								_updatePrompt($('#gv_' + namePrefix), errorMessages);
								_updatePrompt(element, errorMessages);
							}else{
								// グループとしての検証OKなら
								// すべてのグループ項目を再検証する
								// なぜならグループ検証NGの場合はすべてのグループ項目に対して
								// エラープロンプトが設定されている状態のため
								
								$.each(elements, function(){
									_updatePrompt($(this), _validate($(this)));
								});
							}
						}else{
							_updatePrompt(element, _validate(element));
						}
						
					}else{
						_updatePrompt(element, _validate(element));
					}
				});
				
				// チェックボックスの場合はクリックイベントをハンドル
				$(this).find(':regex(class,v\\[[^c])[type=checkbox]').bind('click.validate', function(){
					//_inlineEvent(this);
					//	$.validator.loadValidation(element); 
					_updatePrompt($(this), _validate($(this)));
					alert('TODO');
//					function radioHack(){
//					if($("input[name='"+callerName+"']").size()> 1 && (callerType == "radio" || callerType == "checkbox")) {        // Hack for radio/checkbox group button, the validation go the first radio/checkbox of the group
//						caller = $("input[name='"+callerName+"'][type!=hidden]:first");     
//					    $.validationEngine.showTriangle = false;
//					}
//					    }
				});
			}
		}
		
		if(settings.returnIsValid){
			if(!_validateSubmit($(this))){
				alert('赤枠の入力項目をご確認ください'); // TODO 呼び出し側でやるべき？
				return false;
			}else{
				return true;
			}
		}
	};
	
	
	/**
	 * バリデーションをアンロードします。
	 * 
	 */
	$.fn.unloadValidation = function(){
		if(!$.validator.settings){ // ロードされていない場合
			return;
		}
		
		var _triggers = '';
		$.each($.validator.settings.triggers.split(' '), function(){
			// unbindのための名前空間を付加
			_triggers += this + '.validate ';
		});
		_triggers = $.trim(_triggers);
		
		$(this).find(':regex(class,v\\[)').each(function(){
			var element = $(this);
			
			$.removeData(element.get(0), 'errorPrompt');
			$.removeData(element.get(0), 'rules');
			
			if(element.attr('type') == 'checkbox'){
				element.unbind('click.validate');
			}else{
				element.unbind(_triggers);
			}
			element.unbind('mouseover.error');
			element.unbind('mouseout.error');
			
			// ラジオボタンの場合
			if(element.attr('type') == 'radio'){
				element.removeClass('validateRadioError');
			}else{
				element.removeClass('validateError');
			}
		});
		
		$(this).find('.formError').remove();
	};
	
	
	/**
	 * 検証を実行します。
	 * 
	 */
	function _validate(element){
		if(element.attr('disabled')){
			return '';
		}
		
		var rules = $.data(element.get(0), 'rules');
		if(!rules){
			// バリデーションルールのパース
			var rulesString = element.attr('class').match(/v\[(.*)\]/)[1];
			rules = new Array();
			
	//		if(/^c\[.+\]/.test(rulesString)){ // 条件付きを使う場合は最初に指定してある
	//		}
			
			if(/^.*re\[.+\]$/.test(rulesString)){ // TODO regexpを使う場合は最後に指定すること
				var matches = rulesString.match(/^(.*)(re\[.+\])$/);
				if(matches[1]){
					rules = matches[1].split(',');
					rules.pop();
				}
				rules.push(matches[2]);
				
			}else{
				rules = rulesString.split(',');
			}
			
			// 必須バリデーションがある場合、
			// 優先的に実行させるために配列の最初に持ってくる
			var index = $.inArray('r', rules);
			if(index != -1){
				rules.splice(index, 1);
				rules.unshift('r');
			}
			
			// バリデーションルールを一度パースしたらキャッシュしておく
			$.data(element.get(0), 'rules', rules);
		}
		
		// バリデーション項目にid属性がない場合はデバッグモード表示
		//if(!$(targetElement).attr("id")){
		//	$.validator.debug("This field have no ID attribut( name & class displayed): "+$(targetElement).attr("name")+" "+$(targetElement).attr("class"));
		//}
// radiohack?
//		if($("input[name='"+callerName+"']").size()> 1 && (callerType == "radio" || callerType == "checkbox")) {        // Hack for radio/checkbox group button, the validation go the first radio/checkbox of the group
//			caller = $("input[name='"+callerName+"'][type!=hidden]:first");     
//		    $.validationEngine.showTriangle = false;
//		}
		
		var errorMessages = "";
		for(var i = 0; i < rules.length; i++){
			var rule = rules[i];
			
			if(/^r$/.test(rule)){ // 必須バリデーション
				errorMessages += _validateRequired(element);
				if(errorMessages){
					break;
				}
				
			}else if(/^re\[.+\]$/.test(rule)){ // 正規表現バリデーション
				var pattern = rule.match(/^re\[(.+)\]$/)[1];
				errorMessages += _validateRegexp(element, pattern);
			
			}else if(/^len\[[0-9]*-[0-9]*\]$/.test(rule)){ // lengthバリデーション
				var matches = rule.match(/^len\[([0-9]*)-([0-9]*)\]$/);
				errorMessages += _validateLength(element, matches[1], matches[2]);
				
			}else if(/^mail$/.test(rule)){ // emailバリデーション
				errorMessages += _validateEmail(element);
				
			//}else if(/^con\[.+\]$/.test(rule)){ // 入力一致確認バリデーション
			}else if(/^eq\[.+\]$/.test(rule)){ // 入力一致確認バリデーション
				//var matches = rule.match(/^con\[(.+)\]$/);
				var matches = rule.match(/^eq\[(.+)\]$/);
				var targetSelector = matches[1];
				var target = $('#' + targetSelector);
				errorMessages += _validateConfirm(element, target);
				
			}else if(/^k$/.test(rule)){ // カタカナバリデーション
				errorMessages += _validateKatakana(element);
				
			}else if(/^n$/.test(rule)){ // 数字バリデーション
				errorMessages += _validateNumeric(element);
				
			}else if(/^credit$/.test(rule)){ // クレジットカードバリデーション TODO
				errorMessages += _validateCreditCard(element);
			}
		}
		
		return errorMessages;
	}
	
	
	/**
	 * グループバリデーションを実行します。
	 * 
	 */
	function _validateGroup(elements){
		var name = $(elements[0]).attr('name');
		var namePrefix = name.replace(/(.+)_part[1-9]/, '$1');
		
		var errorMessages = "";
		
		var totalValue = "";
		$.each(elements, function(){
			totalValue += $(this).val();
		});
		
		// 引数に渡される時点で1からソートされているものとする
		//	for(var i = 0; i < elements.length; i++){
		//		var element = elements.find(':regex(name,^.+_part' + (i + 1) + '$)');
		//	}
		
		// まず項目全体としてのバリデーション
		// var groupValidation = $('span#' + namePrefix);
		var groupValidation = $('#gv_' + namePrefix);
		if(groupValidation.size() > 0){
			var matches = groupValidation.attr('class').match(/v\[(.*)\]/);
			var rulesString = matches[1];
			var rules = new Array();
			
			if(/^.*re\[.+\]$/.test(rulesString)){ // TODO regexpを使う場合は最後に指定すること
				matches = rulesString.match(/^(.*)(re\[.+\])$/);
				if(matches[1]){
					rules = matches[1].split(',');
					rules.pop(); // re[ 直前のカンマ
				}
				rules.push(matches[2]);
				
			}else{
				rules = rulesString.split(',');
			}
			
			// 必須バリデーションが存在する場合はそれを優先し、
			// そこでひっかかった場合は他の検証はしない
			var index = $.inArray('r', rules);
			if(index != -1){
				rules.splice(index, 1);
				rules.unshift('r');
			}
			
			for(var i = 0; i < rules.length; i++){
				var rule = rules[i];
				
				if(/^r$/.test(rule)){ 
					if(!totalValue){
						errorMessages += messages.required.alertText;
						break;
					}
					
				}else if(/^re\[.+\]$/.test(rule)){
					var pattern = rule.match(/^re\[(.+)\]$/)[1];
					if(!totalValue.match(pattern)){
						errorMessages += messages.regexp.alertText;
					}
					
				}else if(/^birth$/.test(rule)){
					var year = $(elements.get(0)).val();
					var month = $(elements.get(1)).val();
					var day = $(elements.get(2)).val();
					errorMessages += _validateBirthDate(year, month, day);
					
				}else if(/^tel$/.test(rule)){
					errorMessages += _validateTelephone($(elements.get(0)).val() + '-' + $(elements.get(1)).val() + '-' + $(elements.get(2)).val());
					
				}else if(/^fax$/.test(rule)){
					errorMessages += _validateFax($(elements.get(0)).val() + '-' + $(elements.get(1)).val() + '-' + $(elements.get(2)).val());
					
				}else if(/^zip$/.test(rule)){
					errorMessages += _validateZipCode($(elements.get(0)).val() + '-' + $(elements.get(1)).val());
				}
			}
		}
		
		return errorMessages;
	}
	
	/**
	 * 必須バリデーション
	 * 
	 */
	function _validateRequired(element){
		var errorMessage = "";
		
		var type = element.attr("type");
		
		switch(type){
		case 'text':
		case 'password':
		case 'textarea':
			if(!element.val()){
				errorMessage = messages.required.alertText;
			}
			break;
			
		case 'radio':
		case 'checkbox':
			var name = element.attr("name");
			
			if($('input[name=' + name + ']:visible:checked').size() == 0){
				if($('input[name=' + name + ']').size() == 1){
					errorMessage = messages.required.alertRadioText;
				}else{
					errorMessage = messages.required.alertRadioText;
				}
			}
			break;
			
		case 'select-one':
			if(!element.val()){
				errorMessage = messages.required.alertText;
			}
			break;
			
		case 'select-multiple':
			if(!element.find('option:selected').val()){
				errorMessage = messages.required.alertText;
			}
			break;
		}
		
		return errorMessage;
	}
	
	/**
	 * lengthバリデーション
	 * 
	 */
	function _validateLength(element, min, max){
		var errorMessage = "";
		
		var length = element.val().length;
		if(min){
			if(length < min){
				errorMessage = min + messages.length.minText;
			}
		}
		
		if(max){
			if(length > max){
				errorMessage = max + messages.length.maxText;
			}
		}
		
		return errorMessage;
	}
	
	/**
	 * 正規表現バリデーション
	 * 
	 */
	function _validateRegexp(element, pattern){
		var errorMessage = "";
		
		var pattern = eval(pattern);
		if(!$(element).val().match(pattern)){
			errorMessage = messages.regexp.alertText;
		}
		
		return errorMessage;
	}

	
	/**
	 * emailバリデーション
	 * 
	 */
	function _validateEmail(element){
		var errorMessage = "";
		
		var pattern = eval(messages.email.regex);
		if(!$(element).val().match(pattern)){
			errorMessage = messages.email.alertText;
		}
		
		return errorMessage;
	}

	
	/**
	 * 生年月日バリデーション
	 * 
	 */
	function _validateBirthDate(year, month, day){
		var errorMessage = "";
		var now = new Date();
		var nowYear = now.getFullYear();
		var valid = true;
		if(year >= 1000 && year <= nowYear && month >= 1 && month <= 12 && day >= 1 && day <= 31){
			var date = new Date(year, month - 1, day);
			if(date == null || date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day){
				valid = false;
			}
		}else{
			valid = false;
		}
		
		if(!valid){
			errorMessage = messages.birth_date.alertText;
		}
		
		return errorMessage;
	}

	
	/**
	 * 電話番号バリデーション
	 * 
	 */
	function _validateTelephone(value){
		var errorMessage = "";
		
		// 入力がある場合のみ検証する
		if(value.replace(/-/g, '') && !value.match(/^[0-9]{1,5}-[0-9]{1,5}-[0-9]{1,5}$/)){ // 設定の方へ移動
			errorMessage = messages.telephone.alertText;
		}
		
		return errorMessage;
	}

	
	/**
	 * FAX番号バリデーション
	 * 
	 */
	function _validateFax(value){
		var errorMessage = "";
		
		// 入力がある場合のみ検証する
		//var value = value.replace(/-/g, '');
		if(value.replace(/-/g, '') && !value.match(/^[0-9]{1,5}-[0-9]{1,5}-[0-9]{1,5}$/)){ // 設定の方へ移動
			errorMessage = messages.telephone.alertFaxText;
		}
		
		return errorMessage;
	}

	
	/**
	 * 郵便番号バリデーション
	 * 
	 */
	function _validateZipCode(value){
		var errorMessage = "";
		if(!value.match(/^[0-9]{3}-[0-9]{4}$/)){ // 設定の方へ移動
			errorMessage = messages.zip_code.alertText;
		}
		
		return errorMessage;
	}
	
	/**
	 * 入力一致確認バリデーション
	 * 
	 */
	function _validateConfirm(element, targetElement){
		var errorMessage = "";
		if(element.val() != targetElement.val()){
			errorMessage = messages.confirm.alertText;
		}
		
		return errorMessage;
	}
	
	/**
	 * カタカナバリデーション
	 * 
	 */
	function _validateKatakana(element){
		var errorMessage = "";
		
		var value = element.val();
		value = value.hiragana2Katakana();
		value = value.hankakuKatakana2ZenkakuKatakana();
		value = value.replace(/[^\u30A0-\u30FF]/g, '');
		element.val(value);
		
		return errorMessage;
	}

	/**
	 * 数字バリデーション
	 * 
	 */
	function _validateNumeric(element){
		var errorMessage = "";
		
		var value = element.val();
		//value = _toHankaku(value);
		//element.val(value);
		if(!value.match(/^[0-9]+$/)){
			errorMessage = messages.numeric.alertText;
		}
		
		return errorMessage;
	}
	
	/**
	 * クレジットカードバリデーション
	 * 
	 */
	function _validateCreditCard(element){
		var errorMessage = "";
		
		// TODO 条件付きバリデーションとグループバリデーションの併用に
		// 対応していないための暫定対応
		var value = '';
		
		var name = element.attr('name');
		if(name.match(/^(.+)_part[1-9]$/)){ // 分割の場合
			var namePrefix = name.replace(/(.+)_part[1-9]/, '$1');
			var elements = $(':regex(name,' + namePrefix + '_part[0-9])');
			
			$.each(elements, function(){
				value += $(this).val();
			});
			
		}else{
			value = element.val();
		}
		
		if(!value.match(/^[0-9]{14,16}$/)){
			errorMessage = messages.credit_card.alertText;
		}
		
		$.each(elements, function(){
			_updatePrompt($(this), errorMessage);
		});
		
		return errorMessage;
	}
	
	/**
	 * プロンプトの表示更新
	 * 
	 */
	function _updatePrompt(element, errorMessage){
		var tagName = element.get(0).tagName;
		
		var id = element.attr('id');
		//var prompt = $('div.' + id + 'FormError'); // TODO ラジオボタンの場合にidばらばら
		var prompt = $.data(element.get(0), 'errorPrompt'); // jQueryオブジェクトである場合、get()などを用いてDOM要素を抽出する必要がある
		
		// if(prompt.size() == 0){
		if(!prompt){
			if(errorMessage){ // 作成
				prompt = $('<div />').addClass("formError");
				// TODO dom要素とエラーdivを結びつけておけばid要らない気はする
				prompt.addClass(id + 'FormError');
				var errorContent = $('<div />').addClass("formErrorContent");
				prompt.append(errorContent);
				
				$('body').append(prompt);
				
				if(!tagName.match(/span/i)){ // TODO 
//				if($.validator.showTriangle != false){
					var arrow = $('<div />').addClass('formErrorArrow');
					prompt.append(arrow);
					
					if($.validator.settings.position == "bottomLeft" || $.validator.settings.position == "bottomRight"){
						arrow.addClass("formErrorArrowBottom");
						arrow.html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
					}
					
					if($.validator.settings.position == "topLeft" || $.validator.settings.position == "topRight"){
						prompt.append(arrow);
						arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
					}
				}
				errorContent.html(errorMessage);
				
				var topPosition = element.offset().top;
				var leftPosition = element.offset().left;
				var width =  element.width();
				var inputHeight = prompt.height();
				
				if(!tagName.match(/span/i)){ // TODO 
					switch($.validator.settings.position){
					case 'topRight':
						//leftPosition += width - 45;
						leftPosition += width - 35;
						topPosition += - inputHeight -5;
						break;
					
					case 'topLeft':
						topPosition += - inputHeight - 10;
						break;
						
					case 'centerRight':
						leftPosition += width + 13;
						break;
						
					case 'bottomLeft':
						var height = element.height();
						leftPosition = leftPosition;
						topPosition = topPosition + height + 15;
						break;
						
					case 'bottomRight':
						var height =  element.height();
						leftPosition += width - 30;
						topPosition += height + 15;
						break;
					}
				}else{
					topPosition -= 10;
				}
				
				prompt.css({
					top: topPosition,
					left: leftPosition
//					opacity: 0
				});
				prompt.hide();
				//return prompt.animate({opacity: 0.80}, function(){
				//	return true;
				//});
				
//				var prompt = _updatePrompt(element, errorMessages);
				if(element.attr('type') == 'radio'){
					element.addClass('validateRadioError');
				}else{
					element.addClass('validateError');
				}
				
				$.data(element.get(0), 'errorPrompt', prompt);
				element.bind('mouseover.error', function(event){
					$.data(element.get(0), 'errorPrompt').show();
				});
				element.bind('mouseout.error', function(event){
					$.data(element.get(0), 'errorPrompt').hide();
				});
			}
		}else{
			if(errorMessage){
				// 更新
				//linkTofield = $.validator.linkTofield(caller);
				//var updateThisPrompt =  "."+linkTofield;
				
				prompt.find('.formErrorContent').html(errorMessage);
				var topPosition = element.offset().top;
				var inputHeight = prompt.height();
				
				if(!tagName.match(/span/i)){ // TODO 
					switch($.validator.settings.position){
					case 'bottomLeft':
					case 'bottomRight':
						var height =  element.height();
						topPosition = topPosition + height + 15;
						break;
						
					case 'centerRight':
						// leftPosition += callerWidth +13; TODO
						break;
						
					case 'topLeft':
					case 'topRight':
						topPosition = topPosition - inputHeight - 5;
						break;
					}
				}else{
					topPosition -= 10;
				}
				
				/*
				prompt.css({
					opacity: 0.4
				});
				*/
				prompt.animate({
					opacity: 0.8,
					top: topPosition
				});
				
			}else{
				// 削除
				
				// ラジオボタンの場合
				if(element.attr('type') == 'radio'){
					$(':input[name=' + element.attr('name') + ']').each(function(){
						var radio = $(this);
						
						radio.removeClass('validateRadioError');
						var radioPrompt = $.data(radio.get(0), 'errorPrompt');
						$.removeData(radio.get(0), 'errorPrompt');
						//$.removeData(radio);
						radio.unbind('mouseover.error');
						radio.unbind('mouseout.error');
						if(radioPrompt){ // TODO なぜかnullの場合がある
							radioPrompt.remove();
						}
					});
				}else{
					prompt.fadeTo("fast", 0, function(){
						element.removeClass('validateError');
						$.removeData(element.get(0), 'errorPrompt');
						element.unbind('mouseover.error');
						element.unbind('mouseout.error');
						prompt.remove();
					});
				}
			}
		}
		
		return prompt;
	}
	
	/**
	 * 
	 * 
	 */
	function _validateSubmit(form){
		var stopForm = false;
		
		// エラープロンプトクリア
		form.find('.formError').remove();
		
		var errorFound = false;
		
		// TODO 条件付のバリデーション項目
		form.find(':enabled:visible:regex(class,v\\[c)').each(function(){
			var element = $(this);
			var condition = element.attr('class').match(/v\[c\[(.+?)\]/)[1];
			var matches = condition.match(/(.+)=(.+)/);
			var targetName = matches[1];
			var targetValue = matches[2];
			var targets = $('[name=' + targetName + ']');
			
			if($('[name=' + targetName + ']:checked').val() == targetValue){
				var errorMessages = _validate(element);
				if(errorMessages) errorFound = true;
				_updatePrompt(element, errorMessages);
			}else{
				_updatePrompt(element, null);
			}
		});
		
		
//		form.find(':regex(class,v\\[[^c])').each(function(){
		form.find(':enabled:visible:regex(class,v\\[[^c])').each(function(){
			var element = $(this);
			
			// TODO
			if(element.attr('id').match(/^gv_.+/)){
			//		.tagName.match(/span/i)){
				return true;
			}
			
			var name = element.attr('name');
			if(name.match(/^(.+)_part[1-9]$/)){ // グループバリデーションの可能性
				var namePrefix = name.replace(/(.+)_part[1-9]/, '$1');
				
				if($('#gv_' + namePrefix).size() == 1){ // グループバリデーションの指定がある
					var elements = $(':enabled:regex(name,' + namePrefix + '_part[0-9])');
					var errorMessages = _validateGroup(elements);
					
					if(errorMessages){
						errorFound = true;
						// _updatePrompt($('#gv_' + namePrefix), errorMessages);
						_updatePrompt(element, errorMessages);
					}else{
						var errorMessages = _validate(element);
						if(errorMessages) errorFound = true;
						_updatePrompt(element, errorMessages);
					}

				}else{
					var errorMessages = _validate(element);
					if(errorMessages) errorFound = true;
					_updatePrompt(element, errorMessages);
				}
				
			}else{
				//_updatePrompt($(this), _validate($(this)));
				var errorMessages = _validate(element);
				if(errorMessages) errorFound = true;
				_updatePrompt(element, errorMessages);
			}
		});
		
		if(errorFound){
			var destination = $('.formError:first').offset().top;
//			$('.formError', form).each(function(){
			$('.formError').each(function(){
				testDestination = $(this).offset().top;
				if(destination > testDestination){
					destination = $(this).offset().top;
				}
			});
			$("html:not(:animated),body:not(:animated)").animate({
				scrollTop: destination
			}, 700);
			return false;
		}
		
		return true;
	}
	
	function _toHankaku(target){
		var result = '';
		var length = target.length;
		for(var i = 0; i < length; i++){
			var c = target.charCodeAt(i);
			if(c >= 65281 && c <= 65374 && c != 65340){
				result += String.fromCharCode(c - 65248);
			}else if(c == 8217){
				result += String.fromCharCode(39);
			}else if(c == 8221){
				result += String.fromCharCode(34);
			}else if(c == 12288){
				result += String.fromCharCode(32);
			}else if(c == 65507){
				result += String.fromCharCode(126);
			}else if(c == 65509){
				result += String.fromCharCode(92);
			}else{
				result += target.charAt(i);
			} 
		}
		
		return result;
	};
		
	var messages = {
		"required":{
			"regex":"none",
			"alertText":"必須項目です",
			"alertRadioText": "いずれかひとつ選択してください",
			"alertTextCheckboxMultiple":"選択してください"
		},
		"length":{
			"regex":"none",
			"alertText1":"文字以上",
			"alertText2": "文字以内で入力してください",
			"minText": "文字以上で入力してください",
			"maxText": "文字以内で入力してください"},
		"maxCheckbox":{
			"regex":"none",
			"alertText":"* Checks allowed Exceeded"},	
		"minCheckbox":{
			"regex":"none",
			"alertText":"* Please select ",
			"alertText2":" options"},	
		"confirm":{
			"regex":"none",
			"alertText":"一致しません"
		},
		"email":{
			"regex":"/^[a-zA-Z0-9_\.\-]+\@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9]{2,4}$/",
			"alertText":"メールアドレスとして正しくありません"
		},
		"onlyNumber":{
			"regex":"/^[0-9\ ]+$/",
			"alertText":"* Numbers only"},	
		"noSpecialCaracters":{
			"regex":"/^[0-9a-zA-Z]+$/",
			"alertText":"* No special caracters allowed"},	
		"ajaxUser":{
			"file":"validateUser.php",
			"extraData":"name=eric",
			"alertTextOk":"* This user is available",	
			"alertTextLoad":"* Loading, please wait",
			"alertText":"* This user is already taken"},	
		"ajaxName":{
			"file":"validateUser.php",
			"alertText":"* This name is already taken",
			"alertTextOk":"* This name is available",	
			"alertTextLoad":"* Loading, please wait"},		
		"onlyLetter":{
			"regex":"/^[a-zA-Z\ \']+$/",
			"alertText":"* Letters only"},
		"halfs":{
			"regex":"/^[!-~]+$/",
			"alertText":"英数記号で入力してください"},
		"maxlen":{
			"regex":"none",
			"alertText":"文字以内で入力してください"},
		"katakana":{
			"regex":"none",
			"alertText":"カタカナで入力してください"},
		"zip_code":{
			"regex":"none",
			"alertText": "郵便番号として正しくありません"
		},
		"birth_date":{
			"regex": "none",
			"alertText": "生年月日として正しくありません"
		},
		"telephone":{
			"regex": "none",
			"alertText": "電話番号として正しくありません",
			"alertFaxText": "FAX番号として正しくありません"
		},
		"numeric":{
			"regex":"none",
			"alertText": "数字で入力してください"
		},
		"credit_card":{
			"regex":"none",
			"alertText": "カード番号を14桁から16桁で入力してください"
		},
		"regexp":{
			"regex":"none",
			"alertText":"入力が正しくありません"
		}
	};
})(jQuery);

/**
 * 型Util
 * 
 * @class Type
 * 
 * @static
 */
function Type(){};
Type.isObject = function(v){
	return (Object.prototype.toString.call(v) == "[object Object]");
};
Type.isFunction = function(v){
	return (Object.prototype.toString.call(v) == "[object Function]");
};
Type.isArray = function(v){
	return (Object.prototype.toString.call(v) == "[object Array]");
};
Type.isBoolean = function(v){
	return (Object.prototype.toString.call(v) === "[object Boolean]");
};
Type.isString = function(v){
	return (Object.prototype.toString.call(v) === "[object String]");
};
Type.isNumber = function(v){
	return (Object.prototype.toString.call(v) === "[object Number]");
};
Type.isElement = function(v){
	var check = false;
	switch(Object.prototype.toString.call(v)) {
	case "[object Object]":
		if (v.length) check = true;
		break;
	case "[object Window]":
	case "[object HTMLParagraphElement]":
		if (! Type.isUndefined(v) && ! Type.isNull(v)) check = true;
		break;
	default:
		break;
	}
	
	return check;
};
Type.isElementCollection = function(v){
	return (Object.prototype.toString.call(v) === "[object HTMLCollection]");
};
Type.isNull = function(v){
	return (v === null);
};
Type.isUndefined = function(v){
	return (v === undefined);
};
Type.getType = function(v){
	if (Type.isNull(v)) { return "null"; }
	if (Type.isUndefined(v)) { return "undefined"; }
	if (Type.isElement(v)) { return "HTMLElement"; }
	return Object.prototype.toString.call(v).split(" ")[1].replace("]", "");
};

/**
 * カート情報
 * 
 * @return
 */
function Cart(){};
Cart.MESSAGE_EMPTY = 'ショッピングカートは空です';
Cart.MESSAGE_CART_IN = 'カートには現在<span class="fcr"><span class="num_cart_item_qty">0</span></span>点の商品が入っています';
Cart.SIDE_MENU_MESSAGE_EMPTY = '<p class="fco">ショッピングカートは空です</p>';
Cart.SIDE_MENU_MESSAGE_CART_IN = '<p>カートには現在<span class="fco"><span class="num_cart_item_qty">0</span></span>点の商品が入っています。</p><p>小計 <span class="cart_total">999,999,999</span>円</p>';
Cart.MESSAGE_CARRIAGE_FREE = '送料無料まであと<span id="carriage_free">10,000</span>円です！';
Cart.data = {};
Cart.popUp = null;
Cart.sideMenu = null;
Cart.deletePrompt = null;
Cart.numericStepper = null;
Cart.itemRow = null;
Cart.initialized = false;
Cart.carriageFreeCondition;
/**
 * カート情報の初期化処理
 * 
 * カート(ポップアップ)画面の読み込み
 * サイドメニュー画面ロード
 */
Cart.load = function(callback){
	// サイドメニューが表示されていたら表示更新
	if($('body').is(":has('#side .box_shop-cart')")){
		this.sideMenu = $('#side .box_shop-cart');
		
		// サイドメニュー「カートを見る」ボタンのクリック
		$('#show_cart_button').live('click', function(event){
			event.preventDefault();
			Cart.reload(function(){
				PopUpManager.createPopUp(Cart.view);
			});
			return false;
		});
		
		// サイドメニュー「レジへ進む」ボタンのクリック
		$('#go_register_button').live('click', function(event){
			event.preventDefault();
			
			// ギフト商品と通常商品が混在している場合は下記文言のダイアログボックスを表示し、 
			// 先に進めないように制御する。 
			// “ギフト商品と通常商品は同時ご注文できません。ギフト商品のみ、もしくは 
			// 通常商品のみの組み合わせに変更していただき、「レジへ進む」ボタンを 
			// 再度クリックしてください。” 
			
			var giftFound = false;
			var otherFound = false;
			Cart.reload(function(){
				for(var i = 0; i < Cart.data.cartItems.length; i++){
					var item = Cart.data.cartItems[i];
					if($.inArray(parseInt(item.catalogSpecId, 10), Constants.GIFT_ITEMS) != -1){
						giftFound = true;
					}else{
						otherFound = true;
					}
				}
				
				if(giftFound && otherFound){
					alert('ギフト商品と通常商品は同時ご注文できません。\nギフト商品のみ、もしくは通常商品のみの組み合わせに変更していただき、\n「レジへ進む」ボタンを再度クリックしてください。');
				}else{
					location.replace('https://' + location.host + '/cart/shopping/login.html');
				}
			});
			
			return false;
		});
		
		// 「会員情報の確認と編集」リンクのクリック
		$('#member_edit_link').click(function(event){
			event.preventDefault();
			//location.replace('https://' + location.host + '/mypage/member/');
			location.replace('https://' + location.host + '/mypage/certify/index.html?r=/mypage/member/index.html');
			return false;
		});
		
		// 「ログアウト」リンクのクリック
		$('.logout_link').click(function(event){
			event.preventDefault();
			LogoutDialog.popUp();
			return false;
		});
	}
	
	// カート(ポップアップ)画面の初期化
	var loader = new Loader();
	loader.load('/cart/index.html', {
		selector: '.org_box',
		callback: function(response){
			Cart.view = $(response);
			
			Cart.carriageFreeCondition = parseInt($('#carriage_free_condition', Cart.view).text().replace(',', ''));
			
			// 削除プロンプト
			Cart.deletePrompt = $('.box_delete_top', Cart.view);
			Cart.deletePrompt.hide();
			
			// 数量変更プロンプト
			Cart.numericStepper = $('.box_quantity_top', Cart.view);
			Cart.numericStepper.hide();
			
			// 商品リスト行
			var row = $('#cartItems tr[class=cart_item_row]:first', Cart.view);
			
			Cart.itemRow = row.clone();
			$('#cartItems tr[class=cart_item_row]', Cart.view).remove();
			
			// 「閉じる」ボタンのクリック
			$('#close_button', Cart.view).click(function(event){
				event.preventDefault();
				PopUpManager.removePopUp(false);
				return false;
			});
			
			// 「削除」ボタンのクリック
			//$('.delete_confirm_button', Cart.view).live('click', function(event){
			$('.delete_confirm_button').live('click', function(event){ // TODO Cart.viewつけるとハンドルできない
				event.preventDefault();
				
				var deletePrompt = Cart.deletePrompt;
				
				var tr = $(this).closest('.cart_item_row');
				var index = $('tr.cart_item_row').index(tr);
				var cartItemData = Cart.data.cartItems[index];
				
				var deleteTargetId = $(this).attr('name');
				
				var button = $('#delete_action_button', deletePrompt);
				
				var scroll = $('#cartItems').parent().scrollTop();
				deletePrompt.css({
					left: 31,
					top: 66 + (55 * index) - scroll,
					'z-index': 9100
				});
				
				var block = $('<div id="block" />');
				block.hide();
				block.css({
					position: 'absolute',
					left: 0,
					top: 0,
					'z-index': 9000,
					'background-color': '#000000',
					opacity: '0.0',
					height: '100%',
					width: '100%'
				});
				block.appendTo(Cart.view);
				block.show();
				
				deletePrompt.show();
				
				// 削除プロンプトの「削除」ボタンのクリック
				$('#delete_action_button', deletePrompt).unbind('click');
				$('#delete_action_button', deletePrompt).click(function(event){
					event.preventDefault();
					
					// カート商品削除
					APIManager.CT004(Cart.data.cartId, deleteTargetId, function(response){
						if(!response.result){
							alert('エラーが発生しました');
							if(!location.pathname.match(/^\/(index\.html(\?[^/]+)?)?$/)){
								location.replace('/');
							}
							return false;
						}
						
						// カート更新
						Cart.reload(function(){
							block.remove();
							deletePrompt.hide();
						});
					});
					
					return false;
				});
				
				// 削除プロンプトの「キャンセル」ボタンのクリック
				$('#delete_cancel_button', deletePrompt).unbind('click');
				$('#delete_cancel_button', deletePrompt).click(function(event){
					event.preventDefault();
					block.remove();
					$('.box_delete_top', this.popUp).hide();
					return false;
				});
				
				return false;
			});
			
			// 「レジへ進む」ボタンのクリック
			$('#go_register_button', Cart.view).click(function(event){
				event.preventDefault();
				
				if(Cart.isEmpty()){
					return false;
				}
				
				// ギフト商品と通常商品が混在している場合は下記文言のダイアログボックスを表示し、 
				// 先に進めないように制御する。 
				// “ギフト商品と通常商品は同時ご注文できません。ギフト商品のみ、もしくは 
				// 通常商品のみの組み合わせに変更していただき、「レジへ進む」ボタンを 
				// 再度クリックしてください。” 
				
				var giftFound = false;
				var otherFound = false;
				Cart.reload(function(){
					for(var i = 0; i < Cart.data.cartItems.length; i++){
						var item = Cart.data.cartItems[i];
						if($.inArray(parseInt(item.catalogSpecId, 10), Constants.GIFT_ITEMS) != -1){
							giftFound = true;
						}else{
							otherFound = true;
						}
					}
					
					if(giftFound && otherFound){
						alert('ギフト商品と通常商品は同時ご注文できません。\nギフト商品のみ、もしくは通常商品のみの組み合わせに変更していただき、\n「レジへ進む」ボタンを再度クリックしてください。');
					}else{
						// location.replace('https://' + location.host + '/cart/shopping/login.html');
						PopUpManager.removePopUp();
						PopUpManager.createWaiting();
						setTimeout(function(){
							location.replace('https://' + location.host + '/cart/shopping/login.html'); 
						}, 800);
					}
				});
				
				return false;
			});
			
			// 「ご注文について」リンクのクリック
			$('#about_order_link', Cart.view).click(function(event){
				event.preventDefault();
				PopUpManager.removePopUp();
				location.replace('/guide/order.html');
				return false;
			});
			
			// 「数量」入力エリアのクリック
			// $(':input.quantity_input', Cart.view).live('click', function(event){
			$(':input.quantity_input').live('click', function(event){ // TODO Cart.viewを指定するとライブバインドされない
				event.preventDefault();
				
				var numericStepper = Cart.numericStepper;
				
				var tr = $(this).closest('.cart_item_row');
				var index = $('tr.cart_item_row').index(tr);
				
				var cartItemData = Cart.data.cartItems[index];
				
				var catalogSpecId = $('.delete_confirm_button', tr).attr('name');
				
				var button = $('#quantity_action_button', numericStepper);
				
				var scroll = $('#cartItems').parent().scrollTop();
				numericStepper.css({
					left: 417,
					top: 93 + (55 * index) - scroll,
					'z-index': 9100
				});
				
				var block = $('<div id="block" />');
				block.hide();
				block.css({
					position: 'absolute',
					left: 0,
					top: 0,
					'z-index': 9000,
					'background-color': '#000000',
					opacity: '0.0',
					height: '100%',
					width: '100%'
				});
				block.appendTo(Cart.view);
				block.show();
				
				$('#quantity_input_area', numericStepper).val($(this).val());
				
				// 定期商品の場合は数量に応じて単価が変動するため小計を表示しない
				if(cartItemData.regularPurchase == 1){
					$('#row_total_price', numericStepper).text('');
					$('#row_total_price_yen', numericStepper).hide();
					
				}else{
					$('#row_total_price', numericStepper).text($('.row_total_price', tr).text());
					$('#row_total_price_yen', numericStepper).show();
				}
				
				numericStepper.show();
				
				$('#quantity_input_area', numericStepper).focus();
				
				// 数量プロンプト「+」ボタンのクリック
				$('#plus_button', numericStepper).unbind('click');
				$('#plus_button', numericStepper).click(function(event){
					event.preventDefault();
					
					var quantity = $('#quantity_input_area', numericStepper).val();
					if(!quantity){
						alert('数量が入力されておりません');
						return false;
					}
					
					quantity = quantity.zenkakuNumeric2HankakuNumeric();
					if(!quantity.match(/^[0-9]+$/)){
						alert('数字で入力してください');
						return false;
					}
					
					quantity = Number(quantity);
					
					$('#quantity_input_area', numericStepper).val(quantity + 1);
					
					if(cartItemData.regularPurchase != 1){
						var selling_price = parseInt($('.selling_price', tr).text().replace(',', ''));
						var row_total_price = selling_price * (quantity + 1);
						$('#row_total_price', numericStepper).text($.currency(row_total_price));
					}
					
					return false;
				});
				
				// 数量プロンプト「-」ボタンのクリック
				$('#minus_button', numericStepper).unbind('click');
				$('#minus_button', numericStepper).click(function(event){
					event.preventDefault();
					
					var quantity = $('#quantity_input_area', numericStepper).val();
					if(!quantity){
						alert('数量が入力されておりません');
						return false;
					}
					
					quantity = quantity.zenkakuNumeric2HankakuNumeric();
					if(!quantity.match(/^[0-9]+$/)){
						alert('数字で入力してください');
						return false;
					}
					
					quantity = Number(quantity);
					
					//var quantity = parseInt($('#quantity_input_area', numericStepper).val());
					if(quantity > 0){
						$('#quantity_input_area', numericStepper).val(quantity - 1);
						
						if(cartItemData.regularPurchase != 1){
							var selling_price = parseInt($('.selling_price', tr).text().replace(',', ''));
							var row_total_price = selling_price * (quantity - 1);
							$('#row_total_price', numericStepper).text($.currency(row_total_price));
						}
					}
					return false;
				});
				
				// 数量プロンプト「決定」ボタンのクリック
				$('#quantity_action_button', numericStepper).unbind('click');
				$('#quantity_action_button', numericStepper).click(function(event){
					event.preventDefault();
					
					//PopUpManager.createWaiting();
					
					var quantity = $('#quantity_input_area', numericStepper).val();
					if(!(0 <= parseInt(quantity) && 999 >= parseInt(quantity))){
						alert('数字を入力してください');
						return false;
					}
					
					quantity = Number(quantity);
					
					// カート商品数量変更
					APIManager.CT003(Cart.data.cartId, catalogSpecId, quantity, function(response){
						if(!response.result){
							$.each(response.errors, function(){
								if(this.errorCode == 'ECT003_001'){
									// ECT003_001	catalog_spec_id	商品が売り切れ（sold_out=1の状態）	
									alert('売り切れました');
									
								}else if(this.errorCode == 'ECT003_002'){
									// ECT003_002	catalog_spec_id	商品が終売（end_of_sale=1の状態）	
									alert('取り扱い終了いたしました');
									
								}else if(this.errorCode == 'ECT003_003'){
									// ECT003_003	quantity	数量の入力が不正	
									alert('数量が不正です');
								}else{
									alert('エラーが発生しました');
								}
							});
							
							return false;
						}
						
						Cart.reload(function(){
							block.remove();
							numericStepper.hide();
							
							//PopUpManager.removePopUp();
						});
						
						//$(':input.quantity_input', tr).val(quantity);
						//var row_total_price = parseInt(cartItemData.sellingPrice) * quantity;
						//$('.row_total_price', tr).text($.currency(row_total_price));
					});
					
					return false;
				});
				
				// 数量プロンプト「キャンセル」ボタンのクリック
				$('#quantity_cancel_button', numericStepper).unbind('click');
				$('#quantity_cancel_button', numericStepper).click(function(event){
					event.preventDefault();
					block.remove();
					numericStepper.hide();
					return false;
				});
				
				return false;
			});
			
			// カート情報取得
			Cart.reload(function(){
				if(callback){
					callback.call(this);
				}
			});
		}
	});
};
Cart.reload = function(callback){
	if(!Cart.initialized){
		Cart.initialized = true;
		Cart.load(callback);
//		Cart.load(Cart.relaod(callback));
		return;
	}
	
	// カート情報取得
	APIManager.CT001(function(response){
		if(!response.result){
			alert('エラーが発生しました');
			// var pattern = new RegExp("^\/(index\.html(\?[^/]+)?)?$"); 構文エラーになる
			if(!location.pathname.match(/^\/(index\.html(\?[^/]+)?)?$/)){
				location.replace('/');
			}
			return;
		}
		
		Cart.data = response;
		
		// サイドメニューとカート画面の描画
		var _sideMenu = $('#side');
		
		if(Cart.isEmpty()){
			$('.area_msg', _sideMenu).html(Cart.SIDE_MENU_MESSAGE_EMPTY);
		}else{
			$('.area_msg', _sideMenu).html(Cart.SIDE_MENU_MESSAGE_CART_IN);
		}
		
		if(Cart.isLoggedIn()){
			$('.customer_name', _sideMenu).text(Cart.data.name1 + Cart.data.name2);
			$('.customer_name', Cart.view).text(Cart.data.name1 + Cart.data.name2);
		}else{
			$('.login_function').hide();
			$('.navi_logout').hide();
			$('.customer_name').text('ゲスト');
			$('.customer_name', Cart.view).text('ゲスト');
		}
		
		// サイドメニュー？
		$('.cart_total', _sideMenu).text($.currency(Cart.data.cartTotal));
		$('.cart_total', Cart.view).text($.currency(Cart.data.cartTotal));
		
		// サイドメニュー？
		$('.num_cart_item_qty').text(Cart.data.numCartItemQty);
		
		
		// カート(ポップアップ)画面 送料無料まであと20円です。
		var carriageFree = false;
		$.each(Cart.data.cartItems, function(){
			if(this.regularPurchase == 1){
				$('#carriage_free_message', Cart.view).html('送料が無料です');
				carriageFree = true;
				return false;
			}
		});
		
		if(!carriageFree){
			if(Cart.carriageFreeCondition - Cart.data.cartTotal > 0){
				$('#carriage_free_message', Cart.view).html(Cart.MESSAGE_CARRIAGE_FREE);
				$('#carriage_free', Cart.view).text($.currency(Cart.carriageFreeCondition - Cart.data.cartTotal));
			}else{
				$('#carriage_free_message', Cart.view).html('送料が無料です');
			}
		}
		
		// カートには現在3点の商品が入っています
		$('.num_cart_item_qty', Cart.view).text($.currency(Cart.data.numCartItemQty));
		
		// カートポップアップ 商品一覧更新
		$.each($('#cartItems tr', Cart.view), function(){
			if($(this).children('td').length > 0){
				$(this).remove(); // 一旦クリア
			}
		});
		
		if(!Cart.isEmpty()){
			$.each(Cart.data.cartItems, function(){
				var row = Cart.itemRow.clone();
				$.data(row, 'catalogSpecId', this.catalogSpecId);
				$('.delete_confirm_button', row).attr('name', this.catalogSpecId);
				$('img', row).attr('src', this.thumbnailImageUrl);
				$('.name', row).text(this.fullName);
				$('.selling_price', row).text($.currency(this.sellingPrice));
				$(':input.quantity_input', row).val(this.quantity);
				$('.row_total_price', row).text($.currency(this.sellingPrice * this.quantity));
				
				$('#cartItems', Cart.view).append(row);
			});
			
			$('.txt_status', Cart.view).html(Cart.MESSAGE_CART_IN);
			
			// カートには現在3点の商品が入っています
			$('.num_cart_item_qty', Cart.view).text($.currency(Cart.data.numCartItemQty));
			
			$('#go_register_button', Cart.view).css('opacity', 1);
			
		}else{ // 空の場合
			for(var i = 0; i < 4; i++){
				var row = Cart.itemRow.clone();
			    $('td.btn,td.img,td.name,td.name,td.price,td,quantity,td.price', row).html('&nbsp;');
				$('#cartItems', Cart.view).append(row);
			}
			
			$('.txt_status', Cart.view).html(Cart.MESSAGE_EMPTY);
			
			$('#go_register_button', Cart.view).css('opacity', 0.2);
		}
		
		// 商品一覧の行の色
		$('#cartItems tr.cart_item_row', Cart.view).removeClass('odd').removeClass('even');
		$('#cartItems tr.cart_item_row:odd', Cart.view).addClass('even'); // jquery odd evenはインデックス0から数えるので逆になる
		$('#cartItems tr.cart_item_row:even', Cart.view).addClass('odd');
		
		if(callback){
			callback.call(this, self); // TODO 
		}
	});
};
Cart.isLoggedIn = function(){
	return (Cart.data && Cart.data.customerId);
};
Cart.isEmpty = function(){
	return !(Cart.data && parseInt(Cart.data.numCartItemQty) > 0);
};
Cart.addItemGlow = function(catalogSpecId){
	var row = $('.delete_confirm_button[name=' + catalogSpecId + ']', Cart.view).closest('.cart_item_row');
	var rowIndex = row.parent().children().index(row);
	
	var scrollTop = 0;
	if(rowIndex > 3){ // TODO きめうち3はスクロール無しで4行分表示できるため
		var scrollTop = 55 * (rowIndex - 3); // TODO きめうち55は一行分の高さ
	}
	
	$('.area_tbl_cart', Cart.view).animate({scrollTop: scrollTop}, 600, 'swing', function(){
		row.addClass('remark');
		function blink(count){
			$('td table,td input,td div',row).fadeTo(500, 0.2, function(){
				if(this == $('td table', row).get(0)){
					$('td table,td input,td div',row).fadeTo(500, 1, function(){
						if(this == $('td table', row).get(0)){
							--count;
							if(count > 0){
								blink(count);
							}else{
								row.removeClass('remark');
							}
						}
					});
				}
			});
		}
		blink(4);
	});
	
};


/**
 * 会員データ
 * 
 * 
 */
function Customer()
{
	this.data = {};
	this.customerId;
	this.MY001;
	
	// MY012は会員情報取得
	Customer.prototype.setMY012 = function(response){
		this.customerId = response.customerId;
		
		var person = response.person;
		this.data.name1 = person.name1;
		this.data.name2 = person.name2;
		this.data.kana1 = person.kana1;
		this.data.kana2 = person.kana2;
		this.data.gender = person.gender;
		//var dateParts = person.birthDate.split('-');
		//var birthDate = new Date(person.birthDate.replace(/-/g, '/'));
		var birthDate = Date.parse(person.birthDate, 'yyyy-mm-dd');
		this.data.birth_date_part1 = birthDate.getFullYear();
		this.data.birth_date_part2 = birthDate.getMonth() + 1;
		this.data.birth_date_part3 = birthDate.getDate();
		this.data.country_code = 'JP'; // きめうち
		this.data.zip_code_part1 = person.zipCode.substring(0, 3);
		this.data.zip_code_part2 = person.zipCode.substring(3, 8);
		this.data.pref_id = person.prefId;
		this.data.pref = person.pref;
		//this.data.order_pref = person.pref;
		this.data.address1 = person.address1;
		this.data.address2 = person.address2;
		this.data.address3 = person.address3;
		this.data.email1 = person.email1;
		var tel1parts = person.tel1.split('-');
		this.data.tel1_part1 = tel1parts[0];
		this.data.tel1_part2 = tel1parts[1];
		this.data.tel1_part3 = tel1parts[2];
		if('tel2' in person && person.tel2){
			var tel2parts = person.tel2.split('-');
			this.data.tel2_part1 = tel2parts[0];
			this.data.tel2_part2 = tel2parts[1];
			this.data.tel2_part3 = tel2parts[2];
		}else{
			this.data.tel2_part1 = '';
			this.data.tel2_part2 = '';
			this.data.tel2_part3 = '';
		}
	};
	
	
	// 会員登録時用？
	Customer.prototype.assignTemplate = function(page){
		// ハイフンなしデータの場合
		if(!this.data.tel1_part2){
			if(page){
				$('#tel1', page).text(this.data.tel1_part1);
			}else{
				$('#tel1').text(this.data.tel1_part1);
			}
		}
		
		// ハイフンなしデータの場合
		if(this.data.tel2_part1 && !this.data.tel2_part2){
			$('#tel2', page).text(this.data.tel2_part1);
		}
		
		// FAX無し
		if(!this.data.tel2_part1){
			$('#tel2', page).text('');
		}
		
		$.each(this.data, function(key, value){
			if(page){
				$('#' + key, page).text(value);
			}else{
				$('#' + key).text(value);
			}
		});
		
		if(page){
			$('#gender', page).text(this.data.gender == 1 ? '男性' : '女性');
			$('#mail_permit1', page).text(this.data.mail_permit1 == 1 ? '購読する' : '購読しない');
		}else{
			$('#gender').text(this.data.gender == 1 ? '男性' : '女性');
			$('#mail_permit1').text(this.data.mail_permit1 == 1 ? '購読する' : '購読しない');
		}
		
		//$('#gender', page)assigns.zip_code = assigns.zipCode.substring(0, 3) + '-' + assigns.zipCode.substring(3, 8);
	};

	// 会員登録
	Customer.prototype.getParamsMY006 = function(){
		var params = {};
		params = $.extend(params, this.data);
		
		var birthDate = new Date(params.birth_date_part1, params.birth_date_part2 - 1, params.birth_date_part3);
		//params.birth_date = params.birth_date_part1 + '-' + params.birth_date_part2 + '-' + params.birth_date_part3;
		params.birth_date = birthDate.format('yyyy-mm-dd');
		delete params.birth_date_part1;
		delete params.birth_date_part2;
		delete params.birth_date_part3;
		
		params.zip_code = params.zip_code_part1 + params.zip_code_part2;
		delete params.zip_code_part1;
		delete params.zip_code_part2;
		
		params.tel1 = params.tel1_part1 + '-' + params.tel1_part2 + '-' + params.tel1_part3;
		delete params.tel1_part1;
		delete params.tel1_part2;
		delete params.tel1_part3;
		
		if('tel2_part1' in params && !!params.tel2_part1){
			params.tel2 = params.tel2_part1 + '-' + params.tel2_part2 + '-' + params.tel2_part3;
		}
		delete params.tel2_part1;
		delete params.tel2_part2;
		delete params.tel2_part3;
		
		delete params.login_id_confirm;
		delete login_password_confirm;
		
		params.country_code = 'JP';
		
		return params;
	};
	
	Customer.prototype.assignForm = function(form){
		$.each(this.data, function(key, value){
			var element = $(':input[name=' + key + '],select[name=' + key + ']', form);
			if(element.length == 1){
				element.val(value);
				
			}else if(element.length > 1){
				// TODO ラジオボタンは複数だときめうち
				if($(element[0]).attr('type') == 'radio'){
					$(':input[name=' + key + ']', form).val([value.toString()]);
				}
				
			}else{
				// TODO partxxタイプ
			}
		});
	};
	
	
	
	// MY012で取得したjsonを表示用テンプレート用に変換して返す
	Customer.prototype.toTemplateAssignData = function(){
		var assigns = $.extend(true, {}, this.data);
		
		if('gender' in assigns){
			assigns.gender = assigns.gender == 1 ? '男性' : '女性';
		}
		
		if('birthDate' in assigns){
			assigns.birth_date = assigns.birthDate.replace(/-/g, '/');
		}
		
		if('zipCode' in assigns){
			assigns.zip_code = assigns.zipCode.substring(0, 3) + '-' + assigns.zipCode.substring(3, 8);
		}
		
		if('mail_permit1' in assigns){
			assigns['#mail_permit'] = assigns.mail_permit1 == 1 ? '購読する' : '購読しない';
			delete assigns.address3;
		}
		
		if('login_id' in assigns){
			assigns['#login_id'] = assigns.login_id;
			delete assigns.login_id;
		}
		
		return assigns;
	};
	
	Customer.prototype.toRequestParams = function(){
		var params = $.extend(true, {}, this.data);
		
		if('login_id' in params){
			delete params.login_id_confirm;
		}
		
		if('login_password' in params){
			delete params.login_password_confirm;
		}
		
		// TODO
		if(params.pref){
			//pref_id
		}
		
		
//		$.each(params, function(key, value){
//			if(key.match(/.+_part[1-9]?(_[0-9]+_[0-9]+)?/)){
//				
//			}
//		});
		/*
		if('zip_code_part_0_2' in params && 'zip_code_part_3_6' in params){
			params.zip_code = params.zip_code_part_0_2 + params.zip_code_part_3_6;
			delete params.zip_code_part_0_2;
			delete params.zip_code_part_3_6;
		}
		*/
		
		if('tel1_part1' in params && 'tel1_part2' in params && 'tel1_part3' in params){
			params.tel1 = params.tel1_part1 + '-' + params.tel1_part2 + '-' + params.tel1_part3;
			delete params.tel1_part1;
			delete params.tel1_part2;
			delete params.tel1_part3;
		}
		
		if('tel2_part1' in params && 'tel2_part2' in params && 'tel2_part3' in params){
			params.tel2 = params.tel2_part1 + '-' + params.tel2_part2 + '-' + params.tel2_part3;
			delete params.tel2_part1;
			delete params.tel2_part2;
			delete params.tel2_part3;
		}
		
		if('birth_date_part1' in params && 'birth_date_part2' in params && 'birth_date_part3' in params){
			var birth_date = new Date(params.birth_date_part1, params.birth_date_part2 - 1, params.birth_date_part3);
			params.birth_date = birth_date.format('yyyy-mm-dd');
			delete params.birth_date_part1;
			delete params.birth_date_part2;
			delete params.birth_date_part3;
		}
		
		return params;
	};
};


function Address()
{
	this.data = {};
	
	Address.prototype.setMY015 = function(response){
		this.data.address_book_name = response.addressBookName;
		
		var person = response.person;
		
		this.data.name1 = person.name1;
		this.data.name2 = person.name2;
		this.data.kana1 = person.kana1;
		this.data.kana2 = person.kana2;
		//this.data.gender = person.gender;
		//var birthDate = new Date(person.birthDate.replace(/-/g, '/'));
		//this.data.birth_date_part1 = birthDate.getFullYear();
		//this.data.birth_date_part2 = birthDate.getMonth() + 1;
		//this.data.birth_date_part3 = birthDate.getDate();
		this.data.country_code = 'JP'; // きめうち
		this.data.zip_code_part1 = person.zipCode.substring(0, 3);
		this.data.zip_code_part2 = person.zipCode.substring(3, 8);
		this.data.pref_id = person.prefId;
		this.data.pref = person.pref;
		this.data.address1 = person.address1;
		this.data.address2 = person.address2;
		this.data.address3 = person.address3;
		this.data.email1 = person.email1;
		var tel1parts = person.tel1.split('-');
		this.data.tel1_part1 = tel1parts[0];
		this.data.tel1_part2 = tel1parts[1];
		this.data.tel1_part3 = tel1parts[2];
		//if('tel2' in person && person.tel2){
		//	var tel2parts = person.tel2.split('-');
		//	this.data.tel2_part1 = tel2parts[0];
		//	this.data.tel2_part2 = tel2parts[1];
		//	this.data.tel2_part3 = tel2parts[2];
		//}else{
		//	this.data.tel2_part1 = '';
		//	this.data.tel2_part2 = '';
		//	this.data.tel2_part3 = '';
		//}
	};
	
	Address.prototype.assignForm = function(form){
		$.each(this.data, function(key, value){
			var element = $(':input[name=' + key + '],select[name=' + key + ']', form);
			if(element.length == 1){
				element.val(value);
				
			}else if(element.length > 1){
				// TODO ラジオボタンは複数だときめうち
				if($(element[0]).attr('type') == 'radio'){
					$(':input[name=' + key + ']', form).val([value.toString()]);
				}
				
			}else{
				// TODO partxxタイプ
			}
		});
	};
	
	Address.prototype.assignTemplate = function(page){
		$.each(this.data, function(key, value){
			if(page){
				$('#' + key, page).text(value);
			}else{
				$('#' + key).text(value);
			}
		});
		
		/*
		if(page){
			$('#gender', page).text(this.data.gender == 1 ? '男性' : '女性');
			$('#mail_permit1', page).text(this.data.mail_permit1 == 1 ? '購読する' : '購読しない');
		}else{
			$('#gender').text(this.data.gender == 1 ? '男性' : '女性');
			$('#mail_permit1').text(this.data.mail_permit1 == 1 ? '購読する' : '購読しない');
		}
		//$('#gender', page)assigns.zip_code = assigns.zipCode.substring(0, 3) + '-' + assigns.zipCode.substring(3, 8);
		*/
	};
	
	Address.prototype.getParamsMY017OrMY018 = function(){
		var params = {};
		params = $.extend(params, this.data);
		
		params.zip_code = params.zip_code_part1 + params.zip_code_part2;
		delete params.zip_code_part1;
		delete params.zip_code_part2;
		
		params.tel1 = params.tel1_part1 + '-' + params.tel1_part2 + '-' + params.tel1_part3;
		delete params.tel1_part1;
		delete params.tel1_part2;
		delete params.tel1_part3;
		
		return params;
	};
	
	/*
	Address.prototype.toTemplateAssignData = function(){
		var assigns = $.extend(true, {}, this.data);
		
		if('gender' in assigns){
			assigns['#gender'] = assigns.gender == 1 ? '男性' : '女性';
			delete assigns.gender;
		}
		
//		if('birth_year' in assigns && 'birth_month' in assigns && 'birth_day' in assigns){
		if('birth_date_part1' in assigns && 'birth_date_part2' in assigns && 'birth_date_part3' in assigns){
			var birth_date = new Date(assigns.birth_date_part1, assigns.birth_date_part2 - 1, assigns.birth_date_part3);
			assigns['#birth_date'] = birth_date.format('Y/m/d');
			delete assigns.birth_data_part1;
			delete assigns.birth_data_part2;
			delete assigns.birth_data_part3;
		}
		
		if('zip_code_part_0_2' in assigns && 'zip_code_part_3_6' in assigns){
			assigns['#zip_code'] = assigns.zip_code_part_0_2 + '-' + assigns.zip_code_part_3_6;
			delete assigns.zip_code_part_0-2;
			delete assigns.zip_code_part_3-6;
		}
		
		if('pref' in assigns){
			assigns['#pref'] = assigns.pref;
			delete assigns.pref;
		}
		
		if('tel2_part1' in assigns && 'tel2_part2' in assigns && 'tel2_part3' in assigns){
			//assigns['#fax'] = assigns.tel2_part1 + '-' + assigns.tel2_part2 + '-' + assigns.tel2_part3;
//			delete assigns.tel2_part1;
//			delete assigns.tel2_part2;
//			delete assigns.tel2_part3;
		}else{
			//assigns['#tel2'] = '--';
		}
		
		if('mail_permit1' in assigns){
			assigns['#mail_permit'] = assigns.mail_permit1 == 1 ? '購読する' : '購読しない';
			delete assigns.address3;
		}
		
		if('login_id' in assigns){
			assigns['#login_id'] = assigns.login_id;
			delete assigns.login_id;
		}
		
		return assigns;
	};
	*/
	
	Address.prototype.toRequestParams = function(){
		var params = $.extend(true, {}, this.data);
		//params.registration_mode = 0;
		
		if('login_id' in params){
			delete params.login_id_confirm;
		}
		
		if('login_password' in params){
			delete params.login_password_confirm;
		}
		
		// TODO
		if(params.pref){
			//pref_id
		}
		
		
//		$.each(params, function(key, value){
//			if(key.match(/.+_part[1-9]?(_[0-9]+_[0-9]+)?/)){
//				
//			}
//		});
		
		if('zip_code_part_0_2' in params && 'zip_code_part_3_6' in params){
			params.zip_code = params.zip_code_part_0_2 + params.zip_code_part_3_6;
			delete params.zip_code_part_0_2;
			delete params.zip_code_part_3_6;
		}
		
		if('tel1_part1' in params && 'tel1_part2' in params && 'tel1_part3' in params){
			params.tel1 = params.tel1_part1 + '-' + params.tel1_part2 + '-' + params.tel1_part3;
			delete params.tel1_part1;
			delete params.tel1_part2;
			delete params.tel1_part3;
		}
		
		if('tel2_part1' in params && 'tel2_part2' in params && 'tel2_part3' in params){
			params.tel2 = params.tel2_part1 + '-' + params.tel2_part2 + '-' + params.tel2_part3;
			delete params.tel2_part1;
			delete params.tel2_part2;
			delete params.tel2_part3;
		}
		
		if('birth_date_part1' in params && 'birth_date_part2' in params && 'birth_date_part3' in params){
			var birth_date = new Date(params.birth_date_part1, params.birth_date_part2 - 1, params.birth_date_part3);
			params.birth_date = birth_date.format('yyyymmdd');
			delete params.birth_date_part1;
			delete params.birth_date_part2;
			delete params.birth_date_part3;
		}
		
		return params;
	};
};




/**
 * テンプレート(html)ローダー
 * 
 */
function Loader()
{
	// private
	var templates = new Array();
	
	// ロードします
	Loader.prototype.load = function(urls, options){
		if(Type.isString(urls)){ // URLがひとつ
			urls = [urls];
		}
		
		$.ajax({
			url: urls.shift(),
			cache: false,
			dataType: 'text',
			type: 'GET',
			//error: function(XMLHttpRequest, textStatus, errorThrown){alert(textStatus);},
			success: function(response){
				var templateString = response;
				
				// 抽出の指定(htmlの一部を利用する場合)
				if('selector' in options){
					// bodyの中身だけにする
					// こうしないと下記のdiv付加でエラーになる場合がある
					// いや、そうことではないかもしれない
					var matches = templateString.match(/\<body[^>]*\>([\s\S]+)\<\/body\>/i);
					if(matches){
						templateString = $.trim(matches[1]);
					}
					
					templateString = '<div>' + templateString + '</div>';
					templateString = $(options.selector, templateString).outerHTML(); // 多分、セレクタの結果がcontextのルートだとhtml()とかできないっぽいのでdivをかます
								
					// TODO
					// Firefoxの場合、jQuery.html()やinnerHTMLをかますと
					// 例えば、
					// img src="${item.thumbnailImageUrl}"
					// が
					// img src="$%7Bitem.thumbnailImageUrl%7D"
					// に変換されるため、元に戻す
					templateString = templateString.replace(/src\=\"\$%7B(.+?)%7D/mgi, 'src\=\"\${$1}');
				}
				
				templates.push(templateString);
				
				if(urls.length == 0){
					if('callback' in options){
						if(templates.length == 1){
							options.callback.call(this, templates[0]);
						}else{
							options.callback.call(this, templates);
						}
					}
					
				}else{
					$.ajax({
						url: urls.shift(),
						cache: false,
						dataType: 'text',
						type: 'GET',
						//error: function(XMLHttpRequest, textStatus, errorThrown){alert(textStatus);},
						success: arguments.callee
					});
				}
			}
		});
	};
	
/*	Loader.prototype.getTemplate = function(index, assignData){
		var template = templates[index];
		
		if(assignData && isTemplates[index]){
			var templateObject = TrimPath.parseTemplate(template);
			var template = templateObject.process(assignData);	
		}
		
		return template;
	};
*/
	
	
	/**
	 * 通信失敗時
	 * 
	 */
	//onError: function(XMLHttpRequest, textStatus, errorThrown){
	//	alert('通信失敗:' + textStatus + ':' + errorThrown);
	//},
};



/**
 * APIマネージャー
 * 
 */
function APIManager(){};
APIManager.URL_MY001 = '/harvest/api/mypage/login_check.json';
APIManager.URL_MY002 = '/harvest/api/mypage/login.json';
APIManager.URL_MY003 = '/harvest/api/mypage/protected_login.json';
APIManager.URL_MY004 = '/harvest/api/mypage/logout.json';
APIManager.URL_MY005 = '/harvest/api/mypage/used_id.json';
APIManager.URL_MY006 = '/harvest/api/mypage/registration_customer.json';
APIManager.URL_MY007 = '/harvest/api/mypage/password_reset_request.json';
APIManager.URL_MY008 = '/harvest/api/mypage/password_reset_check.json';
APIManager.URL_MY009 = '/harvest/api/mypage/password_reset.json';
APIManager.URL_MY010 = '/harvest/api/mypage/change_password.json';
APIManager.URL_MY011 = '/harvest/api/mypage/change_id.json';
APIManager.URL_MY012 = '/harvest/api/mypage/customer.json';
APIManager.URL_MY013 = '/harvest/api/mypage/update_customer.json';
APIManager.URL_MY014 = '/harvest/api/mypage/withdrawal.json';
APIManager.URL_MY015 = '/harvest/api/mypage/address_book.json';
APIManager.URL_MY016 = '/harvest/api/mypage/address_book_list.json';
APIManager.URL_MY017 = '/harvest/api/mypage/registration_address_book.json';
APIManager.URL_MY018 = '/harvest/api/mypage/update_address_book.json';
APIManager.URL_MY019 = '/harvest/api/mypage/delete_address_book.json';
APIManager.URL_CT001 = '/harvest/api/cart/cart.json';
APIManager.URL_CT002 = '/harvest/api/cart/add_item.json';
APIManager.URL_CT003 = '/harvest/api/cart/update_item_quantity.json';
APIManager.URL_CT004 = '/harvest/api/cart/delete_item.json';
APIManager.URL_CN001 = '/harvest/api/common/zip.json';
APIManager.URL_OD001 = '/harvest/api/order/start_checkout.json';
APIManager.URL_OD002 = '/harvest/api/order/checkout_items.json';
APIManager.URL_OD003 = '/harvest/api/order/confirm_coupon.json';
APIManager.URL_OD004 = '/harvest/api/order/confirm_checkout.json';
APIManager.URL_OD005 = '/harvest/api/order/commit_checkout.json';


APIManager.initialize = function(){
	$(document.body).ajaxError(function(event, XMLHttpRequest, textStatus, errorThrown){
		alert('エラーが発生しました' + ':' + errorThrown + ':' + XMLHttpRequest.status + ':' + XMLHttpRequest.statusText);
		if(!location.pathname.match(/^\/(index\.html(\?[^/]+)?)?$/)){
			location.replace('/');
		}
	});
};


/**
 * APIをコールします。
 * 
 */
APIManager.call = function(options){
	var _options = {
		dataType: 'json',
		cache: false,
		success: APIManager.onSuccess,
		error: APIManager.onError
	};
	
	_options = $.extend(_options, options);
	
	$.ajax(_options);
};

// ログインチェック
APIManager.MY001 = function(callback){
	var options = {
		//url: 'https://' + location.host + APIManager.URL_MY001,
		url: APIManager.URL_MY001,
		type: 'GET',
		callback: callback
	};
	
	APIManager.call(options);
};

//ログイン
APIManager.MY002 = function(id, password, callback){
	var options = {
		url: APIManager.URL_MY002,
		type: 'POST',
		data: {id: id, password: password},
		callback: callback
	};
	
	APIManager.call(options);
};

// プロテクテッドログイン
APIManager.MY003 = function(id, password, callback){
	var options = {
		url: APIManager.URL_MY003,
		type: 'POST',
		data: {id: id, password: password},
		callback: callback
	};
	
	APIManager.call(options);
};

APIManager.MY004 = function(callback){
	var options = {
		url: APIManager.URL_MY004,
		type: 'POST',
		callback: callback
	};
	
	APIManager.call(options);
};

// IDチェック
APIManager.MY005 = function(id, callback){
	var options = {
		url: APIManager.URL_MY005,
		type: 'GET',
		data: {id: id},
		callback: callback
	};
	
	APIManager.call(options);
};

// 会員登録
APIManager.MY006 = function(params, callback){
	var data = {};
	data = $.extend(data, params);
	
	var options = {
		url: APIManager.URL_MY006,
		type: 'POST',
		data: data,
		callback: callback
	};
	
	APIManager.call(options);
};

// パスワードリセット要求
APIManager.MY007 = function(id, callback){
	var options = {
		url: 'https://' + location.host + APIManager.URL_MY007,
		type: 'POST',
		data: {id: id},
		callback: callback
	};
	APIManager.call(options);
};

// パスワードリセットチェック
APIManager.MY008 = function(key, callback){
	var options = {
		url: 'https://' + location.host + APIManager.URL_MY008,
		type: 'GET',
		data: {key: key},
		callback: callback
	};
	APIManager.call(options);
};

// パスワードリセットチェック
APIManager.MY009 = function(key, password, callback){
	var options = {
		url: 'https://' + location.host + APIManager.URL_MY009,
		type: 'POST',
		data: {key: key, password: password},
		callback: callback
	};
	APIManager.call(options);
};

// パスワード変更
APIManager.MY010 = function(customer_id, old_password, new_password, callback){
	var options = {
		url: APIManager.URL_MY010,
		type: 'POST',
		data: {
			customer_id: customer_id,
			old_password: old_password,
			new_password: new_password
		},
		callback: callback
	};
	APIManager.call(options);
};

//メールアドレス変更
APIManager.MY011 = function(customer_id, password, new_id, callback){
	var options = {
		url: APIManager.URL_MY011,
		type: 'POST',
		data: {
			customer_id: customer_id,
			password: password,
			new_id: new_id
		},
		callback: callback
	};
	APIManager.call(options);
};

APIManager.MY012 = function(callback){
	var options = {
		url: APIManager.URL_MY012,
		type: 'GET',
		callback: callback
	};
	APIManager.call(options);
};


// 会員情報変更
APIManager.MY013 = function(customer_id, update_fields, callback){
	var update_fields_comma = "";
	$.each(update_fields, function(key, value){
		update_fields_comma += key + ',';
	});
	update_fields_comma = update_fields_comma.substr(0, update_fields_comma.length - 1);
	
	var data = {
		customer_id: customer_id,
		update_fields: update_fields_comma
	};
	data = $.extend(data, update_fields);
	
	var options = {
		url: APIManager.URL_MY013,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

// 退会
APIManager.MY014 = function(customer_id, password, params, callback){
	var data = {
		customer_id: customer_id,
		password: password
	};
	data = $.extend(data, params);
	var options = {
		url: APIManager.URL_MY014,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

// アドレス帳取得
APIManager.MY015 = function(address_book_id, callback){
	var options = {
		url: APIManager.URL_MY015,
		type: 'GET',
		data: {address_book_id: address_book_id},
		callback: callback
	};
	APIManager.call(options);
};

// アドレス帳リスト取得
APIManager.MY016 = function(customer_id, callback){
	var options = {
		url: APIManager.URL_MY016,
		type: 'GET',
		data: {customer_id: customer_id},
		callback: callback
	};
	APIManager.call(options);
};

//アドレス帳登録
APIManager.MY017 = function(customer_id, address_book_name, fields, callback){
	var data = {
		customer_id: customer_id,
		address_book_name: address_book_name
	};
	data = $.extend(data, fields);
	
	var options = {
		url: APIManager.URL_MY017,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

//アドレス帳更新
APIManager.MY018 = function(address_book_id, update_fields, callback){
	var update_fields_comma = "";
	$.each(update_fields, function(key, value){
		update_fields_comma += key + ',';
	});
	update_fields_comma = update_fields_comma.substr(0, update_fields_comma.length - 1);
	
	var data = {
		address_book_id: address_book_id,
		update_fields: update_fields_comma
	};
	data = $.extend(data, update_fields);
	
	var options = {
		url: APIManager.URL_MY018,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

//アドレス帳削除
APIManager.MY019 = function(address_book_id, callback){
	var data = {
		address_book_id: address_book_id
	};
	
	var options = {
		url: APIManager.URL_MY019,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

// カート情報の取得
APIManager.CT001 = function(callback){
	var options = {
		url: APIManager.URL_CT001,
		type: 'GET',
		callback: callback
	};
	
	APIManager.call(options);
};

//カートに商品追加
APIManager.CT002 = function(catalog_spec_id, quantity, callback){
	var options = {
		url: APIManager.URL_CT002,
		type: 'POST',
		data: {
			catalog_spec_id: catalog_spec_id,
			quantity: quantity
		},
		callback: callback
	};
	APIManager.call(options);
};

//カート商品数量変更
APIManager.CT003 = function(cart_id, catalog_spec_id, quantity, callback){
	var options = {
		url: APIManager.URL_CT003,
		type: 'POST',
		data: {
			cart_id: cart_id,
			catalog_spec_id: catalog_spec_id,
			quantity: quantity
		},
		callback: callback
	};
	APIManager.call(options);
};

// カート商品削除
APIManager.CT004 = function(cart_id, catalog_spec_id, callback){
	var options = {
		url: APIManager.URL_CT004,
		type: 'POST',
		data: {
			cart_id: cart_id,
			catalog_spec_id: catalog_spec_id
		},
		callback: callback
	};
	APIManager.call(options);
};

// 郵便番号から住所検索
APIManager.CN001 = function(country_code, zip_code, callback){
	var options = {
		url: APIManager.URL_CN001,
		type: 'GET',
		data: {
			country_code: country_code,
			zip_code: zip_code
		},
		callback: callback
	};
	APIManager.call(options);
};

// 注文フロー開始
APIManager.OD001 = function(cart_id, callback){
	var options = {
		url: APIManager.URL_OD001,
		type: 'POST',
		data: {cart_id: cart_id},
		callback: callback
	};
	APIManager.call(options);
};

// 注文商品情報取得
APIManager.OD002 = function(checkout_id, callback){
	var options = {
		url: APIManager.URL_OD002,
		type: 'GET',
		data: {checkout_id: checkout_id},
		callback: callback
	};
	APIManager.call(options);
};

// クーポンチェック
APIManager.OD003 = function(checkout_id, coupon_code, callback){
	var data = {
		checkout_id: checkout_id,
		coupon_code: coupon_code
	};
	var options = {
		url: APIManager.URL_OD003,
		type: 'GET',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

// チェックアウト確認
APIManager.OD004 = function(checkout_id, params, callback){
	var data = {
		checkout_id: checkout_id
	};
	data = $.extend(data, params);
	var options = {
		url: APIManager.URL_OD004,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};

// チェックアウト
APIManager.OD005 = function(checkout_id, checkout_confirm_id, credit_card_info, callback){
	var data = {
		checkout_id: checkout_id,
		checkout_confirm_id: checkout_confirm_id
	};
	data = $.extend(data, credit_card_info);
	var options = {
		url: APIManager.URL_OD005,
		type: 'POST',
		data: data,
		callback: callback
	};
	APIManager.call(options);
};


/**
 * 
 * 
 */
APIManager.onSuccess = function(response, dataType){
	if('httpStatus' in response && response.httpStatus != 200){
		switch(response.httpStatus){
		case 401:
			location.replace('https://' + location.host + '/mypage/certify/index.html');
			return;
		}
		
		alert('エラーが発生しました : ' + response.httpStatus);
		return;
	}

	if('callback' in this){
		this.callback.call(this, response); // TODO nullでOK？
	}
	
	// this; はAJAX送信時に設定したオプションを示す
};


/**
 * 通信失敗時
 * 
 */
APIManager.onError = function(XMLHttpRequest, textStatus, errorThrown){
	//alert('エラーが発生しました:' + textStatus + ':' + errorThrown);
	alert('エラーが発生しました');
	if(!location.pathname.match(/^\/(index\.html(\?[^/]+)?)?$/)){
		location.replace('/');
	}
	// this; は他のコールバック関数同様にAJAX通信時のオプションを示す
};


/**
 * ページャ
 * 
 */
function Pager()
{
	var loader = new Loader();
	var pages = new Array();
	var current;
	var assign;
	var templateDatas = {}; // テンプレートに展開する連想配列データ
	var validationEnabled = false;
	var _urls = new Array();
	
	/**
	 * ページ群を一括ロードします。
	 * 
	 */
	Pager.prototype.load = function(urls, options){
		for(var i = 0; i < urls.length; i++){
			_urls.push(urls[i]);
		}
		
		if('validationEnabled' in options){
			validationEnabled = options.validationEnabled;
		}
		
		loader.load(urls, {
			selector: options.selector,
			callback: function(templates){
				for(var i = 0; i < templates.length; i++){
					var page = $(templates[i]);
					page.hide();
					pages.push(page);
				}
				current = pages[0];
				
				if('assign' in options){ // ページ群を埋め込む対象となる、DOM要素の指定があるか
					
					if('assignTarget' in options){
						assign = $(options.assign, options.assignTarget);
						
						if(assign.outerHTML() == ''){ // options.assignTarget と assignは同じ
							assign = options.assignTarget;
						}
						
					}else{
						assign = $(options.assign);
					}
					assign.empty();
					for(var i = 0; i < pages.length; i++){
						assign.append(pages[i]);
					}
					
					pages[0].show();
					if(validationEnabled){
						$('form:visible', pages[0]).loadValidation();
					}
					//pages[0].fadeIn('slow', function(){
					//	if(validationEnabled){
					//		$('form:visible').loadValidation();
					//	}
					//});
					
					// show()に引数つけるとエフェクトがついてしまう
					//pages[0].show(function(){
					//	if(validationEnabled){
					//		$('form:visible').loadValidation();
					//	}
					//});
					//Pager.pages[0].fadeIn('slow');
				}
				
				$.preloadRollover();
				if('callback' in options){
					//jrollover(); // TODO
					options.callback.call(this, pages);
				}
			}
		});
	};
	
	
	/**
	 * 次のページへ
	 * 
	 */
	Pager.prototype.next = function(callback){
		PopUpManager.createWaiting();
		
		var currentIndex = $.inArray(current, pages);
		
		var nextPage = pages[currentIndex + 1];
		
		// TODO 要らないか要確認
		//if(validationEnabled){
		//	// バリデーションプロンプトクリア
		//	$.validationEngine.closePrompt('form');
		//}
		
		if(assign){
			// safariではbody?
			$($.browser.safari ? 'body' : 'html').animate({scrollTop: 0}, 800, 'swing', function(){
				current.fadeOut('slow', function(){
					nextPage.fadeIn('slow', function(){
						$.preloadRollover();
						if(validationEnabled){
							$('form:visible').loadValidation();
						}
						if(callback){
							callback.call(this);
						}
						PopUpManager.removePopUp();
						
						if(pageTracker){
							pageTracker._trackPageview(_urls[currentIndex + 1]);
						}
					});
					current = nextPage;
				});
			});
			
		}else{
			current = nextPage;
		}
		
		return nextPage;
	};
	
	
	/**
	 * 前のページへ
	 * 
	 */
	Pager.prototype.prev = function(callback){
		PopUpManager.createWaiting();
		
		var currentIndex = $.inArray(current, pages);
		
		var prevPage = pages[currentIndex - 1];
		
		// TODO 不要か要確認
		//if(validationEnabled){
		//	// プロンプトクリア
		//	$.validationEngine.closePrompt('form');
		//}
		
		if(assign){
			$($.browser.safari ? 'body' : 'html').animate({scrollTop: 0}, 800, 'swing', function(){
				current.fadeOut('slow', function(){
					prevPage.fadeIn('slow', function(){
						//if(validationEnabled){
						//	$('form:visible').loadValidation();
						//}
						$.preloadRollover(); // TODO 要らない？
						if(callback){
							callback.call(this);
						}
						PopUpManager.removePopUp();
						
						if(pageTracker){
							pageTracker._trackPageview(_urls[currentIndex - 1]);
						}
					});
					current = prevPage;
				});
			});
		}else{
			current = prevPage;
		}
		
		return prevPage;

		//$('form:visible').loadValidation();
	};
	
	/**
	 * ページを移動します。
	 * 
	 */
	Pager.prototype.move = function(index, callback){
		PopUpManager.createWaiting();
		
		var movePage = pages[index];
		
		// TODO 不要か要確認
		//if(validationEnabled){
		//	// プロンプトクリア
		//	$.validationEngine.closePrompt('form');
		//}
		
		if(assign){
			$($.browser.safari ? 'body' : 'html').animate({scrollTop: 0}, 800, 'swing', function(){
				current.fadeOut('slow', function(){
					movePage.fadeIn('slow', function(){
						if(callback){
							callback.call(this);
						}
						PopUpManager.removePopUp();
						
						if(pageTracker){
							pageTracker._trackPageview(_urls[index]);
						}
					});
					current = movePage;
				});
			});
		}else{
			current = movePage;
		}
		
		return movePage;
	};
	
	Pager.prototype.current = function(){
		return current;
	};
};


/**
 * ポップアップマネージャー
 * 
 */
function PopUpManager(){};
/**
 * 引数に渡されたオブジェクトを
 * ポップアップ表示します。
 * 
 */
PopUpManager.createPopUp = function(target, callback){
	var windowWidth = document.documentElement.clientWidth;
	var windowHeight = document.documentElement.clientHeight;

	var popUp;
	if(Type.isString(target)){
		popUp = $(target);
	}else{
		popUp = target;
	}
	
	PopUpManager.mask.css({
		// position: 'fixed',
		position: 'absolute',
		left: 0,
		top: 0,
		'z-index': 8000,
		// overflow: 'visible',
		'background-color': '#666666',
		'display': 'none',
		// height: '100%',
		// width: '100%'
		//width: $(document).width(),
		height: $(document).height()
	});
	$('body').children(':first').before(PopUpManager.mask);
	PopUpManager.mask.css({
//		//height: '100%',
		width: '100%'
	});
	
	$('body').children(':first').after(popUp);
	
	popUp.css({
		'z-index': 8100,
		display: 'none',
		//opacity: 1.0,
		//position: 'fixed',
		position: 'absolute',
		//overflow: 'visible',
		'background-color':'transparent',
		// margin: '0 auto',
		top: windowHeight / 2 - popUp.height() / 2 + $(document).scrollTop(),
		//top: windowHeight / 2 - 482 / 2,
		left: windowWidth / 2 - popUp.width() / 2  + $(document).scrollLeft()
		//left: windowWidth / 2 - 660 / 2
	});
	
	//	PopUpManager.mask.append(popUp);
	//	popUp.appendTo($('body'));
	//	popUp.appendTo($('html'));
	//	popUp.appendTo($('#main'));
	//	$('body').children(':first').before(popUp.hide());
	
	//	PopUpManager.mask.appendTo($('body'));
	//	PopUpManager.mask.appendTo($('#wrapper'));
	//	PopUpManager.mask.appendTo($('html'));
	//	PopUpManager.mask.appendTo($('#main'));

	if($(window).height() < popUp.height()){
		$($.browser.safari ? 'body' : 'html').animate({scrollTop: 0}, 800, 'swing', function(){
			popUp.css({
				top: 10,
				position: 'absolute'
			});
			
			PopUpManager.mask.fadeTo('fast', 0.6, function(){
				popUp.fadeIn(500, callback);
				//jrollover();
				$.preloadRollover();
			});
		});
	}else{
		PopUpManager.mask.fadeTo('fast', 0.6, function(){
			popUp.fadeIn(500, callback);
			//jrollover();
			$.preloadRollover();
		});
	}
	
	// for ie6
	if(popUp == Cart.view){
		if($.browser.msie && $.browser.version < 7.0){
			$('select').addClass('hide');
		}
		
		if(pageTracker){
			pageTracker._trackPageview('/cart/index.html');
		}
	}
	
	PopUpManager.popUps.push(popUp);
};
/**
 * 現在のポップアップを非表示にします。
 * 
 */
PopUpManager.removePopUp = function(removeFromDom){
	var popUp = PopUpManager.popUps.pop();
	
	if(!popUp) return;
	
	// for ie6
	if(popUp == Cart.view){
		if($.browser.msie && $.browser.version < 7.0){
			$('select').removeClass('hide');
		}
	}
	
	if(popUp.attr('id') == 'waiting'){
		PopUpManager.waitingMask.remove();
		PopUpManager.isWaiting = false;
	}else{
		PopUpManager.mask.remove();
	}
	
	if(removeFromDom === false){
		popUp.hide();
	}else{
		popUp.remove();
	}
};
/**
 * 
 * 
 */
PopUpManager.createWaiting = function(callback){
	if(PopUpManager.isWaiting){
		return;
	}
	
	PopUpManager.isWaiting = true;
	
	PopUpManager.waitingMask.css({
		// position: 'fixed',
		position: 'absolute',
		left: 0,
		top: 0,
		'z-index': 9000,
		'background-color': '#eeeeee',
		'display': 'none',
		// height: '100%',
		// width: '100%'
		//width: $(document).width(),
		height: $(document).height()
	});
	//PopUpManager.waitingMask.appendTo($('body'));
	$('body').children(':first').before(PopUpManager.waitingMask);
	PopUpManager.waitingMask.css({
		//height: '100%',
		width: '100%'
	});

	var windowWidth = document.documentElement.clientWidth;
	var windowHeight = document.documentElement.clientHeight;
	
	var waiting = $('<div><img src="/img/common/loader.gif" width="32px" height="32px" /></div>');
	waiting.attr('id', 'waiting');
	// waiting.appendTo($('body'));
	waiting.css({
		'z-index': 9100,
		display: 'none',
		position: 'fixed',
		top: windowHeight / 2 - 32 / 2,
		left: windowWidth / 2 - 32 / 2
		// position: "expression('absolute')"
		// top: "expression((documentElement.scrollTop || document.body.scrollTop) + 100 + 'px')",
		// left: "expression((documentElement.scrollLeft || document.body.scrollLeft) + 80 + 'px')"
	});
	
	// PopUpManager.waitingMask.append(waiting);
	$('body').children(':first').after(waiting);
	
	// for ie6
	if($.browser.msie && $.browser.version < 7.0){
		var waitingHeight = windowHeight / 2 - 32 / 2;
		waiting.css({
			position: 'absolute',
			top: waitingHeight + $(document).scrollTop()
		});
		
		$(window).scroll(function(){
			waiting.css('top', waitingHeight + $(document).scrollTop());
		});
	}
	
	PopUpManager.popUps.push(waiting);
	PopUpManager.waitingMask.fadeTo('fast', 0.25, function(){
		waiting.fadeIn(300, callback);
	});
};
/**
 * 
 * 
 */
//PopUpManager.createZipCode2Address = function(response, event, callback){
PopUpManager.createZipCode2Address = function(zipCode, event, callback){
	APIManager.CN001('JP', zipCode, function(response){
		if(!response.result){
			alert('エラーが発生しました');
			return false;
		}
		
		var _found = response.zip_code_list.length > 0 ? true : false;
		
		var addressList = $('<div />');//.attr('id', 'tess');
		
		for(var i = 0; i < response.zip_code_list.length; i++){
			var address = response.zip_code_list[i];
			var item = $('<div />').text(address.pref + address.address1 + address.address2 + address.address3);
			item.css({
				cursor: 'pointer'
			});
			addressList.append(item);
		}
		
		if(!_found){
			var item = $('<div />').text('該当する住所がみつかりません');
			//item.css({
			//	cursor: 'pointer'
			//});
			addressList.append(item);
		}
		
		addressList.css({
			'z-index': 9100,
			display: 'none',
			position: 'absolute',
                        'padding' : '10px',
                        'background-color' : '#fff',
                        'font-size' : '150%',
                        'border' : '#FF9900 solid 2px',
                        'color' : '#0000FF',
                        'text-decoration' : 'underline',
                         top: event.pageY,
			left: event.pageX - 40
		});
		
		var _mask = $('<div id="mask" />');
		_mask.css({
			//position: 'fixed',
			position: 'absolute',
			left: 0,
			top: 0,
			'z-index': 9000,
			'background-color': '#eeeeee',
			'display': 'none',
			//height: '100%',
			//width: '100%',
			//width: $(document).width(),
			height: $(document).height(),
			opacity: 0.0
		});
		//_mask.appendTo($('body'));
		$('body').children(':first').before(_mask);
		_mask.css({
			width: '100%'
		});
		
		_mask.show();
		addressList.appendTo($('body'));
		addressList.fadeIn('fast', function(){
			if(_found){
				addressList.children().hover(function(event){
					$(this).css({
						'background-color': '#dddddd'
					});
				},
				function(event){
					$(this).css({
						'background-color': '#ffffff'
					});
				});
				
				addressList.children().click(function(event){
					var index = addressList.children().index($(this));
					$('[name$=pref_id] option').each(function(){
						if($(this).text() == response.zip_code_list[index].pref){
							$(this).attr('selected', true);
							return false;
						}
					});
					
					//$('[name$=pref_id]').val(response.zip_code_list[index].pref);
					$(':input[name$=address1]').val(response.zip_code_list[index].address1);
					$(':input[name$=address2]').val(response.zip_code_list[index].address2);
					$(':input[name$=address3]').val(response.zip_code_list[index].address3);
					addressList.remove();
					_mask.remove();
				});
			}
		});
		_mask.click(function(event){
			addressList.remove();
			_mask.remove();
		});
	});
};
PopUpManager.popUps = new Array();
PopUpManager.mask = $('<div id="mask" />');
PopUpManager.waitingMask = $('<div id="mask" />');
PopUpManager.isWaiting = false;

/**
 * ログアウトダイアログ
 * 
 * @return
 */
function LogoutDialog(){};
LogoutDialog.popUp = function(){
	var loader = new Loader();
	loader.load('/logout/index.html', {
		selector: '.org_box',
		callback: function(response){
			var dialog = $(response);
			
			var pager = new Pager();
			pager.load(['/logout/index.html', '/logout/finish.html'], {
				selector: '.org_box_top',
				assign: '.org_box',
				assignTarget: dialog,
				callback: function(response){
					PopUpManager.createPopUp(dialog);
					
					// ○○さん
					$('#customer_name', dialog).text(Cart.data.name1 + Cart.data.name2);
					
					// 「キャンセル」ボタンのクリック
					$('#cancel_button', dialog).click(function(event){
						event.preventDefault();
						PopUpManager.removePopUp();
						return false;
					});
					
					// 「ログアウト」ボタンのクリック
					$('#logout_button', dialog).click(function(event){
						event.preventDefault();
						
						// ログアウトAPI実行
						APIManager.MY004(function(response){
							if(!response.result){
								alert('エラーが発生しました');
								if(!location.pathname.match(/^\/(index\.html(\?[^/]+)?)?$/)){
									location.replace('/');
								}
								return false;
							}
							
							Cart.reload(function(){
								$('.box_lohas-member').show();
								pager.next();
								
								if(pageTracker){
									pageTracker._trackPageview('/logout/finish.html');
								}
							});
						});
						
						return false;
					});
					
					// 「トップページに戻る」ボタンのクリック
					$('#go_home_button', dialog).click(function(event){
						event.preventDefault();
						location.replace('/');
						return false;
					});
					
					if(pageTracker){
						pageTracker._trackPageview('/logout/index.html');
					}
				}
			});
		}
	});
};
