/**
 *	javascript utility
 *
 *  (c) 1999-2010 MATSUMURA, Masayoshi
 */


function func_get_args(args) {
	var result = Array();
	for (var i = 0; i < args.length; i++) {
		result.push(args[i]);
	}
	
	return result;
}


function get_class(obj) {
	if ((null == obj) || ('function' != typeof(obj.constructor)))
		return "unknown";
	
	return String(obj.constructor)
					.replace(/\r?\n/g, "")
					.replace(/^function\s+(\w+).*$/, "$1");
}


function isEmpty(o) {
	return ((null == o) || (o.toString().match(/^\s*$/)));
}


function isNotEmpty(o) {
	return ! isEmpty(o);
}


function isInt(value) {
	return ! String(value).match(/\D/);
}

function isNumber(value) {
	if (null == value)
		return false;
		
	return value.toString().match(/^[\+\-]?\d+(\.\d+)?$/);
}

function isNumeric(value) {
	if (null == value)
		return false;
		
	return value.toString().match(/^[\+\-]?(?:\d+|(?:\d{1,3}(,\d{3})*))(?:\.\d+)?$/);
}

function isArray(obj) {
	return (('object' == typeof(obj)) && (Array == obj.constructor));
}


function isCollection(obj) {
	if ('undefined' != typeof(obj.type))
		return false;
		
	return (('object' == typeof(obj)) && 
			((Array == obj.constructor) || 
			 (('undefined' != typeof(HTMLCollection)) && (HTMLCollection == obj.constructor)) ||
			 (null != obj.item)));
}


function trim(value) {
	return String(value).replace(/^[\s　]*/, "").replace(/[\s　]*$/, "");
}

function trimLeft(value) {
	return String(value).replace(/^[\s　]*/, "");
}

function trimRight(value) {
	return String(value).replace(/[\s　]*$/, "");
}

function T(value) {
	return strDef(value, "&nbsp;");
}

function byteStr(value, max) {
	if (null == value && 0 == value.length)
		return value;
	value = String(value);
	if (null != max && max >= 0) {
		var bytes = 0;
		var i = 0;
		for (; i < value.length && bytes < max; i++) {
			var b = (value.charCodeAt(i) > 0xff)? 2 : 1;	//	恐らくこの判定は正しくない
			if ((bytes + b) > max)
				return value.substr(0, i - 1);
				bytes += b;
		}
		return value.substr(0, i);
	}
	return value;
}

function byteSize(value) {
	value = String(value);
	var bytes = 0;
	for (var i = 0; i < value.length; i++) {
		++bytes;
		if (value.charCodeAt(i) > 0xff)	//	恐らくこの判定は正しくない
			++bytes;
	}
	return bytes;
}

function format(fmt) {
	if (null == fmt)
		return "";
	if (arguments.length < 2 || null == arguments[1])
		return fmt;
	
	var args = [ ];
	if ((2 == arguments.length && 'object' == typeof(arguments[1]))) {	// [ ] pattern
		args = arguments[1];
	}
	else {
		for (var i = 1; i < arguments.length; i++) {
			args.push(arguments[i]);
		}
	}
	
	var result = "";
	while (fmt.match(/%\d+/)) {
		result += RegExp.leftContext;
		fmt = RegExp.rightContext;
		var index = parseInt(RegExp.lastMatch.substr(1), 10) - 1;
		if (args.length > index)
			result += args[index];
	}
	return result + fmt;
}

function zeroInt(value, digit) {
	if ((null == value) || ! String(value).match(/^\-?\d+$/))
		return value;
		
	value = String(parseInt(value, 10));
	var N = digit - value.length;
	if (N <= 0)
		return value;
	return stringOfChar("0", N) + String(value);
}


function number(value, def) {
	if (null == def)
		def = 0;
		
	if (! isNumeric(value))
		return def;
		
	value = value.replace(/[^\-\d\.]/g, "");
	if (value.indexOf(".") < 0)
		return parseInt(value, 10);
	
	return new Number(value);
}

function commaFormat(value, _sign) {
	if (String(value).match(/[^\d\.\,\+\-]+/))
		return value;
		
    var result = "";
    var dec    = "";
    var sign   = "";
    value = String(value).replace(/,/g, "");
    if (value.match(/^([^1-9]+)(\d*)/)) {
        value = RegExp.$2;
        sign  = String(RegExp.$1).replace(/0/g, "");
    }
    if (value.match(/(\d*)(\.\d+)/)) {
        value = RegExp.$1;
        dec   = RegExp.$2;
    }
    
    while (value.length > 0 && value.match(/^(\d+)(\d{3})$/)) {
        if (result.length > 0)
            result = "," + result;
        result = String(RegExp.$2) + result;
        value = String(RegExp.$1);
    }
    if (value.length > 0) {
        if (result.length > 0)
            result = "," + result;
        result = value + result;
    }
    if (0 == result.length)
        result = "0";
    
    if (_sign)
		return signEdit(Format("%1%2%3", [sign, result, dec]), _sign);
    return format("%1%2%3", [sign, result, dec]);
}


function signEdit(value, sign) {
	var N = String(value).replace(/\,/g, "");
	if (isNaN(Number(N)))
		return value;
	var tmp = sign.split(';');
	if (N > 0 && typeof(tmp[0]) != 'undefined')
		return tmp[0] + value;
	else if (N < 0 && typeof(tmp[1]) != 'undefined')
		return tmp[1] + value;
	else if (N == 0 && typeof(tmp[2]) != 'undefined')
		return tmp[2] + value;
	return value;
}


function stringOfChar(ch, count) {
	var c = "";
	while (count--)
		c += ch;
	return c;
}


function toDate() {
	if (0 == arguments.length)
		return toDate(toDateStr());
	
	var args = new Array();
	for (var i = 0; i < arguments.length; i++) {
		args.push(arguments[i]);
	}
	
	if (1 == args.length && args[0] instanceof Array)
		args = args[0];
		
	var year 	= 0;
	var month	= 0;
	var day		= 0;
	
	if (1 == args.length) {
		var val = args.shift();
		if (null == val)
			return toDate(toDateStr());
		if (String(val).match(/^(\d{4}[\/\-\.]\d{1,2}[\/\-\.]\d{1,2})\D?/)) {
			var date = String(RegExp.$1);
			
			var tmp = date.split(/[\/\-\.]/);
			if (tmp.length < 3)
				return null;
			year 	= tmp[0];
			month	= tmp[1];
			day		= tmp[2];
		}
	}
	else if (args.length >= 3) {
		year	= args.shift();
		month	= args.shift();
		day		= args.shift();
	}
	
	if ((0 >= year)	 ||
		((month < 1) || (12 < month)) ||
		((day   < 1) || (31 < day)))
		return null;
		
	return new Date(year, month - 1, day);
}


