{ // define trace().
	function printfire()
	{
		document._e = arguments[0];

		if (document.createEvent)
		{
			printfire.args = arguments;
			var ev = document.createEvent("Events");
			ev.initEvent("printfire", false, true);
			dispatchEvent(ev);
		}
	}

	if (document.all) {
		window.trace = function (e) {
			var ie = 3;
		}
	} else if (window.console) {
		window.trace = function (e) {
			if (e) {
				window.console.log(e);
			}
		}
	} else if ( navigator.userAgent.match( "Firefox" ) ) {
		window.trace = printfire;
	} else {
		window.trace = function () {};
	}
	window.TRACE = window.trace;

	window._ = function ()
	{
		trace(document._e);
		return document._e.stack.replace(/(:\d+)/,"$1\n");
	}

	window.debug_show_rss = function ()
	{
		var rssurl = $A(document.getElementsByTagName("link")).collect( function(e) { return (e.type == "application/rss+xml") ? e.href: null; } ).max();

		if (rssurl == null) {
			trace(
				'' + location.href + '\t'+
				('' + document.title + '\t')
			); 
			trace(" ");
			return;
		}
		
		var aj = new Ajax.Request( rssurl, {
										method: 'get',
										parameters: null,
										onException: function (res, e) {
											trace(e);
										},
										onComplete: function (res) {
											var title = $A( res.responseXML.getElementsByTagName('title')).collect(
												function (e) { return e.firstChild ? e.firstChild.nodeValue : null ;}
											).shift();
											var desc = $A( res.responseXML.getElementsByTagName('description')).collect(
												function (e) { return e.firstChild ? e.firstChild.nodeValue : null;}
											).shift();
											trace(
											'' + location.href + '\t'+
											('' + document.title + '\t') +
											('' + rssurl + '\t')+
											('' + title  + '\t')+
											('' + desc  + '\t' ) );
											trace(",");
										}
									} );

	}
}

var wc = null;

function is_valid_mailaddress( v, treat_empty_as_ok )
{
	if (v == '' && treat_empty_as_ok)
		return true;
	var re = /[!-~]+@[a-z0-9\-_]+(\.[a-z0-9\-_]{2,})+/i;
	var b = re.exec(v); 
	trace(b);
	return b;
}

function toggle_details(elementid)
{
	var details = [
		"detailtabevent",
		"detailtabgroup",
		"detailtabpeople",
		"detailtabmoguelog",
		"detailtabprofile",
		"detailtabarea",
		"detailtablocation"
	];
	
	details.each( function (i) {
		var e = $(i);
		if (e == null)
			return;

		if (i == elementid) {
				Element.show(e);
		} else {
			Element.hide(e);
		}
	} );

	return void(0);
}

function load_dynamic(src)
{
	var element_script = document.createElement('script');
	element_script.src = src;
	element_script.charset = 'utf8';

	document.body.appendChild(element_script);
}

function stop_propagation(e)
{
	if( document.all ){
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	} else {
		if (e) { 
			e.preventDefault();
			e.stopPropagation()
			// for safari.
			// stopPropagation() is defined but do nothing on safari.
			this['on' + e.type] = function() { return false };
		}
	}
	
}


function declare_exec_get_ready() {
	function exec_get_ready(symbol, fn, suspended)
	{
		this.symbol = symbol;
		this.fn = fn;
		this.timer = null;
		this.expired = false;

		if ( ! suspended ) {
			this.wait();
		}
	}
	window.exec_get_ready = exec_get_ready;

	exec_get_ready.prototype.nowait = function () {
		this.fn.apply(this);
	}
	exec_get_ready.prototype.wait = function () {
		if (this.expired)
			return;
		if (this.timer == null) {
			this.timer = setInterval(this.wait.bind(this), 50);
		}

		//var exp = ( "typeof(" + this.symbol + ") ? " + this.symbol + " : null" );
		var exp = ( "typeof(" + this.symbol + ")" );
		var val = eval( exp );
		// document.body is not needed. but its usefull to wait till its ready.
		if ( (val != "undefined" && this.symbol != null) && document.body ) {
			
			this.fn.apply(this);
			clearInterval(this.timer);
			this.timer = null;
			this.expired = true;
		}
	}
} declare_exec_get_ready();


