//--------------------- UIElement class
var UIElement = Class.create({
	type: null,

//	id: null,
//	parent: null,
//	element: null,
//	events: $H(),

	// ------- init

	initialize: function(id, parent, data)
	{
		this.id = id;
		this.parent = parent;
		if (data.events) {
			data.events.each(function(pair) {
				var event_name = pair.key;
				var event_handlers = pair.value;
				event_handlers.each(function(pair) {
					var event_handler_name = pair.key;
					var event_handler = eval(pair.value);
					this.addEventHandler(event_name, event_handler_name, event_handler);
				}, this);
			}, this);
		}
	},
	
	getData: function(changedOnly)
	{
		var isChanged = this.isChanged();

		if (changedOnly && !isChanged)
			return null;

	   var data = $H();
//	   data.set("id", this.getId());
//	   data.set("type", this.getType());
	   return data;
	},
	
	make: function(type, id, data)
	{
		var className = this.getClassName(type);
		return eval("new " + className +"(id, this, data);");
	},
	
	getClassName: function (type)
	{
		return "UIE__" + type;
	},
	
	isChanged: function()
	{
		return false;
	},

	// ------ specific
	
	getId: function()
	{
		return this.id;
	},

	getType: function getType()
	{
		return this.type;
	},
	
	getParent: function()
	{
		return this.parent ? this.parent : null;
	},

	// ------ DOM
	
	getElement: function()
	{
		if ( ! this.element ) {
			this.element = this.constructElement();
			this.bindEventsHandlers(this.element);
		}
		return this.element;
	},
	
	// ------ events
	
	getEventsHandlers: function()
	{
		if ( !this.events ) {
			this.events = $H();
		}
		return this.events;
	},
	
	getEventHandlers: function(event)
	{
		var events_handlers = this.getEventsHandlers();
		if ( ! events_handlers.get(event) ) {
			events_handlers.set(event, $H());
		}
		return events_handlers.get(event);
	},

	addEventHandler: function(event, event_handler_name, event_handler)
	{
		var event_handlers = this.getEventHandlers(event);
		event_handlers.set(event_handler_name, event_handler);
	},
	
	bindEventsHandlers: function(element)
	{
		this.getEventsHandlers().each(function(pair) {
			var event_name = pair.key;
			var event_handlers = pair.value;
			event_handlers.each(function(pair) {
				var event_handler_name = pair.key;
				var event_handler = pair.value;
				this.bindEventHandler(element, event_name, event_handler);
			}, this);
		}, this);
	},
	
	bindEventHandler: function(element, event, handler, useCapture)
	{
		Event.observe(element, event, handler.bind(this), useCapture);
	},
	
	// --------- service
	
	getWidget: function()
	{
		return this.parent.getWidget();
	},
	
	getWidgetManager: function()
	{
		return this.getWidget().getManager();
	}
});

//--------------------- container class

var UIE__container = Class.create(UIElement, {
	type: "container",
	cContainerContainer: "container",
	eContainerContainer: "div",

//	containerElement: null,
//	containerData: null,
//	container: {},

	// ---- initialize

	initialize: function($super, id, parent, data)
	{
		$super(id, parent, data);
		this.containerData = data.childs;
	},
	
	getData: function($super, changedOnly)
	{
		var containerData = this.getContainerData(changedOnly);
		var data = $super(changedOnly);
		
		if	(containerData) {
			data.set("childs", containerData);
		}
		
		return data;
	},
	
	isChanged: function($super)
	{
		return $super() || this.isContainerChanged();
	},
	
	isContainerChanged: function()
	{
		var isChanged = false;
		if (this.container) { //childs touched
			this.getContainer().each(function(pair) {
				var element = pair.value;
				if (element.isChanged()) {
					isChanged = true;
					throw $break;
				}
			}, this);
		}
		return isChanged;
	},
	
	hasContainer: function()
	{
		return (
				this.container &&
				this.container.keys().length
			) ||
			this.containerData;
	},

	getContainerData: function(changedOnly)
	{
		if (changedOnly && !this.isContainerChanged())
			return null;
		
		var data = $H();
		this.getContainer().each(function(pair) {
			var id = pair.key;
			var element = pair.value;
			var elementData = element.getData(changedOnly);
			if (elementData) {
				data.set(id, elementData);
			}
		}, this);
		
		return data;
	},
	
	// ---- DOM
	
	constructElement: function()
	{
		return this.getContainerElement();
	},
	
	getContainerElement: function()
	{
		if ( !this.containerElement ) {
			this.containerElement = this.constructContainerElement();
		}
		return this.containerElement;
	},
	
	constructContainerElement: function()
	{
		var containerNode = new Element(this.eContainerContainer, {
			'class': this.cContainerContainer
		});
		
		this.getContainer().each(function(pair) {
			var element = pair.value;
			containerNode.appendChild(element.getElement());
		}, this);
		
		return containerNode;
	},

	// ------- specific
	
	getContainerChildById: function(id)
	{
		var match = null;
		
		this.getContainer().each(function(pair) {
			var childId = pair.key;
			var child = pair.value;
			if ( id == childId ) {
				match = child;
			} else
			if ( child instanceof UIE__container ) {
				match = child.getContainerChildById(id);
			}
			if (match)
				throw $break;
		}, this);
		
		return match;
	},
	
	appendChild: function(childId, child)
	{
		this.getContainer().set(childId, child);
	},
	
	getContainer: function()
	{
		if ( ! this.container ) {
			this.container = $H();
			if ( this.containerData ) {
				$H(this.containerData).each(function(pair) {
					var childId = pair.key;
					var childData = pair.value;
					var child = this.make(childData.type, childId, childData);
					this.appendChild(childId, child);
				}, this);
			}
		}
		return this.container;
	}
});

//---------- uri

var UIE__uri = Class.create(UIE__container, {
	type: "uri",
	
	eURI: "a",

//	uri: null,
//	title: null,

	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		if (data.uri) {
			this.setURI(data.uri);
		}
		if (data.title) {
			this.setTitle(data.title);
		}
	},
	setURI: function(uri) {
		this.uri = uri;
		if ( this.element ) {
			this.element.href = this.uri;
		}
	},
	getURI: function()
	{
		return this.uri;
	},
	setTitle: function(title) {
		this.title = title;
		if ( this.element ) {
			this.element.title = this.title;
		}
	},
	getTitle: function()
	{
		return this.title ? this.title : '';
	},	
	constructElement: function($super)
	{	
		var elementNode = new Element(this.eURI, {
			'href': this.getURI()
		});
		if (this.getTitle()) { //suppress empty title code
			elementNode.setAttribute('title', this.getTitle());
		}

		var containerElement = $super();
		$A(containerElement.childNodes).each(function(childNode) {
			elementNode.appendChild(childNode);
		}, this);

		return elementNode;
	}
});

//---------- caption class

var UIE__caption = Class.create(UIElement, {
	type: "caption",
//	caption: "",

	// --- initialize
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		if (data.caption) {
			this.setCaption(data.caption);
		}
	},

	// -- specific 
	
	getCaption: function()
	{
		if ( !this.caption ) {
			this.caption = "";
		}
		return this.caption;
	},

	setCaption: function(caption)
	{
		this.caption = caption;
	},

	// --- DOM
	
	constructElement: function()
	{
		return document.createTextNode(this.getCaption());
	}
});

