var PathUtility = {};
PathUtility.inheritPath = "/";
PathUtility.httpPath = "http://www.sigonsoft.com/";
PathUtility.httpsPath = "https://www.sigonsoft.com/";
﻿var delegate = function(callee, method) {
	return function() {
		return method.apply(callee, arguments);
	};
};
var eventHandler = function(method) {
	return function(event_arg) {
		var _event_arg = null;
		if (typeof (event) != "undefined") {
			_event_arg = event;
		}
		else {
			_event_arg = event_arg;
			_event_arg.x = event_arg.clientX;
			_event_arg.y = event_arg.clientY;
		}
		return method(_event_arg);
	}
};
var Property = function(initValue) {
	var value = initValue;
	this.setValue = function(v) {
		var oldValue = value;
		value = v;
		this.onValueChanged(value,oldValue);
	};
	this.getValue = function() {
		return value;
	};
	this.onValueChanged = function(newValue,oldValue) { };
};
RegExp.escape = function(text) {
	return text.replace(/(\-|\*|\+|\?|\^|\$|\(|\)|\{|\}|\[|\]|\\|\|)/g, "\\$1");
}
String.empty = "";
String.prototype.replaceAll = function(replaceString) {
	return this.replace(new RegExp(RegExp.escape(text), "g"), replaceString);
};
String.prototype.startWith = function(prefix) {
	return (this.match("^" + RegExp.escape(prefix)) == prefix);
};
String.prototype.endWith = function(suffix) {
	return (this.match(suffix.escape(suffix) + "$") == suffix);
};
String.prototype.trimLeft = function() {
	return this.replace(/^[ \n\r\t　]+/, String.empty);
};
String.prototype.trimRight = function() {
	return this.replace(/[ \n\r\t　]+$/, String.empty)
};
String.prototype.trim = function() {
	return this.trimLeft().trimRight();
};
String.prototype.contains = function(substr) {
	return this.indexOf(substr) != -1;
};
// 現在の文字列を指定回数繰り返してつなげた文字列を返します。
String.prototype.repeat = function(count) {
	var array = new Array();
	for (var c = 0; c < count; c++)
		array.push(this);
	return array.join(String.empty);
};
Array.prototype.insert = function(index, value) {
	this.splice(index, 0, value);
}
Array.prototype.removeAt = function(index) {
	if (index < this.length)
		this.splice(index, 1);
}
Array.prototype.add = function(value) {
	this.push(value);
}
Array.prototype.indexOf = function(value) {
	for (var c = 0; c < this.length; c++)
		if (this[c] == value) return c;
	return -1;
}
Array.prototype.contains = function(value) {
	return this.indexOf(value) != -1;
}
Array.prototype.remove = function(value) {
	var index = this.indexOf(value);
	if (index == -1) return;
	this.removeAt(index);
}
Array.prototype.dequeue = function() {
	if (this.length <= 0) return null;
	var deq = this[0];
	this.splice(0, 1);
	return deq;
}
Array.prototype.enqueue = function(value) {
	this.unshift(value);
}
Array.prototype.last = function() {
	if (this.length == 0) return null;
	return this[this.length - 1];
};
Array.prototype.first = function() {
	if (this.length == 0) return null;
	return this[0];
};
Array.prototype.clear = function() {
	this.length = 0;
};
Array.prototype.clone = function() {
	return this.slice(0);
};
// 通貨形式の文字列に変換します。1234.56 -> 1,234.56
// fractionLengthには小数点部分の長さを指定します。0以下を指定すると整数部だけを文字列にします。
Number.prototype.toCurrencyString = function(fractionLength) {
	if (fractionLength == null) fractionLength = 0;

	var splitedString = this.toString(10).split(".");
	var intergerRegion = splitedString[0];
	var fractionRegion = splitedString.length > 1 ? splitedString[1] : String.empty;

	var blockes = new Array();
	var c = intergerRegion.length;
	while (c > 0) {
		if (c >= 3)
			blockes.push(intergerRegion.substr(c - 3, 3));
		else
			blockes.push(intergerRegion.substr(0, c));
		c -= 3;
	};
	intergerRegion = blockes.reverse().join(",");
	if (fractionLength <= 0)
		return intergerRegion;

	var builder = new StringBuilder();
	builder.append(intergerRegion).append(".");
	var insufficiency = fractionLength - fractionRegion.length;
	if (insufficiency >= 0)
		builder.append(fractionRegion).append("0".repeat(insufficiency));
	else
		builder.append(fractionRegion.substring(0, fractionLength));
	return builder.toString();
};
// プロトコルの変換は ~/ または / から始まるパスのみに対応します。
PathUtility.toAbsolute = function(virtualPath, protocol) {
	var suffix;
	if (virtualPath.startWith("~/"))
		suffix = virtualPath.substr(2, virtualPath.length - 2);
	else if (virtualPath.startWith(PathUtility.httpsPath))
		suffix = virtualPath.substr(PathUtility.httpsPath.length, virtualPath.length - PathUtility.httpsPath.length);
	else if (virtualPath.startWith(PathUtility.httpPath))
		suffix = virtualPath.substr(PathUtility.httpPath.length, virtualPath.length - PathUtility.httpPath.length);
	else if (virtualPath.startWith(PathUtility.inheritPath))
		suffix = virtualPath.substr(PathUtility.inheritPath.length, virtualPath.length - PathUtility.inheritPath.length);
	else if(virtualPath.startWith("/"))
		suffix = virtualPath.substr(1, virtualPath.length - 1);
	else
		return virtualPath;
	switch (protocol) {
		case "https":
			return PathUtility.httpsPath + suffix;
		case "http":
			return PathUtility.httpPath + suffix;
		default:
			return PathUtility.inheritPath + suffix;
	}
}; //PathUtility.toAbsolute
// 指定したタグ名が見つかるまで上(親)方向にトレースします。
document.traceUpByTagName = function(startNode, tagName) {
	var node = startNode;
	tagName = tagName.toLowerCase();
	while (node = node.parentNode) // '=' is correct
	{
		if (node === document.body || node === document)
			return null;
		if (node.nodeName.toLowerCase() === tagName) {
			return node;
		}
	}
};
// すべてのリンクをフックします
document.hookLinks = function(alertMessage, event) {
	for (var c = 0; c < document.links.length; c++) {
		document.links.item(c)._0adee498553b44f39cc7b24b212489f6 = document.links.item(c).onclick;
		document.links.item(c).onclick = function() {
			if (document.links.item(c)._0adee498553b44f39cc7b24b212489f6 != null)
				return event() & document.links.item(c)._0adee498553b44f39cc7b24b212489f6();
			else return event();
		};
	}
};
// すべてのリンクをアンフックします。
document.unhookLinks = function(alertMessage, event) {
	for (var c = 0; c < document.links.length; c++) {
			document.links.item(c).onclick = document.links.item(c)._0adee498553b44f39cc7b24b212489f6;
	}
};
// リンクをすべて無効化します
document.killLinks = function(childNodes) {
	for (var c = 0; c < childNodes.length; c++) {
		switch (childNodes[c].nodeType) {
			case 1:
				switch (childNodes[c].nodeName.toLowerCase()) {
					case "a": childNodes[c].setAttribute("href", "javascript:function(){return false;}"); break;
				};
				document.killLinks(childNodes[c].childNodes);
				break;
		}
	}
};
// エレメントスタイル
document.showElement = function(element) {
	element.style.display = "block";
	element.style.visibility = "visible";
};
document.hideElement = function(element) {
	element.style.display = "none";
	element.style.visibility = "hidden";
};
document.getElementOpacity = function(element, opacity) {
	if (element.style.opacity == null) return 1.0;
	return parseFloat(element.style.opacity);
};
document.setElementOpacity = function(element, opacity) {
	if (opacity == 1.0) {
		//operaのバグ？一旦、1.0にした後に、nullにしないと、不透明なままになる。
		element.style.opacity = 1.0;
		element.style.filter = null;
		element.style.MozOpacity = null;
		element.style.opacity = null;
	}
	else {
		element.style.filter = "alpha(opacity=" + Math.round(opacity * 100.0) + ")";
		element.style.MozOpacity = opacity;
		element.style.opacity = opacity;
	}
};
document.getElementBounds = function(element) { //IEでのみ動作を確認済み
	var rect = new Rectangle();
	rect.x = element.offsetLeft;
	rect.y = element.offsetTop;
	rect.width = element.clientWidth;
	rect.height = element.clientHeight;
	return rect;
};
var NameValueCollection = function() {
	var buffer = new Array();
	this.add = function(name, value) {
		var index = this.indexOf(name);
		if (index == -1)
			buffer.push({ name: name, value: value });
		else
			buffer[index].value = value;
	};
	this.setValue = function(name, value) {
		this.add(name, value);
	};
	this.getValue = function(name) {
		var index = this.indexOf(name);
		if (index == -1)
			return null;
		else
			return buffer[index].value;
	};
	this.contains = function(name) {
		return this.indexOf(name) != -1;
	};
	this.indexOf = function(name) {
		name = name.toLowerCase();
		for (var c = 0; c < buffer.length; c++)
			if (buffer[c].name == name)
			return c;
		return -1;
	};
	this.getCount = function(){
		return buffer.length;
	}
	this.toArray = function(){
		return buffer.clone();
	};
};
// StringBuilder
var StringBuilder = function() {
	var buffer = new Array();
	this.append = function(text) {
		buffer.push(text);
		return this;
	};
	this.clear = function() {
		buffer.splice(0, buffer.length);
		return this;
	};
	this.toString = function() {
		return buffer.join("");
	};
};
var FunctionCollection = function() {
	var functions = new Array();
	this.add = function(event) {
		if (typeof (event) != "function")
			throw new Error();
		functions.push(event);
	};
	this.call = function() {
		for (var c = 0; c < functions.length; c++) {
			functions[c]();
		}
	};
};