function toDateTime() {
	if (0 == arguments.length)
		return new Date();
	if (1 == arguments.length) {
		if (Date == arguments[0].constructor)
			return arguments[0];
		else if (String(arguments[0]).match(/^\-?\d+$/))
			return new Date(parseInt(arguments[0], 10));
	}
	
	var args = new Array();
	for (var i = 0; i < arguments.length; i++) {
		args.push(arguments[i]);
	}
	
	if (1 == args.length && args[0] instanceof Array)
		args = args[0];
		
	var year 	= 0;
	var month	= 0;
	var day		= 0;
	var hour	= 0;
	var minute	= 0;
	var second	= 0;
	
	if (1 == args.length) {
		var val = args.shift();
		if (null == val)
			return new Date();
		if (String(val).match(/^(\d{4}[\/\-\.]\d{1,2}[\/\-\.]\d{1,2})[\sT]?(\d{1,2}[\:\.]\d{1,2}([\:\.]\d{1,2})?)?/)) {
			var date = String(RegExp.$1);
			var time = (RegExp.$2)? String(RegExp.$2) : null;
			
			var tmp = date.split(/[\/\-\.]/);
			if (tmp.length < 3)
				return null;
			year 	= tmp[0];
			month	= tmp[1];
			day		= tmp[2];
			
			if (time) {
				tmp = time.split(/[\:\.]/);
				if (tmp.length >= 2) {
					hour	= tmp[0];
					minute	= tmp[1];
					if (tmp.length > 2)
						second	= tmp[2];
				}
			}
		}
	}
	else if (args.length >= 3) {
		year	= args.shift();
		month	= args.shift();
		day		= args.shift();
		if (args.length > 0)
			hour	= args.shift();
		if (args.length > 0)
			minute	= args.shift();
		if (args.length > 0)
			second	= args.shift();
	}
	
	if ((0 >= year)	  ||
		((month  < 1) || (12 < month)) ||
		((day    < 1) || (31 < day))   ||
		((hour   < 0) || (23 < hour))  ||
		((minute < 0) || (59 < minute))||
		((second < 0) || (59 < second)))
		return null;
		
	return new Date(year, month - 1, day, hour, minute, second);
}


function toDateStr(value) {
	if (0 == arguments.length)
		value = new Date();
		
	if (null == value)
		return null;
		
	value = new Date(value);
	if (isNaN(value.getFullYear()))
		return value;

	return value.getFullYear() + "/" + zeroInt(value.getMonth() + 1, 2) + "/" + zeroInt(value.getDate(), 2);
}


function toDateTimeStr(value, withMilliseconds) {
	if (0 == arguments.length)
		value = new Date();
		
	if (null == value)
		return null;
		
	value = new Date(value);
	if (isNaN(value.getFullYear()))
		return value;

	return value.getFullYear() 				+ "/" + 
		   zeroInt(value.getMonth() + 1, 2) + "/" + 
		   zeroInt(value.getDate(), 2) 		+ " " +
		   zeroInt(value.getHours(), 2) 	+ ":" + 
		   zeroInt(value.getMinutes(), 2) 	+ ":" + 
		   zeroInt(value.getSeconds(), 2)	+ 
		   (withMilliseconds? ("." + zeroInt(value.getMilliseconds(), 3)) : "");
}


function incSeconds(value, num) {
	value = new Date(value);
	return new Date(value.getFullYear(), value.getMonth(), value.getDate(),
					value.getHours(), value.getMinutes(), value.getSeconds() + parseInt(num, 10));
}


function incMinutes(value, num) {
	value = new Date(value);
	return new Date(value.getFullYear(), value.getMonth(), value.getDate(),
					value.getHours(), value.getMinutes() + parseInt(num, 10), value.getSeconds());
}


function incHours(value, num) {
	value = new Date(value);
	return new Date(value.getFullYear(), value.getMonth(), value.getDate(),
					value.getHours() + parseInt(num, 10), value.getMinutes(), value.getSeconds());
}


function incDates(value, num) {
	value = new Date(value);
	return new Date(value.getFullYear(), value.getMonth(), value.getDate() + parseInt(num, 10),
					value.getHours(), value.getMinutes(), value.getSeconds());
}


function incMonths(value, num) {
	value = new Date(value);
	var day = value.getDate();
	value = new Date(value.getFullYear(), value.getMonth() + parseInt(num, 10), value.getDate(),
					value.getHours(), value.getMinutes(), value.getSeconds());
					
	if (day != value.getDate())
		value = IncDate(value, -value.getDate());
	return value;
}


function incMonthsEx(value, num, complete) {
	complete = ifNull(complete, false);
	
	var p = new Date(value);
	var maxd = end_of_month(p.getFullYear(), p.getMonth() + 1);
	if (complete) {
		if (p.getDate() != maxd)
			return new Date(value.getFullYear(), value.getMonth() + parseInt(num, 10), value.getDate(),
						    value.getHours(), value.getMinutes(), value.getSeconds());
		
		return new Date(value.getFullYear(), value.getMonth() + parseInt(num, 10) + 1, 0,
					    value.getHours(), value.getMinutes(), value.getSeconds());
	}
	
	var date = p.getMonth();
	p = new Date(value.getFullYear(), value.getMonth() + parseInt(num, 10), value.getDate(),
				 value.getHours(), value.getMinutes(), value.getSeconds());
	if (date <= p.getMonth())
		return p;
		
	return new Date(value.getFullYear(), value.getMonth(), 0,
				    value.getHours(), value.getMinutes(), value.getSeconds());
}


function incYears(value, num) {
    value = new Date(value);
    return new Date(value.getFullYear() + parseInt(num, 10), value.getMonth(), value.getDate(),
                    value.getHours(), value.getMinutes(), value.getSeconds());
}


function nextDay(value) {
	return incDates(toDate(value), 1);
}

function toTime() {
	if (0 == arguments.length)
		return new Date(0).getTime();
	
	var args = func_get_args(arguments);
	if (1 == args.length) {
		if (isEmpty(args[0]))
			return new Date(0).getTime();
			
		if (isArray(args[0]))
			args = args[0];
		else if (String(args[0]).match(/^\d+\:\d+(?:\:\d+(?:\.\d+)?)?$/))
			args = String(args[0]).split(/[\:\.]/);
	}
	
	while (args.length < 4)
		args.push(0);
	
	var result = new Date(0);
	result.setHours(result.getHours() + parseInt(args[0], 10));
	result.setMinutes(result.getMinutes() + parseInt(args[1], 10));
	result.setSeconds(result.getSeconds() + parseInt(args[2], 10));
	result.setMilliseconds(result.getMilliseconds() + parseInt(args[3], 10));
	
	return result.getTime();
}