//new exec_get_ready("Event.observe", function () {
//	debug_show_rss();
//} );

function is_empty(s)
{
	return (s == null || s == "");
}
/**
 * get epoch.
 * @return seconds from 1970.1.1.
 **/
function localtime(epoch) {

	var t = new Date();

	if (epoch == null) {
		epoch = t.getTime();
	}
	
	// maybe '* 1000' is not needed. maybe a wrong code.
	t.setTime( epoch * 1000 );
	return t;
}
/**
 * @return date in YYYY.DD.MM .
 **/
function format_date_string(t, fmt)
{
	if ( typeof(t) == "number" )
		t = localtime(t);

	var Y = (t.getYear() < 2000) ? (t.getYear() + 1900) : t.getYear() ;
	var M = t.getMonth() + 1;
	var D = t.getDate();

	if (fmt == "ja")
		return String(Y) + " 年 " + String((M<10)?"0"+M:M) + " 月 " + String((D<10)?"0"+D:D) + " 日";
	else
		return String(Y) + "." + String((M<10)?"0"+M:M) + "." + String((D<10)?"0"+D:D);
}
/**
 *
 * @return time in HH:MM
 **/
function format_time_string(t)
{
	if ( typeof(t) == "number" )
		t = localtime(t);

	var h = t.getHours();
	var m = t.getMinutes();

	return String((h<10)?"0"+h:h) + ":" + String((m<10)?"0"+m:m);
}

function getat(e, index)
{
	var i = index.shift();
	e = e[i];
	while (index.length > 0) {
		i = index.shift();
		e = e.childNodes[i];
	}
	return e;
}

function createHtmlString(param)
{
	function extract_recursive(obj, prop)
	{
		var html  = "";
		for (var i in prop) {
			var v = prop[i];

			if ( i == 'style') {
				var styles = $H( v );
				var pairs = styles.collect( function(k) 
				{
					return k.key + ": " + k.value + ";";
				});

				var style = pairs.join(" ");
				obj[i] = style;
				//html = extract_recursive(obj[i], v);
			} else if ( i == 'childNode') {
				var e = v.collect( createHtmlString );
				html += e.join("");
			} else {
				obj[i] = v;
			}
		}
		return html;
	}
	var tagname = param[0];
	var properties = param[1];

	if (tagname == "")
		return null;

	var e;

	if (tagname == 'text') {
		e = (properties);
	} else {
		var t = $H();
		var innerHTML = extract_recursive(t, properties);
		var props = t.collect(
			function (h) {
				var v = "";
				if (h) {
					//v = h.value.toString().replace(/\"/g, '&qout;');
					return h.key + '="' +  h.value  + '"';
				}
				return "";
			}
		);
		var properties = props.join(" ");
		if (innerHTML == "")
			e = "<" + tagname + " " + properties + " />";
		else
			e = "<" + tagname + " " + properties + " >" + innerHTML + "</" + tagname + ">";
	}
	return e;
}

function createElement(param)
{
	function extract_recursive(obj, prop)
	{
		for (var i in prop) {
			var v = prop[i];

			if ( i == 'style') {
				extract_recursive(obj[i], v);
			} else if ( i == 'childNode') {
				var elements = v.collect( createElement );
				elements.map( function (o) { obj.appendChild(o); } );
			} else if ( i.substr(0, 2) == 'on' ) {
				if ( typeof(v) == 'function' ) {
					if ( typeof(Prototype) != "undefined" ) {
						var eventname = i.substr(2);
						Event.observe(obj, eventname, v, false );
					} else {
						obj[i] = v;
					}
				}
			} else {
				obj[i] = v;
			}
		}
	}
	var tagname = param[0];
	var properties = param[1];

	if (tagname == "")
		return null;

	var e;
	if (tagname == 'text') {
		e = document.createTextNode(properties);
	} else {
		e = document.createElement(tagname);
		extract_recursive(e, properties);
	}
	return e;
}

