if (typeof Choistudy == "undefined" || !Choistudy) {
	var Choistudy = {};
}

// Ajax のトラッキング処理を追加した asyncRequest
Choistudy.asyncRequest = function(method, uri, callback, postData) {
	var wrapped = Choistudy._wrapCallback(uri, callback);
	YAHOO.util.Connect.asyncRequest(method, uri, wrapped, postData);
};

// wrap 処理
Choistudy._wrapCallback = function(uri, callback) {
	var YUIL = YAHOO.lang;
	if (!YUIL.isUndefined(pageTracker)
			&& YUIL.isFunction(pageTracker._trackPageview)) {
		var baseUrl = location.protocol + "//" + location.host;
		var trackUrl = uri.replace(baseUrl, "");
		if (callback && callback.success) {
			var orig = callback.success;
			callback.success = function(o) {
				var scope = callback.scope || window;
				pageTracker._trackPageview(trackUrl);
				orig.apply(scope, [ o ]);
			};
		} else {
			callback = callback || {};
			callback.success = function(o) {
				pageTracker._trackPageview(trackUrl);
			};
		}
	}
	return callback;
};

Choistudy.Util = {
	basePath : function(base) {
		var url = "" + window.location;
		var array = url.split(base);
		return url.substr(0, array[0].length);
	},
	removeChilds : function(elem) {
		if (elem) {
			while (elem.lastChild) {
				elem.removeChild(elem.lastChild);
			}
		}
	},
	removeElem : function(elem) {
		if (elem) {
			var parent = elem.parentNode;
			parent.removeChild(elem);
		}
	},
	checkRedirect : function(data) {
		if (data.needRedirect) {
			location.href = data.redirectUrl;
			return true;
		}
		return false;
	},
	elemChecked : function(form, elemName) {
		var filterFunc = Choistudy.Util.checkboxFilter(elemName);
		var nodeList = YAHOO.util.Dom.getElementsBy(filterFunc, 'input', form);
		for ( var i = 0; i < nodeList.length; i++) {
			var checkbox = nodeList[i];
			if (checkbox.checked) {
				return true;
			}
		}
		return false;
	},
	checkboxFilter : function(elemName) {
		return function(elem) {
			if (!elem.type) {
				return false;
			}
			return (elem.type == 'checkbox') && (elem.name == elemName);
		};
	},
	elemUncheck : function(form, elemName) {
		var filterfunc = Choistudy.Util.checkboxFilter(elemName);
		var nodeList = YAHOO.util.Dom.getElementsBy(filterfunc, 'input', form);
		for ( var i = 0; i < nodeList.length; i++) {
			nodeList[i].checked = false;
		}
	},
	abbreviate : function(str, width) {
		var length = str.length;
		if (width < 4) {
			width = 4;
		}
		if (length <= width) {
			return str;
		}
		return str.substring(0, width - 3) + '...';
	},
	isNode : function(node, name) { // ノードが指定の名前かを調べる
		return node.nodeName
				&& node.nodeName.toUpperCase() == name.toUpperCase();
	}
};