function toTimeSpanStr(value) {
	value = toDateTime(value);
	if (null == value)
		return "";
	
	value = value.getTime();
	var sign = "";
	if (value < 0) {
		sign = "-";
		value = -value;
	}
	
	var msec   = value % 1000; value = Math.floor(value / 1000);
	var second = value % 60;   value = Math.floor(value / 60);
	var minute = value % 60;
	var hour   = Math.floor(value / 60);

	return sign + zeroInt(hour, 2) + ":" + zeroInt(minute, 2) + ":" + zeroInt(second, 2) + "." + zeroInt(msec, 3);
}

function jpToGrace(ee, year, month, date) {
	var result = null;
	
	if (! ee ||
		year.match(/\D/) ||
		month.match(/\D/) ||
		date.match(/\D/)) {
		
		return null;
	}
	
	year = parseInt(year, 10);
	month = parseInt(month, 10);
	date = parseInt(date, 10);
	
	if ((1 <= month) && (month <= 31) &&
		(1 <= date)  && (date <= 31)  &&
		(1 <= year)) {

		ee = ee.toUpperCase();
		if ("M" == ee) {
			if (((1 == year) && (9 == month) && (date < 8)) || (45 < year)) {
				// nop
			}
			else if ((year < 45) || (month < 7) || ((7 == month) && (date <= 30))) {
				result = toDate(year + 1867, month, date);
			}
		}
		else if ("T" == ee) {
			if (((1 == year) && (7 == month) && (date < 30)) || (15 < year)) {
				// nop
			}
			else if ((year < 15) || (month < 12) || ((12 == month) && (date <= 25))) {
				result = toDate(year + 1911, month, date);
			}
		}
		else if ("S" == ee) {
			if (((1 == year) &&  (12 == month) && (date < 25)) || (64 < year)) {
				// nop
			}
			else if ((year < 64) || ((1 == month) && (date <= 7))) {
				result = toDate(year + 1925, month, date);
			}
		}
		else if ("H" == ee) {
			if ((1 == year) && (1 == month) && (date < 8)) {
				// nop;
			}
			else {
				result = toDate(year + 1988, month, date);
			}
		}
	}
	
	return result;
}