var UIE__html = Class.create(UIElement, {
	type: "html",
	
	eHTMLContainer: "div",

//	HTML: "",

	// --- initialize
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		if ( data.html ) {
			this.setHTML(data.html);
		}
	},

	// -- specific 
	
	getHTML: function()
	{
		if ( !this.HTML ) {
			this.HTML = "";
		}
		return this.HTML;
	},

	setHTML: function(html)
	{
		this.HTML = HTML;
	},

	// --- DOM
	
	constructElement: function()
	{
		var elementNode = new Element(this.eHTMLContainer).insert(this.getHTML());
		return elementNode;
	}
});

// --------- input class

var UIE__input = Class.create(UIElement, {
	type: "input",
	
	eInput: "input",
//	value: null,
//	valueChanged: false,
//	ref: null,

	// --------- init

	initialize: function ($super, id, parent, data)
	{
		this.addEventHandler(
			"change",
			"updateValue",
			this.inputValueHandler
		);
		$super(id, parent, data);
		this.value = data.value ? data.value : null;
		this.valueChanged = data.valueChanged ? data.valueChanged : false;
		this.ref = data.ref ? data.ref : null;
	},
	
	inputValueHandler: function() {
		this.value = this.element.value;
		this.valueChanged = true;
	},
	
	isChanged: function($super)
	{
		return $super() || this.isValueChanged();
	},
	
	getData: function($super, changedOnly)
	{
		var isChanged = this.isValueChanged();
		var data = $super(changedOnly);
		
		if (isChanged) {
			data.set("value", this.getValue());
		}
		
		return data;
	},
	
	// -------- specific
	
	getRef: function()
	{
		return this.ref ? this.ref : this.getId();
	},
	
	isValueChanged: function()
	{
		return this.valueChanged;
	},
	
	getValue: function()
	{
		return this.value;
	},
	
	// ---------- DOM

	constructElement: function()
	{
		var inputElement = new Element(this.eInput, {
			"id": "fid-" + this.getId(),
			"name": this.getRef(),
			"value": this.getValue()
		});
		return inputElement;
	}
});

var UIE__checkbox = Class.create(UIE__input, {
	type: "checkbox",
	
	eInput: "checkbox",

	inputValueHandler: function() {
		this.value = this.element.checked;
		this.valueChanged = true;
	},

	// ---------- DOM

	constructElement: function()
	{
		var inputElement = new Element(this.eInput, {
			"id": "fid-" + this.getId(),
			"type": "checkbox",
			"name": this.getRef(),
			"value": this.getValue()
		});
		return inputElement;
	}
});

// -------------- treeNodesContainer class

var UIE__treeNodesContainer = Class.create(UIE__container, {
	type: "treeNodesContainer",
	
	cTreeNodesContainer: "treeNodesContainer",
	cTreeShowNodesButton: "shButton",
	cTreeNodesShow: "treeNodesShow",
	cTreeNodesHide: "treeNodesHide",
	cTreeNodes: "treeNodes",
	
	eTreeNodesContainer: "div",
	eTreeNodes: "div",
	eTreeShowNodesButton: "button",

//	showNodes: true,
//	nodes: {},
//	nodesData: null,
//	nodesElement: null,
	
	// ---- initialize
	
	initialize: function($super, id, parent, data)
	{
		$super(id, parent, data);
		this.nodesInitData = data.nodes;
		if (data.show) {
			this.setCollapsed(false);
		}
	},
	
	isNodesChanged: function()
	{
		var isChanged = false;
		if (this.nodes) { //nodes touched
			this.getNodes().each(function(pair) {
				var node = pair.value;
				if (node.isChanged()) {
					isChanged = true;
					throw $break;
				}
			}, this);
		}
		return isChanged;
	},
	
	isChanged: function($super)
	{
		return $super() || this.isNodesChanged();
	},

	getData: function($super, changedOnly)
	{
		var nodesData = this.getNodesData(changedOnly);
		var data = $super(changedOnly);
		
		if (nodesData) {
			data.set("nodes", nodesData);
		}
//		if (!this.isCollapsed()) {
//			data.set("showNodes", true);
//		}
		
		return data;
	},
	
	hasNodesInitData: function()
	{
		return this.nodesInitData;
	},

	getNodesInitData: function()
	{
		return $H(this.nodesInitData);
	},

	getNodesData: function($super, changedOnly)
	{
		if (changedOnly && !this.isNodesChanged())
			return null;

		var data = $H();
		this.getNodes().each(function(pair) {
			var nodeId = pair.key;
			var node = pair.value;
			var nodeData = node.getData(changedOnly);
			if (nodeData) {
				data.set(nodeId, nodeData);
			}
		}, this);

		return data;
	},
	
	//  ------ specific

	getNodeById: function(id)
	{
		var match = null;

		this.getNodes().each(function(pair) {
			var nodeId = pair.key;
			var node = pair.value;
			if ( id == nodeId ) {
				match = node;
			} else
			if ( node instanceof UIE__container ) {
				match = node.getNodeById(id);
			}
			if (match)
				throw $break;
		}, this);

		return match;
	},

	getNodes: function()
	{
		if ( ! this.nodes ) {
			this.nodes = $H();
			if (this.hasNodesInitData()) {
				this.getNodesInitData().each(function(pair){
					var nodeId = pair.key;
					var nodeData = pair.value;
					var node = this.make(nodeData.type, nodeId, nodeData);
					this.appendNode(nodeId, node);
				}, this);
			}
		}
		return this.nodes;
	},
	
	appendNode: function(nodeId, node)
	{
		var nodes = this.getNodes();
		nodes.set(nodeId, node);
	},
	
	isCollapsed: function ()
	{
		return !this.show;
	},
	
	setCollapsed: function(collapsed)
	{
		this.show = !collapsed;
		
		if (collapsed) {
			this.hideNodes();
		} else {
			this.showNodes();
		}
	},	

	// ------- DOM
	
	constructElement: function($super)
	{
		var nodeContainerElement = new Element(this.eTreeNodesContainer, {
			'class': this.cTreeNodesContainer
		});

		if (this.getNodes().keys().length) {
			var shShowHideButtonElement = new Element(this.eTreeShowNodesButton, {
				"type": "button",
				"class": this.cTreeShowNodesButton
			});

			this.bindEventHandler(
				shShowHideButtonElement,
				"click",
				function(event) 
				{
					this.setCollapsed( !this.isCollapsed() );
				}
			);
			
			nodeContainerElement.appendChild(shShowHideButtonElement);
		}
		
		var containerElement = $super();
		nodeContainerElement.appendChild(containerElement);
		
		if ( this.isCollapsed() ) {
			this.hideNodes(nodeContainerElement);
		} else {
			this.showNodes(nodeContainerElement);
		}
		
		return nodeContainerElement;
	},
	
	showNodes: function(nodesContainerElement)
	{
		var parent = this.getParent();
		if (
			parent instanceof UIE__treeNodesContainer &&
			parent.isCollapsed()
		) {
			parent.setCollapsed(false);
		}
		
		if (!nodesContainerElement) {
			nodesContainerElement = this.element;
		}
		if (!nodesContainerElement) {
			return;
		}
		if (this.getNodes().keys().length) {
			if ( !this.nodesElement ) {
				this.nodesElement = this.createNodesElements();
				nodesContainerElement.appendChild(this.nodesElement);
			}
			nodesContainerElement.removeClassName(this.cTreeNodesHide);
			nodesContainerElement.addClassName(this.cTreeNodesShow);
		}
	},
	
	hideNodes: function(nodesContainerElement)
	{
		if (!nodesContainerElement) {
			nodesContainerElement = this.element;
		}
		if (!nodesContainerElement) {
			return;
		}
 		nodesContainerElement.removeClassName(this.cTreeNodesShow);
		nodesContainerElement.addClassName(this.cTreeNodesHide);
	},

	createNodesElements: function(container)
	{
		var nodesElement = new Element(this.eTreeNodes, {
			'class': this.cTreeNodes
		});
		
		this.getNodes().each(function(pair) {
			var node = pair.value;
			nodesElement.appendChild(node.getElement());
		}, this);
		
		return nodesElement;
	}
});