var Size = function(width, height) {
	this.width = width;
	this.height = height;
	this.toString = function() {
		return new StringBuilder().append("(").append(this.width).append(",")
			.append(this.height).append(")").toString();
	};
}
var Rectangle = function(x, y, width, height) {
	this.x = x;
	this.y = y;
	this.width = width;
	this.height = height;
	this.contains = function(rect) {
		return this.x <= rect.x && this.y <= rect.y
			&& (this.x + this.width) >= (rect.x + rect.width)
			&& (this.y + this.height) >= (rect.y + rect.height);
	};
	this.toString = function() {
		return new StringBuilder().append("(").append(this.x).append(",")
			.append(this.y).append(",").append(this.width)
			.append(",").append(this.height).append(")").toString();
	};
};

var Page = {};
new function() {
	var loaded = false;
	var events = new FunctionCollection();
	var _queryCache = null;
	Page.addLoadEvent = function(eventHandler) {
		events.add(eventHandler);
	};
	Page.onLoad = function() {
		events.call();
	};
	var uniqueNumber = 0;
	Page.getUniqueID = function() {
		return "__scriptgen" + uniqueNumber++;
	};
	Page.getQuery = function() {
		if (_queryCache != null) return _queryCache;
		_queryCache = new NameValueCollection();
		var queryText = location.href.split("?");
		if (queryText.length <= 1) return _queryCache;
		var queryParts = queryText[1].split("&");
		for (var c = 0; c < queryParts.length; c++) {
			var operatorIndex = queryParts[c].indexOf("=");
			if (operatorIndex == -1) {
				_queryCache.add(queryParts[c], String.empty);
			}
			else {
				var name = queryParts[c].substr(0, operatorIndex);
				var value = queryParts[c].substr(operatorIndex + 1, queryParts[c].length - (operatorIndex + 1));
				_queryCache.add(decodeURI(name), decodeURI(value));
			}
		}
		return _queryCache;
	};
	//ページの最大幅・高さを取得します。
	Page.getSize = function() {
		var size = new Size();
		size.width = document.documentElement.scrollWidth || document.body.scrollWidth;
		size.height = document.documentElement.scrollHeight || document.body.scrollHeight;
		return size;
	};
	//アクティブな領域(id="activeRegion"で示される領域)を取得します。
	Page.getActiveBounds = function() {
		var activeRegionElement = document.getElementById("activeRegion");
		if (activeRegionElement != null)
			return document.getElementBounds(activeRegionElement);
		else
			return null;
	};
	//クライアント領域を取得します。
	Page.getClientBounds = function() {
		var rect = new Rectangle();
		rect.x = document.documentElement.scrollLeft || document.body.scrollLeft;
		rect.y = document.documentElement.scrollTop || document.body.scrollTop;
		if (window.innerWidth)
			rect.width = window.innerWidth;
		else if (document.documentElement && document.documentElement.clientWidth)
			rect.width = document.documentElement.clientWidth;
		else if (document.body && document.body.clientWidth)
			rect.width = document.body.clientWidth;
		else rect.width = -1;
		if (window.innerHeight)
			rect.height = window.innerHeight;
		else if (document.documentElement && document.documentElement.clientHeight)
			rect.height = document.documentElement.clientHeight;
		else if (document.body && document.body.clientHeight)
			rect.height = document.body.clientHeight;
		else rect.height = -1;
		return rect;
	};
};

