// GreenFish base helper library

var TXT_ERROR_UNKNOWN = 'Ootamatu tehniline viga! Vea kordumisel anna sellest teada ' + 'video' + '@toru.' + 'ee';
var TXT_ERROR_JSON = 'Ootamatu tehniline viga! Vigane vastus serverist. ';
var TXT_ERROR_YUI = 'Ootamatu tehniline viga! YUI liides on laadimata. ';
var TXT_XFORM_LOAD = 'Laeb...';
var TXT_XFORM_POST = 'Üks hetk...';
//var SERVICE_XFORM_URI = '/nagi/module_photo_upload.html';


function GF () {
	return {
		UI: {},
		DOM: {},
		RPC: {},
		classmgr: {},
		session: {},
		reload: {},
		screen: {},
		form: {},
		util: {}
	}
}

/*	DOM namespace for DOM queries
	*/
GF.DOM = function () {
	return {

		/*	Get single node by its id
			you can pass multiple arguments and get an collection in this case
			you can also pass collection or element itself,
			an single first element or element itself is returned in that case
			*/
		get: function (el) {
			if (arguments.length > 1) {
				collect = [];
				for (var i = 0; i < arguments.length; i++) {
					collect[i] = YAHOO.util.Dom.get(arguments[i].toString());
				}
				return collect;
			} else return (!el[0] || (typeof el == 'string')) ? YAHOO.util.Dom.get(el) : el[0];
		},

		/*	Get child node collection
			*/
		classChildren: function (el, classname) {
			//alert(el);
		},
		
		/*	Get single child element by class name
			*/
		classChild: function (el, classname) {
			if (GF.classmgr.isSet(el, classname))
					return el;
			else {
				for (var i=0; i < el.childNodes.length; i++) {
					if ((el.childNodes[i].nodeType == 1) && (GF.DOM.classChildren(el.childNodes[i], classname) != false)) return el.childNodes[i];
				}
			}
			return false;
		},
		
		/*	Get parent element by class name
			*/
		classParent: function (el, classname) {
			while (el.parentNode) {
				if (GF.classmgr.isSet(el, classname))
					return el;
				el = el.parentNode;
			}
			return null;
		},

		/*	Get parent element by tagname
			*/
		tagParent: function (el, tagname) {
			while (el.parentNode) {
				if (el.tagName.toLowerCase() == tagname)
					return el;
				el = el.parentNode;
			}
			return null;
		},
		
		/*	Performs CSS syntax query against entire DOM
			The following code is Copyright (C) Simon Willison 2004.
			ripped from Behaviour v1.1 by Ben Nolan, June 2005. 
			*/
		query: function (selector) {
			// Attempt to fail gracefully in lesser browsers
			if (!document.getElementsByTagName) {
				return new Array();
			}
			// Split selector in to tokens
			var tokens = selector.split(' ');
			var currentContext = new Array(document);
			for (var i = 0; i < tokens.length; i++) {
				token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
				if (token.indexOf('#') > -1) {
					// Token is an ID selector
					var bits = token.split('#');
					var tagName = bits[0];
					var id = bits[1];
					var element = document.getElementById(id);
					if (tagName && element.nodeName.toLowerCase() != tagName) {
						// tag with that ID not found, return false
						return new Array();
					}
					// Set currentContext to contain just this element
					currentContext = new Array(element);
					continue; // Skip to next token
				}
				if (token.indexOf('.') > -1) {
					// Token contains a class selector
					var bits = token.split('.');
					var tagName = bits[0];
					var className = bits[1];
					if (!tagName) {
						tagName = '*';
					}
					// Get elements matching tag, filter them for class selector
					var found = new Array;
					var foundCount = 0;
					for (var h = 0; h < currentContext.length; h++) {
						var elements;
						if (tagName == '*') {
							elements = currentContext[h].all ? currentContext[h].all : currentContext[h].getElementsByTagName('*');
						} else {
							elements = currentContext[h].getElementsByTagName(tagName);
						}
						for (var j = 0; j < elements.length; j++) {
							found[foundCount++] = elements[j];
						}
					}
					currentContext = new Array;
					var currentContextIndex = 0;
					for (var k = 0; k < found.length; k++) {
						if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
							currentContext[currentContextIndex++] = found[k];
						}
					}
					continue; // Skip to next token
				}
				// Code to deal with attribute selectors
				if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
					var tagName = RegExp.$1;
					var attrName = RegExp.$2;
					var attrOperator = RegExp.$3;
					var attrValue = RegExp.$4;
					if (!tagName) {
						tagName = '*';
					}
					// Grab all of the tagName elements within current context
					var found = new Array;
					var foundCount = 0;
					for (var h = 0; h < currentContext.length; h++) {
						var elements;
						if (tagName == '*') {
							elements = getAllChildren(currentContext[h]);
						} else {
							elements = currentContext[h].getElementsByTagName(tagName);
						}
						for (var j = 0; j < elements.length; j++) {
							found[foundCount++] = elements[j];
						}
					}
					currentContext = new Array;
					var currentContextIndex = 0;
					var checkFunction; // This function will be used to filter the elements
					switch (attrOperator) {
						case '=': // Equality
							checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
							break;
						case '~': // Match one of space seperated words 
							checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
							break;
						case '|': // Match start with value followed by optional hyphen
							checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
							break;
						case '^': // Match starts with value
							checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
							break;
						case '$': // Match ends with value - fails with "Warning" in Opera 7
							checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
							break;
						case '*': // Match ends with value
							checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
							break;
						default :
							// Just test for existence of attribute
							checkFunction = function(e) { return e.getAttribute(attrName); };
					}
					currentContext = new Array;
					var currentContextIndex = 0;
					for (var k = 0; k < found.length; k++) {
						if (checkFunction(found[k])) {
							currentContext[currentContextIndex++] = found[k];
						}
					}
					// alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
					continue; // Skip to next token
				}
				if (!currentContext[0]){
					return;
				}
				// If we get here, token is JUST an element (not a class or ID selector)
				tagName = token;
				var found = new Array;
				var foundCount = 0;
				for (var h = 0; h < currentContext.length; h++) {
					var elements = currentContext[h].getElementsByTagName(tagName);
					for (var j = 0; j < elements.length; j++) {
						found[foundCount++] = elements[j];
					}
				}
				currentContext = found;
			}
			return currentContext;
			/* That revolting regular expression explained 
			/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
			  \---/  \---/\-------------/    \-------/
				|      |         |               |
				|      |         |           The value
				|      |    ~,|,^,$,* or =
				|   Attribute 
			   Tag
			*/
		}

	};
}();