//----------- tree class

var UIE__tree = Class.create(UIE__treeNodesContainer, {
	type: "tree"
});

//----------- treeNode class

var UIE__treeNode = Class.create(UIE__treeNodesContainer, {
	type: "treeNode"
});

//----------- collapsible class

var UIE__collapsible = Class.create(UIE__container, {
	type: "collapsible",
	cCollpasibleContainer: "collapsible",
	cCollpasibleContainerUncollapsed: "uncollapsed",
	cCollpasibleContainerCollapsed: "collapsed",
	cCollpasibleElement: "collapsibleElement",
	cCollpasibleAnchor: "collapsibleAnchor",

	eCollpasibleElement: "div",
	eCollpasibleAnchor: "span",
	eCollpasibleContainer: "div",
	tCollpasibleAnchor: '+',
//	collapsibleData: null,
//	collapsibleElement: null,
//	collapsibleAnchorElement: null,
//	collapsibleAnchorTooltip: null,
//	collapsible: null,
//  collapsibleCollapsed: true,

	initialize: function($super, id, parent, data)
	{
		$super(id, parent, data);
		this.collapsibleData = data.collapsible;
		this.collapsibleAnchorTooltip = data.anchorTooltip;
		this.collapsibleCollapsed = data.isCollapsed !== false;
		this.bindEventHandler(
			document,
			"click",
			function(event) 
			{
				if ( this.isCollapsed() ) {
					return;
				}
				var element = Event.element(event);
				if ( this.getElement() === Element.up(element, '.' + this.cCollpasibleContainer) ) {
					return;
				}
				var anchor = Element.hasClassName(element, this.cCollpasibleAnchor)
					 ? element
					 : Element.up(element, '.' + this.cCollpasibleAnchor);
//				if ( this.getCollapsibleAnchorElement() === anchor ) {
//					return;
//				}
				this.collapse();
			}
		);
	},
	unCollapse: function()
	{
		if ( this.collapsibleCollapsed === false ) {
			return;
		}
		this.collapsibleCollapsed = false;
		if ( !this.collapsibleElement ) {
			this.getElement().appendChild(this.getCollapsibleElement());
		}

		this.getElement().removeClassName(this.cCollpasibleContainerCollapsed);
		this.getCollapsibleElement().show();
	},
	collapse: function()
	{
		if ( this.collapsibleCollapsed === true ) {
			return;
		}
		this.collapsibleCollapsed = true;
		this.getElement().addClassName(this.cCollpasibleContainerCollapsed);
		this.getCollapsibleElement().hide();
	},
	isCollapsed: function()
	{
		return this.collapsibleCollapsed;
	},
	hasCollapsible: function()
	{
		return (
			(
				this.collapsible &&
				this.collapsible.keys().length
			) ||
			this.collapsibleData
		);
	},
	getCollapsible: function()
	{
		if ( !this.collapsible ) {
			this.collapsible = $H();
			if ( this.collapsibleData ) {
				$H(this.collapsibleData).each(function(pair) {
					var id = pair.key;
					var data = pair.value;
					this.collapsible.set(id, this.make(data.type, id, data));
				}, this);
			}
		}
		return this.collapsible;
	},
	getCollapsibleElement: function()
	{
		if ( !this.collapsibleElement ) {
			this.collapsibleElement = this.constructCollapsibleElement();
		}
		return this.collapsibleElement;
	},
	constructCollapsibleElement: function()
	{
		var element = new Element(this.eCollpasibleElement, {
			'class': this.cCollpasibleElement
		});

		if ( this.hasCollapsible() ) {
			this.getCollapsible().each(function(pair) {
				var childNode = pair.value.getElement();
				element.appendChild(childNode);
			}, this);
		}

		return element;
	},
//	getCollapsibleAnchorElement: function()
//	{
//		if ( !this.collapsibleAnchorElement ) {
//			this.collapsibleAnchorElement = this.constructCollapsibleAnchorElement();
//		}
//		return this.collapsibleAnchorElement;
//	},
	constructCollapsibleAnchorElement: function()
	{
		var element = new Element(this.eCollpasibleAnchor, {
			'class': this.cCollpasibleAnchor
		}).update(this.tCollpasibleAnchor);
		
		this.bindEventHandler(
			element,
			"click",
			function(event) 
			{
				if ( this.isCollapsed() ) {
				    if ( tooltip ) tooltip.hide(event);
					this.unCollapse();
				} else {
					this.collapse();
				}
			}
		);
		if ( this.collapsibleAnchorTooltip ) {
			this.bindEventHandler(
				element,
				"mouseover",
				function(event)
				{
					if ( tooltip && this.isCollapsed() ) {
						tooltip.set(event, [{'type':'string','string':this.collapsibleAnchorTooltip}]);
					}
				}
			);
		}
		return element;
	},
	constructElement: function()
	{
		var element = new Element(this.eCollpasibleContainer, {
			'class': this.cCollpasibleContainer
		});

		element.appendChild(this.getContainerElement());
		
		element.appendChild(this.constructCollapsibleAnchorElement());
		if ( !this.isCollapsed() )
			element.appendChild(this.getCollapsibleElement());
		else
			element.addClassName(this.cCollpasibleContainerCollapsed);
		
		return element;
	},
	isChanged: function($super)
	{
		return $super() || this.isCollapsibleChanged();
	},
	isCollapsibleChanged: function()
	{
		var isChanged = false;
		if (this.colpasible) { //touched
			this.getCollapsible().each(function(pair) {
				var element = pair.value;
				if (element.isChanged()) {
					isChanged = true;
					throw $break;
				}
			}, this);
		}
		return isChanged;
	},
	getData: function($super, changedOnly)
	{
		var collapsibleData = this.getCollapsibleData(changedOnly);
		var data = $super(changedOnly);
		
		if	(collapsibleData) {
			data.set("collapsible", collapsibleData);
		}
		
		return data;
	},
	getCollapsibleData: function()
	{
		if (changedOnly && !this.isCollpasibleChanged())
			return null;
		
		var data = $H();
		this.getCollpasible().each(function(pair) {
			var id = pair.key;
			var element = pair.value;
			var elementData = element.getData(changedOnly);
			if (elementData) {
				data.set(id, elementData);
			}
		}, this);
		
		return data;
	}
});