var Browser = {};
Browser.parse = function(userAgent) {
	if (Browser._current != null) return Browser._current;
	var browser = {};
	var browserList = new Array();
	browserList.add("(MSIE)[ ]([0-9]+)\.([0-9]+)");
	browserList.add("(Firefox)/([0-9]+)\.([0-9]+)");
	browserList.add("(Chrome)/([0-9]+)\.([0-9]+)");
	browserList.add("(Opera)[/ ]([0-9]+)\.([0-9]+)");
	browserList.add("(Safari)/([0-9]+)\.([0-9]+)");
	var regex = new RegExp("(?:" + browserList.join(")|(?:") + ")");
	var matched = userAgent.match(regex);
	browser.name = String.empty;
	browser.version = { major: 0, minor: 0 };
	if (!(matched.length > browserList.length * 3))
		return browser;
	for (var c = 1; c < matched.length; c += 3) {
		if (typeof (matched[c]) == "undefined") continue;
		browser.name = matched[c];
		browser.version.major = parseInt(matched[c + 1], 10);
		browser.version.minor = parseInt(matched[c + 2], 10);
		break;
	}
	return browser;
};
Browser.current = Browser.parse(navigator.userAgent);

var TimeSpan = function() {
	var totalMilliseconds;
	if (arguments.length == 2)
		totalMilliseconds = arguments[0].getTime() - arguments[1].getTime();
	else if (arguments.length == 1)
		totalMilliseconds = arguments[0];
	else
		totalMilliseconds = 0;
	this.abs = function() {
		return Math.abs(totalMilliseconds);
	};
	this.getTotalMilliseconds = function() {
		return totalMilliseconds;
	};
	this.getTotalSeconds = function() {
		return totalMilliseconds / TimeSpan.msPerSeconds;
	};
	this.getTotalMinutes = function() {
		return totalMilliseconds / TimeSpan.msPerMinutes;
	};
	this.getTotalHours = function() {
		return totalMilliseconds / TimeSpan.msPerHours;
	};
	this.getTotalDays = function() {
		return totalMilliseconds / TimeSpan.msPerDays;
	};
	this.getTotalMonths = function() {
		return totalMilliseconds / TimeSpan.msPerMonths;
	};
	this.getTotalYears = function() {
		return totalMilliseconds / TimeSpan.msPerYears;
	};
	this.toString = function() {
		return this.toShortString();
	};
	this.toShortString = function(international) {
		if (totalMilliseconds < TimeSpan.msPerDays)
			return Math.ceil(this.getTotalHours()).toString() + (!international ? "時間" : " hours");
		else if (totalMilliseconds < TimeSpan.msPerMonths)
			return Math.ceil(this.getTotalDays()).toString() + (!international ? "日" : " days");
		else if (totalMilliseconds < TimeSpan.msPerYears)
			return Math.ceil(this.getTotalMonths()).toString() + (!international ? "ヵ月" : " months");
		else return Math.ceil(this.getTotalYears()).toString() + (!international ? "年" : " years");
	};
	this.toLongString = function() {
		var longString = new StringBuilder();
		var found = false;
		var years = Math.floor(ms / TimeSpan.msPerYears);
		ms -= years * TimeSpan.msPerYears;
		if (found |= (years > 0)) longString.append(years).append("年");
		var days = Math.floor(ms / TimeSpan.msPerDays);
		ms -= days * TimeSpan.msPerDays;
		if (found |= (days > 0)) longString.append(years).append("日");
		var hours = Math.floor(ms / TimeSpan.msPerHours);
		ms -= hours * TimeSpan.msPerHours;
		if (found |= (hours > 0)) longString.append(years).append("時間");
		var minutes = Math.floor(ms / TimeSpan.msPerMinutes);
		ms -= minutes * TimeSpan.msPerMinutes;
		if (found |= (minutes > 0)) longString.append(years).append("分");
		var seconds = Math.round(ms / TimeSpan.msPerSeconds);
		longString.append(years).append("秒");
		return longString.toString();
	};
};
TimeSpan.msPerSeconds = 1000.0;
TimeSpan.msPerMinutes = TimeSpan.msPerSeconds * 60.0;
TimeSpan.msPerHours = TimeSpan.msPerMinutes * 60.0;
TimeSpan.msPerDays = TimeSpan.msPerHours * 24.0;
TimeSpan.msPerMonths = TimeSpan.msPerDays * (365.0 / 12.0);
TimeSpan.msPerYears = TimeSpan.msPerMonths * 365.0;
TimeSpan.fromMilliseconds = function(milliseconds) {
	return new TimeSpan(milliseconds);
};
TimeSpan.fromSeconds = function(seconds) {
	return new TimeSpan(seconds * TimeSpan.msPerSeconds);
};
TimeSpan.fromMinutes = function(minutes) {
	return new TimeSpan(minutes * TimeSpan.msPerMinutes);
};
TimeSpan.fromHours = function(hours) {
	return new TimeSpan(hours * TimeSpan.msPerHours);
};
TimeSpan.fromDays = function(days) {
	return new TimeSpan(days * TimeSpan.msPerDays);
};
TimeSpan.fromYears = function(years) {
	return new TimeSpan(years * TimeSpan.msPerYears);
};

// タイマーを表現します
var Timer = function() {
	this.interval = 1000;
	this.onTick = null;
	this.autoRestart = true;

	var timerID = null;
	var active = false;
	var active_autoRestart;
	var startTime = null;
	this.getStartTime = function() {
		return startTime;
	}
	this.start = function() {
		if (active) this.suspend();
		active = true;
		active_autoRestart = this.autoRestart;
		startTime = new Date();
		if (active_autoRestart)
			timerID = setInterval(this.onTick, this.interval);
		else
			timerID = setTimeout(delegate(this, function() { this.onTick(); this.suspend(); }), this.interval);
	};
	this.suspend = function() {
		if (active && timerID != null) {
			if (timerID != null) {
				if (active_autoRestart) clearInterval(timerID)
				else clearTimeout(timerID);
			}
			active = false;
			timerID = null;
		}
	};
};