Choistudy.Render = {
	renderList : function(parent, dataList, listfunc) {
		this.doRenderList(parent, dataList, listfunc, 'ul');
	},
	renderNumList : function(parent, dataList, listfunc) {
		this.doRenderList(parent, dataList, listfunc, 'ol');
	},
	doRenderList : function(parent, dataList, listfunc, type) {
		if (dataList) {
			var ul = document.createElement(type);
			for ( var i = 0; i < dataList.length; i++) {
				listfunc(ul, dataList[i], i);
			}
			parent.appendChild(ul);
		}
	},
	renderAnchor : function(parent, href, label, target) {
		var a = this.getAnchor(href, label, false, target);
		parent.appendChild(a);
	},
	renderAnchorHTML : function(parent, href, label, target) {
		var a = this.getAnchor(href, label, true, target);
		parent.appendChild(a);
	},
	getAnchor : function(href, label, isHTML, target) {
		var a = document.createElement('a');
		a.setAttribute('href', href);
		if (target) {
			a.setAttribute('target', target);
		}
		if (isHTML) {
			a.innerHTML = label;
		} else {
			a.appendChild(document.createTextNode(label));
		}
		return a;
	},
	renderInfo : function(msg, needRemove) {
		var infoArea = document.getElementById('infoArea');
		if (needRemove) {
			Choistudy.Util.removeChilds(infoArea);
		}
		this.renderList(infoArea, [ msg ], function(parent, data, i) {
			var li = document.createElement('li');
			li.className = 'info';
			li.appendChild(document.createTextNode(data));
			parent.appendChild(li);
			parent.className = 'infos';
		});
	},
	renderMessage : function(msg, needRemove) {
		var messageArea = document.getElementById('messageArea');

		if (!messageArea) {
			messageArea = document.createElement('div');
			messageArea.className = 'messages';
			messageArea.id = 'messageArea';
			YAHOO.util.Dom.insertAfter(messageArea, 'errorMessageArea');
		}

		if (needRemove) {
			Choistudy.Util.removeChilds(messageArea);
		}
		messageArea.appendChild(document.createTextNode(msg));
	},
	cleanUpMessage : function() {
		var elem = document.getElementById('messageArea');
		Choistudy.Util.removeElem(elem);
	},
	escape : function(str) {
		// from prototype.js
	var div = document.createElement('div');
	var txt = document.createTextNode('');
	txt.data = str;
	div.appendChild(txt);
	return div.innerHTML;
}
};

Choistudy.ShowHide = {

	showElement : function(elemName) {
		this.doShowHide(elemName, 'visible');
	},
	hideElement : function(elemName) {
		this.doShowHide(elemName, 'hidden');
	},
	doShowHide : function(elemName, value) {
		var elem = document.getElementById(elemName);
		if (elem) {
			elem.style.visibility = value;
		}
	}
};

// ----- [ドリルの追加] -----
Choistudy.Drill = {
	dadd : function(base, drillid, linkid, parentid) {
		// 二度押し防止
		var progress = this.progress || false, self = this;		
		if(progress){
			return;
		}else{
			this.progress = true;
		}
	
		// base を引数にしているのはクラス機能からも呼ばれるため
		var basePath = Choistudy.Util.basePath(base);
		var url = basePath + 'drill/put/' + drillid;
		var elem = document.getElementById(linkid);
		var parent = document.getElementById(parentid);
		var fadeout = new YAHOO.util.Anim(elem, {
			opacity : {
				from : 1,
				to : 0
			}
		}, 1);
		// fadeout 開始時に実行される関数
		fadeout.onStart.subscribe(function() {
			// request 後に実行される fadein
				var fadein = new YAHOO.util.Anim(elem, {
					opacity : {
						from : 0,
						to : 1
					}
				});
				fadein.onStart.subscribe(function() {
//					YAHOO.util.Dom.replaceClass(parent, "ui-button-pink",
//							"ui-button-blue");
				});
				Choistudy.asyncRequest('GET', url, {
					success : function(o) {
						var data = eval('(' + o.responseText + ')');
						Choistudy.Render.renderMessage(data['message'], true);
						if (data['added']) {
							elem.setAttribute('href', basePath + 'drill/'
									+ drillid);

							elem.innerHTML = '<img src="./../image/start_drill_button.png" alt="学習を開始"/>';
							// TODO おそらく IE では切り替わりが上手くいかない.
							
						}
						fadein.animate();
						self.progress = false;						
					},
					failure : function(o) {
						fadein.animate();
						alert('接続に失敗しました :[' + o.status + '] errorText:['
								+ o.statusText + ']');
						self.progress = false;						
					}
				}, null);
			});
		// fadeout の開始
		fadeout.animate();
	}
};