//----------- objectSwitcher class

var UIE__objectSwitcher = Class.create(UIE__collapsible, {
	type: "objectSwitcher",
	
	cCollpasibleElement: "collapsibleWrapper",
	eContainerContainer: "div",
	eCollpasibleContainer: "div",
	
	cObjectSwitcherHeader: "header",
	eObjectSwitcherHeader: "div",
	
	eObjectSwitcherChoice: "ul",
	
	eObjectSwitcherChoiceItem: "li",
	
	cObjectSwitcherMore: "more",
	eObjectSwitcherMore: "div",
	
	cObjectSwitcherSearch: "search",
	eObjectSwitcherSearch: "div",
	
	tCollpasibleAnchor: '&nbsp;',

	objectSwitcherChoiseLength: 10,
//	objectSwitcherLength: null,
//	objectSwitcherHeader: null,
//	objectSwitcherMore: null,
//	objectSwitcherURI: null,

//	objectSwitcherHeaderElement: null,
//	objectSwitcherChoiceElement: null,
//	objectSwitcherMoreElement: null,
//	objectSwitcherSearchElement: null,
//	objectSwitcherSearchInputElement: null,

	initialize: function($super, id, parent, data)
	{
		$super(id, parent, data);
		this.objectSwitcherLength = data.length;
		this.objectSwitcherHeader = data.header;
		this.objectSwitcherMore = data.more;
		this.objectSwitcherURI = data.uri;
	},
	hasObjectSwitcherHeaderElement: function()
	{
		return this.objectSwitcherHeader;
	},
	getObjectSwitcherHeaderElement: function()
	{
		if (! this.objectSwitcherHeaderElement ) {
			this.objectSwitcherHeaderElement = this.constructObjectSwitcherHeaderElement();
		}
		return this.objectSwitcherHeaderElement;
	},
	constructObjectSwitcherHeaderElement: function()
	{
		var span = new Element('span');
		span.appendChild(this.constructCollapsibleAnchorElement());
		span.insert(this.objectSwitcherHeader);

		var element = new Element(this.eObjectSwitcherHeader, {
			'class': this.cObjectSwitcherHeader
		});
		
		element.appendChild(span);

		return element;
	},
	hasObjectSwitcherChoiceElement: function()
	{
		return true;
	},
	getObjectSwitcherChoiceElement: function()
	{
		if (! this.objectSwitcherChoiceElement ) {
			this.objectSwitcherChoiceElement = this.constructObjectSwitcherChoiceElement();
		}
		return this.objectSwitcherChoiceElement;
	},
	constructObjectSwitcherChoiceElement: function()
	{
		var element = new Element(this.eObjectSwitcherChoice);
		if ( this.hasCollapsible() ) {
			this.getCollapsible().each(function(pair) {
				var childNode = new Element(this.eObjectSwitcherChoiceItem);
				childNode.appendChild(pair.value.getElement());

				this.bindEventHandler(childNode, 'mouseover', function(event){	
							   childNode.addClassName('hover');
				});
				this.bindEventHandler(childNode, 'mouseout', function(event){	
							   childNode.removeClassName('hover');
				});

				element.appendChild(childNode);
			}, this);
		}
		return element;
	},
	hasObjectSwitcherMoreElement: function()
	{
		return this.objectSwitcherMore &&
			( this.objectSwitcherLength > this.objectSwitcherChoiseLength );
	},
	getObjectSwitcherMoreElement: function()
	{
		if (! this.objectSwitcherMoreElement ) {
			this.objectSwitcherMoreElement = this.constructObjectSwitcherMoreElement();
		}
		return this.objectSwitcherMoreElement;
	},
	constructObjectSwitcherMoreElement: function()
	{
		var element = new Element(this.eObjectSwitcherMore, {
			'class': this.cObjectSwitcherMore
		});
		element.appendChild(
			new Element("a", {
				'href': this.objectSwitcherURI + '?cmd=clearFilter'
			}).update(this.objectSwitcherMore)
		);
		return element;
	},
	hasObjectSwitcherSearchElement: function()
	{
		return this.objectSwitcherLength > this.objectSwitcherChoiseLength;
	},
	getObjectSwitcherSearchElement: function()
	{
		if (! this.objectSwitcherSearchElement ) {
			this.objectSwitcherSearchElement = this.constructObjectSwitcherSearchElement();
		}
		return this.objectSwitcherSearchElement;
	},
	constructObjectSwitcherSearchElement: function()
	{
		var element = new Element(this.eObjectSwitcherSearch, {
			'class': this.cObjectSwitcherSearch
		});
		this.objectSwitcherSearchInputElement = new Element('input', {
			'type': 'text',
			'value': ''
		});
		element.appendChild(this.objectSwitcherSearchInputElement);
		var objectSwitcherSearchButtonElement = new Element('a', {
			'href': '#'
		}).update('Search');
		this.bindEventHandler(
			objectSwitcherSearchButtonElement,
			'click',
			function(event)
			{
				lon();
				document.location = this.objectSwitcherURI + '?' + $H({
					"cmd": "setFilter",
					"redirect_on_single_match": "true",
					"filter": this.objectSwitcherSearchInputElement.value
				}).toQueryString()
			}
		);
		
		element.appendChild(objectSwitcherSearchButtonElement);
		return element;
	},
	constructElement: function()
	{
		var element = new Element('div', {
			'class': this.cCollpasibleContainer
		});
		
		element.appendChild(this.getContainerElement());
		if ( !this.isCollapsed() )
			element.appendChild(this.getCollapsibleElement());	
		else
			element.addClassName(this.cCollpasibleContainerCollapsed);
		return element;
	},
	constructContainerElement: function($super) {
		var inner = new Element('span', {
			'class': 'inner'
		});
		$A($super().childNodes).each(function(childNode) {
			inner.appendChild(childNode);
		}, this);
		
		if ( this.parent instanceof UIWidget) {
			var widgetElement = this.parent.widgetElement;
			$A(widgetElement.childNodes).each(function(childNode) {
				widgetElement.removeChild(childNode);
				inner.appendChild(childNode);
			});
		}
		
		inner.appendChild(this.constructCollapsibleAnchorElement());

		var outer = new Element('span', {
			'class': 'outer'
		});
		outer.appendChild(inner);

		var element = new Element('span', {
			'class': this.cContainerContainer
		})
		element.appendChild(outer);

		return element;
	},
	constructCollapsibleElement: function()
	{
		var inner = new Element('div', {
			'class': 'inner'
		});
		if ( this.hasObjectSwitcherHeaderElement() )
			inner.appendChild(this.getObjectSwitcherHeaderElement());
		if ( this.hasObjectSwitcherChoiceElement() )
			inner.appendChild(this.getObjectSwitcherChoiceElement());
		if ( this.hasObjectSwitcherMoreElement() )
			inner.appendChild(this.getObjectSwitcherMoreElement());
		if ( this.hasObjectSwitcherSearchElement() )
			inner.appendChild(this.getObjectSwitcherSearchElement());

		var outer = new Element('div', {
			'class': 'outer'
		});
		outer.appendChild(inner);

		var element = new Element(this.eCollpasibleElement, {
			'class': this.cCollpasibleElement
		});
		element.appendChild(outer);
		
		return element;
	}	
});