function checkDate(value) {
	value = value.replace(/\/(\d)\//, "/0$1/")
	             .replace(/\/(\d)$/, "/0$1");
	if (! value.match(/^[12]\d{3}\/(?:0[1-9]|1[0-2])\/(?:0[1-9]|[12][0-9]|3[01])$/))
		return false;
	
	var checkValue = toDateStr(value);
	if (checkValue != value)
		return false;
	
	return true;
}

function toAge(date, baseDate) {
	date = toDate(date);
	if (! baseDate)
		baseDate = toDate();
	
	return Math.floor(((baseDate.getFullYear() * 10000 + (baseDate.getMonth() + 1) * 100 + baseDate.getDate())
						- (date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate())) / 10000);
}

function hashLength(ar) {
	var result = 0;
	for (var e in ar)
		++result;
	return result;
}


function In(a, b) {
	if (null == b)
		return false;
	
	if (isArray(b)) {
		for (var x in b) {
			if (a == b[x])
				return true;
		}
	}
	else {
		for (var x in b) {
			if (a == x)
				return true;
		}
	}
	return false;
}

function enumElements(args, e) {
	var result = new Array();
	if (null == e)
		e = document.body;
	
	e = e.firstChild;
	if (! isArray(args))
		args = new Array(args);
		
	while (null != e) {
		if ((1 == e.nodeType) && e.tagName) {
			if (0 == args.length) {
				result.push(e);
			}
			else {
				var tagName = e.tagName.toUpperCase();
				for (var i = 0; i < args.length; i++) {
					if (args[i].startsWith("#")) {
						if (args[i].substr(1) == e.id)
							result.push(e);
					}
					else if (args[i].startsWith(".")) {
						if (args[i].substr(1) == e.className)
							result.push(e);
					}
					else if (args[i].startsWith("$")) {
						if (args[i].substr(1) == e.name)
							result.push(e);
					}
					else {
						if (args[i].toUpperCase() == tagName)
							result.push(e);
					}
				}
			}
		
			if (e.hasChildNodes()) {
				result = result.concat(enumElements(args, e));
			}
		}
		
		e = e.nextSibling;
	}
	
	return result;
}


function $TD(e) {
	while ((e = e.parentNode) != null) {
		if (("TD" == e.tagName) || ("TH" == e.tagName))
			return e;
	}
	
	return null;
}

function $TR(e) {
	var e = $TD(e);
	if (e) {
		while ((e = e.parentNode) != null) {
			if ("TR" == e.tagName)
				return e;
		}
	}
	return null;
}

function $Table(e) {
	var e = $TR(e);
	if (e) {
		while ((e = e.parentNode) != null) {
			if ("TABLE" == e.tagName)
				return e;
		}
	}
	return null;
}



function prevTag(e, name) {
	if (! name)
		name = e.tagName;
		
	if (! name)
		return null;
	
	if (! isArray(name))
		name = [ name ];
		
	while ((e = e.previousSibling) && ! In(e.tagName, name))
		;
		
	return e;
}


function nextTag(e, name) {
	if (! name)
		name = e.tagName;
		
	if (! name)
		return null;
	
	if (! isArray(name))
		name = [ name ];
		
	while ((e = e.nextSibling) && ! In(e.tagName, name))
		;
		
	return e;
}

function parentTag(e, name) {
	if (! name)
		name = e.tagName;
		
	if (! name)
		return null;
	
	if (! isArray(name))
		name = [ name ];
		
	while ((e = e.parentNode) && ! In(e.tagName, name))
		;
		
	return e;
}

function childTag(e, name) {
	if (! name)
		name = e.tagName;
		
	if (! name)
		return null;
	
	if (! isArray(name))
		name = [ name ];
		
	e = e.firstChild;
	if (e && In(e.tagName, name))
		return e;
	
	return nextTag(e, name);
}


function getDocumentSize() {
	if (document.getElementsByTagName('html')[0].clientHeight > 0) {
		return {
			"height": document.getElementsByTagName('html')[0].clientHeight,
			"width":  document.getElementsByTagName('html')[0].clientWidth,
			"offsetX": document.getElementsByTagName('html')[0].scrollLeft,
			"offsetY": document.getElementsByTagName('html')[0].scrollTop
		};
	}
	if (document.all) {
		return {
			"height": document.body.clientHeight,
			"width":  document.body.clientWidth,
			"offsetX": document.body.scrollLeft,
			"offsetY": document.body.scrollTop
		};
	}
	else {
		return {
			"height": window.innerHeight,
			"width" : window.innerWidth,
			"offsetX": document.body.scrollLeft,
			"offsetY": document.body.scrollTop
		}
	}
}

function getElementPosition(e) {
	var left = (e && e.offsetLeft)? e.offsetLeft : 0;
	var top  = (e && e.offsetTop)? e.offsetTop : 0;
	
	if (e) {
		while ((e = e.offsetParent) != null) {
			if (null != e.offsetLeft)
				left += e.offsetLeft;
	
			if (null != e.offsetTop)
				top  += e.offsetTop;
		}
	}
	
	return {
		"top" : top,
		"left": left,
		"x": left,
		"y": top,
		"scrollX": left - document.body.scrollLeft,
		"scrollY": top - document.body.scrollTop
	};
}


function getElementRect(e) {
	var pos = getElementPosition(e);
	pos.width = (e && e.offsetWidth)? e.offsetWidth : 0;
	pos.height = (e && e.offsetHeight)? e.offsetHeight : 0;
	pos.right = pos.left + pos.width;
	pos.bottom = pos.top + pos.height;
	
	return pos;
}

function getElementsFromPoint(x, y, args) {
	var result = new Array();
	if (null == args)
		args = new Array();
	else if (! isArray(args))
		args = [ args ];
	
	if ((0 == args.length) || ('object' != typeof(args[0]))) {
		args = enumElements(args);
		return getElementsFromPoint(x, y, args);
	}
	else {
		for (var i = 0; i < args.length; i++) {
			var rect = getElementRect(args[i]);
			if ((rect.left <= x) && (rect.top <= y) &&
				(x <= rect.right) && (y <= rect.bottom)) {
				
				result.push(args[i]);
			}
		}
	}
	
	return result;
}

function getElementsByTagNames(root, names, depth) {
	var result = new Array();
	if (! root.hasChildNodes() || ((null != depth) && (--depth < 0)))
		return result;

	if (! isArray(names))
		names = new Array(names);
	
	var child = root.firstChild;
	while (null != child) {
		if (In(child.nodeName, names))
			result.push(child);
		if (child.hasChildNodes())
			result = result.concat(getElementsByTagNames(child, names, depth));
		
		child = child.nextSibling;
	}
	
	return result;
}

var $jsext = null;

function jsext() {
	if (null == $jsext) {
		var sc = document.getElementsByTagName("SCRIPT");
		var path = "";
		for (var i = 0; i < sc.length; i++) {
			if (sc[i].src.match(/^(.*)toolbox\.js$/)) {
				path = String(RegExp.$1);
			}
		}
		document.write('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="' + location.protocol + '//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="1" height="1" id="jsext" align="middle"><param name="allowScriptAccess" value="sameDomain" /><param name="allowFullScreen" value="false" /><param name="movie" value="' + path + 'jsext.js" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed id="_jsext" src="' + path + 'jsext.js" quality="high" bgcolor="#ffffff" width="1" height="1" name="_jsext" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="' + location.protocol + '//www.macromedia.com/go/getflashplayer" /></object>');
		if (document.all) {
			$jsext = document.getElementById("jsext");
		}
		else {
			$jsext = document.getElementById("_jsext");
		}
	}
	
	return $jsext;
}

function DEBUG() {
	if ('undefined' == typeof(debug)) {
		debug = $("debug");
	}
	
	var args = func_get_args(arguments);
	var msg = format(args.shift(), args);
	if (null == debug)
		alert(msg);
	else {
		debug.innerHTML += msg.replace(/&/g, "&amp;")
		                      .replace(/\'/g, "&#39;")
							  .replace(/\"/g, "&quot;")
							  .replace(/">/g, "&gt;")
							  .replace(/</g, "&lt;")
							  .replace(/\r?\n/g, "<br />")
							  + "<br />";
	}
}

if ("undefined" != typeof(Class)) {
	var Table = Class.create({
	initialize: function(id, options) {	
		if ("string" == typeof(id)) {
			this.id   = id;
			this.element = $(id);
		}
		else if ("object" == typeof(id)) {
			this.element = id;
			this.id = this.element.id;
		}
		
		var e = this.element.firstChild;
		while ((null != e) && ((1 != e.nodeType) || ('TBODY' != e.tagName)))
			e = e.nextSibling;

		if (! this.id || ! this.element || ! e)
			return;
		
		this.body = e;
		this.reset();
	},
	
	reset: function() {
		this.rows = new Array();
		
		var maxcol = 0;
		var rowSpans = new Array();
		for (var i = 0; i < this.element.rows[0].cells.length; i++) {
			var colSpan = this.element.rows[0].cells[i].colSpan;
			while (colSpan-- > 0)
				rowSpans[maxcol++] = 0;
		}
		for (var i = 0; i < this.element.rows.length; i++) {
			var row = {
				element: this.element.rows[i],
				rowIndex: i,
				cells: [ ]
			};
			
			var colSpan = 0;
			var j = 0;
			for (var c = 0; c < row.element.cells.length; c++) {
				if (colSpan > 0) {
					while (colSpan-- > 0) {
						row.cells[j++] = null;
					}
				}

				while (rowSpans[j]-- > 0) {
					row.cells[j++] = null;
				}

				var cell = {
					element: row.element.cells[c],
					rowIndex: i,
					colIndex: j
				};
				
				colSpan = cell.element.colSpan - 1;
				rowSpans[j] = cell.element.rowSpan - 1;
				if ((colSpan > 0) && (rowSpans[j] > 0)) {
					for (var x = 1; x <= colSpan; x++) {
						rowSpans[j + x] = rowSpans[j];
					}
				}

				row.cells[j++] = cell;
			}
			while ((j < maxcol) && (rowSpans[j]-- > 0)) {
				row.cells[j++] = null;
			}
			
			this.rows.push(row);
		}
		
		this.rowCount = this.rows.length;
		this.colCount = maxcol;
	},
	
	debugTableImage: function() {
		if (0 == this.rows.length)
			return "nothing";
			
		var s = "";
		for (var i = 0; i < this.rows.length; i++) {
			s += String(i % 10) + ": ";
			for (var j = 0; j < this.rows[i].cells.length; j++) {
				if (null == this.rows[i].cells[j])
					s += "●";
				else
					s += "○";
			}
		
			s += "\n";
		}
		
		return s;
	},
	
	insertRow: function(index, row) {
		if ((index < 0) || (index > this.rows.length))
			index = this.rows.length;
		
		if (null == row) {
			if (0 == this.rows.length)
				return null;
			
			row = this.rows[ index - 1 ].element.cloneNode(true);
		}
		
		if (document.all) {
			if (index == this.rows.length)
				this.body.appendChild(row);
			else {
				this.body.insertBefore(row, this.rows[index].element);
			}
		}
		else {
			var rowx = this.body.insertRow(index);
			rowx.className = row.className;
			for (var i = 0; i < row.cells.length; i++) {
				var cell = rowx.insertCell(-1);
				
				cell.className = row.cells[i].className;
				cell.colSpan = row.cells[i].colSpan;
				cell.rowSpan = row.cells[i].rowSpan;
				cell.align = row.cells[i].align;
				cell.valign = row.cells[i].valign;
				cell.innerHTML = row.cells[i].innerHTML;
			}
		}
		
		this.reset();
		
		return this.rows[index];
	},
	
	appendRow: function(row) {
		return this.insertRow(-1, row);
	},
	
	clone: function(index) {
		if ((index < 0) || (index >= this.rows.length))
			return null;
		
		var base = this.rows[index].element;
		var row = base.cloneNode(true);
		row.className = base.className;

		if (! document.all) {
			for (var i = 0; i < row.cells.length; i++) {
				var cell = row.cells[i];
				
				cell.className = base.cells[i].className;
				cell.colSpan = base.cells[i].colSpan;
				cell.rowSpan = base.cells[i].rowSpan;
				cell.align = base.cells[i].align;
				cell.valign = base.cells[i].valign;
				cell.innerHTML = base.cells[i].innerHTML;
			}
		}
		return row;
	},
	
	remove: function(index) {
		if ('object' == typeof(index))
			this.body.removeChild(index);
		else {
			if ((index < 0) || (index >= this.rows.length))
				return null;
		
			var row = this.rows[index].element;
			this.body.removeChild(row);
		}
		this.reset();
		
		return row;
	},
	
	parentCell: function(e) {
		while (e) {
			if ((1 == e.nodeType) && (('TD' == e.tagName) || ('TH' == e.tagName)))
				return e;
			
			e = e.parentNode;
		}
		
		return null;
	},
	
	parentRow: function(e) {
		while (e) {
			if ((1 == e.nodeType) && ('TR' == e.tagName))
				return e;
			
			e = e.parentNode;
		}
		
		return null;
	}
});


var AutoComplete = Class.create({
	initialize: function(targetElement, keywordList, options) {
		if ('undefined' == typeof(AutoComplete.items)) {
			AutoComplete.lastId = 0;
			AutoComplete.items = { };
			AutoComplete.queue = [ ];
		}
		this.id = ++AutoComplete.lastId;
		AutoComplete.items[this.id] = this;

		this.showing = false;

		if (! options)
			options = { };

		this.target = ("string" == typeof(targetElement))? $(targetElement) : targetElement;
		if (! this.target.id)
			this.target.id = this.target.name;
		
		this.list = document.createElement("DIV");
		this.list.id = this.target.id + ":autoList";
		this.list.visibility = "hidden";
		this.list.style.position = "absolute";
		this.list.style.zIndex = "99999";
		this.list.style.padding = "0px";
		this.list.style.backgroundColor = options.backgroundColor? options.backgroundColor : "#FFF";
		this.list.style.border = options.border? options.border : "1px solid #CCC";
		this.list.$autoComplete = this;
		this.clear();

		document.body.appendChild(this.list);

		this.padding = options.padding? options.padding: "1px 3px 1px 3px";
		this.textColor = options.textColor? options.textColor: "#000";
		this.selectedColor = options.selectedColor? options.selectedColor: "#39F";
		this.selectedTextColor  = options.selectedText? options.selectedText: "#FFF";
		this.maxLines = options.maxLines? options.maxLines : 10;
		this.minWidth = options.minWidth? options.minWidth : null;
		
		this.keywordList = keywordList;
		
		this.target.$autoComplete = this;
		this.target.autocomplete = "off";
		Event.observe(this.target, "keydown", function(event) {
			var sender = Event.element(event);
			AutoComplete.prototype.onCursor.call(sender.$autoComplete, event);
		}, false);
		Event.observe(this.target, "keyup", function(event) {
			var sender = Event.element(event);
			AutoComplete.prototype.onInput.call(sender.$autoComplete, event);
		}, false);
		Event.observe(this.target, "blur", function(event) {
			var sender = Event.element(event);
			AutoComplete.prototype.onBlur.call(sender.$autoComplete, event);
		}, false);
		Event.observe(this.target, "click", function(event) {
			var sender = Event.element(event);
			AutoComplete.prototype.onTextClick.call(sender.$autoComplete, event);
		}, false);
		
		if (document.all) {
			Event.observe(this.list, "focus", function(event) {
				var sender = Event.element(event);
				sender.focused = true;
			}, false);
			Event.observe(this.list, "blur", function(event) {
				var sender = Event.element(event);
				sender.focused = false;
				AutoComplete.prototype.closeList.call(sender.$autoComplete);
			}, false);
		}
	},
	
	onCursor: function(e) {
		if (document.all)
			e = window.event;
			
		var keyCode = (0 == e.keyCode)? e.charCode : e.keyCode;
		switch (keyCode) {
		  case KEY.UP:
			this.selectUp();
			this.target.value = this.selectedText;
			break;
			
		  case KEY.DOWN:
			if (! this.showing && (this.keywordList.length > 0)) {
				this.showAll();
			}
			else {
				this.selectDown();
			}
			this.target.value = this.selectedText;
			break;
			
		  case KEY.PGUP:
			this.select(Math.max(0, this.selectedIndex - this.maxLines));
			break;
		
		  case KEY.PGDOWN:
			this.select(Math.min(this.selectList.length - 1, this.selectedIndex + this.maxLines));
		  	break;
			
		  case KEY.HOME:
		  	this.select(0);
		  	break;
			
		  case KEY.END:
		  	this.select(this.selectList.length - 1);
		  	break;
			
		  case KEY.ENTER:
			if (document.all) {
				window.event.cancelBubble = true;
			}
			else {
				e.stopPropagation();
			}
		  	this.closeList();
			break;
		}
	},
	
	onInput: function(e) {
		if (document.all)
			e = window.event;
		var keyCode = (0 == e.keyCode)? e.charCode : e.keyCode;
		if (In(keyCode, [ KEY.ESC, KEY.TAB ])) {
			if (document.all) {
				window.event.cancelBubble = true;
			}
			else {
				e.stopPropagation();
			}
			this.closeList();
		}
		else if (In(keyCode, [ KEY.UP, KEY.DOWN, KEY.PGUP, KEY.PGDOWN, KEY.HOME, KEY.END ])) {
		}
		else if ((keyCode >= KEY.SPACE) || In(keyCode, [ KEY.BS, KEY.ENTER, KEY.DEL ])) {
			var value = this.target.value
			if ((KEY.ENTER == keyCode) || this.target.prevValue != value) {
				this.target.prevValue = value;
			
				if (0 == value.length) {
					this.closeList();
					return;
				}

				var val = value.toLowerCase();
				this.clear();
				for (var i = 0; i < this.keywordList.length; i++) {
					if (this.keywordList[i].toLowerCase().startsWith(val)) {
						this.append(this.keywordList[i]);
					}
				}
				this.update();
				if (0 == this.count()) {
					this.closeList();
					return;
				}
				
				this.showList();
				if (In(keyCode, [ KEY.BS, KEY.DEL ]))
					return;

				//this.target.value = this.selectedText;
			}
		}
	},
	
	onBlur: function(e) {
		AutoComplete.queue.push({ sender: this, method: "closeList" });
		window.setTimeout(this.pump, 200);
	},
	
	onTextClick: function(e) {
		if (! this.showing && (this.keywordList.length > 0)) {
			this.showAll();
		}
	},
	
	onElementMouseDown: function(id, e, index) {
		var self = AutoComplete.items[id];
		self.list.focused = true;
	},
	
	onElementClick: function(id, e, index) {
		if (null == index)
			return;

		var self = AutoComplete.items[id];
		self.select(index);
		self.list.focused = false;
		self.closeList();
	},
	
	showAll: function() {
		this.clear();
		for (var i = 0; i < this.keywordList.length; i++) {
			this.append(this.keywordList[i]);
		}
		this.update();
		this.showList();
	},
	
	showList: function() {
		if (! this.showing) {
			this.showing = true;
			var rect = getElementRect(this.target);
			this.list.style.left = rect.left + "px";
			this.list.style.top  = rect.bottom + "px";
			this.list.style.visibility = "visible";
		}
	},
	
	closeList: function() {
		if (this.showing) {
			if (! this.list.focused) {
				this.showing = false;
				if (this.selectedText.length > 0)
					this.target.value = this.selectedText;
				this.target.prevValue = this.target.value;
				this.list.style.visibility = "hidden";
			}
		}
	},
	
	count: function() {
		return this.selectList.length;
	},
	
	clear: function() {
		this.selectedIndex = 0;
		this.selectList = [ ];
		this.list.innerHTML = "";
		this.list.style.height = "";
		this.list.style.width  = "";
		this.list.style.overflowY = "";
	},
	
	append: function(value) {
		if (this.maxLines == this.selectList.length) {
			if (! this.maxHeight) {
				this.setupList();
				this.maxHeight = this.list.offsetHeight + "px";
				this.list.innerHTML = "";
			}
			
			this.list.style.height = this.maxHeight;
		}
		
		this.selectList.push(value);
	},
	
	setupList: function() {
		var index = 0;
		var s = "";
		for (var i = 0; i < this.selectList.length; i++) {
			if (this.selectList[i] == this.target.value)
				index = i;
				
			s += '<div style="padding: ' + this.padding + ';' +
				             'color: ' + this.textColor + ';' + 
							 'margin: 0;' +
							 'cursor: pointer;' +
							 'background-color: ' + this.list.style.backgroundColor + ';"' +
				  	  ' onclick="AutoComplete.prototype.onElementClick(' + this.id + ', event, ' + i + ')"' + 
					  ' onmousedown="AutoComplete.prototype.onElementMouseDown(' + this.id + ', event, ' + i + ')"' +
							 '>' + this.selectList[i] + '</div>';
		}
		this.list.innerHTML = s;
		return index;
	},
	
	update: function() {
		var index = this.setupList();
		if (this.maxLines < this.selectList.length)
			this.list.style.overflowY = "scroll";
		
		var min = this.minWidth? this.minWidth: this.target.offsetWidth;
		if (this.list.offsetWidth < min)
			this.list.style.width = min + "px";
			
		this.select(index);
	},
	
	select: function(index) {
		if ((index < 0) || (index >= this.selectList.length))
			return;
			
		this.selectedIndex = index;
		this.selectedText  = "";
		var node = this.list.firstChild;
		for (var i = 0; i < this.selectList.length; i++) {
			if (i == this.selectedIndex) {
				node.style.color = this.selectedTextColor;
				node.style.backgroundColor = this.selectedColor;
				var text = node.firstChild;
				if (text && text.nodeValue)
					this.selectedText = text.nodeValue;
			}
			else {
				node.style.color = this.textColor;
				node.style.backgroundColor = this.list.style.backgroundColor;
			}
			
			if ((node = node.nextSibling) == null)
				break;
		}
		
		var elementHeight = this.list.scrollHeight / this.selectList.length;
		var ePos = elementHeight * this.selectedIndex;
		if (this.list.scrollTop > ePos)
			this.list.scrollTop = ePos;
		else if ((ePos + elementHeight) > (this.list.scrollTop + this.list.offsetHeight))
			this.list.scrollTop = (this.selectedIndex + 1 - this.maxLines) * elementHeight;
	},
	
	selectUp: function() {
		if (this.selectedIndex > 0)
			this.select(this.selectedIndex - 1);
	},
	
	selectDown: function() {
		if (this.selectedIndex < (this.selectList.length - 1))
			this.select(this.selectedIndex + 1);
	},
	
	pump: function() {
		var method = AutoComplete.queue.shift();
		if (method) {
			AutoComplete.prototype[method.method].call(method.sender);
		}
	}
});
}

var KEY = {
	BS	 	:8,
	TAB		:9,
	ENTER	:13,
	CTRL 	:17,
	ESC	 	:27,
	SPACE	:32,
	PGUP	:33,
	PGDOWN	:34,
	END		:35,
	HOME	:36,
	LEFT 	:37,
	UP	 	:38,
	RIGHT	:39,
	DOWN 	:40,
	DEL	 	:46
};

function $VALUE(id, notfoundvalue) {
	if ("string" == typeof(id))
		elm = mainForm.elements[id];
	else if (id.tagName)
		return coalesce($F(id)).strip();
	else
		elm = id;
	
	if (elm) {
		if (elm.tagName)
			elm = [ elm ];
		
		var result = [ ];
		for (var i = 0; i < elm.length; i++) {
			if (In(elm[i].type, [ "radio", "checkbox" ])) {
				if (elm[i].checked)
					result.push(elm[i].value);
			}
			else {
				result.push(elm[i].value);
			}
		}
		if (0 == result.length)
			return "";

		if (result.length <= 1)
			return result[0];
		
		return result;
	}
	
	var elm = $(id);
	if (elm)
		return coalesce($F(id)).strip();
	
	return notfoundvalue;
}

function coalesce() {
	for (var i = 0; i < arguments.length; i++) {
		if (null != arguments[i])
			return arguments[i];
	}
	return "";
}

var dependentRegexp = null;

function checkDependentChars(str) {
	/*
	if (! dependentRegexp) {
		dependentRegexp = new RegExp("[" + 
			String.fromCharCode(0x00A0) + "-" + String.fromCharCode(0x200f) + 
			String.fromCharCode(0x2153) + "-" + String.fromCharCode(0x2182) + 
			String.fromCharCode(0x2190) + "-" + String.fromCharCode(0x219f) +
			String.fromCharCode(0x00A0) + "-" + String.fromCharCode(0x200F) + 
			String.fromCharCode(0x2153) + "-" + String.fromCharCode(0x2182) + 
			String.fromCharCode(0x2194) + "-" + String.fromCharCode(0x219F) + 
			String.fromCharCode(0x2460) + "-" + String.fromCharCode(0x24EA) + 
			String.fromCharCode(0x2600) + "-" + String.fromCharCode(0x2604) + 
			String.fromCharCode(0x2607) + "-" + String.fromCharCode(0x2669) + 
			String.fromCharCode(0x266B) + "-" + String.fromCharCode(0x266F) + 
			String.fromCharCode(0x2701) + "-" + String.fromCharCode(0x2767) + 
			String.fromCharCode(0x2776) + "-" + String.fromCharCode(0x2793) + 
			String.fromCharCode(0x2794) + "-" + String.fromCharCode(0x27BE) + 
			String.fromCharCode(0x3220) + "-" + String.fromCharCode(0x3243) + 
			String.fromCharCode(0x3280) + "-" + String.fromCharCode(0x32B0) + 
			String.fromCharCode(0x32C0) + "-" + String.fromCharCode(0x32CB) + 
			String.fromCharCode(0x32D0) + "-" + String.fromCharCode(0x32FE) + 
			String.fromCharCode(0x3300) + "-" + String.fromCharCode(0x3370) + 
			String.fromCharCode(0x337B) + "-" + String.fromCharCode(0x337F) + 
			String.fromCharCode(0x33E0) + "-" + String.fromCharCode(0x33FE) + 
			String.fromCharCode(0xFF61) + "-" + String.fromCharCode(0xFF9F) + "]");
	}

	var matches = { };
	while (str.match(dependentRegexp)) {
		matches[RegExp.lastMatch] = RegExp.lastMatch;
		str = RegExp.rightContext;
	}
	
	var result = [ ];
	for (var e in matches) {
		result.push(e);
	}
	if (0 == result.length)
	*/
		return null;
		
	//return result.join("");
}


var mainForm = null;
var defaultAction = null;
var onLoad = null;

Event.observe(window, "load", function(e) {
	if ("undefined" == typeof(formId))
		formId = "mainForm";
	
	mainForm = $(formId);
	if (! mainForm)
		return;
	Event.observe(mainForm, "keydown", function(e) {
		var sender = Event.element(e);
		if (! e.ctrlKey && ! e.altKey && ! e.shiftKey) {
			if (27 == e.keyCode) {
				if ("function" == typeof(onEscape)) {
					Event.stop(e);
					onEscape(sender);
				}
			}
			else if (13 == e.keyCode) {
				if (('undefined' == typeof(onEnter)) || ! onEnter(sender)) {
					if ((("text" == sender.type) || ("password" == sender.type) || ("radio" == sender.type) || ('checkbox' == sender.type)) &&
						mainForm.defaultCommand && 
						mainForm.defaultCommand.value.length > 0) {
						Event.stop(e);
						var o = $(mainForm.defaultCommand.value);
						if (o && (
							('BUTTON' == o.tagName) || 
							(('A' == o.tagName) && o.onclick) ||
							(('INPUT' == o.tagName) && 
							 (o.type && ('SUBMIT' == o.type.toUpperCase()) || ('BUTTON' == o.type.toUpperCase()))
							))
						) o.click();
						else if (o && ('A' == o.tagName) && unescape(o.href).startsWith("javascript:"))
						  eval(unescape(o.href).substr(11));
						else cmd(mainForm.defaultCommand.value);
					}
				}
			}
		}
	}, false);
	
	if (! mainForm.command) {
		var c = document.createElement("input");
		c.id = c.name = "command";
		c.type = "text";
		c.className = "blind";
		if (mainForm.firstChild)
			mainForm.insertBefore(c, mainForm.firstChild);
		else
			mainForm.appendChild(c);
	}

	var focus = null;
	if (mainForm.focusItem && (mainForm.focusItem.value.length > 0)) {
		focus = $(mainForm.focusItem.value);
		if (! focus)
			focus = mainForm.elements[mainForm.focusItem.value];
		if (! focus)
			focus = mainForm.command;
	}
		
	var textCount = 0;
	for (var i = 0; i < mainForm.elements.length; i++) {
		var elem = mainForm.elements[i];
		if (elem && elem.type) {
			if ("text" == elem.type)
				++textCount;

			if (("hidden" != elem.type) &&
				("submit" != elem.type) &&
				("button" != elem.type) &&
				("select-one" != elem.type)) {
				
				if (! elem.disabled && ! focus)
					focus = elem;
			}
		}
	}

	if (textCount < 2) {
		var c = document.createElement("input");
		c.type = "text";
		c.className = "blind";
		mainForm.appendChild(c);
	}
	
	setTimeout(function () {
		try {
			if (focus)
				focus.focus();
		}
		catch (e) {
			//	nop;
		}
	}, 100);
	
	if ("function" == typeof(onLoad))
		onLoad(e);
	
}, false);


function on(sender) {
	if ("string" == typeof(sender))
		cmd(sender);
	else {
		sender.form.command.value = sender.name;
		submit(mainForm);
	}
}


function cmd(command) {
	mainForm.command.value = command;
	submit(mainForm);
}

var submitted = false;

function submit(form) {
	if (submitted)
		return;
	
	submitted = true;
	try {
		var button = $("autoSubmit");
		if (null == button) {
			button = document.createElement("input");
			button.id = "autoSubmit";
			button.type = "submit";
			button.style.display = "none";
			form.appendChild(button);
		}
		button.click();
	}
	catch (e) {
		submitted = false;
	}
}


var onPageChangeCommand = "cmdPageChange";

function onPageChange(page) {
	mainForm.page.value = page;
	if (mainForm.aName && mainForm.aName.value)
		mainForm.action = mainForm.action + "#" + mainForm.aName.value;

	cmd(onPageChangeCommand);
}

var onSortCommand = "show";

function onSort(value, name) {
	mainForm.page.value = 1;
	if (String(value).match(/\s/))
		mainForm.sort.value = value;
	else {
		var tmp = mainForm.sort.value.split(/\s+/);
		if ((tmp[0] != value) || ("DESC" == tmp[1]))
			mainForm.sort.value = value + " ASC";
		else
			mainForm.sort.value = value + " DESC";
	}

	if (mainForm.aName && mainForm.aName.value)
		mainForm.action = mainForm.action + "#" + mainForm.aName.value;

	cmd(onSortCommand);
}

var Mask = {
	show: function (cursor) {
		if (Mask.showing)
			return;
		
		Mask.showing = true;
		Mask.defaultCursor = document.body.style.cursor;
		if (cursor)
			document.body.style.cursor = cursor;
			
		var mask = $("mask");
		if (! mask) {
			mask = document.createElement("div");
			mask.id = "mask";
			document.body.appendChild(mask);
		}
	
		var offset = document.viewport.getScrollOffsets();
		if (document.getElementsByTagName('html')) {
			Mask.overFlow = document.getElementsByTagName('html')[0].style.overflow;
			document.getElementsByTagName('html')[0].style.overflow = "hidden";
		}
		else {
			Mask.overFlow = document.body.style.overflow;
			document.body.style.overflow = "hidden";
		}
	
		mask.style.height = (document.viewport.getHeight() + offset.top) + "px";
		mask.style.width  = (document.viewport.getWidth() + offset.left) + "px";
		mask.style.left = "0px";
		mask.style.top  = "0px";
		mask.style.visibility = "visible";
	
		if (("Netscape" == navigator.appName) &&
			! navigator.userAgent.match(/\s+Safari/))
			scrollBy(0, offset.top);

		if (navigator.appVersion.match(/MSIE\s+[1-6]\./)) {
			Mask.selectHide = new Array();
			$$("select").each(function(e) {
				Mask.selectHide.push({
					obj: e,
					visibility: e.style.visibility
				});
				e.style.visibility = "hidden";
			});
		}
	},
	hide: function() {
		if (! Mask.showing)
			return;
			
		Mask.showing = false;
		for (var i = 0; i < Mask.selectHide.length; i++) {
			var o = Mask.selectHide[i];
			o.obj.style.visibility = o.visibility;
		}
		var mask = $("mask");
		if (mask) {
			mask.style.visibility = "hidden";
			mask.style.height = "0px";
			mask.style.width = "0px";
		}

		var offset = document.viewport.getScrollOffsets();

		if (document.getElementsByTagName('html'))
			document.getElementsByTagName('html')[0].style.overflow = Mask.overFlow;
		else
			document.body.style.overflow = Mask.overFlow;
	
		if ("Netscape" == navigator.appName)
			scrollBy(0, offset.top);

		document.body.style.cursor = Mask.defaultCursor;
	},
	selectHide: [],
	showing: false
};


function showWait(msg, type) {
	Mask.show("wait");
}

function hideWait() {
	Mask.hide();
}

var cookie = {
	set: function (key, value, days) {
		value = key + "=" + escape(value) + ";";
		if (days) {
			var expires = incDates(new Date(), days? parseInt(days, 10): 0).toString();
			value += " expires=" + (expires.match(/GMT/)? 
			                          expires.replace(/^(\w{3})\s+(\w{3})\s+(\d+)\s+(\d+)\s+(\d+:\d+:\d+).*$/, "$1, $3-$2-$4 $5")
								 	  : expires.replace(/^(\w{3})\s+(\w{3})\s+(\d+)\s+(\d+:\d+:\d+)\s+UTC\S+\s+(\d+)$/, "$1, $3-$2-$5 $4"));
		}
		
		document.cookie = value;
	},
	
	get: function(key) {
		var values = document.cookie.split(/;\s+/);
		for (var i = 0; i < values.length; i++) {
			var value = values[i].split(/=/);
			if (value[0] == key) {
				if (value.length > 1)
					return unescape(value[1]);
				return "";
			}
		}
		return "";
	},
	
	remove: function (key) {
		document.cookie = key + "=; expires=Tue, 1-Jan-1980 00:00:00;";
	}
};

var Popup = Class.create({
    initialize: function(id, width, height, close_img, close_bottom) {
        $$popup$$ = this;
        this.width = width;
        this.height = height;
        
        this.popup = document.createElement("div");
        this.popup.id = "popup";
        document.body.appendChild(this.popup);
        
		this.popup.upperPanel = document.createElement("div");
		this.popup.upperPanel.className = "upper-panel";
		this.popup.appendChild(this.popup.upperPanel);
		this.popup.popupTitle = document.createElement("span");
		this.popup.upperPanel.appendChild(this.popup.popupTitle);
		
        this.popup.body = document.createElement("p");
        this.popup.appendChild(this.popup.body);
        
    	this.popup.bottomPanel = document.createElement("div");
		this.popup.bottomPanel.className = "bottom-panel";
    	this.popup.appendChild(this.popup.bottomPanel);
        
        var img = document.createElement("img");
        img.src = close_img;
        img.popup = this;
        Event.observe(img, "click", function(e) {
            var img = Event.element(e);
            img.popup.close();
        }, false);
		
		if (close_bottom)
        	this.popup.bottomPanel.appendChild(img);
		else
        	this.popup.upperPanel.appendChild(img);
        
        $$("." + id).each(function(elm) {
			var title = null;
            var body = elm.nextSibling;
            while (body) {
                if ("SPAN" == body.tagName) {
					if ("popup-title" == body.className) {
						title = body;
					}
					else if ("popup-body" == body.className)
                    	break;
                }
                
                body = body.nextSibling;
            }

            if (body) {
                var trigger = null;
                var e = getElementsByTagNames(elm, "A");
                for (var i = 0; i < e.length; i++) {
                    if ("trigger" == e[i].className) {
                        trigger = e[i];
                        break;
                    }
                }
                
                if (trigger) {
                    trigger.headline = elm;
					elm.popupTitle = title;
                    elm.body = body;
                    Event.observe(trigger, "click", function(e) {
                        var elm = Event.element(e);
						while ("A" != elm.tagName) {
							elm = elm.parentNode;
							if (null == elm)
								return;
						}
						
                       	$$popup$$.open(elm.headline);
                    }, false);
                }
            }
        });
    },
    
    open: function(sender) {
        var width  = Math.min(this.width, document.viewport.getWidth());
        var height = Math.min(this.height, document.viewport.getHeight());
        if (height < 30) {
            alert("ウインドウが小さくて表示できません。");
            return;
        }

		Mask.show();
        
		var adjustHeight = document.all? 50: 100;
		var adjustWidth  = document.all? 23: 20;
		var offset = document.viewport.getScrollOffsets();
        this.popup.style.left = (Math.floor((document.viewport.getWidth() - width) / 2) + offset.left) + "px";
        this.popup.style.top  = (Math.floor((document.viewport.getHeight() - height) / 2) + offset.top) + "px";
        this.popup.style.width = width + "px";
		
        this.popup.body.style.height = (height - adjustHeight) + "px";
		this.popup.body.style.width = (width - adjustWidth) + "px";
        
		if (sender.popupTitle)
			this.popup.popupTitle.innerHTML = sender.popupTitle.innerHTML;
			
        this.popup.body.innerHTML = sender.body.innerHTML;
        this.popup.style.visibility = "visible";
    },
    
    close: function() {
        this.popup.style.visibility = "hidden";
		Mask.hide();
    }
});