Choistudy.Confirm = {
	redirectTo : function(url, message) {
		if (window.confirm(message)) {
			location.href = url;
		}
	}
};

Choistudy.Dialog = {
	// 呼び出しのスコープに注意 - this は Dialog
	handleSubmit : function() {
		this.submit();
	},
	handleCancel : function() {
		this.cancel();
	},
	handleSuccess : function(func, arg) {
		return function(o) {
			var data = eval('(' + o.responseText + ')');
			if (Choistudy.Util.checkRedirect(data)) {
				return;
			}
			Choistudy.Render.cleanUpMessage();
			if (data['message']) {
				Choistudy.Render.renderMessage(data['message'], true);
				return;
			}
			func(data, arg);
		};
	},
	// メッセージのみが返る場合
	handleVoidSuccess : function(func) {
		return function(o) {
			var data = eval('(' + o.responseText + ')');
			if (Choistudy.Util.checkRedirect(data)) {
				return;
			}
			Choistudy.Render.cleanUpMessage();
			if (data['message']) {
				Choistudy.Render.renderMessage(data['message'], true);
			}
			func(data);
		};
	},
	handleFailure : function(msg) {
		return function(o) {
			alert(msg + ":" + o.status);
		};
	}
};

Choistudy.Calendar = function(appendTo, configProps) {
	this.cal = new YAHOO.widget.Calendar(appendTo, configProps);
	for ( var p in Choistudy.Calendar.JA_OPTS) {
		this.cal.cfg.setProperty(p, Choistudy.Calendar.JA_OPTS[p]);
	}
};

Choistudy.Calendar.JA_OPTS = {
	"MONTHS_SHORT" : [ "1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708",
			"6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708",
			"12\u6708" ],
	"MONTHS_LONG" : [ "1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708",
			"6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708",
			"12\u6708" ],
	"WEEKDAYS_1CHAR" : [ "\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728",
			"\u91D1", "\u571F" ],
	"WEEKDAYS_SHORT" : [ "\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728",
			"\u91D1", "\u571F" ],
	"WEEKDAYS_MEDIUM" : [ "\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728",
			"\u91D1", "\u571F" ],
	"WEEKDAYS_LONG" : [ "\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728",
			"\u91D1", "\u571F" ],
	"MY_LABEL_YEAR_POSITION" : 1,
	"MY_LABEL_MONTH_POSITION" : 2,
	"MY_LABEL_YEAR_SUFFIX" : "\u5E74",
	"MY_LABEL_MONTH_SUFFIX" : ""
};

Choistudy.Calendar.prototype = {
	getCalendar : function() {
		return this.cal;
	}
};

Choistudy.Tooltip = {
	background : {
		'contextMouseOver' : '#f9f99e',
		'contextMouseOut' : ''
	},
	colorChange : function(type, args, obj) {
		obj.style.backgroundColor = Choistudy.Tooltip.background[type];
	}
};

/**
 * ホームのツールチップを扱うクラス
 */
Choistudy.HomeToolTip = function(id, elmprefix, ttprefix) {
	this.id = id;
	this.elmprefix = elmprefix;
	this.ttprefix = ttprefix;
};

Choistudy.HomeToolTip.prototype = {
	prepare : function() {
		var YUID = YAHOO.util.Dom, YUIL = YAHOO.lang, self = this;
		var parent = YUID.get(self.id);
		var nodes = YUID.getElementsBy(function(elm) {
			if (!elm.id) {
				return false;
			}
			return elm.id.indexOf(self.elmprefix) == 0;
		}, 'li', parent);

		if (YUIL.isArray(nodes)) {
			for ( var i = 0; i < nodes.length; i++) {
				var tooltip = new YAHOO.widget.Tooltip(self.ttprefix + i);
				tooltip.cfg.setProperty('context', nodes[i]);
				tooltip.contextMouseOutEvent.subscribe(
						Choistudy.Tooltip.colorChange, nodes[i], true);
				tooltip.contextMouseOverEvent.subscribe(
						Choistudy.Tooltip.colorChange, nodes[i], true);
			}
		}
	}
};