//----------- dropDown class

var UIE__dropDown = Class.create(UIE__collapsible, {
	type: "dropDown",
	
	cCollpasibleElement: "collapsibleWrapper",
	eContainerContainer: "div",
	eCollpasibleContainer: "div",
	
//	cDropDownHeader: "header",
//	eDropDownHeader: "div",
//	cDropDownList: "dropDownList",
	eDropDownList: "ul",
	eDropDownListItem: "li",
	
//	dropDownHeader: null,

//	dropDownListElement: null,

	initialize: function($super, id, parent, data)
	{
		$super(id, parent, data);
		this.dropDownLength = data.length;
		this.tCollpasibleAnchor = data.header;
	},
	
	getDropDownListElement: function()
	{
		if (!this.dropDownListElement) {
			this.dropDownListElement = this.constructDropDownListElement();
		}
		return this.dropDownListElement;
	},
	
	constructDropDownListElement: function()
	{
		var element = new Element(this.eDropDownList, this.id + '_list');
		if (this.hasCollapsible()) {
			this.getCollapsible().each(function(pair) {
				var childNode = new Element(this.eDropDownListItem);
				childNode.appendChild(pair.value.getElement());

				this.bindEventHandler(childNode, 'mouseover', function(event){	
							   childNode.addClassName('hover');
				});
				this.bindEventHandler(childNode, 'mouseout', function(event){	
							   childNode.removeClassName('hover');
				});

				element.appendChild(childNode);
			}, this);
		}
		return element;
	},
	
	constructElement: function()
	{
		var element = new Element('div', {
			'class': this.cCollpasibleContainer
		});
		
		element.appendChild(this.getContainerElement());
		if ( !this.isCollapsed() )
			element.appendChild(this.getCollapsibleElement());	
		else
			element.addClassName(this.cCollpasibleContainerCollapsed);
		return element;
	},
	
	constructContainerElement: function($super) {
		var inner = new Element('span', {
			'class': 'inner'
		});
		$A($super().childNodes).each(function(childNode) {
			inner.appendChild(childNode);
		}, this);
		
		if ( this.parent instanceof UIWidget) {
			var widgetElement = this.parent.widgetElement;
			$A(widgetElement.childNodes).each(function(childNode) {
				widgetElement.removeChild(childNode);
				inner.appendChild(childNode);
			});
		}
		
		inner.appendChild(this.constructCollapsibleAnchorElement());

		var outer = new Element('span', {
			'class': 'outer'
		});
		outer.appendChild(inner);

		var element = new Element('span', {
			'class': this.cContainerContainer
		})
		element.appendChild(outer);

		return element;
	},
	
	constructCollapsibleElement: function()
	{
		var inner = new Element('div', {
			'class': 'inner'
		});		
		
		inner.appendChild(this.getDropDownListElement());
		
		var outer = new Element('div', {
			'class': 'outer'
		});
		outer.appendChild(inner);
		
		var element = new Element(this.eCollpasibleElement, {
			'class': this.cCollpasibleElement
		});
		element.appendChild(outer);
		
		return element;
	}	
});