/**
 * GF util namespace
 * container various shorthand wrappers
 */
GF.util = function () {
	return {
		dump: function (obj) {
			var str = '';
			for (var k in obj) { str += k + ':' + obj[k] + '\n'; }
			return str;
		},
		isFunction: function (obj) {
			return (obj.toString().toLowerCase().indexOf('function') == 0 && obj.toString().lastIndexOf('}') == obj.toString().length-1) ? true : false;
		},
		QueryStrFromArgs: function (obj) {
			var start = (arguments[1]) ? arguments[1] : 0;
			var uri = '';
			for (var i=start; i<obj.length-1; i=i+2) {
				uri += ((uri == '') ? '' : '&') + obj[i] + '=' + obj[i+1];
			}
			/*var uri = '';
			for (key in obj) {
				uri += ((uri == '') ? '' : '&') + key + '=' + obj[key];
			}*/
			return uri;
		}
	}
}();



GF.form = function () {
	return {
		selectbox: {},
		/*	Submit a form while setting elements' values before
			form name or element as first argument
			arbitrary even number of additional arguments to set existing values
			or create new ones
			*/
		create: function() {
			frm = document.createElement('form');
			return frm;
		},
		submit: function (frm, args) {
			var f = GF.DOM.get(frm);
			for (var i=1; i < arguments.length; i=i+2) {
				var el = f.elements[arguments[i]];
				if (el == null) {
					el = document.createElement('input');
					el.type = 'hidden';
					el.name = arguments[i];
					f.appendChild(el);
				}
				el.value = arguments[i+1];
			}
			f.submit();
			return false;
		},
		populate: function (frm) {
			var f = GF.DOM.get(frm);			
			for (var i=1; i < arguments.length; i=i+2) {
				var el = f.elements[arguments[i]];
				if (el == null) {
					el = document.createElement('input');
					el.type = 'hidden';
					el.name = arguments[i];
					f.appendChild(el);
				}
				el.value = arguments[i+1];
			}
			return f;
		}/**/
	}
}();



