
(function ()
{
	var _notdom_write = document.write;

	document.write = function (s)
	{
		try
		{
			_notdom_write(s);
		}
		catch(e)
		{
			var script = (function _script(p)
				{
					return(p.nodeName.toLowerCase() == 'script' ? p : (p.lastChild ? _script(p.lastChild) : p));
				})(document);
			
			var v = document.createElement('div');
			v.innerHTML = s;
			
			while(v.childNodes.length > 0)
			{
				script.parentNode.insertBefore(v.childNodes[0], script);
			}
		}
	};
})();

//include('class.js');
//class.js include start

function class_(v)
{
	return(class_inherit(Object, v));
}

function class_inherit(super_, v)
{
	var obj = new Function("this.initialize.apply(this, arguments);");
	extends_(obj.prototype,
	{
		initialize : function () {}
	});
	extends_(obj.prototype, super_.prototype);
	extends_(obj.prototype,
	{
		myclass    : obj,
		super_     : super_.prototype
	});
	extends_(obj.prototype, v);
	return(obj);
}

function extends_(obj, v)
{
	for(var p in v) {obj[p] = v[p];}
	return(obj);
}

extends_(Object, {
	keys : function (v)
	{
		var xs = [];
		for(var c in v) {xs.push(c);}
		return(xs);
	},
	values : function (v)
	{
		var xs = [];
		Object.keys(v).each(function (key) {xs.push(v[key]);});
		return(xs);
	}
});

var Iterator = {
	each : function (iter)
	{
		try
		{
			for(var i = 0; i < this.length; i++)
			{
				iter(this[i], i);
			}
		}
		catch(e)
		{
			if(e != this._break) {throw(e);}
		}
	},
	map : function (iter)
	{
		var xs = [];
		this.each(function (v, i)
		{
			xs.push(iter(v, i));
		});
		return(xs);
	},
	grep : function (iter)
	{
		var xs = [];
		this.each(function (v, i)
		{
			iter(v, i) && xs.push(v);
		});
		return(xs);
	},
	_break : new Error("Iterator break"),
	break_ : function () {throw(this._break);}
};
extends_(Array.prototype, Iterator);
extends_(Array.prototype, {
	toHash : function ()
	{
		var vs = {};
		this.each(function (x) {vs[x] = true;});
		return(vs);
	}
});
extends_(Array, {
	from : function (vs)
	{
		var xs = [];
		for(var i = 0; i < vs.length; i++)
		{
			xs.push(vs[i]);
		}
		return(xs);
	}
});

extends_(String.prototype,
{
	replaceAll : function (s, v, n)
	{
		n         = n || 0;
		var t     = this.toString();
		var start = 0;
		while((start = t.indexOf(s, start)) >= 0 && start < t.length)
		{
			t = t.left(start) + t.substring(start, t.length).replace(s, v);
			if(n > 0 && --n == 0) {break;}
			start += v.length;
		}
		return(t);
	},
	countOf : function (s, n)
	{
		n         = n || 0;
		var t     = this.toString();
		var start = 0;
		var count = 0;
		while((start = t.indexOf(s, start)) >= 0 && start < t.length)
		{
			count++;
			if(n > 0 && --n == 0) {break;}
			start += s.length;
		}
		return(count);
	},
	left  : function (n) {return(this.substring(0, n));},
	right : function (n)
	{
		var first = this.length < n ? 0 : this.length - n;
		return(this.substring(first, first + n));
	},
	patern : function (n)
	{
		var s = '';
		for(var i = 0; i < n; i++) {s += this.toString();}
		return(s);
	},
	padLeft  : function (n, c) {return(((c || ' ').patern(n) + this.toString()).right(n));},
	padRight : function (n, c) {return((this.toString() + (c || ' ').patern(n)).left(n));},
	
	trim : function()
	{
		return(this.toString().replace(/^\s+/, '').replace(/\s+$/, ''));
	},
	
	tr : function (a, b)
	{
		var t = this.toString();
		for(var i = 0; i < t.length; i++)
		{
			var find;
			if((find = a.indexOf(t.charAt(i), 0)) >= 0)
			{
				var ax = a.charAt(find);
				var bx = b.charAt(find);
				t = t.left(i) + bx + t.substring(i + 1, t.length);
				i -= ax.length - bx.length;
			}
		}
		return(t);
	},
	
	format : function ()
	{
		var f = this.toString();
		for(var i = 0; i < arguments.length; i++)
		{
			f = f.replaceAll('${' + i + '}', arguments[i]);
		}
		return(f);
	}
});

var StringText = class_(
{
	initialize : function (v)
	{
		this._value = [];
		this.toString = function ()
		{
			return(this._value.join(''));
		};
		
		if(typeof(v) != 'undefined') {this.append(v);}
	},
	append : function (v)
	{
		this._value.push(v);
	},
	length : function ()
	{
		var len = 0;
		this._value.each(function (v) {len += v.length;});
		return(len);
	}
});