function xml2js(domelement)
{
	var ret = {};

	if (domelement.childNodes == null)
		return null;

	for (var i = 0; i < domelement.childNodes.length; i++) {
		var obj = domelement.childNodes[i];
		var name = obj.nodeName;
		
		if (obj.nodeValue == null ) {
			//Node.TEXT_NODE == 3
			//Node.CDATA_SECTION_NODE == 4
			if (obj.childNodes && obj.childNodes.length == 1 &&
				(obj.firstChild.nodeType == 3 || obj.firstChild.nodeType == 4) ) {
				var v = obj.firstChild.nodeValue;
				var re = /^\d+(\.\d+)?$/;

				if( re.exec(v) ) {
					ret[name] = Number(v);
				} else {
					ret[name] = v;
				}
			} else if ( obj.childNodes && obj.childNodes.length == 0) {
					ret[name] = "";
			} else {
				var children = xml2js(obj);

				if( ret[name] == null ) {
					ret[name] = [];
				}

				ret[name].push( children );

			}
		} else {
		}
	}
	return ret;
}

function is_enter(e)
{
	if (document.all)
		e = event;
	var b = (e.keyCode == Event.KEY_RETURN);
	return b;
}

function menu(ID) {
	if ( ID == 'info' ) {
		new Effect.Appear('info',
			{
				duration: 0.25
			}
		);
		new Effect.Fade('mogue',
			{
				duration: 0.25
			}
		);
	} else if ( ID == 'mogue' ) {
		new Effect.Appear('mogue',
			{
				duration: 0.25
			}
		);
		new Effect.Fade('info',
			{
				duration: 0.25
			}
		);
	}
}

new Image().src = 'http://img.mogue.jp/img/checked.gif';

function toggle(ID, options) {
	if( options ) {
		options.duration = 0.25;
	} else {
		options = {
				duration: 0.25
		};
	}
	if (document.getElementById(ID).style.display == 'none') {
//		new Effect.Appear(ID, options);
		document.getElementById(ID).style.display = 'block';
		if ( options.afterFinish() )
			options.afterFinish.call();
	} else {
		new Effect.Fade(ID, options);
	}
}


function toggleGroups() {
	if (document.getElementById('groups').style.display == 'none') {
		new Effect.BlindDown('groups',
			{
				duration: 0.1
			}
		);
		//group.style.backgroundColor='#eee';
	} else {
		new Effect.SlideUp('groups',
			{
				duration: 0.1
			}
		);
		//group.style.backgroundColor='#dde';
	}
}

function deleteItem(ID) {
	new Effect.Fade(ID,
		{
			duration: 0.2
		}
	);
}



function menuHighlight(ID,COLOR) {
//	new Effect.Highlight(ID, {startcolor: COLOR, endcolor: '#ffcc00', restorecolor: COLOR})
	new Effect.Pulsate(ID);
}

var buttonOk = new Array();
buttonOk[0] = new Image(); buttonOk[0].src= 'http://img.mogue.jp/img/bg/button/ok0.gif';
buttonOk[1] = new Image(); buttonOk[1].src= 'http://img.mogue.jp/img/bg/button/ok1.gif';

function replaceSubmit(obj,num)
{
	obj.src = buttonOk[num].src;
}

function replaceCancel(ID,num)
{
	if ( num == 1 )
		document.images[ID].src = 'http://img.mogue.jp/img/bg/button/ng1.gif';
	else {
		document.images[ID].src = 'http://img.mogue.jp/img/bg/button/ng0.gif';
	}
}


var persistentimg;

function persistentCheck()
{
	if(document.loginform.persistent.checked) {
		document.loginform.persistent.checked = false;
		document.persistentimg.src = 'http://img.mogue.jp/img/check.gif';
	} else {
		document.loginform.persistent.checked = true;
		document.persistentimg.src = 'http://img.mogue.jp/img/checked.gif';
	}
}

function is_visible(a)
{
	var e = (typeof a == 'string') ? document.getElementById(a) : a;
	return ( e.style.visibility != 'hidden');
}

function toggle_visibility(a)
{
	var e = (typeof a == 'string') ? document.getElementById(a) : a;
	e.style.visibility = is_visible(a) ? 'hidden' : 'visible';
}


function pagetype2ja(type)
{
	var ja = {
		tag:		'タグ',
		event:		'イベント',
		location:	'スポット',
		people:		'ひと',
		group:		'グループ',
		area:		'エリア',
		review:		'モグログ'
	};
	return ja[type];
}