GF.form.selectbox = function () {
	return {
		createOptions: function (el, data) {
			var sel = GF.DOM.get(el);
			var opt = null;
			var cur = (arguments[2]) ? arguments[2] : null;
			for (var key in data) {
				opt = document.createElement("option");
				opt.appendChild(document.createTextNode(data[key]));
				opt.value = key;
				opt.selected = (key == cur);
				sel.appendChild(opt);
			}
		},
		removeOptions: function (el, empty) {
			var sel = GF.DOM.get(el);
			var idx = (empty) ? 0 : 1;
			while (sel.options.length > idx) {
				sel.removeChild(sel.options[idx]);
			}
		},
		replaceOptions: function (el, data, empty) {
			GF.form.selectbox.removeOptions(el, empty);
			GF.form.selectbox.createOptions(el, data);
		}
	}
}();


/**
* function for page reloading
**/
GF.reload = function () {
        document.location.reload();
}


/**
 * GF classMGR namespace
 * for managing multiple node classes runtime
 */
GF.session = {
                set: function (name, value, days) {
                                if (days)
                                {
                                        var date = new Date();
                                        date.setTime(date.getTime()+(days*24*60*60*1000));
                                        var expires = "; expires="+date.toGMTString();
                                }else var expires = "";

                                var tmp1 = document.location.toString().split('//');
                                var tmp2 = tmp1[1].split('/');
                                var tmp3 = tmp2[0].split('.');
                                var domain = '.'+tmp3[tmp3.length-2] + '.' + tmp3[(tmp3.length-1)];

                                document.cookie = name+"="+value+expires+"; path=/; domain="+escape(domain);
                        },
                get: function (name) {
				var tmp = '';
				var cname = '';
                                var ca = document.cookie.split(';');
                                for(var i=0;i < ca.length;i++)
                                {
					tmp = ca[i].split( '=' );
					cname = tmp[0].replace(/^\s+|\s+$/g, '');
					if (cname == name)
						return(unescape(tmp[1].replace(/^\s+|\s+$/g, '')));
                                }
                                return null;
                        },
                remove: function (name) {
                                GF.session.set(name,"",-1);
                        }
}

GF.screen = function () {
	return {
		getViewportWidth: function () {
			return window.innerWidth != null? window.innerWidth: document.documentElement && document.documentElement.clientWidth ? document.documentElement.clientWidth:document.body != null? document.body.clientWidth:null;
			},
		getViewportHeight: function (name) {
			return window.innerHeight != null? window.innerHeight: document.documentElement && document.documentElement.clientHeight ? document.documentElement.clientHeight:document.body != null? document.body.clientHeight:null;
			}
		}
}();



/**
 * GF classMGR namespace
 * for managing multiple node classes runtime
 */
GF.classmgr = function () {
	return {
		//	set class name if it does not exist, remove otherwise
		toggle: function (elm, classItem) {
			var f = function (elm, classItem) {
				return (YAHOO.util.Dom.hasClass(elm, classItem)) ? YAHOO.util.Dom.removeClass(elm, classItem) : YAHOO.util.Dom.addClass(elm, classItem);
			}
			YAHOO.util.Dom.batch(elm, f, classItem, true);
			return false;
		},
		// swap class presence in two nodes
		swap: function (el1, el2, classItem) {
			YAHOO.util.Dom.removeClass(el2, classItem);
			YAHOO.util.Dom.addClass(el1, classItem);
			return true;
		},
		//	set single class item to the node
		attach: function(elm, classItem) {
			return YAHOO.util.Dom.addClass(elm, classItem);
		},
		setStyle: function(elm, styleItem, styleVal) {
			return YAHOO.util.Dom.setStyle(elm, styleItem, styleVal);
		},
		//	return true if class is specified on the node 
		isSet: function(elm, classItem) {
			return YAHOO.util.Dom.hasClass(elm, classItem);
		},
		//	remove single class from node class collection
		remove: function(elm, classItem) {
			return YAHOO.util.Dom.removeClass(elm, classItem);
		},
		//	get node classes as a array
		toArray: function(elm) {
			classStr = (elm.className != 'undefined') ? elm.className : '';
			classArr = (classStr) ? elm.className.split(" ") : new Array();
			return classArr;
		}
	}
}();