Choistudy.Question = function(prop, keyHandler) {
	this.prop = prop;
	this.keyHandler = keyHandler;
	this.dlg = new Choistudy.Loading("infoArea");
};

// 試験-ドリル共有 (サーバ側で返す innerHTML でコントロールする)
Choistudy.Question.prototype = {
	nextQuestion : function(callback) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + this.prop.base + this.prop.nextId
				+ '/next_question';
		this.connect(url, "GET");
		if (this.keyHandler) {
			this.keyHandler.disable();
		}
		// 純粋な意味での callback ではないが、nextQuestion 後に処理されるように
		if (callback && YAHOO.lang.isFunction(callback)) {
			callback();
		}
	},
	btnClick : function(btnId) {
		var btn = YAHOO.util.Dom.get(btnId);
		if (btn && btn.click) {
			btn.click();
		}
	},
	changeAnswerStatus : function(qid){
		var icon = YAHOO.util.Dom.get('check_icon_'+qid);
		YAHOO.util.Dom.removeClass(icon,'notanswered_question');
		YAHOO.util.Dom.addClass(icon,'answered_question');
	},
	choiceSingle : function(hashedId, qid) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + this.prop.base + this.prop.nextId
				+ '/answer/single/choice/' + hashedId + '?questionId=' + qid;
		// 二度押し対策/mail の場合はない
		var choiceList = YAHOO.util.Dom.get('choiceList');
		if (choiceList) {
			choiceList.style.backgroundColor = '#ddd';
			var choices = YAHOO.util.Dom.getElementsByClassName(
					'single.choice.link', 'a', 'choiceList');
			for ( var i = 0; i < choices.length; i++) {
				var choice = choices[i];
				choice.setAttribute('href', '#');
			}
		}
		
		this.connect(url);
		this.changeAnswerStatus(qid);
		if (this.keyHandler) {
			this.keyHandler.enable();
		}
	},
	choiceMulti : function(qid) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + this.prop.base + this.prop.nextId
				+ '/answer/multi/choice';
		var form = YAHOO.util.Dom.get('multi.choice.form');

		// 二度押し対策
		var submit = YAHOO.util.Dom.get('choice.submit');
		submit.disabled = true;

		if (!Choistudy.Util.elemChecked(form, 'hashedId')) {
			Choistudy.Render
					.renderMessage('どの選択肢も選択されていません。最低一つは選択して下さい', true);
			submit.disabled = false;
			return;
		}

		YAHOO.util.Connect.setForm(form, false);
		this.connect(url, 'POST');
		this.changeAnswerStatus(qid);
		if (this.keyHandler) {
			this.keyHandler.enable();
		}
	},
	inputSingle : function(qid) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + this.prop.base + this.prop.nextId
				+ '/answer/single/input';
		var form = YAHOO.util.Dom.get('single.input.form');

		// 二度押し対策
		var submit = YAHOO.util.Dom.get('choice.submit');
		submit.disabled = true;

		var answer = YAHOO.util.Dom.get('choice.answer');
		if (answer.value == null || answer.value == '') {
			Choistudy.Render.renderMessage('回答が空です。回答を入力して下さい', true);
			answer.focus();
			submit.disabled = false;
			return;
		}

		YAHOO.util.Connect.setForm(form, false);
		this.connect(url, 'POST');
		this.changeAnswerStatus(qid);
		if (this.keyHandler) {
			this.keyHandler.enable();
		}
	},
	connect : function(url, method) {
		var target = YAHOO.util.Dom.get(this.prop.id), self = this;
		if (!method) {
			method = 'GET';
		}
		// 前画面でのメッセージ処理をクリアする
	Choistudy.Render.cleanUpMessage();
	this.dlg.start();
	Choistudy.asyncRequest(method, url, {
		success : function(o) {
			var contentType = o.getResponseHeader["Content-Type"];
			if(contentType.indexOf("text/javascript") >= 0){
				var data = eval('(' + o.responseText + ')');
				if(Choistudy.Util.checkRedirect(data)){
					return;
				}
			}
			// event handler をすべて削除
			self.dlg.stop();
			YAHOO.util.Event.purgeElement(target);
			Choistudy.Util.removeChilds(target);
			target.innerHTML = o.responseText;
			// innerHTML で読み込んできたファイルの script 要素の評価
			if (!YAHOO.env.ua.ie) { // IE の場合は既に eval されている
				var scriptArray = YAHOO.util.Dom.getElementsBy(function(obj) {
					return true;
				}, 'script', target);
				for ( var i = 0; i < scriptArray.length; i++) {
					var script = scriptArray[i];
					eval(script.innerHTML);
				}
			}
			var scroll_target = YAHOO.util.Dom.get('scroll_target');
			var xy = YAHOO.util.Dom.getXY(scroll_target);
			window.scrollTo(xy[0], xy[1]-10);
		},
		failure : function(o) {
			alert('接続に失敗しました :[' + o.status + '] errorText:[' + o.statusText
					+ ']');
			self.dlg.stop();
		}
	}, null);
}
};