//----------- favoritesDropDown class
var UIE__favoritesDropDown = Class.create(UIE__dropDown, {
	type: "favoritesDropDown",
	
	cGroupHeader: "group-header",
	cNoFavorites: "no-favorites",
	cButtons: "actions",
	cFavoritesHeader: "favoritesHeader",
	cFavoritesAddHeader: "favoritesAddHeader",
	cshowElementChild: "showElementChild",
	chideElementChild: "hideElementChild",
	
	cShowEditForm: "showEditForm",
	cHideEditForm: "hideEditForm",
	
	headerPrefix: "favorite_header",
	noFavoritesPrefix: "favorite_no_favorites",	
	noFavoritesSuffix: "visible",	
	
//	tCollapsibleAnchor: null,

//  current page
//	isBookmarkable: null,
//	shortcutId: null,
//	uri: null,
//	title: null,
//	description: null,
//  group: null,
//	oldTitle: null;
//	oldDescription: null,

//	child UIElements
//	editButton: null,
//	removeButton: null,
//	addButton: null,

// 	headerDiv: null,
// 	ajaxHandlerUri: null,

//  captions
//	deleteButtonCaption: null,
//	editButtonCaption: null,
//	addButtonCaption: null,
//	saveButtonCaption: null,
//	cancelButtonCaption: null,
//	titleInputCaption: null,
//  descriptionInputCaption: null,
//	noFavoritesCaption: null,

	initialize: function($super, id, parent, data)
	{
		$super(id, parent, data);
		this.tCollpasibleAnchor = data.header;
		this.isBookmarkable = data.isBookmarkable;
		this.shortcutId = data.shortcutId;
		this.uri = data.uri;
		this.oldTitle = this.title = data.title;
		this.oldDescription = this.description = data.description;
		this.group = data.group;
		
		this.ajaxHandlerUri = data.ajaxHandlerUri;
		
		this.deleteButtonCaption = data.deleteButtonCaption;
		this.editButtonCaption = data.editButtonCaption;
		this.addButtonCaption = data.addButtonCaption;
		this.saveButtonCaption = data.saveButtonCaption;
		this.cancelButtonCaption = data.cancelButtonCaption;
		this.titleInputCaption = data.titleInputCaption;
		this.descriptionInputCaption = data.descriptionInputCaption;
		this.noFavoritesCaption = data.descriptionInputCaption;
	},
	
	constructDropDownListElement: function()
	{
		var element = new Element(this.eDropDownList);
		if (this.hasCollapsible()) {
			this.getCollapsible().each(function(pair) {
				var childNode = null;
				if (pair.key.startsWith(this.headerPrefix) || pair.key.startsWith(this.noFavoritesPrefix)) {
					childNode = new Element(this.eDropDownListItem, {'id' : pair.key});
					var div = new Element('div');
					var span = new Element('span');
					span.appendChild(pair.value.getElement());
					div.appendChild(span);
					childNode.appendChild(div);
					if (pair.key.startsWith(this.headerPrefix)) {
						childNode.addClassName(this.cGroupHeader);	
					} else {
						childNode.addClassName(this.cNoFavorites);	
						if (pair.value.visible) {
							childNode.addClassName(this.cshowElementChild);	
						} else {
							childNode.addClassName(this.chideElementChild);	
						}
					}					
				} else {
					childNode = pair.value.getElement();
				}
				element.appendChild(childNode);
			}, this);
		}		
		return element;
	},
	
	constructCollapsibleElement: function()
	{
		var inner = new Element('div', {
			'class': 'inner'
		});		
		
		if (this.isBookmarkable) {
			//append header
			var div = new Element('div', {'class' : 'header'});
			var editButtonData = $H();
			editButtonData.set('caption', this.editButtonCaption);
			editButtonData.set('cActionButton', this.cFavoritesHeader);
			this.editButton = this.make('editFavoriteButton', '', editButtonData);
			var editButtonElement = this.editButton.getElement();
							
			var deleteButtonData = $H();
			deleteButtonData.set('caption', this.deleteButtonCaption);
			deleteButtonData.set('cActionButton', this.cFavoritesHeader);
			this.deleteButton = this.make('deleteFavoriteButton', '', deleteButtonData);
			var deleteButtonElement = this.deleteButton.getElement();
			
			div.appendChild(deleteButtonElement);			
			div.appendChild(editButtonElement);
			
			var addButtonData = $H();
			addButtonData.set('caption', this.addButtonCaption);
			addButtonData.set('cActionButton', this.cFavoritesAddHeader);
			this.addButton = this.make('addFavoriteButton', '', addButtonData);
			var addButtonElement = this.addButton.getElement();
			div.appendChild(addButtonElement);
			
			if (this.shortcutId) {
				editButtonElement.addClassName(this.cshowElementChild);		
				deleteButtonElement.addClassName(this.cshowElementChild);
				addButtonElement.addClassName(this.chideElementChild);
			} else {
				editButtonElement.addClassName(this.chideElementChild);		
				deleteButtonElement.addClassName(this.chideElementChild);
				addButtonElement.addClassName(this.cshowElementChild);
			}	
			inner.appendChild(div);		
			this.headerDiv = div;
		}
		
		//append list
		inner.appendChild(this.getDropDownListElement());
		
		var outer = new Element('div', {
			'class': 'outer'
		});
		outer.appendChild(inner);
		
		var element = new Element(this.eCollpasibleElement, {
			'class': this.cCollpasibleElement
		});
		element.appendChild(outer);
		
		var collapsibleData = this.getCollapsible();
			
		return element;
	},
	
	collapse : function($super) { // hide last opened form on collapse
		$super();
		if (UIE__favoritesDropDownItem.lastAccessItem) {
			UIE__favoritesDropDownItem.lastAccessItem.hideEditForm();
		}				
	},
	
	//Form
	showEditForm: function()
	{
		if (this.shortcutId) {	//show edit form only if current page is in favorites
			if (UIE__favoritesDropDownItem.lastAccessItem) {	// hide last opened form
				UIE__favoritesDropDownItem.lastAccessItem.hideEditForm();
			}
			this.hideButton(this.editButton);
			if (!this.hasEditForm()) {
				this.headerDiv.appendChild(this.getEditForm().getElement());		
			}
			this.editForm.getElement().removeClassName(this.cHideEditForm);		
			this.editForm.getElement().addClassName(this.cShowEditForm);
			this.editForm.setTitle(this.title);
			this.editForm.setDescription(this.description);
			UIE__favoritesDropDownItem.lastAccessItem = this;
		}
	},
	
	hideEditForm: function()
	{
		if (this.shortcutId && this.isBookmarkable) {	//hide edit form only if current page is in favorites and bookmarkable
			this.showButton(this.editButton);
			if (this.hasEditForm()) {
				this.editForm.getElement().removeClassName(this.cShowEditForm);		
				this.editForm.getElement().addClassName(this.cHideEditForm);
			}
		}
	},
	
	hasEditForm: function()
	{
		if (this.editForm) {
			return true;
		}
		return false;
	},
	
	getEditForm: function()
	{
		if (!this.hasEditForm()) {
			this.editForm = this.constructEditForm();
		}
		return this.editForm;
	},
	
	constructEditForm: function()
	{
		var formData = $H();
		formData.set('title', this.title);
		formData.set('description', this.description);
		formData.set('shorcutId', this.shortcutId);
		formData.set('saveButtonCaption', this.saveButtonCaption);
		formData.set('cancelButtonCaption', this.cancelButtonCaption);
		formData.set('titleInputCaption', this.titleInputCaption);
		formData.set('descriptionInputCaption', this.descriptionInputCaption);
		return this.make('editFavoriteForm', '', formData);
	},	
	
	//Buttons
	showButton: function(button)
	{
		button.getElement().removeClassName(this.chideElementChild);
		button.getElement().addClassName(this.cshowElementChild);
	},
	
	hideButton: function(button)
	{
		button.getElement().removeClassName(this.cshowElementChild);
		button.getElement().addClassName(this.chideElementChild);
	},
	
	
	onEdit: function()
	{
		this.showEditForm();	
	},
	
	onDelete: function()
	{
		this.deleteRequest(this.shortcutId);
	
		this.hideEditForm();
		this.hideButton(this.editButton);
		this.hideButton(this.deleteButton);	
		this.showButton(this.addButton);
		this.title = this.oldTitle;
		this.description = this.oldDescription;
		
		var dropDownItem = this.getCollapsible().get('favorite_' + this.group + '_' + this.shortcutId);
		dropDownItem.removeElement();
		this.getCollapsible().unset('favorite_' + this.group + '_' + this.shortcutId);		
		this.shortcutId = null;
	},
	
	onAdd: function()
	{
		this.createRequest(this.title, this.decription, this.uri);
	},
	
	onSave: function()
	{
		this.title = this.editForm.title;	
		this.description = this.editForm.description;
		
		this.updateRequest(this.shortcutId, this.title, this.description);
				
		var dropDownItem = this.getCollapsible().get('favorite_' + this.group + '_' + this.shortcutId);
		dropDownItem.setTitle(this.title);
		dropDownItem.setDescription(this.description);
		this.hideEditForm();
	},
	
	onCancel: function()
	{
		this.hideEditForm();
	},
	
	//AJAX requests
	deleteRequest: function(shortcutId) {
		new Ajax.Request(this.ajaxHandlerUri, {
			method: 'post',
			parameters: {'cmd': 'delete', 'shortcutId': shortcutId, 'ajax' : 'ajax'},
			onSuccess: function(transport) {
				//alert("deleteRequest");
			}			
		});	
	},
	
	updateRequest: function(shortcutId, title, description) {
		new Ajax.Request(this.ajaxHandlerUri, {
			method: 'post',
			parameters: {'cmd': 'update', 'shortcutId': shortcutId, 'title' : title, 'description' : description, 'ajax' : 'ajax'},
			onSuccess: function(transport) {
				//alert("updateRequest");				
			}
		});
	},
	
	createRequest: function(title, description, uri) {
		new Ajax.Request(this.ajaxHandlerUri, {
			method: 'post',
			parameters: {'cmd': 'create', 'title' : title, 'description' : description, 'uri' : uri, 'ajax' : 'ajax'},
			onSuccess: function(transport) {
				//alert("createRequest");			
				var favoritesWidget = UIWidgetManager.getWidgetById('favorites');
				favoritesWidget.getContainerChildById('favorites').createRequestHandler(transport);
			}
		});
	},
	
	createRequestHandler : function(transport) {
		if (!transport.responseText.match(/\d+/)) {
			return;
		}
		this.shortcutId = transport.responseText;	
	
		var elementId = 'favorite_' + this.group + '_' + this.shortcutId;
		var elementData = $H();
		elementData.shortcutId = this.shortcutId;
		elementData.uri = this.uri;
		elementData.title = this.title;
		elementData.description = this.description;
		elementData.group = this.group;
		elementData.editButtonCaption = 'edit';
		elementData.deleteButtonCaption = 'delete';
		var dropDownItem = this.make('favoritesDropDownItem', elementId, elementData);
		this.getCollapsible().set(elementId, dropDownItem);
		
		var dropDownItemElement = dropDownItem.getElement();
		if ('shortcuts' == this.group) {
			var headerElement = $(this.headerPrefix +'_clients');
			if (!headerElement) {
				headerElement = $(this.headerPrefix +'_domains');
			} 
			if (!headerElement) {
				headerElement = $(this.headerPrefix +'_mailnames');
			} 
			if (!headerElement) {
				$('favorites_list').appendChild(dropDownItemElement);
			} else {
				headerElement.up().insertBefore(dropDownItemElement, headerElement);
			}
		}
		else {
			var headerElement = $(this.headerPrefix + '_' + this.group);
			headerElement.up().insertBefore(dropDownItemElement, headerElement.next());
			
			//hide 'No favorites yet' element
			var noFavoritesElement = $('favorite_no_favorites_' + this.group);
			noFavoritesElement.removeClassName(this.cshowElementChild);	
			noFavoritesElement.addClassName(this.chideElementChild);
		}			
		this.hideButton(this.addButton);
		this.showButton(this.editButton);
		this.showButton(this.deleteButton);
	}
});