/**
 * NAGI UI namespace
 * for user interface library specific functions
 * should use this as a wrapper for common ui actions
 * such as menu switching, module handling, messaging
 */

GF.UI = function () {
	return {
		menu: {
			tabToggle: function (el) { // el - tab link reference or id
				var li = GF.DOM.tagParent(el, 'li');
				if (GF.classmgr.isSet(li, 'selected')) {
					GF.UI.menu.reset( GF.DOM.tagParent(el, 'ul') );
				} else {
					return GF.UI.menu.tabOpenSingle(el);
				}
				el.blur();
				return false;
			},
			tabSwitch: function (el) { // el - tab link reference or id
				var li = GF.DOM.tagParent(el, 'li');
				if (!GF.classmgr.isSet(li, 'selected')) {
					return GF.UI.menu.tabOpenSingle(el);
				}
				el.blur();
				return false;
			},
			isSelected: function (el) { // el - tab link reference or id
				var li = GF.DOM.tagParent(el, 'li');
				return GF.classmgr.isSet(li, 'selected');
			},
			tabOpenSingle: function (el) { // el - tab link reference or id
				//var c = (arguments[1]) ? arguments[1] : el.hash.substring(1);
				var ul = GF.DOM.tagParent(el, 'ul');
				var li = GF.DOM.tagParent(el, 'li');
				GF.UI.menu.reset(ul, el.hash.substring(1));
				try {
					GF.classmgr.remove( GF.DOM.get(el.hash.substring(1)), 'hide' );
				} catch (e) {
					throw new Error('Link hash not found in current document!');
				}
				GF.classmgr.attach(li, 'selected');
				el.blur();
				return false;
			},
			tickToggle: function (el) {
				var container = el.parentNode;
				GF.classmgr.toggle(container, 'on');
				return false;
			},
			reset: function (el) { // el - menu container ul reference or id
				var ul = GF.DOM.get(el);
				var except = arguments[1] ? arguments[1] : '';
				for (var i=0; i<ul.childNodes.length; i++) {
					oli = ul.childNodes[i];
					if ((oli.nodeType==1) && GF.classmgr.isSet(oli, 'selected')) {
						GF.classmgr.remove(oli, 'selected');
						var a = oli.getElementsByTagName('a');
						if (a) {
							try {
								var id = a[0].hash.substring(1);
								if (id != except) {
									GF.classmgr.attach( GF.DOM.get(id), 'hide' );
								} 
							} catch (e) {
								throw new Error('Link hash not found in current document!');
							}
						}
					}
				}
				return true;
			}
		},
		message: {
			create: function (container, stat, message) {
				if (message.length > 0) {
					GF.UI.message.reset(container);
					div = GF.DOM.get(container);
					if (div != null) {
						msg = document.createElement('div');
						h2 = document.createElement('h2');
							GF.classmgr.attach(h2, 'pagemessage');
							GF.classmgr.attach(h2, stat);
						a = document.createElement('a');
							a.href = '#' + container;
							a.onclick = function () { return GF.UI.message.close(a) };
						em = document.createElement('em');
						em.appendChild(document.createTextNode('Sulge'));
						a.appendChild(em);
						h2.appendChild(document.createTextNode(message));
						h2.appendChild(a);
						msg.appendChild(h2);
						div.appendChild(msg);
					}
				}
			},
			close: function (el) {
				msg = GF.DOM.classParent(el, 'pagemessage');
				msg.parentNode.removeChild(msg);
				return false;
			},
			reset: function (container) {
				div = GF.DOM.get(container);
				if (div != null) {
					while (child = div.firstChild) {
						div.removeChild(child);
					}
				}
			}
		},
		module: {
			minimizeToggle: function (el) {
				var f = function(el) {
					moduleElm = GF.DOM.classParent(el, 'module');
					if (moduleElm) {
						if (GF.classmgr.isSet(moduleElm, 'closed')) GF.classmgr.remove(moduleElm, 'closed');
						else GF.classmgr.attach(moduleElm, 'closed');
					}
					return false;
				}
				YAHOO.util.Dom.batch(el, f, this, true);
				return false;
			},
			create: function (id) {
			},
			open: function (el) {
			},
			close: function (el) {
				var f = function(el) {
					moduleElm = GF.DOM.classParent(el, 'module');
					if (moduleElm) {
						moduleElm.parentNode.removeChild(moduleElm);
						//todo: check if containing zone is empty. hide in this case
						return false;
					}
				}
				YAHOO.util.Dom.batch(el, f, this, true);
				return false;
			},
			load: function (el) {
				},
			reload: function (el) {
				}
		},
		zone: {},
		general: {
			showHide: function (el) {
				if (arguments.length > 1) {
					if (!arguments[1]) GF.classmgr.attach(el, 'hide');
					else GF.classmgr.remove(el, 'hide');
				} else GF.classmgr.toggle(el, 'hide');
			}
		}
	}
}();