var Ajax = function() {
	// 成功した場合に呼び出されます
	this.onSuccess = null;
	// タイムアウトまたはエラーの場合に呼び出されます
	this.onFailure = null;
	this.query = new NameValueCollection();
	// onSuccessまたはonFailureが呼び出されるまでの遅滞をミリ秒単位で指定します。
	// 通信時間が、この遅滞時間よりも短かった場合でも、最低限この遅滞時間だけは保障されます。
	this.delay = 0;
	// タイムアウトまでの時間をミリ秒単位で指定します。規定値は20,000ミリ秒(20秒)です。
	this.timeout = TimeSpan.fromSeconds(20).getTotalMilliseconds();

	this.errorCode = 0;

	this.getRequiredDelay = function() {
		var left = this.delay - new TimeSpan(new Date(), timeoutTimer.getStartTime()).getTotalMilliseconds();
		if (left <= 0) return 0;
		else return left;
	};
	this.serizlizeQuery = function(method) {
		var nameValues = this.query.toArray();
		var serizlized = new StringBuilder();
		for (var c = 0; c < nameValues.length; c++) {
			if (c == 0 && method == "get") serizlized.append("?");
			else if (c > 0) serizlized.append("&");
			serizlized.append(escape(nameValues[c].name))
					.append("=").append(escape(nameValues[c].value));
		}
		return serizlized.toString();
	};
	var xmlRequest = null;

	var timeoutTimer = new Timer();
	timeoutTimer.onTick = delegate(this, function() {
		this.errorCode = "CONNECTION TIMEOUT";
		xmlRequest.abort();
		if (typeof (this.onFailure) == "function")
			setTimeout(this.onFailure, this.getRequiredDelay());
	});
	timeoutTimer.autoRestart = false;

	if (window.ActiveXObject) {
		try {
			xmlRequest = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e1) {
			try {
				xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e2) {
				xmlRequest = null;
			}
		}
	}
	else if (window.XMLHttpRequest) {
		xmlRequest = new XMLHttpRequest();
	}
	else {
		xmlRequest = null;
	}
	var timeoutTimerID = null;
	if (xmlRequest == null) throw new Error();
	xmlRequest.onreadystatechange = delegate(this, function() {
		if (xmlRequest.readyState == 4) {
			timeoutTimer.suspend();
			if (xmlRequest.status == 200) {
				if (typeof (this.onSuccess) == "function")
					setTimeout(this.onSuccess, this.getRequiredDelay());
			}
			else {
				this.errorCode = "HTTP " + xmlRequest.status;
				if (typeof (this.onFailure) == "function")
					setTimeout(this.onFailure, this.getRequiredDelay());
			}
		}
	});

	var sendCount = 0;
	this.send = function(method, url) {
		method = method.toLowerCase();
		timeoutTimer.interval = this.timeout;
		timeoutTimer.start();
		switch (method) {
			case "post":
				xmlRequest.open(method, PathUtility.toAbsolute(url), true);
				xmlRequest.setRequestHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
				xmlRequest.send(this.serizlizeQuery("post"));
				break;
			case "head": //fall through
			case "get":
				xmlRequest.open(method, PathUtility.toAbsolute(url) + this.serizlizeQuery("get"), true);
				xmlRequest.send(null);
				break;
			default:
				throw new Error();
		}
		sendCount++;
	};
	this.getResponseText = function() {
		return xmlRequest.responseText;
	}
	this.getResponseXML = function() {
		return xmlRequest.responseXML;
	}
};
//色を表現します。
var Color = function(red, green, blue) {
	this.red = (red == null ? 0 : red);
	this.green = (green == null ? 0 : green);
	this.blue = (blue == null ? 0 : blue);
	var makeHex = function(value) {
		var hex = (Math.abs(Math.round(value)) % 256).toString(16);
		if (hex.length == 2) return hex;
		else return "0" + hex;
	};
	this.toHtml = function() {
		return new StringBuilder()
					.append("#")
					.append(makeHex(this.red))
					.append(makeHex(this.green))
					.append(makeHex(this.blue))
					.toString();
	};
};
//一定期間の間、時間軸に沿って滑らかに変遷する値を表現します。
var TransitionValue = function(minValue, maxValue, startTime, duration) {
	this.minValue = minValue;
	this.maxValue = maxValue;
	this.startTime = startTime;
	this.duration = duration;
	// 現在の値を0.0 ~ 1.0で返します。0.0のとき最少値、1.0のとき最大値を示します。
	this.getCurrentRatio = function() {
		var elapsed = new TimeSpan(new Date(), this.startTime);
		var ratio = elapsed.getTotalMilliseconds() / this.duration.getTotalMilliseconds();
		if (ratio <= 0.0) return 0.0;
		else if (ratio >= 1.0) return 1.0;
		else return (Math.cos((ratio + 1) * Math.PI) / 2 + 0.5);
	};
	// 現在の値をminValue~maxValueの間で返します。値は浮動小数点数の場合があります。
	this.getCurrentValue = function() {
		return this.minValue + this.getCurrentRatio() * (this.maxValue - this.minValue);
	};
	// 変遷の開始位置を現在の時刻に設定します。
	this.restart = function() {
		this.startTime = new Date();
	};
};
// 一定周期で最小値と最大値との間で無限にループする値を表現します。
var LoopValue = function() {
	this.maxValue = 1.0;
	this.minValue = 0.0;
	this.startTime = new Date();
	this.cycleTimeSpan = TimeSpan.fromSeconds(200);
	//現在の値を0.0~1.0の間で返します。
	this.getCurrentRatio = function() {
		var elapsedMilliseconds = new TimeSpan(new Date(), this.startTime).getTotalMilliseconds();
		var cycleMilliseconds = this.cycleTimeSpan.getTotalMilliseconds();
		// xは0.0以上1.0未満の値で1周囲内の位置を表す。 x=(経過時間%周期時間)/周期時間
		var x = (elapsedMilliseconds % cycleMilliseconds) / cycleMilliseconds;
		// xが0.0 ~ 1.0の間でyが0.0～1.0の間を一周する三角関数
		return (Math.cos(Math.PI * (2.0 * x + 1.0)) / 2.0 + 0.5);
	};
	//現在の値をminValue以上maxValue以下の値で返します。値は浮動小数点数になる場合があります。
	this.getCurrentValue = function() {
		return this.getCurrentRatio() * (this.maxValue - this.minValue) + this.minValue;
	};
	// 周期の開始位置を現在の時刻に設定します。
	this.restart = function() {
		return this.startTime = new Date();
	};
};
// テキストフィールド(inputまたはtextareaエレメント)の動作を拡張します
var TextFieldEnhancer = function(elementToEnhance) {
	var english = Page.getQuery().getValue("lang") == "en";
	var ownerForm = null;
	var watermarkActived = true;
	var enhanced = false;
	this.elementToEnhance = elementToEnhance;
	this.elementToMessage = null;
	this.isRequired = false;
	this.maxLength = 0;
	this.enableTrimming = true;
	this.watermarkText = "入力してください";
	this.watermarkColor = new Color(170, 158, 158);
	this.trim = function() {
		if (this.enableTrimming)
			this.elementToEnhance.value = this.elementToEnhance.value.trim();
	};
	this.validate = function() {
		this.trim();
		var value = (watermarkActived ? String.empty : this.elementToEnhance.value);
		if (this.isRequired && value.length == 0) {
			this.onValidateError(english ? "Required" : "この項目はご入力が必要です");
			return false;
		}
		if (this.maxLength < value.length) {
			var overLength = (value.length - this.maxLength).toCurrencyString();
			this.onValidateError(english ? "too long, please cut " + overLength + " chars short." :
				 "文字が多すぎます。あと" + overLength + "文字減らしてください");
			return false;
		}
		return true;
	};
	this.enhance = function() {
		if (enhanced) {
			this.elementToEnhance.onfocus.call(this);
			this.elementToEnhance.onblur.call(this);
			return;
		}
		enhanced = true;
		this.elementToEnhance.enhancer = this;
		this.elementToEnhance.value = String.empty;
		this.elementToEnhance.onfocus = delegate(this, this.onEnter);
		this.elementToEnhance.onblur = delegate(this, this.onLeave);
		this.elementToEnhance.getValue = delegate(this, this.getValue);
		this.elementToEnhance.setValue = delegate(this, this.setValue);
		try {
			// DOMから作成した場合はこのブロックは失敗し、catchで相応の処理を行う
			// DOMから作成しなかった場合は、更新ボタンを押した場合、ブラウザの動作によっては、
			// フォーカスが維持されたままになる場合があるため、このブロックは必ず必要。
			this.elementToEnhance.focus();
			this.elementToEnhance.blur();
		}
		catch (e) {
			this.elementToEnhance.onfocus.call(this);
			this.elementToEnhance.onblur.call(this);
		}
		var ownerForm = document.traceUpByTagName(this.elementToEnhance, "form");
		if (ownerForm.validate == null) {
			ownerForm.validate = function() {
				var success = true;
				for (var c = 0; c < ownerForm.elementsToValidate.length; c++) {
					if (!ownerForm.elementsToValidate[c].enhancer.validate())
						success = false;
				}
				return success;
			};
			ownerForm.onsubmit = ownerForm.validate;
			ownerForm.elementsToValidate = new Array();
		}
		ownerForm.elementsToValidate.push(this.elementToEnhance);
		if (TextFieldEnhancer.enhancedElements == null)
			TextFieldEnhancer.enhancedElements = new Array();
		TextFieldEnhancer.enhancedElements.push(this.elementToEnhance);
		if (TextFieldEnhancer.messageUpdator == null) {
			TextFieldEnhancer.messageUpdator = new Timer();
			TextFieldEnhancer.messageUpdator.interval = 500;
			TextFieldEnhancer.messageUpdator.onTick = function() {
				for (var c = 0; c < TextFieldEnhancer.enhancedElements.length; c++)
					TextFieldEnhancer.enhancedElements[c].enhancer.updateMessage();
			};
			TextFieldEnhancer.messageUpdator.start();
		}
	};
	var validateErrorMessage = String.empty;
	var validateRedSplashed = false;
	var focused = false;
	this.onValidateError = function(errorMessage) {
		this.elementToEnhance.blur();
		validateErrorMessage = errorMessage;
		validateRedSplashed = false;
	};
	this.onEnter = function() {
		focused = true;
		validateErrorMessage = String.empty;
		if (watermarkActived) {
			this.elementToEnhance.value = "";
			watermarkActived = false;
		}
		this.updateWatermark();
	};
	this.onLeave = function() {
		focused = false;
		this.trim();
		watermarkActived = (this.elementToEnhance.value.length <= 0);
		this.updateWatermark();
	};
	this.getValue = function() {
		return (watermarkActived ? String.empty : this.elementToEnhance.value);
	};
	this.setValue = function(text) {
		if (focused) {
			this.elementToEnhance.value = text;
		}
		else {
			this.elementToEnhance.value = text;
			this.onLeave();
		}
	};
	this.updateMessage = function() {

		if (this.elementToMessage == null) return;
		if (validateErrorMessage != String.empty) {
			validateRedSplashed = !validateRedSplashed;
			this.elementToMessage.innerHTML = (validateRedSplashed ? "<span style='color:#FF0000'>" : "<span style='color:#FFAAAA'>") + validateErrorMessage + "</span>";
		}
		else {
			var redalert;
			var difference = this.maxLength - (watermarkActived ? 0 : this.elementToEnhance.value.length);
			if (difference < 0) {
				var overLength = Math.abs(difference).toCurrencyString();
				message = english ? "Too long, please cut " + overLength + " chars short." :
				 "文字が多すぎます。あと" + overLength + "文字減らしてください"
				redalert = true;
			}
			else if (difference == 0) {
				message = english ? "Capacity max reached" : "これ以上入力することはできません";
				redalert = true;
			}
			else {
				var availableLength = difference.toCurrencyString();
				message = english ? "Enterable " + availableLength + " chars" : "あと" + availableLength + "文字入力できます";
				redalert = false;
			}
			this.elementToMessage.innerHTML = redalert ? "<span style='color:red'>" + message + "</span>" : message;
		}
	};
	this.updateWatermark = function() {
		if (this.elementToEnhance._2294932fa57a4055a06771b52347ab1f == null) {
			this.elementToEnhance._2294932fa57a4055a06771b52347ab1f = this.elementToEnhance.style.fontWeight;
			this.elementToEnhance._22a640be733d442d85e6e7de8a5a4861 = this.elementToEnhance.style.color;
		}
		if (watermarkActived) {
			this.elementToEnhance.style.fontWeight = "bold";
			this.elementToEnhance.style.color = this.watermarkColor.toHtml();
			this.elementToEnhance.value = this.watermarkText;
		}
		else {
			this.elementToEnhance.style.fontWeight = this.elementToEnhance._2294932fa57a4055a06771b52347ab1f;
			this.elementToEnhance.style.color = this.elementToEnhance._22a640be733d442d85e6e7de8a5a4861;
		}
	};
};
var ProgressBar = function(width, height, degree) {
	var paddingWidth = 1;
	var innerWidth = width - paddingWidth * 2;
	var innerHeight = height - paddingWidth * 2;
	degree = Math.abs(degree);
	if (degree > 1.0)
		degree = degree % 1.0;
	this.toHTML = function() {
		return new StringBuilder().append("<table cellspacing='").append(paddingWidth)
			.append("' style='background-color:dimgray;width:")
			.append((width).toString()).append("px;height:").append(height.toString()).append("px;'><tr><td>")
			.append("<table cellspacing='0' style='background-color:#BFBFBF;width:")
			.append(Math.ceil(degree * innerWidth).toString()).append("px;")
			.append("height:").append(innerHeight.toString())
			.append("px;'><tr><td></td></tr></td></tr></table>").toString();
	};
};
var Unit = function(value, type) {
	this.value = value;
	this.type = type;
	this.toString = function() {
		return this.value.toString() + this.type;
	};
};
Unit.pixel = function(value) {
	return new Unit(value, "px");
};
Unit.percentage = function(value) {
	return new Unit(value, "%");
};
Unit.parse = function(text) {
	var matched = text.match(new RegExp("(-?[0-9]+)\b*([a-z]+|[%])"), "i");
	if (matched.length < 1)
		return Unit.pixel(0);
	var unitValue = parseInt(matched[1], 10);
	var unitType = matched.length > 2 ? matched[2] : "px";
	return new Unit(unitValue, unitType);
};
var HtmlUtility = function() { }
HtmlUtility.createRawHTMLElement = function(rawHTML) {
	var spanElement = document.createElement("span");
	spanElement.innerHTML = rawHTML;
	return spanElement;
};
HtmlUtility.createBorderElement = function(width) {
	var tableElement = document.createElement("table");
	var tbodyElement = document.createElement("tbody");
	var trElement = document.createElement("tr");
	var tdElement = document.createElement("td");
	tableElement.appendChild(tbodyElement);
	tbodyElement.appendChild(trElement);
	trElement.appendChild(tdElement);
	tableElement.setAttribute("cellspacing", "0");
	tableElement.style.width = (width instanceof Unit) ? width.toString() : "100%";
	tableElement.style.height = "1px";
	tdElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/dotborder.gif") + ") repeat-x";
	return tableElement;
};
HtmlUtility.createImageElement = function(url, width, height, border) {
	var imageElement = document.createElement("img");
	imageElement.src = PathUtility.toAbsolute(url);
	if (border != null)
		mageElement.style.border = border + "px #BFBFBF";
	if (width != null)
		imageElement.style.width = width + "px";
	if (height != null)
		imageElement.style.height = height + "px"
	return imageElement;
};
HtmlUtility.createTextWithIconElement = function(iconUrl, text, textColor) {
	var tableElement = document.createElement("table");
	var tbodyElement = document.createElement("tbody");
	tableElement.appendChild(tbodyElement);
	var trElement = document.createElement("tr");
	var td1Element = document.createElement("td");
	var td2Element = document.createElement("td");
	tbodyElement.appendChild(trElement);
	trElement.appendChild(td1Element);
	trElement.appendChild(td2Element);
	tableElement.setAttribute("cellspacing", "2");
	td2Element.style.paddingLeft = "5px";
	var iconElement;
	var spanElement = document.createElement("span");
	spanElement.className = "sentence";
	spanElement.style.color = textColor;
	spanElement.innerHTML = text;
	if (iconUrl != null) {
		iconElement = HtmlUtility.createImageElement(iconUrl, 16, 16);
		td1Element.appendChild(iconElement);
	}
	else {
		td1Element.innerHTML = "<table cellspacing=\"0\" style=\"width:16px;height:16px;\"><tr><td></td></tr></table>";
	}
	td2Element.appendChild(spanElement);
	return tableElement;
};
HtmlUtility.createTitledElement = function(titleElement, contentElement, width) {
	if (titleElement == null)
		titleElement = document.createElement("span");
	if (contentElement == null)
		contentElement = document.createElement("span");
	if (width == null)
		width = Unit.percentage(100);
	// Outer
	var tableOuterElement = document.createElement("table");
	var tbodyOuterElement = document.createElement("tbody");
	var trOuterElement = document.createElement("tr");
	var tdOuterElement = document.createElement("td");
	tableOuterElement.setAttribute("cellspacing", "0");
	tableOuterElement.style.marginBottom = "5px";
	tableOuterElement.style.width = "100%";
	tableOuterElement.appendChild(tbodyOuterElement);
	tbodyOuterElement.appendChild(trOuterElement);
	trOuterElement.appendChild(tdOuterElement);
	// Inner
	var tableInnerElement = document.createElement("table");
	var tbodyInnerElement = document.createElement("tbody");
	var trInnerElement = document.createElement("tr");
	var tdLeftInnerElement = document.createElement("td");
	var tdCenterInnerElement = document.createElement("td");
	var tdRightInnerElement = document.createElement("td");
	tableInnerElement.setAttribute("cellspacing", "0");
	tableInnerElement.style.width = "100%";
	tableInnerElement.appendChild(tbodyInnerElement);
	tbodyInnerElement.appendChild(trInnerElement);
	trInnerElement.appendChild(tdLeftInnerElement);
	trInnerElement.appendChild(tdCenterInnerElement);
	trInnerElement.appendChild(tdRightInnerElement);
	tdLeftInnerElement.style.width = "23px";
	tdLeftInnerElement.style.height = "38px";
	tdLeftInnerElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/fixedSingle_topLeft.gif") + ") no-repeat";
	tdCenterInnerElement.style.width = "auto";
	tdCenterInnerElement.style.height = "38px";
	tdCenterInnerElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/fixedSingle_topRepeat.gif") + ") repeat-x";
	tdRightInnerElement.style.width = "23px";
	tdRightInnerElement.style.height = "38px";
	tdRightInnerElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/fixedSingle_topRight.gif") + ") no-repeat";
	// Entity
	var tableEntityElement = document.createElement("table");
	var tbodyEntityElement = document.createElement("tbody");
	var trEntityTopElement = document.createElement("tr");
	var tdEntityTopElement = document.createElement("td");
	var trEntityBottomElement = document.createElement("tr");
	var tdEntityBottomElement = document.createElement("td");
	tableEntityElement.appendChild(tbodyEntityElement);
	tbodyEntityElement.appendChild(trEntityTopElement);
	tbodyEntityElement.appendChild(trEntityBottomElement);
	trEntityTopElement.appendChild(tdEntityTopElement);
	trEntityBottomElement.appendChild(tdEntityBottomElement);
	tableEntityElement.setAttribute("cellspacing", "0");
	tableEntityElement.style.width = "100%";
	tdEntityTopElement.style.height = "33px";
	tdEntityTopElement.style.verticalAlign = "middle";
	tdEntityBottomElement.style.height = "6px";
	// Outer <- Inner
	tdOuterElement.appendChild(tableInnerElement);
	// Inner <- Entity
	tdCenterInnerElement.appendChild(tableEntityElement);
	// Entity <- Title
	tdEntityTopElement.appendChild(titleElement);

	// Total Top Bottom
	var tableElement = document.createElement("table");
	var tbodyElement = document.createElement("tbody");
	var trTopElement = document.createElement("tr");
	var tdTopElement = document.createElement("td");
	var trBottomElement = document.createElement("tr");
	var tdBottomElement = document.createElement("td");

	tableElement.setAttribute("cellspacing", "0");
	tableElement.style.width = width.toString();

	tableElement.appendChild(tbodyElement);
	tbodyElement.appendChild(trTopElement);
	tbodyElement.appendChild(trBottomElement);
	trTopElement.appendChild(tdTopElement);
	trBottomElement.appendChild(tdBottomElement);

	// Top <- Outer
	tdTopElement.appendChild(tableOuterElement);

	tdBottomElement.style.paddingLeft = "5px";
	tdBottomElement.style.paddingRight = "5px";

	var divElement = document.createElement("div");
	divElement.style.border = "1px solid #BFBFBF";
	divElement.appendChild(contentElement);
	tdBottomElement.appendChild(divElement);
	
	tableElement.titleElement = titleElement;
	tableElement.contentElement = contentElement;
	return tableElement;
};