function mogue_button_behaviour_applyer()
{
	function Button() {
		
	}

	Button.prototype.OK = function (id) {
		var e = document.getElementById(id);
		if (e) {
			e.onmouseover = function () {
				replaceSubmit(e, 1);
			};
			e.onmouseout = function () {
				replaceSubmit(e, 0);
			};
		// addEventListener does not exist on IE.
		//	e.addEventListener("mouseover", function () {
		//		replaceSubmit(e, 1);
		//	}, false );
		//	e.addEventListener("mouseout", function () {
		//		replaceSubmit(e, 0);
		//	}, false );
		}
	};

	Button.prototype.Cancel = function (id) {
		var e = document.getElementById(id);
		if (e) {
			e.onmouseover = function () {
				replaceCancel(id, 1);
			};
			e.onmouseout = function () {
				replaceCancel(id, 0);
			};
		//	e.addEventListener("mouseover", function () {
		//		replaceCancel(id, 1);
		//	}, false );
		//	e.addEventListener("mouseout", function () {
		//		replaceCancel(id, 0);
		//	}, false );
		}
	}
	window.Button = new Button();
}


function formColor(ID, b)
{
	if ( navigator.userAgent.indexOf('Safari') < 1 ) {
		if (b == true) {
			ID.style.backgroundColor='#f6f6f6';
			ID.style.borderColor='#aab';
			ID.style.color='#433';
		} else if (b == false) {
			ID.style.backgroundColor='#eee';
			ID.style.borderColor='#bdd';
			ID.style.color='#aab';
		}
	}
}

function enlargetextarea(ID)
{
	var e = document.getElementById(ID);

	var re = /(\d+)/;
	var height = e.style.height;
	window.t =  e.style.height;
	if ( re.exec( height ) ) {
		var newvalue = Math.floor( Number(RegExp.$1) * 1.25);
		e.style.height = height.replace(re, newvalue);
	} else {
		trace("regex failed on enlargetextarea() for " + height);
	}
	e.focus();
}

window.$$ = function(id) { return document.getElementById(id) };