/*	Nagi namespace for application specific UI procedures */


Nagi = function () {
	return {
		module: {},
		actions: {},
		masterpage: {},
		session: {},
		json: {}
	};
};


Nagi.masterpage = {
	toggleSidebar: function (elm) {
		GF.classmgr.toggle(GF.DOM.get('container'), 'compact');
		return false;
	},
	toggleSubheader: function (trigger) {
		var shd = GF.DOM.get('subheader');
		var div = GF.DOM.get(trigger.hash.substring(1));
		var tab = GF.DOM.tagParent(trigger, 'li');
		if (GF.classmgr.isSet(div, 'hide')) {
			GF.classmgr.remove(div, 'hide');
			GF.classmgr.attach(tab, 'selected');
			GF.classmgr.remove(shd, 'hide');
		} else {
			GF.classmgr.attach(div, 'hide');
			GF.classmgr.remove(tab, 'selected');
			if (!Nagi.masterpage.isSubheaders()) GF.classmgr.attach(shd, 'hide');
		}
		return false;
	},
	showSubheader: function (trigger) {
		GF.classmgr.remove(GF.DOM.get(trigger.hash.substring(1)), 'hide');
		GF.classmgr.remove(GF.DOM.get('subheader'), 'hide');
		return false;
	},
	hideSubheader: function (trigger) {
		GF.classmgr.attach(GF.DOM.get(trigger.hash.substring(1)), 'hide');
		if (!Nagi.masterpage.isSubheaders()) GF.classmgr.attach(GF.DOM.get('subheader'), 'hide');
		return false;
	},
	isSubheaders: function () {
		var shd = GF.DOM.get('subheader');
		var cld = shd.getElementsByTagName('p');
		for (var i=0; i < cld.length; i++) {
			if (!GF.classmgr.isSet(cld[i], 'hide')) return true;
		}
		return false;
	}
};