HtmlUtility.createTextWithRadioButton = function(radioName, text) {
	var tableElement = document.createElement("table");
	var tbodyElement = document.createElement("tbody");
	var trElement = document.createElement("tr");
	var td1Element = document.createElement("td");
	var td2Element = document.createElement("td");
	tableElement.appendChild(tbodyElement);
	tbodyElement.appendChild(trElement);
	trElement.appendChild(td1Element);
	trElement.appendChild(td2Element);
	var radioBox = document.createElement("input");
	radioBox.name = radioName;
	radioBox.setAttribute("type", "radio");
	var textNode = document.createElement("span");
	textNode.style.cursor = "pointer";
	textNode.onclick = function() {
		radioBox.focus();
		radioBox.checked = !radioBox.checked;
	};
	textNode.innerHTML = text;
	tableElement.radioBox = radioBox;
	tableElement.textNode = textNode;
	td1Element.appendChild(radioBox);
	td2Element.appendChild(textNode);
	return tableElement;
}

HtmlUtility.createTextWithCheckBox = function(checkBoxId, text) {
	var tableElement = document.createElement("table");
	var tbodyElement = document.createElement("tbody");
	var trElement = document.createElement("tr");
	var td1Element = document.createElement("td");
	var td2Element = document.createElement("td");
	tableElement.appendChild(tbodyElement);
	tbodyElement.appendChild(trElement);
	trElement.appendChild(td1Element);
	trElement.appendChild(td2Element);
	var checkBox = document.createElement("input");
	checkBox.id = checkBox.name = checkBoxId;
	checkBox.setAttribute("type", "checkbox");
	checkBox.value = "true";
	var textNode = document.createElement("span");
	textNode.style.cursor = "pointer";
	textNode.onclick = function() {
		checkBox.focus();
		checkBox.checked = !checkBox.checked;
	};
	textNode.innerHTML = text;
	tableElement.checkBox = checkBox;
	tableElement.textNode = textNode;
	td1Element.appendChild(checkBox);
	td2Element.appendChild(textNode);
	return tableElement;
};