function declare_delete_confirmation()
{
	function delete_confirmation(element_id_prefix)
	{
		this.element_id_prefix = element_id_prefix;
	}

	delete_confirmation.prototype.onException = function (req, e)
	{
		trace(e);
	}
	delete_confirmation.prototype.onComplete = function (req)
	{
		var dom = req.responseXML.documentElement;
		var res = xml2js(dom);

		trace( res );
			
		if (res.errorcode != 0) {
			this.anchor_element.innerHTML = "削除できませんでした";
			return;
		}
		
		if ( this.on_delete_complete() )
			return;

		var id = this.element_id_prefix + this.element_suffix_id;

		new Effect.BlindUp(id, {duration: 0.2});

		if ( this.element_id_prefix == 'moguelog' ) {
			if ( typeof("myLightbox") != 'undefined' ) {
				myLightbox.end();
			}
		} 
	}
	delete_confirmation.prototype.on_delete_complete = function ()
	{
		return false;
	}

	delete_confirmation.prototype.show_confirmation = function (uniqid)
	{
try{
		this.element_suffix_id = uniqid;

		this.anchor_element = $( this.element_id_prefix + "anchor" + uniqid );
		this.confirmation_id = this.element_id_prefix + "confirmation" + uniqid;
		
		if ( this.buttons == null ) {
			var buttons = createElement(
				[ "span", {
					id: this.element_id_prefix + "confirmation" + uniqid,
					childNode: [
						[ "text", '本当に削除しますか？' ],
						[ "span", {
							className: "areabutton s",
							childNode: [
								[ "a", {
									href: "javascript:void(1);",
									onclick: function () {
										this.send_request();
										return false;
									}.bind(this),
									childNode: [
										["text", "はい"]
									]
								} ]
							]
						} ],
						[ "span", {
							className: "areabutton s",
							childNode: [
								[ "a", {
									href: "javascript:void(0);",
									onclick: function () {
										Element.toggle(this.anchor_element, this.confirmation_id);
										this.anchor_element.parentNode.removeChild(buttons);
										this.buttons = null;
										return false;
									}.bind(this),
									childNode: [
										["text", "いいえ"]
									]
								} ]
							]
						} ]
					]
				} ]
			);
			this.anchor_element.parentNode.insertBefore(buttons, this.anchor_element);
			Element.hide(this.anchor_element);
			this.buttons = buttons;
		}
} catch (e) {
	trace(e);
}
	}
	
	delete_confirmation.prototype.send_request = function ()
	{
		Element.hide(this.confirmation_id);
		Element.show(this.anchor_element);
		this.anchor_element.innerHTML = "削除しています...";
		this.anchor_element.href = "javascript:void(0);";

		var pars = this.cmd + "=cmd&" + ( $H( this.params ) .collect( function (a, b) {
									return a.key + "=" + encodeURIComponent(a.value)
								}) ) . join("&");

		var aj = new Ajax.Request( this.request_url, {
										method: 'post',
										parameters: pars,
										onComplete: this.onComplete.bind(this),
										onException: this.onException.bind(this)
									} );
	}

	window.delete_confirmation = delete_confirmation;

	window.delete_message = function (mid)
	{
		var confirmer = new delete_confirmation("msg");

		confirmer.show_confirmation(mid);
		confirmer.request_url = "/api/grouptopic";
		confirmer.cmd = "deletemessage";
		confirmer.params = {
			mid: mid,
			cred: cred
		};

	};

	window.delete_moguelog = function (uniqid)
	{
		var confirmer = new delete_confirmation("moguelog");

		confirmer.show_confirmation(uniqid);
		confirmer.request_url = "/api/moguelog";
		confirmer.cmd = "_delete";
		confirmer.params = {
			uniqid: uniqid,
			cred: cred
		};

	};

	window.delete_tb = function (itemtype, uniqid, tbid)
	{
try {
		var anchor = $("tbanchor" + tbid);
		var confirmer;
		if ( anchor.__tmp__confirmer == null ) {
			confirmer = new delete_confirmation("tb");
			anchor.__tmp__confirmer = confirmer;
		} else {
			confirmer = anchor.__tmp__confirmer;
			Element.show("confirmation" + tbid);
		}

		confirmer.show_confirmation(tbid);
		confirmer.request_url = "/api/trackback";
		confirmer.cmd = "_delete";
		confirmer.params = {
			itemtype: itemtype,
			uniqid: uniqid,
			tbid: tbid,
			cred: cred
		};
} catch(e) {
	trace(e);
}
	};

	window.delete_topic = function (uniqid)
	{
		try {
			var confirmer = new delete_confirmation("topic");

			confirmer.show_confirmation(uniqid);
			confirmer.request_url = "/api/grouptopic";
			confirmer.cmd = "deletetopic";
			confirmer.params = {
				uniqid: uniqid,
				cred: cred
			};
		} catch(e) {
			trace(e);
		}
	};

	window.delete_comment = function (itemtype, uniqid, cid)
	{
		var confirmer = new delete_confirmation("comment");

		confirmer.show_confirmation(cid);
		confirmer.request_url = "/api/comment";
		confirmer.cmd = "_deletecomment";
		confirmer.params = {
			itemtype: itemtype,
			uniqid: uniqid,
			cid: cid,
			cred: cred
		};

	};
}

declare_delete_confirmation();

function show_review(cid,tnailurl)
{
	var review = null;
	for (var i = 0; i < reviews.length; i++) {
		if (reviews[i].cid == cid) {
			review = reviews[i];
			break;
		}
	}

	if (review == null)
		return;

	if (review.iid != null) {
		Element.show("review_view_image");
		var i = $("review_view_image");
		var orgurl = tnailurl.replace('/' + "\/t([^/]+)$" + '/', "/$1");
		i.src = orgurl;
		i.style.width  = review.x + "px";
		i.style.height = review.y + "px";
	} else {
		Element.hide("review_view_image");
	}
	
	$("review_view_text").innerHTML = review.body;
	$("review_view_date").innerHTML =
		format_date_string(review.posted_at) + " " + format_time_string(review.posted_at);
	//$("review_view_name").innerHTML = review.name.escapeHTML();

	Element.show("photo");
}