Nagi.actions = {
	current: [],
	toggle: function (trigger) {
		try {
			var args = (arguments[1]) ? arguments[1] : new Object();
			GF.UI.menu.tabToggle(trigger);
			if (GF.UI.menu.isSelected(trigger)) return Nagi.actions.open(trigger, args);
			else return Nagi.actions.close(trigger);
		} catch (e) {
			GF.UI.message.create('messagebox', 'error', ((e.message)?e.message:e));
			return false;
		}
	},
	choose: function (trigger) {
		try {
			var args = (arguments[1]) ? arguments[1] : new Object();
			GF.UI.menu.tabSwitch(trigger);
			if (GF.UI.menu.isSelected(trigger)) return Nagi.actions.open(trigger, args);
		} catch (e) {
			GF.UI.message.create('messagebox', 'error', ((e.message)?e.message:e));
			return false;
		}
	},
	open: function (trigger) {
		var args = (arguments[1]) ? arguments[1] : new Object();
		var container = (args.container) ? args.container : trigger.hash.substring(1);
		var uri = (args.action) ? args.action : trigger.href;
		if (uri.indexOf('#') > 0) uri = uri.substring(0, uri.indexOf('#'));
		var success = function (r) {
			var module = GF.DOM.get(r.argument.container);
			Nagi.actions.hideStatus(module);
			module.innerHTML = r.responseText;
			if (args.success)
			{
				var func = args.success;
				func();
			}
		};
		var failure = function (r) {
			var module = GF.DOM.get(r.argument.container);
			Nagi.actions.displayStatus(module, TXT_ERROR_UNKNOWN, 'no');
		};
		var div = GF.DOM.get(container);
		div.innerHTML = '';
		Nagi.actions.displayStatus(div, TXT_XFORM_LOAD);
		if (YAHOO.util.Connect != null) {
			Nagi.actions.current[Nagi.actions.current.length] = YAHOO.util.Connect.asyncRequest(
				'GET', uri, { success:success, failure:failure, argument:{container:container} }
				);
		} else {
			Nagi.actions.displayStatus(div, TXT_ERROR_UNKNOWN, 'no');
		}
		return false;
	},
	close: function (trigger) {
		var div = GF.DOM.get(trigger.hash.substring(1));
		return false;
	},
	tickRequest: function (trigger, uri) {
		var success = function (r) {
			GF.UI.menu.tickToggle(r.argument.trigger);
			GF.UI.message.create('messagebox', 'confirm', r.responseText); /*trigger.blur();*/
		};
		var callback = (arguments[2]) ? arguments[2] : {success:success, argument:{trigger:trigger}};
		if (!callback.success) callback.success = success;
		var args = (arguments[3]) ? arguments[3] : null;
		Nagi.actions.requestGET(uri, callback, args);
		return false;
	},
	requestGET: function (uri) {
		var success = function (r) { GF.UI.message.create('messagebox', 'confirm', r.responseText); };
		var failure = function (r) { GF.UI.message.create('messagebox', 'error', r.responseText); };
		try {
			var args = (arguments[2]) ? arguments[2] : new Array();
			var request = uri + '?' + GF.util.QueryStrFromArgs(args);
			var callback = (arguments[1]) ? arguments[1] : {success:success, failure:failure};
			if (!callback.success) callback.success = success;
			if (!callback.failure) callback.failure = failure;
			Nagi.actions.current[Nagi.actions.current.length] = YAHOO.util.Connect.asyncRequest( 'GET', request, callback); 
		} catch (e) {
			GF.UI.message.create('messagebox', 'error', ((e.message)?e.message:e));
		}
		return false;
	},
	requestPostSuccess: function (r) {
		if (Nagi.JSON.responseCode(r.responseText) >= 0) {
			var tmpurl = Nagi.JSON.redirect(r.responseText);
			var tmpreload = Nagi.JSON.reload(r.responseText);
			if (tmpurl != '') {
				document.location.href = tmpurl;
			} else if (tmpreload) {
				document.location.reload();
			} else if (r.argument.redirect) {
				document.location.href = r.argument.redirect;
			} else {
				if (r.argument.container) {
					Nagi.actions.hideStatus(r.argument.container);
					if (r.argument.form.onreset) r.argument.form.onreset();
				}
				GF.UI.message.create(r.argument.messagebox, 'confirm', Nagi.JSON.responseMessage(r.responseText) );
			}
		} else {
			Nagi.actions.requestPostFailure(r);
		}
	},
	requestPostFailure: function (r) {
		//Nagi.actions.hideStatus(r.argument.container);
		Nagi.actions.displayStatus(r.argument.container, Nagi.JSON.responseMessage(r.responseText), 'error');
		// Todo: display error message inside form instead of general page message!!!
		//GF.UI.message.create(r.argument.messagebox, 'error', Nagi.JSON.responseMessage(r.responseText) );
	},
	requestPOST: function (frm) {
		try {
			//var f = GF.DOM.get(frm);
			var parameter = (arguments[1]) ? arguments[1] : {};
			var argument = {
				action: (parameter.action) ? parameter.action : frm.action,
				redirect: (parameter.redirect) ? ((frm.elements.redirect && frm.elements.redirect.value) ? frm.elements.redirect.value : parameter.redirect) : null,
				container: (parameter.container) ? parameter.container : GF.DOM.classParent(frm, 'actionform'),
				messagebox: (parameter.messagebox) ? parameter.messagebox : 'messagebox',
				form: frm
				};
			var callback = {
				success: (parameter.success) ? parameter.success : Nagi.actions.requestPostSuccess,
				failure: (parameter.failure) ? parameter.failure : Nagi.actions.requestPostFailure,
				argument: argument
				};
			if (argument.container) Nagi.actions.displayStatus(argument.container, TXT_XFORM_POST);
			/*if (arguments[2]) {
				frm.action = frm.action + '?' + GF.util.QueryStrFromArgs(arguments[2]);
			}
			if (parameter.action) {
				
			}*/
			frm.action = argument.action;
			YAHOO.util.Connect.setForm(frm);
			Nagi.actions.current[Nagi.actions.current.length] = YAHOO.util.Connect.asyncRequest( frm.method.toUpperCase(), frm.action, callback); 
		} catch (e) {
			GF.UI.message.create(argument.messagebox, 'error', e.message);
			return true;
		}
		return false;
	},
	displayStatus: function (module, message) {
		//var module = GF.DOM.get(module);
		var module = YAHOO.util.Dom.get(module);
		if (module != null) {
			//var e = module.childNodes;
			Nagi.actions.hideStatus(module);
			d = document.createElement('div');
			d.appendChild( document.createTextNode(message) );
			d.className = 'status';
			module.insertBefore(d, module.firstChild);
			if (arguments[2]) {
				GF.classmgr.attach(d, arguments[2]);
			} else d.className = 'status';
		}
	},
	hideStatus: function (module) {
		//var m = GF.DOM.get(module);
		var module = YAHOO.util.Dom.get(module);
		if (module != null) {
			var div = module.firstChild;
			if (div != null && div.nodeType == 1) {
				if (GF.classmgr.isSet(div, 'status')) module.removeChild(div);
			}
		}
	},
	loadPage: function (trigger) {
		document.location.href = trigger.href;
	}
};