Number._formatcache = {};
extends_(Number.prototype,
{
	toFormatString : function (v)
	{
		if(Number._formatcache[v]) {return(Number._formatcache[v](this));}
		
		var intat     = 0;  /* 0...int, 1...dec */
		var comadigit = -1;
		var decdigit  = 0;
		var intzero   = false;
		for(var i = 0; i < v.length; i++)
		{
			switch(v.charAt(i))
			{
			case ',':
				if(intat != 0) {throw new Error('decimal comma error.');}
				comadigit = 0;
				break;
			case '0':
				if     (intat == 0) {intzero = true;}
				else if(intat == 1) {decdigit++;}
				
				if(intat == 0 && comadigit >= 0) {comadigit++;}
				break;
			case '#':
				if(decdigit > 0) {throw new Error('decimal digit error.');}
				if(intat == 0 && comadigit >= 0) {comadigit++;}
				break;
			case '.':
				if(intat != 0) {throw new Error('tow decimal point error.');}
				intat = 1;
				break;
			default:
				throw new Error('unknown format charcter.');
				break;
			}
		}
		if(comadigit == 0) {throw new Error('int comma digit error.');}
		
		var digreg;
		if(comadigit > 0) {digreg = new RegExp('^(-?\\d+)(\\d{' + comadigit + '})');}
		Number._formatcache[v] = function (num)
		{
			if(num == 0 && !intzero) {return('');}
			
			var integer = parseInt(num);
			if(comadigit > 0)
			{
				integer = '' + integer;
				while(integer != (integer = integer.replace(digreg, '$1,$2'))) ;
			}
			if(decdigit > 0)
			{
				var decimal = ('' + num);
				var index   = decimal.indexOf('.');
				if(index < 0) {decimal = '0';}
				else
				{
					decimal = decimal.substring(index + 1, index + 1 + decdigit);
				}
				integer += '.' + decimal + '0'.patern(decdigit - decimal.length);
			}
			return(integer);
		};
		return(Number._formatcache[v](this));
	}
});