Choistudy.Loading = function(target) {
	this.panel = new YAHOO.widget.Panel(target, {
		width : "120px",
		fixedcenter : true,
		close : false,
		draggable : false,
		modal : true,
		visible : false
	});
	this.panel.setHeader("読み込み中...");
	this.panel.setBody('<img src="./../image/loading.gif" />');
	this.panel.render(document.body);
};

Choistudy.Loading.prototype = {
	start : function() {
		this.panel.show();
	},
	stop : function() {
		this.panel.hide();
	}
};

Choistudy.Result = function(prop, keyHandler) {
	this.prop = prop;
	this.keyHandler = keyHandler;
};

Choistudy.Result.prototype = {
	postit : function(qid) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + 'postit/add/drill/' + this.prop.nextId
				+ '/question/' + qid;
		var input = YAHOO.util.Dom.get('postitcheck');
		// TODO 「次へ」「成績へ」の表示／非表示の対処 対処
		input.disabled = true;
		// Firefox 対策/フォーカスを外しておく
		input.blur();
		Choistudy.asyncRequest('GET', url, {
			success : function(o) {
				var data = eval('(' + o.responseText + ')');
				Choistudy.Render.renderMessage(data['message'], false);
			},
			failure : function(o) {
				alert('接続に失敗しました :[' + o.status + '] errorText:['
						+ o.statusText + ']');
			}
		}, null);
	},
	editInplace : function(qid) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + 'question/exposition/' + qid;

		Choistudy.ShowHide.hideElement('exposition');
		Choistudy.ShowHide.hideElement('edit.in.place');
		YAHOO.util.Dom.get('exposition').style.height = 0;
		this.keyHandler.disable();
		Choistudy.asyncRequest('GET', url, {
			success : function(o) {
				var data = eval('(' + o.responseText + ')');
				if (Choistudy.Util.checkRedirect(data)) {
					return;
				}
				var form = YAHOO.util.Dom.get('edit.in.place.form');
				var textarea = YAHOO.util.Dom.getFirstChildBy(form, function(
						node) {
					return node.name && node.name == 'exposition';
				});
				textarea.value = data.questionDto.rawExposition;
				form.style.display = '';
			},
			failure : function(o) {
				alert('接続に失敗しました :[' + o.status + '] errorText:['
						+ o.statusText + ']');
			}
		}, null);
	},
	editInplaceCancel : function() {
		this.editInplaceReset();
		this.keyHandler.enable();
	},
	editInplaceSubmit : function(qid) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + 'question/exposition_post/' + qid;
		var resetfunc = this.editInplaceReset;
		var form = YAHOO.util.Dom.get('edit.in.place.form');
		YAHOO.util.Connect.setForm(form, false);
		Choistudy
				.asyncRequest(
						'POST',
						url,
						{
							success : function(o) {
								var data = eval('(' + o.responseText + ')');
								if (Choistudy.Util.checkRedirect(data)) {
									return;
								}
								// TODO: ここは要注意 (返り値がまだ question のまま)
								var question = data.question;
								YAHOO.util.Dom.get('exposition').innerHTML = question.exposition;
								resetfunc();
							},
							failure : function(o) {
								alert('接続に失敗しました :[' + o.status
										+ '] errorText:[' + o.statusText + ']');
							}
						}, null);
		this.keyHandler.enable();
	},
	editInplaceReset : function() {
		Choistudy.ShowHide.showElement('exposition');
		Choistudy.ShowHide.showElement('edit.in.place');
		YAHOO.util.Dom.get('exposition').style.height = '';
		YAHOO.util.Dom.get('edit.in.place.form').style.display = 'none';
	}
};