{
	function button_confirm(opts)
	{
		this.opts = opts;

		// each does not iterate function objects. so must use for in.
		for (var key in this.opts.actions ) {
			// make function to preserve key value.
			( function (key) {
				var id = this.opts.item + key;
				Event.observe(id, 'click', function () {
					var action = this.opts.actions[key];
					
					$(this.opts.message).innerHTML = this.opts.message_callback(id);
					Element.show( this.opts.container );

					this.start_observe(action);
					return false;
				}.bind(this) );
			} ).apply(this, [key]) ;
		}
	}

	button_confirm.prototype.start_observe = function (action) {
		this.observer_yes = function () {
			action.apply(this);
			Element.hide(this.opts.container);
		}.bind(this);
		this.observer_no = function () {
			this.stop_observe();
			Element.hide(this.opts.container);
		}.bind(this);

		Event.observe( this.opts.yes, 'click', this.observer_yes );
		Event.observe( this.opts.no, 'click', this.observer_no );
	}
	button_confirm.prototype.stop_observe = function () {
			Event.stopObserving( this.opts.yes, 'click', this.observer_yes );
			Event.stopObserving( this.opts.no, 'click', this.observer_no);
	}
}

function each_periodic( period, ar, fn )
{
	this.period = period;
	this.iterative = ar;
	this.progress_index = 0;
	this.fn = fn;
	
	// store keys for hash.
	if ( this.iterative.length ) {
		this.keys = null;
	} else {
		this.keys = this.iterative.collect( function(it) {
			return it.key;
		} );
	}
	this.exec();
}

each_periodic.prototype.exec = function ( )
{
	try{
		var lasttime = (new Date()).getTime();
		var i;
		var elapsed;
		
		var ar = (this.keys) ? this.keys : this.iterative;

		for ( i = this.progress_index; i < ar.length; i++) {
			var now = (new Date()).getTime();
			
			var index = (this.keys) ? ar[i] : i;
			this.fn( this.iterative[index], index );

			if ( (elapsed = now - lasttime) > this.period ) {
				break;
			}
		}

		if ( ++i < ar.length ) {
			this.progress_index = i;
			window.setTimeout(this.exec.bind(this), 5 );
		}
	} catch(e) {
			trace(e);
 	}
}

function action_search(is_from_top)
{
try{
	var q = ( $("q").value );

	var itemtype_element = (document.forms.search_form.elements.itemtype);
	var itemtype;

	var params = null;

	if (itemtype_element.type == 'hidden' || itemtype_element.type == 'select-one' ) {
		itemtype = $F('itemtype');
	} else {
		var radios = $A(itemtype_element);
		var e = radios.detect ( function (b) { return b.checked; } );
		itemtype = e.value;
	}

	var path = [ "search", itemtype, encodeURIComponent(q) ];
	// set some options.
	if (is_from_top == null) {
		if ( itemtype == 'event') {
			path.push( $F( itemtype + '_selected_area') );
			path.push( $F('at') );
		}
		if ( itemtype == 'location') {
			path.push( $F( itemtype + '_selected_area') );
		}
		if ( itemtype == 'group') {
			var radios = $A( document.forms.search_form.elements.sort );
			var e = radios.detect ( function (b) { return b.checked; } );
			params = $H( { "sort": e.value } );
		}
	} else {
		if ( itemtype == 'event') {
			path.push( '' );
			path.push( 0x1600 ); // EXTENT_DEFAULT.
		}
	}

	path = path.collect( function ( pchar ) {
							return (pchar == 0 || pchar == '') ? '*' : pchar ;
						} );
	
	var uri = '/' + path.join('/');
	if ( params )
		uri += '?' + params.toQueryString();
	location.href =  uri;
} catch(e) {
	trace(e);
}
}

function show_logout_buttons(flag)
{
	if (flag) {
		( document.getElementById( 'logoutsheet' ) ).style.display = 'block';
		( document.getElementById( 'logoutsheet_bg' ) ).style.display = 'block';
	} else {
		( document.getElementById( 'logoutsheet' ) ).style.display = 'none';
		( document.getElementById( 'logoutsheet_bg' ) ).style.display = 'none';
	}
	
}

function goto_url(u)
{
	location.href = u;
}