//----------- favoritesDropDownItem class
var UIE__favoritesDropDownItem = Class.create(UIElement, {
	type: "favoritesDropDownItem",
	
	eTitleElement: "span",
	eDropDownListElement: 'li',
	
	cGroupHeader: "group-header",
	cNoFavorites: "no-favorites",
	cshowElementChild: "showElementChild",
	chideElementChild: "hideElementChild",
	cEditFavoriteButton: "favorites-edit",
	cDeleteFavoriteButton: "favorites-delete",
	cActions: "actions",
	
	cShowEditForm: "showEditForm",
	cHideEditForm: "hideEditForm",
	
	lastAccessedItem: null,
	
//	group: null, //one of: 'clients', 'domains', 'mailnames', 'shortcuts'
//	shortcutId: null,
//	uri: null,
//	title: null,
//	description: null,
//	editButtonCaption: null,
//	deleteButtonCaption: null,

//	child UIElements
//	uri: null,
//	editButton: null,	
//	deleteButton: null,
//	editForm: null,

//	divElement: null,
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.group = data.group;
		this.shortcutId = data.shortcutId;
		this.uri = data.uri;
		this.title = data.title;
		this.description = data.description;
	},
	
	constructElement: function()
	{
		//create href
		var uri = this.make('uri', '', $H());
		uri.setURI(this.uri);
		uri.setTitle(this.description);
		var uriElement = uri.getElement();
		uriElement.appendChild(new Element(this.eTitleElement).update(this.title));
		this.uri = uri;
		
		//create buttons
		var editButtonData = $H();
		editButtonData.set('caption', this.parent.editButtonCaption);
		editButtonData.set('cActionButton', this.cEditFavoriteButton);
		this.editButton = this.make('editFavoriteButton', '', editButtonData);
		var editButtonElement = this.editButton.getElement();
		editButtonElement.addClassName(this.cshowElementChild);
			
		var deleteButtonData = $H();
		deleteButtonData.set('caption', this.parent.deleteButtonCaption);
		deleteButtonData.set('cActionButton', this.cDeleteFavoriteButton);
		this.deleteButton = this.make('deleteFavoriteButton', '', deleteButtonData);
		var deleteButtonElement = this.deleteButton.getElement();
		deleteButtonElement.addClassName(this.cshowElementChild);
		
		var span = new Element('span', {'class' : this.cActions});
		span.appendChild(editButtonElement);
		span.appendChild(deleteButtonElement);
		
		var div = new Element('div', {'class' : this.cshowElementChild});	
		div.appendChild(uriElement);
		div.appendChild(span);
		this.divElement = div;
		
		//create dropdown element
		var element = new Element(this.eDropDownListElement, {'id' : this.id});
		element.appendChild(div);
		
		this.bindEventHandler(
			element,
			'mouseover',
			function(event)
			{	
				this.getElement().addClassName('hover');	
			}
		);
		
		this.bindEventHandler(
			element,
			'mouseout',
			function(event)
			{
				this.getElement().removeClassName('hover');	
			}
		);
		
		return element;
	},
	
	removeElement : function()
	{
		if (this.hasEditForm()) {
			this.getEditForm().getElement().remove();
		}
		
		//show 'No Favorites Yet' if needed
		if ('shortcuts' != this.group) {
			var element = this.getElement();
			if ( (((element.next() && Element.hasClassName(element.next(), this.cNoFavorites))) || (!element.next())) &&
				(((element.previous() && Element.hasClassName(element.previous(), this.cGroupHeader))) || (!element.previous())) ) {
				var noFavoritesElement = $(this.parent.noFavoritesPrefix + '_' + this.group);
				noFavoritesElement.removeClassName(this.chideElementChild);
				noFavoritesElement.addClassName(this.cshowElementChild);
			}
		}
		
		this.getElement().remove();
	},
	
	setTitle: function(title)
	{
		this.title = title;
		var span = this.uri.getElement().down();
		span.update(this.title);
		if (this.parent.shortcutId == this.shortcutId) {
			this.parent.title = this.title;
		}
	},
	
	setDescription: function(description)
	{
		this.description = description;
		this.uri.setTitle(this.description);
		if (this.parent.shortcutId == this.shortcutId) {
			this.parent.description = this.description;
		}
	},	
	
	showElement: function(button)
	{
		this.divElement.removeClassName(this.chideElementChild);
		this.divElement.addClassName(this.cshowElementChild);
	},
	
	hideElement: function(button)
	{
		this.divElement.removeClassName(this.cshowElementChild);
		this.divElement.addClassName(this.chideElementChild);
	},
	
	showEditForm: function()
	{
		if (UIE__favoritesDropDownItem.lastAccessItem) {	// hide last opened form
			UIE__favoritesDropDownItem.lastAccessItem.hideEditForm();
		}
		this.hideElement();
		if (!this.hasEditForm()) {
			var itemElement = this.getElement();
			itemElement.appendChild(this.getEditForm().getElement());		
		}
		this.editForm.getElement().removeClassName(this.cHideEditForm);		
		this.editForm.getElement().addClassName(this.cShowEditForm);
		this.editForm.setTitle(this.title);
		this.editForm.setDescription(this.description);
		UIE__favoritesDropDownItem.lastAccessItem = this;
	},
	
	hideEditForm: function()
	{
		if (this.hasEditForm()) {
			this.editForm.getElement().removeClassName(this.cShowEditForm);		
			this.editForm.getElement().addClassName(this.cHideEditForm);
			this.showElement();
		}
	},
	
	hasEditForm: function()
	{
		if (this.editForm) {
			return true;
		}
		return false;
	},
	
	getEditForm: function()
	{
		if (!this.hasEditForm()) {
			this.editForm = this.constructEditForm();
		}
		return this.editForm;
	},
	
	constructEditForm: function()
	{
		var formData = $H();
		formData.set('title', this.title);
		formData.set('description', this.description);
		formData.set('shorcutId', this.shortcutId);
		formData.set('saveButtonCaption', this.parent.saveButtonCaption);
		formData.set('cancelButtonCaption', this.parent.cancelButtonCaption);
		formData.set('titleInputCaption', this.parent.titleInputCaption);
		formData.set('descriptionInputCaption', this.parent.descriptionInputCaption);
		return this.make('editFavoriteForm', '', formData);
	},	
	
	onEdit: function()
	{
		this.showEditForm();		
	},
	
	onDelete: function()
	{
		if (this.parent.shortcutId == this.shortcutId) {
			this.parent.onDelete();
		} else {
			this.parent.deleteRequest(this.shortcutId);
			this.removeElement();
		}				
	},
	
	onSave: function()
	{
		this.setTitle(this.editForm.title);
		this.setDescription(this.editForm.description);
		
		this.parent.updateRequest(this.shortcutId, this.title, this.description);
		
		this.hideEditForm();
		this.showElement();
	},
	
	onCancel: function()
	{
		this.hideEditForm();
		this.showElement();
	}
});