(function ()
{
	var _getYear     = Date.prototype.getYear;
	var _toString    = Date.prototype.toString;
	var _toGMTString = Date.prototype.toGMTString;
	
	extends_(Date,
	{
		DAY_SUNDAY    : 0,
		DAY_MONDAY    : 1,
		DAY_TUESDAY   : 2,
		DAY_WEDNESDAY : 3,
		DAY_THURSDAY  : 4,
		DAY_FRIDAY    : 5,
		DAY_SATURDAY  : 6
	});
	extends_(Date.prototype,
	{
		getWeek     : function () {return(['Sun',    'Mon',    'Tue',     'Wed',       'Thu',      'Fri',    'Sat']     [this.getDay()]);},
		getWeekfull : function () {return(['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][this.getDay()]);},
		
		setYear     : function (n) {this.setFullYear(n);},
		getYear     : function ()  {var y = _getYear.apply(this); return(y < 1900 ? y + 1900 : y);},
		toDate      : function ()  {return(new Date(this.getYear(), this.getMonth(), this.getDate()));},
		toGMTString : function ()  {return(_toGMTString.apply(this).replace('UTC', 'GMT'));},
		toFormatString : function (f)
		{
			if(!f) {return(_toString.apply(this));}
			return(f
				.replaceAll('yyyy',   this.getYear().toString().padLeft(4, '0'))
				.replaceAll('yyy',    this.getYear() - 1900)
				.replaceAll('yy',   ((this.getYear() - 1900) % 100).toString().padLeft(2, '0'))
				.replaceAll('y',     (this.getYear() - 1900) % 100)
				.replaceAll('MM',    (this.getMonth() + 1).toString().padLeft(2, '0'))
				.replaceAll('M',      this.getMonth() + 1)
				.replaceAll('dd',     this.getDate().toString().padLeft(2, '0'))
				.replaceAll('d',      this.getDate())
				.replaceAll('HH',     this.getHours().toString().padLeft(2, '0'))
				.replaceAll('H',      this.getHours())
				.replaceAll('hh',    (this.getHours() % 12).toString().padLeft(2, '0'))
				.replaceAll('h',     (this.getHours() % 12))
				.replaceAll('mm',     this.getMinutes().toString().padLeft(2, '0'))
				.replaceAll('m',      this.getMinutes())
				.replaceAll('ss',     this.getSeconds().toString().padLeft(2, '0'))
				.replaceAll('s',      this.getSeconds())
				.replaceAll('DD',     this.getWeekfull())
				.replaceAll('D',      this.getWeek())
			);
		},
		addYear         : function (n) {var v = new Date(this); v.setYear        (v.getYear()         + n); return(v);},
		addMonth        : function (n) {var v = new Date(this); v.setMonth       (v.getMonth()        + n); return(v);},
		addDate         : function (n) {var v = new Date(this); v.setDate        (v.getDate()         + n); return(v);},
		addHours        : function (n) {var v = new Date(this); v.setHours       (v.getHours()        + n); return(v);},
		addMinutes      : function (n) {var v = new Date(this); v.setMinutes     (v.getMinutes()      + n); return(v);},
		addSeconds      : function (n) {var v = new Date(this); v.setSeconds     (v.getSeconds()      + n); return(v);},
		addMilliseconds : function (n) {var v = new Date(this); v.setMilliseconds(v.getMilliseconds() + n); return(v);},
		
		compare : function (d) {return(this.getTime() == d.getTime());}
	});
})();


extends_(Function.prototype, {
	bind : function (self)
	{
		var _this = this;
		return(function () {return(_this.apply(self, arguments));});
	},
	curry : function()
	{
		if(arguments.length == 0) {return(this);}
		
		var self = this;
		var args = Array.from(arguments);
		return(function()
		{
			return self.apply(this, args.concat(Array.from(arguments)));
		});
	}
});
//class.js include end
if(document.domain == 'localhost') {include('debug/ieerbug.js');}

function include(src)
{
	if(window['__included_' + src]) {return;}
	window['__included_' + src] = true;
	
	if(typeof(document.includeBasePath) == 'undefined')
	{
		var scripts = document.getElementsByTagName('script');
		
		for(var i = 0; i < scripts.length; i++)
		{
			var matches;
			
			if(typeof(scripts[i].src) != 'string' || !(matches = scripts[i].src.match(/^(.*\b)boot\.js(\?.*)?$/))) {continue;}
			
			document.includeBasePath = matches[1];
			if(document.includeBasePath != '' &&
				document.includeBasePath.charAt(document.includeBasePath.length - 1) != '/') {document.includeBasePath += '/';}
			break;
		}
	}
	
	document.write('<script type="text/javascript" src="' + document.includeBasePath + src + '"></script>');
}

function importcss(href)
{
	if(window['__importedcss_' + href]) {return;}
	window['__importedcss_' + href] = true;
	
	document.write('<link rel="stylesheet" href="' + href + '" />');
}

var Element = {};
(function ()
{
	var ElementMethods = {
		display         : function ()     {return(this.style.display != 'none');},
		setDisplay      : function (show) {this.style.display = show ? '' : 'none';},
		clientRect      : function ()
		{
			var v    = this;
			var rect = {x : 0, y : 0, width : v.offsetWidth, height : v.offsetHeight};
			do
			{
				rect.x += v.offsetLeft;
				rect.y += v.offsetTop;
				v = v.offsetParent;
			}while(v);
			return(rect);
		},
		addClassName    : function ()
		{
			this.className = Object.keys((this.className + ' ' + Array.from(arguments).join(' ')).split(/\s+/).toHash()).join(' ');
		},
		removeClassName : function (remove)
		{
			var xs = this.className.split(/\s+/).toHash();
			delete(xs[remove]);
			this.className = Object.keys(xs).join(' ');
		},
		hasClassName : function (classname)
		{
			return(typeof(this.className.split(/\s+/).toHash()[classname]) != 'undefined');
		}
	};
	
	var EventMethods = {
		attach      : function (s, callback)
		{
			var this_      = this;
			var eventf     = function (sender, event) {};
			var eventb     = function (sender, event) {};
			var event_call = function (e)
			{
				e = e || window.event;
				
				var event =
				{
					cancel : function ()
					{
						if(e.preventDefault) {e.preventDefault();}
						else                 {e.returnValue = false;}
					},
					stop : function ()
					{
						if(e.stopPropagation) {e.stopPropagation();}
						else                  {e.cancelBubble = true;}
					}
				};
				eventf(e, event);
				try
				{
					callback(this_, event);
				}
				catch(ex)
				{
					if(typeof(console) != 'undefined') {console.log(ex, s);}
				}
				eventb(e, event);
			};
			
			if(s.indexOf('key', 0) == 0)
			{
				eventf = function (e, event)
				{
					var prop     = (s                  == 'keypress'  ? 'charCode' : 'keyCode');
					var charprop = (typeof(e.charCode) != 'undefined' ? 'charCode' : 'keyCode');
					event[prop]  = e[charprop];
					
					eventb = function (e, event)
					{
						if(e[charprop] != event[prop]) {e[charprop] = event[prop];}
					};
					
					extends_(event,
					{
						altKey   : e.altKey,
						shiftKey : e.shiftKey,
						ctrlKey  : e.ctrlKey
					});
				};
			}
			else if(s == 'mousewheel')
			{
				eventf = function (e, event)
				{
					extends_(event,
					{
						x : (typeof(e.x) != 'undefined' ? e.x : e.pageX - document.body.scrollLeft),
						y : (typeof(e.y) != 'undefined' ? e.y : e.pageY - document.body.scrollTop),
						scroll : (e.wheelDelta ? e.wheelDelta / 120 * (!window.opera ? -1 : 1) : (e.detail ? e.detail / 3 : 0))
					});
				};
			}
			else if(s.indexOf('mouse', 0) == 0 || s == 'dblclick')
			{
				eventf = function (e, event)
				{
					extends_(event,
					{
						x : (typeof(e.x) != 'undefined' ? e.x : e.pageX - document.body.scrollLeft),
						y : (typeof(e.y) != 'undefined' ? e.y : e.pageY - document.body.scrollTop)
					});
				};
			}
			
			if(this.addEventListener) {this.addEventListener((s == 'mousewheel' ? 'DOMMouseScroll' : s), event_call, false);}
			else                      {this.attachEvent('on' + s, event_call);}
			return(
			{
				detach : function ()
				{
					if(this_.removeEventListener) {this_.removeEventListener((s == 'mousewheel' ? 'DOMMouseScroll' : s), event_call, false);}
					else                          {this_.detachEvent('on' + s, event_call);}
				}
			});
		},
		attach_once : function (s, e)
		{
			if(s.indexOf('key', 0) == 0 || s.indexOf('mouse', 0) == 0)
			{
				var v = this.attach(s, function (sender, other) {e(sender, other); v.detach();});
			}
			else
			{
				var v = this.attach(s, function (sender) {e(sender); v.detach();});
			}
		}
	};
	
	var Methods = {
		getElements : function (iter)
		{
			function _have(vs, iter)
			{
				if(typeof(iter) == 'function') {return(iter(vs));}
				else
				{
					for(var c in iter)
					{
						if(iter[c] != vs[c])
						{
							if(c != 'className' || typeof(vs[c]) == 'undefined' || vs[c] == '') {return(false);}
							
							var vx = vs[c].split(/\s+/).toHash();
							var ix = iter[c].split(/\s+/);
							for(var i = 0; i < ix.length; i++)
							{
								if(typeof(vx[ix[i]]) == 'undefined') {return(false);}
							}
						}
					}
					return(true);
				}
			}
			
			var xs = [];
			var found = function (v)
			{
				_have(v, iter) && xs.push(v);
				Array.from(v.childNodes).each(found);
			};
			found(this);
			return(xs);
		},
		getElementsByTagNodes : function () 
		{
			if(arguments.length < 1) {return(null);}
			
			var xs = [this];
			for(var i = 0; i < arguments.length; i++)
			{
				var xxs = [];
				for(var j = 0; j < xs.length; j++)
				{
					var tags = xs[j].getElementsByTagName(arguments[i]);
					for(var k = 0; k < tags.length; k++) {xxs.push(tags[k]);}
				}
				xs = xxs;
			}
			return(xs);
		},
		getElementsByClassName : function (cname)
		{
			return(this.getElements({'className' : cname}));
		}
	};
	
	for(var p in EventMethods) {window[p]   = EventMethods[p];}
	for(var p in EventMethods) {document[p] = EventMethods[p];}
	for(var p in Methods)      {document[p] = Methods[p];}
	Element.$ = function (v)
	{
		for(var p in ElementMethods) {v[p] = ElementMethods[p];}
		for(var p in EventMethods)   {v[p] = EventMethods[p];}
		for(var p in Methods)        {v[p] = Methods[p];}
		return(v);
	};
	
	var _createElement = document.createElement;
	document.createElement = function (name, params)
	{
		return(extends_(Element.$(typeof(_createElement) == 'object' ? _createElement(name) : _createElement.apply(document, arguments)), params));
	};
})();

window.dump = function (v)
{
	var s = new StringText;
	for(var c in v)
	{
		s.append(c + ' = ' + v[c] + '\n');
	}
	window.alert(s.toString());
};

Function.prototype.async = function(time)
{
	var _this = this;
	return function()
		{
			var args = arguments;
			var p    = this;
			
			var ret =
				{
					completed : false,
					cancel    : function () {window.clearTimeout(id);},
					notify    : function () {this.cancel(); later();}
				};
			function later()
			{
				_this.apply(p, args);
				ret.completed = true;
			};
			var id = window.setTimeout(later, time);
			return(ret);
		};
};

(function ()
{
	var _alert = window.alert;
	window.alert = function ()
	{
		try
		{
			_alert.apply(window, arguments);
		}
		catch(e)
		{
			_alert(arguments[0]);
		}
	};
})();