var X33Encoder = function() { }
X33Encoder.splitter = "x";
X33Encoder.keyDigit = 33;
X33Encoder.encode = function(plainText) {
	var charCodes = new Array();
	for (var c = 0; c < plainText.length; c++)
		charCodes.push(plainText.charCodeAt(c));
	var encodeText = new StringBuilder();
	for (var c = 0; c < charCodes.length; c++)
		encodeText.append(charCodes[c].toString(X33Encoder.keyDigit))
				.append(X33Encoder.splitter);
	return encodeText.toString();
};
X33Encoder.decode = function(encodeText) {
	var plainText = new StringBuilder();
	var array = encodeText.split(X33Encoder.splitter);
	for (var c = 0; c < array.length; c++)
		plainText.append(String.fromCharCode(parseInt(array[c], X33Encoder.keyDigit)));
	return plainText.toString();
};

// SplashActivatorは、Ajaxでデーターをロードし、次々と表示が変わるスプラッシュ広告の動作を提供します。
// 派生し必ずparseNodeToHTMLをオーバーライドして使用してください。
var SplashActivatorBase = function(xmlUrl, splashElement, nextButtonElement, backButtonElement, autoNextTimeSpan, useOpacity) {
	var opacity = new TransitionValue(0, 1, new Date(), TimeSpan.fromMilliseconds(100));
	var updateTimer;
	var opacityMaxReached = false;
	var opacityMaxReachedTime = new Date();
	var parsedElements = new Array();
	var index = new Property(0);
	// Ajaxでロードしたノードと共に呼び出されます。
	// オーバーライドしたメソッドでElementにパースして返してください。
	// CustomActionに受け渡す時には返すElementにuserDataなどとして登録します。
	this.parseNodeToElement = function(node) {
		return null;
	};
	// エフェクトをさらにカスタムしたい場合はオーバーライドしてください。
	// actionの値は次の通りです。
	//  0 : IndexChanged
	//  1 : OpacityChanged
	//  2 : OpacityMaxReached
	//  3 : Waiting
	this.onCustomEffect = function(status, element, opacity) {
		return;
	};
	this.activate = function() {
		var ajax = new Ajax();
		ajax.onSuccess = delegate(this, function() {
			splashElement.innerHTML = String.empty;
			var xml = ajax.getResponseXML();
			var nodes = xml.getElementsByTagName("item");
			for (var c = 0; c < nodes.length; c++) {
				var element = this.parseNodeToElement(nodes.item(c));
				if (element != null) {
					document.setElementOpacity(element, 0.0);
					document.hideElement(element);
					parsedElements.push(element);
					splashElement.appendChild(element);
				}
			} //for
			nextButtonElement.onclick = delegate(this, this.next);
			backButtonElement.onclick = delegate(this, this.back);
			updateTimer = new Timer();
			updateTimer.interval = 25;
			updateTimer.onTick = delegate(this, this.onTick); //updateTimer.onTick
			updateTimer.start();
			index.setValue(0);
			opacity.restart();
		});
		ajax.onFailure = delegate(this, function() { });
		ajax.send("get", PathUtility.toAbsolute(xmlUrl));
	};
	this.back = function() {
		var val = index.getValue() - 1;
		index.setValue(val < 0 ? parsedElements.length - 1 : val);
	};
	this.next = function() {
		var val = index.getValue() + 1;
		index.setValue(val >= parsedElements.length ? 0 : val);
	};
	this.onOpacityChanged = function(opacityValue) {
		if (useOpacity) {
			document.setElementOpacity(parsedElements[index.getValue()], opacityValue);
		}
		else {
			if (opacityValue == 0.0)
				document.setElementOpacity(parsedElements[index.getValue()], 0.0);
			else
				document.setElementOpacity(parsedElements[index.getValue()], 1.0);
		}
	};
	var elementModifies = null;
	index.onValueChanged = delegate(this, function(newValue, oldValue) {
		elementModifies = { newElement: parsedElements[newValue], oldElement: parsedElements[oldValue] };
	});
	this.onTick = function() {
		if (elementModifies != null) {
			// IEのバグ？(Firefox,Opera,Chromeでは動作
			// 同じエレメントについて、同時期にhideElementとshowElementの2つを適用するとshowElementのほうが実行されない様子。
			// 回避策：同じエレメント同士の場合は、hideを行わないようにすればよい。
			if (elementModifies.oldElement != elementModifies.newElement)
				document.hideElement(elementModifies.oldElement);
				
			document.setElementOpacity(elementModifies.oldElement, 0.0);
			document.showElement(elementModifies.newElement);
			this.onCustomEffect(0/*IndexChanged*/, elementModifies.newElement, 0.0);
			opacity.restart();
			opacityMaxReached = false;
			elementModifies = null;
		}
		else if (!opacityMaxReached) {
			var opacityValue = opacity.getCurrentValue();
			this.onOpacityChanged(opacityValue);
			if (opacityValue >= 1.0) {
				opacityMaxReached = true;
				opacityMaxReachedTime = new Date();
				this.onCustomEffect(2 /*OpacityMaxReached*/, parsedElements[index.getValue()], opacityValue);
			}
			else {
				this.onCustomEffect(1 /*OpacityChanged*/, parsedElements[index.getValue()], opacityValue);
			}
		}
		else {
			if (new TimeSpan(new Date(), opacityMaxReachedTime).getTotalSeconds() >= autoNextTimeSpan.getTotalSeconds()) {
				this.next();
			}
			else {
				this.onCustomEffect(3 /*Waiting*/, parsedElements[index.getValue()], 1.0);
			}
		}
	};
};