// --------- actionButton class

var UIE__actionButton = Class.create(UIElement, {
	type: "actionButton",
	
	eActionButton: "span",
//	cActionButton: null,
//	caption: null;
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.caption = data.get('caption');
		this.cActionButton = data.get('cActionButton');
	},
	
	constructElement: function()
	{
		var element = new Element(this.eActionButton, {
			"class" : this.cActionButton,
			"title" : this.caption
		});
		element.update(this.caption);
		return element;
	}
});

// --------- editFavoriteButton class

var UIE__editFavoriteButton = Class.create(UIE__actionButton, {
	type: "editFavoriteButton",
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.addEventHandler(
			"click",
			"clickHandler",
			this.clickHandler
		);
	},
	
	clickHandler: function() {
		this.parent.onEdit();	
	}
});

// --------- editFavoriteForm class

var UIE__editFavoriteForm = Class.create(UIElement, {
	type: "editFavoriteForm",
	
	cEditFavoriteForm: "editFavoriteForm",
	cSaveButton:	"saveButton",
	cCancelButton:	"cancelButton",
	
//	shorcutId: null,
//	title: null,
//	description: null,

//	titleInputElement: null,
//	descriptionInputElement: null,

// 	captions
//	saveButtonCaption: null,
//	cancelButtonCaption: null,
//	titleInputCaption: null,
//	descriptionInputCaption: null,
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.shortcutId = data.get('shorcutId');
		this.title = data.get('title');
		this.description = data.get('description');
		this.saveButtonCaption = data.get('saveButtonCaption');
		this.cancelButtonCaption = data.get('cancelButtonCaption');
		this.titleInputCaption = data.get('titleInputCaption');
		this.descriptionInputCaption = data.get('descriptionInputCaption');
	},
	
	constructElement: function()
	{
		var form = new Element('form', {"class" : this.cEditFavoriteForm});
		
		this.titleInputElement = new Element("input", {
			"type" : "text",
			"value" : this.title
		});		
		this.descriptionInputElement = new Element("input", {
			"type" : "text",
			"value" : this.description
		});
		
		var saveButtonElement = new Element('span', {'class': this.cSaveButton}).update(this.saveButtonCaption);
		var cancelButtonElement = new Element('span', {'class': this.cCancelButton}).update(this.cancelButtonCaption);
		var buttonsDiv = new Element('div');
		buttonsDiv.appendChild(saveButtonElement);		
		buttonsDiv.appendChild(cancelButtonElement);		
		
		form.appendChild(document.createTextNode(this.titleInputCaption));
		form.appendChild(this.titleInputElement);
		form.appendChild(document.createTextNode(this.descriptionInputCaption));
		form.appendChild(this.descriptionInputElement);
		form.appendChild(buttonsDiv);
		
		this.bindEventHandler(
			saveButtonElement,
			'click',
			this.saveHandler
		);
		
		this.bindEventHandler(
			cancelButtonElement,
			'click',
			this.cancelHandler
		);
		
		return form;
	},
	
	setTitle : function(title) {
		this.title = title;
		this.titleInputElement.value = this.title;
	},
	
	setDescription : function(description) {
		this.description = description;
		this.descriptionInputElement.value = this.description;
	},
	
	saveHandler: function() {
		this.title = this.titleInputElement.value;
		this.description = this.descriptionInputElement.value;
		this.parent.onSave();	
	},
	
	cancelHandler: function() {
		this.titleInputElement.value = this.title;
		this.descriptionInputElement.value = this.description;
		this.parent.onCancel();
	}
});

// --------- deleteFavoriteButton class

var UIE__deleteFavoriteButton = Class.create(UIE__actionButton, {
	type: "deleteFavoriteButton",
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.addEventHandler(
			"click",
			"clickHandler",
			this.clickHandler
		);
	},
	
	clickHandler: function() {
		this.parent.onDelete();
	}
});

// --------- addFavoriteButton class

var UIE__addFavoriteButton = Class.create(UIE__actionButton, {
	type: "addFavoriteButton",
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.addEventHandler(
			"click",
			"clickHandler",
			this.clickHandler
		);
	},
	
	clickHandler: function() {
		this.parent.onAdd();
	}
});

// --------- favoritesCaption class

var UIE__favoritesCaption = Class.create(UIE__caption, {
	type: "noFavoritesCaption",
	
// visible: null,
	
	initialize: function ($super, id, parent, data)
	{
		$super(id, parent, data);
		this.visible = data.visible;
	}
});

//----------- UIWidgetManager class

var UIWidgetManager = {
	widgets: {},
	
	getWidgetClassName: function(type)
	{
		return "UIWidget" + (type ? "__" + type : "");
	},

	makeWidget: function(id, data, type)
	{
		var className = this.getWidgetClassName(type);
		var widget = eval("new " + className + '(id, {"childs": data});');
		this.registerWidget(widget);
		return widget;
	},
	
	registerWidget: function(widget)
	{
		this.widgets[widget.id] = widget;
	},
	
	getWidgetById: function(id)
	{
		return this.widgets[id];
	}
};

// -------- UIWidget class

var UIWidget = Class.create(UIE__container, {
	type: "widget",
//	widgetElement: null,
//	dataElement: null,
//	submitChangesOnly: true;

	initialize: function($super, id, data)
	{
		$super(id, this, data);
		this.submitChangesOnly = !data.submitAll;
		this.widgetElement = $(this.getId());
		
		$A(this.getElement().childNodes).each(function(childNode) {
			this.widgetElement.appendChild(childNode);
		}, this);
	},
		
	// --- specific
	
	getManager: function()
	{
		return UIWidgetManager;
	},
	
	getWidget: function()
	{
		return this;
	}
	
});

// ----------- UIWidget__form
var UIWidget__form = Class.create(UIWidget, {
	type: "widget_form",

	initialize: function($super, id, data)
	{
		$super(id, data);
		// form submission value update
		var form = this.widgetElement.up("form");
		if (form) {
			this.bindEventHandler(
				form,
				"submit",
				function() {
					var data = this.getData(this.submitChangesOnly);
					if (data && !this.dataElement) {
						this.dataElement = new Element("input", {
							"name": this.getId(),
							"type": "hidden",
							"value": data ? data.toJSON() : '{}'
						});
						this.widgetElement.appendChild(this.dataElement);
					}
				}
			);
		}
	}
});