Choistudy.KeyHandler = function() {
	this.handlers = [];
};

Choistudy.KeyHandler.prototype = {
	disable : function() {
		for ( var i = 0; i < this.handlers.length; i++) {
			var handler = this.handlers[i];
			handler.disable();
		}
	},
	enable : function() {
		for ( var i = 0; i < this.handlers.length; i++) {
			var handler = this.handlers[i];
			handler.enable();
		}
	},
	add : function(keys, func, scope) {
		// scope に注意
	var handler = new YAHOO.util.KeyListener(document, {
		keys : keys
	}, {
		fn : func,
		correctScope : scope
	});
	this.handlers.push(handler);
}
};

/**
 * 戻れる試験用に拡張した Choistudy.Question
 */
Choistudy.ExamQuestion = function(prop, keyHandler) {
	this.prop = prop;
	this.keyHandler = keyHandler;
	this.finished = false;
	this.skipDisabled = true;
	this.dlg = new Choistudy.Loading("infoArea");
};

YAHOO.lang.extend(Choistudy.ExamQuestion, Choistudy.Question, {
	listStatus : function() {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + 'retryable_exam/' + this.prop.nextId + '/list';
		this.connect(url);
	},
	showQuestion : function(questionId) {
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + 'retryable_exam/' + this.prop.nextId
				+ '/question/' + questionId;
		this.connect(url);
	},
	finishExam : function() {
		// タイマーのエリアを非表示にする (なければ何もしない)
		Choistudy.ShowHide.hideElement("limit.area");
		var basePath = Choistudy.Util.basePath(this.prop.base);
		var url = basePath + 'retryable_exam/' + this.prop.nextId + '/finish';
		this.connect(url);
		this.finished = true;
	},
	skipQuestion : function() {
		// 二度押し防止
		if (this.skipDisabled) {
			return;
		}
		this.skipDisabled = true;
		if (this.nextQuestionId && this.nextQuestionId > 0) {
			this.showQuestion(this.nextQuestionId);
			this.nextQuestionId = -1;
		} else {
			this.listStatus();
		}
	},
	setNextQuestion : function(nextQuestionId) {
		if (nextQuestionId && YAHOO.lang.isNumber(nextQuestionId)) {
			this.nextQuestionId = nextQuestionId;
		}
		this.skipDisabled = false;
	},
	choiceSingleForm : function(qid) {
		var YUID = YAHOO.util.Dom;
		var form = YUID.get('single.choice.form');
		// 二度押し対策
		var submit = YUID.get('choice.submit');
		submit.disabled = true;

		var checked = YUID.getElementsBy(function(elem) {
			if (!elem.type) {
				return false;
			}
			return (elem.type == 'radio') && (elem.name == "hashedId")
					&& elem.checked;
		}, "input", form);

		if (!checked || checked.length == 0) {
			Choistudy.Render
					.renderMessage('どの選択肢も選択されていません。最低一つは選択して下さい', true);
			submit.disabled = false;
			return;
		}
		var hashedId = checked[0].value;
		this.choiceSingle(hashedId, qid);
	}
});