HtmlUtility.createShadedElement = function() {
	var tableElement = document.createElement("table");
	var tbodyElement = document.createElement("tbody");
	tableElement.appendChild(tbodyElement);
	tableElement.setAttribute("cellspacing", "0");
	tableElement.style.position = "absolute";
	var tr1Element = document.createElement("tr");
	tbodyElement.appendChild(tr1Element);
	var tdLeftTopElement = document.createElement("td");
	tdLeftTopElement.style.width = "10px";
	tdLeftTopElement.style.height = "10px";
//	tdLeftTopElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_leftTop.png") + ") left top no-repeat";
	tr1Element.appendChild(tdLeftTopElement);
	var tdTopRepeatElement = document.createElement("td");
	tdTopRepeatElement.style.width = "auto";
//	tdTopRepeatElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_topRepeat.png") + ") repeat-x";
	tr1Element.appendChild(tdTopRepeatElement);
	var tdRightTopElement = document.createElement("td");
	tdRightTopElement.style.width = "10px";
	tdRightTopElement.style.height = "10px";
//	tdRightTopElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_rightTop.png") + ") no-repeat";
	tr1Element.appendChild(tdRightTopElement);
	var tr2Element = document.createElement("tr");
	tbodyElement.appendChild(tr2Element);
	var tdLeftRepeatElement = document.createElement("td");
	tdLeftRepeatElement.style.width = "10px";
	tdLeftRepeatElement.style.height = "auto";
//	tdLeftRepeatElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_leftRepeat.png") + ") repeat-y";
	tr2Element.appendChild(tdLeftRepeatElement);
	var tdCenterElement = document.createElement("td");
	tdCenterElement.style.width = "auto";
	tdCenterElement.style.height = "auto";
	tr2Element.appendChild(tdCenterElement);
	var tdRightRepeatElement = document.createElement("td");
	tdRightRepeatElement.style.width = "10px";
	tdRightRepeatElement.style.height = "auto";
//	tdRightRepeatElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_rightRepeat.png") + ") repeat-y";
	tr2Element.appendChild(tdRightRepeatElement);
	var tr3Element = document.createElement("tr");
	tbodyElement.appendChild(tr3Element);
	var tdLeftBottomElement = document.createElement("td");
	tdLeftBottomElement.style.width = "10px";
	tdLeftBottomElement.style.height = "10px";
//	tdLeftBottomElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_leftBottom.png") + ") no-repeat";
	tr3Element.appendChild(tdLeftBottomElement);
	var tdBottomRepeatElement = document.createElement("td");
	tdBottomRepeatElement.style.width = "auto";
	tdBottomRepeatElement.style.height = "10px";
//	tdBottomRepeatElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_bottomRepeat.png") + ") repeat-x";
	tr3Element.appendChild(tdBottomRepeatElement);
	var tdRightBottomElement = document.createElement("td");
	tdRightBottomElement.style.width = "10px";
	tdRightBottomElement.style.height = "10px";
//	tdRightBottomElement.style.background = "url(" + PathUtility.toAbsolute("~/resource/shade_rightBottom.png") + ") no-repeat";
	tr3Element.appendChild(tdRightBottomElement);
	tdCenterElement.style.border = "1px solid #BFBFBF";
	tdCenterElement.style.backgroundColor = "#FFFFFF";
	tableElement.contentElement = tdCenterElement;
	return tableElement;
};