Nagi.module = {
	toggle: function (el) {
		GF.UI.module.minimizeToggle(el);
		return false;
	}
};


Nagi.JSON = {
	varMessage: 'NagiStatusMsg',
	varCode: 'NagiStatusCode',
	varRedirect: 'NagiRedirect',
	varReload: 'NagiReload',

	responseData: function (text) {
		var r = "var d=" + text + ";";
		try {
			eval(r);
		}
		catch (e)
		{
			var d = { NagiStatusCode: -1, NagiStatusMsg: TXT_ERROR_UNKNOWN, NagiRedirect: "" };
		}
		return d;
	},
	responseMessage: function (text) {
		var data = Nagi.JSON.responseData(text);
		return (data[Nagi.JSON.varMessage]) ? data[Nagi.JSON.varMessage] : "";
	},
	redirect: function (text) {
		var data = Nagi.JSON.responseData(text);
		return (data[Nagi.JSON.varRedirect]) ? data[Nagi.JSON.varRedirect] : "";
	},
	reload: function (text) {
		var data = Nagi.JSON.responseData(text);
		return (data[Nagi.JSON.varReload]) ? data[Nagi.JSON.varReload] : "";
        },
        responseCode: function (text) {
		var data = Nagi.JSON.responseData(text);
		return (data[Nagi.JSON.varCode]) ? parseInt(data[Nagi.JSON.varCode]) : 0;
	}
};

function KuvaBanner(url, w, h, wmode)
{
	document.writeln('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="'+w+'" height="'+h+'">');
	document.writeln('<param name="movie" value="'+url+'" />');
	document.writeln('<param name="quality" value="high" />');
	document.writeln('<param name="name" value="movie" />');
	document.writeln('<param name="swLiveConnect" value="true" />');
	if (wmode == 1)
	{
		document.writeln('<param name="wmode" value="transparent" />');
		document.writeln('<embed src="'+url+'" wmode="transparent" quality="high" scale="noscale" width="'+w+'" height="'+h+'" align="middle" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />');
	}
	else
	{
		document.writeln('<embed src="'+url+'" quality="high" scale="noscale" width="'+w+'" height="'+h+'" align="middle" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />');
	}
	document.writeln('</object>');
}