/**
 * 指定のノードの表示／非表示を切り替えるためのリンクに適用するクラス
 */
Choistudy.ToggleLink = function(id, opened) {
	this.id = id;
	this.opened = opened || false;
};

Choistudy.ToggleLink.prototype = {
	getListener : function() {
		var self = this, YUID = YAHOO.util.Dom, YUIL = YAHOO.lang;
		return function() {
			var link = this;
			var target = YUID.get(self.id);
			if (self.opened) { // オープン状態で呼び出された場合
		self.closeFunc(target);
		YUID.replaceClass(link, 'delete', 'add');
		self.opened = false;
	} else { // クローズ状態で呼び出された場合
		self.openFunc(target);
		self.opened = true;
		YUID.replaceClass(link, 'add', 'delete');
	}
};
},
openFunc : function(target) {
var YUID = YAHOO.util.Dom;
var fadein = new YAHOO.util.Anim(target, {
	opacity : {
		from : 0,
		to : 1
	}
}, 0.5);
fadein.onStart.subscribe(function() {
	YUID.setStyle(target, 'display', 'block');
});
fadein.animate();
},
closeFunc : function(target) {
var YUID = YAHOO.util.Dom;
var fadeout = new YAHOO.util.Anim(target, {
	opacity : {
		from : 1,
		to : 0
	}
}, 0.5);
fadeout.onComplete.subscribe(function() {
	YUID.setStyle(target, 'display', 'none');
});
fadeout.animate();
}
};

Choistudy.Timer = function(id, limit) {
	this.limit = limit;
	this.elm = YAHOO.util.Dom.get(id);
};

Choistudy.Timer.prototype = {
	start : function(endFunc) {
		var self = this;
		if (this.limit < 0) {
			endFunc(this.elm);
			return;
		}
		this.render();
		this.limit--;
		setTimeout(function() {
			self.start(endFunc);
		}, 1000);
	},
	padzero : function(num) {
		return (num < 10) ? "0" + num : "" + num;
	},
	render : function() {
		var min = parseInt(this.limit / 60);
		var sec = this.limit % 60;
		this.elm.innerHTML = this.padzero(min) + ":" + this.padzero(sec);
	}
};

Choistudy.DialogConfirm = function() {
};

Choistudy.DialogConfirm.prototype = {
	_create : function(url) {
		var self = this;
		
		var yHandler = function() {
			location.href = url;
		};

		var nHandler = function() {
			self.dlg.hide();
		};

		this.dlg = new YAHOO.widget.SimpleDialog("infoArea", {
			visible : false,
			width : "24em",
			fixedcenter : true,
			modal : true,
			draggable : false,
			close : false
		});
		this.dlg.cfg.queueProperty("buttons", [ {
			text : "はい",
			handler : {
				fn : yHandler
			},
			isDefault : true
		}, {
			text : "いいえ",
			handler : {
				fn : nHandler,
				scope : this.dlg
			}
		} ]);
		this.dlg.cfg.setProperty("icon", YAHOO.widget.SimpleDialog.ICON_INFO);
	},
	_show : function(){
		if(this.dlg){
			this.dlg.render(document.body);
			this.dlg.show();
		}
	}
}

Choistudy.ExamConfirm = function() {
};