// ポップアップパネルを表現します。
// ポップアップパネルは絶対配置で、影を持っています。
// パネルはコンストラクタ実行中に自動的にドキュメントに埋め込まれます。
// 通常のエレメント同様に、appendChildで子エレメントを追加することもできます。
var PopupPanel = function(x, y, width, height) {
	var element = HtmlUtility.createShadedElement();
	this.centerling = false;
	this.getElement = function() {
		return element.contentElement;
	};
	this.getZIndex = function() {
		return element.style.zIndex;
	};
	this.setZIndex = function(zIndex) {
		element.style.zIndex = zIndex
	};
	this.move = function(x, y, width, height) {
		if (x != null)
			element.style.left = x > 0 ? x + "px" : 0;
		if (y != null)
			element.style.top = y > 0 ? y + "px" : 0;
		if (width != null)
			element.contentElement.style.width = width + "px";
		if (height != null)
			element.contentElement.style.height = height + "px";
	};
	this.appendChild = function(child) {
		return element.contentElement.appendChild(child);
	}
	this.show = function() {
		document.showElement(element);
		var bounds = document.getElementBounds(element);
		var clientBounds = Page.getClientBounds();
		if (this.centerling) {
			var activeBounds = Page.getActiveBounds();
			var centerlingBounds = clientBounds.contains(activeBounds) ? activeBounds : clientBounds;
			bounds.x = (centerlingBounds.width - bounds.width) / 2 + centerlingBounds.x;
			bounds.y = (centerlingBounds.height - bounds.height) / 2 + centerlingBounds.y;
		}
		var overRight = (bounds.x + bounds.width) - (clientBounds.x + clientBounds.width);
		var overBottom = (bounds.y + bounds.height) - (clientBounds.y + clientBounds.height);
		var overLeft = clientBounds.x - bounds.x;
		var overTop = clientBounds.y - bounds.y;
		if (overRight > 0)
			bounds.x -= overRight;
		if (overLeft > 0)
			bounds.x += overLeft;
		if (overBottom > 0)
			bounds.y -= overBottom;
		if (overTop > 0)
			bounds.y += overTop;
		this.move(bounds.x, bounds.y);
	}
	this.hide = function() {
		document.hideElement(element);
	}
	this.hide();
	this.move(x, y, width, height);
	document.body.appendChild(element);
	this.enableDrag = function(enabledDrag) {
		if (enabledDrag) {
			element.style.cursor = "move";
			element.onmousedown = eventHandler(function(eventArgs) {
				var offsetX;
				var offsetY;
				var currentX = Unit.parse(element.style.left).value;
				var currentY = Unit.parse(element.style.top).value;
				offsetX = currentX - eventArgs.x;
				offsetY = currentY - eventArgs.y;
				document.onmousemove = eventHandler(function(eventArgs) {
					tableElement.style.left = Unit.pixel(eventArgs.x + offsetX);
					tableElement.style.top = Unit.pixel(eventArgs.y + offsetY);
				});
				document.onmouseup = eventHandler(function(eventArgs) {
					document.onmouseup = null;
					document.onmousemove = null;
				});
			});
		} //enabledDrag
		else {
			element.style.cursor = "auto";
			element.onmousedown = null;
			document.onmouseup = null;
			document.onmousemove = null;
		}
	};
};