YAHOO.lang.extend(Choistudy.ExamConfirm, Choistudy.DialogConfirm,{
	open : function(url,title,course){
		this._create(url);
		this.dlg.setHeader("受験開始");
		if (course) {
			this.dlg.setBody("<br/>『" + title + "』<br/>関連コース：" + course
					+ "<br/>を受験します。<br/>準備はよろしいですか？");
		} else {
			this.dlg.setBody("<br/>『" + title + "』<br/>を受験します。<br/>準備はよろしいですか？");
		}		
		this._show();
	}	
});

Choistudy.DrillConfirm = function(){
};

YAHOO.lang.extend(Choistudy.DrillConfirm, Choistudy.DialogConfirm,{
	open : function(url,title){
		this._create(url);
		this.dlg.setHeader("ドリルの中止");
		this.dlg.setBody("<br/>『" + title + "』<br/>の学習を中止します。<br/>再度同一のドリルを学習することは可能ですが、今までの学習履歴はクリアされます。<br/>中止してもよろしいですか？");
		this._show();
	}	
});

/**
 * UL/OL などのリストをナビゲーション化するクラス (/exam/index.html を参照のこと)
 * 
 * @param listid
 * @param targetid
 */
Choistudy.ListNav = function(listid, targetid) {
	this.targetid = targetid;
	this.listElems = new Array();
	this.links = {};
	this._append(listid);
	this.dlg = new Choistudy.Loading("infoArea");
};

Choistudy.ListNav.callListeners = function(elem, sType) {
	var YUIE = YAHOO.util.Event;
	var listeners = YUIE.getListeners(elem, sType);
	for ( var i = 0; i < listeners.length; i++) {
		var listener = listeners[i];
		if (listener.fn && listener.fn.call) {
			listener.fn.apply(listener.scope, []);
		}
	}
};

Choistudy.ListNav.prototype = {
	_append : function(listid) {
		var YUID = YAHOO.util.Dom;
		var list = YUID.get(listid);
		if (list && list.nodeName) {
			this._appendList(list.getElementsByTagName("li"));
		}
	},
	_appendList : function(nodeList) {
		var YUIL = YAHOO.lang;
		if (nodeList && YUIL.isNumber(nodeList.length)) {
			var length = nodeList.length;
			for ( var i = 0; i < length; i++) {
				this.listElems.push(nodeList[i]);
			}
		}
	},
	_isAnchor : function(node) {
		return Choistudy.Util.isNode(node, 'a');
	},
	_linkClick : function(url) {
		var YUID = YAHOO.util.Dom, elem = YUID.get(this.targetid), self = this;
		if (elem) {
			// Ajax
			self.dlg.start();
			Choistudy.asyncRequest('GET', url, {
				success : function(o) {
					self.dlg.stop();
					elem.innerHTML = o.responseText;
				},
				failure : function(o) {
					self.dlg.stop();
					alert('接続に失敗しました :[' + o.status + '] errorText:['
							+ o.statusText + ']');
				}
			}, null);
		}
	},
	setup : function() {
		var YUID = YAHOO.util.Dom, YUIE = YAHOO.util.Event, clickClass = "listnav-clicked", overClass = "listnav-over", self = this;

		YUID.batch(this.listElems, function(item) {
			var anchor = YUID.getFirstChild(item, self._isAnchor);
			if (anchor) {
				self.links[YUID.generateId(item)] = anchor.href;
				anchor.href = "javascript:void(0);";
			}
		});
		YUIE.addListener(this.listElems, "click", function() {
			// 他が選択されている場合それをまず外す
				YUID.removeClass(self.listElems, clickClass);
				YUID.removeClass(this, overClass);
				YUID.addClass(this, clickClass);
				self._linkClick(self.links[this.id]);
			});
		YUIE.addListener(this.listElems, 'mouseover', function() {
			if (!YUID.hasClass(this, clickClass)) {
				YUID.addClass(this, overClass);
			}
		});
		YUIE.addListener(this.listElems, 'mouseout', function() {
			if (!YUID.hasClass(this, clickClass)) {
				YUID.removeClass(this, overClass);
			}
		});
	}
};