var widget_heights = new Array();
var laconica_config = '';
var laconica_init_once = 0;
function setWidgetHeight(id, second_try) {
	var e = widget_heights.pop();
	if(!e) return;
	
	e.setHeight(id);
	
	if(second_try) return;
	
	widget_heights.push(e);
	setTimeout("setWidgetHeight('" + id + "', 1)", 2000);
	
	widget_heights.push(e);
	setTimeout("setWidgetHeight('" + id + "', 1)", 5000);
}

var agt = navigator.userAgent.toLowerCase();
var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));

/**
 * widget object
 * encapsules the loading and storage procedures
 * for the widget content and arrangement
 */
var widget={
 	/**
 	 * Widget attributes, config settings
 	 */
 	 // url to receive environmental settings
 	 url_get_environment:"/ajax/widget/",
 	 
 	 // url to store user configuration
 	 url_set_userconfig:"/ajax/widget/",
 	 
 	 // url to receive single widget's data
 	 url_get_widgetdata:"/ajax/widget/",
 	 
 	 // url to store user specific data for a widget
 	 url_set_userwidget_config:"/ajax/widget",
 	 
 	 // path to the "loading" image
	 url_image_ajax_loader:"/global/images/widget/ajax_loader.gif",
	 
	 // path to the "refresh" icon
	 url_image_ajax_refresh:"/global/images/widget/ajax_refresh.gif",
	 
	 // path to the "closer" icon
	 url_image_widget_close:"/global/images/widget/widget_close.gif",
	 url_image_widget_close_active:"/global/images/widget/widget_close_active.gif",
	 
	 // path to the "config" icon
	 url_image_widget_config:"/global/images/widget/widget_config.gif",
	 url_image_widget_config_active:"/global/images/widget/widget_config_active.gif",
	 
	 // path to the "hide" icon
	 url_image_widget_hide:"/global/images/widget/widget_hide.gif",
	 url_image_widget_hide_active:"/global/images/widget/widget_hide_active.gif",
	 
	 // path to the "show" icon
	 url_image_widget_show:"/global/images/widget/widget_show.gif",
	 url_image_widget_show_active:"/global/images/widget/widget_show_active.gif",
 	 
 	 // id from the container for all widgets
 	 key_widget_container_id:"widgetarea",
 	 
 	 // id from show-customizer-link
 	 key_page_customizer_link_id:"link_customizer_menu",
 	 
 	 // prefix for widget ids
 	 key_insert_widgets_id:"widget-",
 	 
 	 // prefix for widget tabs
	 key_widgets_tab_id:"widgettab-",
	 
	 // class of widgettab
	 key_widgets_tab_class:"widgettab",
	 	 
	 // amount of desired tabs, default: 2
	 key_tab_amount:2,
	 
	 // class from widget content window
	 key_widget_content_window:"content-window",
	 
	 // class of widget-header
	 // It is important to define this key. Its used by widgets-interface to prevent false event handling
	 key_widget_header_class:"header",
	 
	 // class of widget-header title
	 key_widget_header_title_class:"title",
	 
	 // class of widget-header options holder
	 key_widget_header_options_class:"options",
	 
	 // class of widget-header options config
	 key_widget_header_options_config_class:"config",
	 
	 // class of widget-header options hide/show
	 key_widget_header_options_hide_class:"hide",
	 key_widget_header_options_show_class:"show",
	 
	 // class of widget-header options close
	 key_widget_header_options_close_class:"close",
	 
	 // class of widget-header options refresh
	 key_widget_header_options_refresh_class:"refresh",
	 
	 // class of widget-header options refresh infotext
	 key_widget_header_options_refreshinfo_class:"info",
	 
	 // id of widget info container
	 key_loading_element:"widget_info",
	 
	 // id of user config menu container
	 key_menu_id:"widget_menu",
	 
	 // class of a widget
	 key_widget_class:"widget",
	 
	 // class of all elements to hide when config menu is shown
	 key_hide_elements_class:"widget_hide",
	 
	 // class of the configuration container (from widget template)
	 key_config_container_class:"widget_config",
	 
	 // class of the widget content container (from widget template)
	 key_content_container_class:"widget_content",
	 
	 // class of response result dialog container
	 key_config_result_class:"result",
	 
	 // timeout for server response display in milliseconds
	 key_config_display_timeout:3000,
	 
	 // max height for widget content in pixel
	 key_widget_content_max_height: 400,
	 
	 // class definition for submission form elements, they are disabled to prevent sending double ajax requests
	 key_config_submit_class:'store',
	 key_config_cancel_class:'cancel',
	 key_config_options_panel:'widget_config_options',
	 
	 // environment settings and user settings
	 environment:null,
	 
	 // state of customizer-menu (shown=true/hidden=false)
	 menu_customizer_state:false,
	 
	 // default widgets, loaded when user widget list is empty: list is outsourced to sm_widget_lang_[LANG].js
	 default_widgets:[],
	 
	 // system messages .. translations are outsourced into sm_widget_lang_[LANG].js ..
	 messages:{},
	 
	 button_functions:{
	 	submit:"sendRequest()"
	 },
	 
 	/**
 	 * Initializes the loading of the user specified widgets
 	 * @param -
 	 * @return -
 	 */
 	init:function(){
 		// init widget state var
 		widget.state = {};
 		// bind action to customizer-link
 		widget.menu.bindCustomizerLink(widget.menu.display);
 		// show loading information
 		widget.loadingInfo();
 		// get user settings, setup data
 		widget.getEnvironment();
 	},
 	/**
 	 * gets environment data in json format via AJAX
 	 * returns a list of available widgets and a list of 
 	 * widgets selected by the user
 	 * @param -
 	 * @return -
 	 */
 	getEnvironment:function(){
 		$.post(widget.url_get_environment,{POSTDATA:'{"method":"initialise","id":"JsonRpcClient"}'},function(json){
			var obj = eval('('+json+')');
			widget.environment=obj.result;
			widget.render(obj.result);
			widget.menu.generateForm();
		});
 	},
 	/**
 	 * submits user data of all shown widgets via AJAX
 	 * @param obj<JSON>
 	 * @return -
 	 */
 	setAllUserWidgets:function(){
		// get widgetslist
		var objList = $.SortSerialize().o;
		
		for(x=1;x<=widget.key_tab_amount;x++)
		{
			var tabList = objList[widget.key_widgets_tab_id+x];
			
			for(y=1;y<=tabList.length;y++)
			{
				$.post(widget.url_set_userconfig,{POSTDATA:'{"method":"store_widget_settings","id":"JsonRpcClient","params":["'+tabList[y-1]+'",1,'+x+','+y+']}'});
			}
		}
 	},
 	 /**
 	 * remove a widget and submit it
 	 * @param string - widget_id
 	 */
	removeWidget:function(widget_id){
		// slide-up widget
		$('#'+widget_id).slideUp(600,function(){
			// destroy itself
			$(this).remove();
			// submit widget as inactive
			$.post(widget.url_set_userconfig,{POSTDATA:'{"method":"store_widget_settings","id":"JsonRpcClient","params":["'+widget_id+'",0,1,1]}'});
			// save new widget-coordinates to backend (this isnt necessary)
			widget.setAllUserWidgets();
		});
		// uncheck checkbox
		$('#widget_menu form input[value='+widget_id+']').attr('checked',false);
	},
	/**
	 * Log and execute function after defined time. 
	 * @param: string - widget_id
	 * @param: function - widget function to execute
	 * @param: int - time in ms
	 */
	 startTrigger:function(widget_id, exec_function, time){
	 	if(!eval("widget.state."+widget_id+".triggered")){
	 		eval("widget.state."+widget_id+".triggered = 1");
	 		window.setTimeout(widget_id+"."+exec_function+"()", time);
	 	}
	 },
 	/**
 	 * Renders all widgets
 	 * @param obj<JSON>
 	 * @return -
 	 */
 	 render:function(p_obj){
 	 	var objList = p_obj.user_widget_list;
 	 	
 	 	// prevent empty widget display
 	 	if(p_obj.user_widget_list.length <= 0 || !p_obj.user_widget_list){
 	 		objList = widget.default_widgets;
 	 	}
 	 	
 	 	// sort the list using the "y" attribute
 	 	objList.sort(widget.callbackSort);
			
 	 	// render widget tabs
 	 	// force minimum of two widget tabs
 	 	for(var i=0;i<widget.key_tab_amount;i++){
 	 		widget.renderWidgetTab((i+1));
 	 	}
 	 	
 	 	// rendering widget content
 	 	for(var i=0;i<objList.length;i++){
 	 		// init widget state holder
 	 		eval("widget.state."+objList[i].identifier+" = {}");
 	 		// save widget state (opened or not)
 	 		eval("widget.state."+objList[i].identifier+".state = "+objList[i].state);
 	 		// render widget
 	 		widget.renderWidget(objList[i].identifier, objList[i].x, objList[i].title, objList[i].state);
 	 	}
 	 },
 	 /**
 	  * Renders a single widget
 	  * @param obj, obj Widget and Widgetdata JSON Object
 	  * @param int tab tab x coord
 	  * @param String title (optional)
 	  * @return -
 	  */
 	 renderWidget:function(p_widget, tab, opt_title, widget_state){
	 	
	 	// use title or identifier as declarator
	 	var title = opt_title || p_widget;
	 	
	 	// generate refresh-icon
	 	var templ_refresh_icon = '';
	 	templ_refresh_icon += '<span class="'+widget.key_widget_header_options_refresh_class+'" style="display:none">';
	 	templ_refresh_icon += 	'<img src="'+widget.url_image_ajax_refresh+'" style="position:relative;top:-2px">';
	 	templ_refresh_icon += 	'<span class="'+widget.key_widget_header_options_refreshinfo_class+'"><!-- --></span>';
	 	templ_refresh_icon += '</span>';
	 	
	 	// generate config-icon
		var templ_config_icon = '<img class="'+widget.key_widget_header_options_config_class+'" style="display:none" src="'+widget.url_image_widget_config+'" title="'+widget.messages.show_config_dialog+'">';
	 	
	 	// generate hide- or show-icon, depending on widget state (opened or not)
	 	if(widget_state){
	 		var templ_hide_icon = '<img class="'+widget.key_widget_header_options_hide_class+'" src="'+widget.url_image_widget_hide+'" title="'+widget.messages.hide_widget_dialog+'">';
	 	}
	 	else{
	 		var templ_hide_icon = '<img class="'+widget.key_widget_header_options_show_class+'" src="'+widget.url_image_widget_show+'" title="'+widget.messages.hide_widget_dialog+'">';
	 	}
	 	
	 	// generate closer-icon
	 	var templ_closer_icon = '<img class="'+widget.key_widget_header_options_close_class+'" src="'+widget.url_image_widget_close+'" title="'+widget.messages.close_widget_dialog+'">';
	 	
	 	// check and set widget-state (if it is opened or not)
	 	var templ_widget_state = "";
	 	if(!widget_state) templ_widget_state = "height:0px";
	 	else templ_widget_state = "height:100px;";
	 	
		// render template data
		var template = "";
		template += '<div class="'+widget.key_widget_class+'" id="'+p_widget+'" style="opacity:0.6;display:none">';
		template += 	'<div class="'+widget.key_widget_header_class+'">';
		template += 		'<span class="'+widget.key_widget_header_options_class+'">' + templ_closer_icon + templ_hide_icon + templ_config_icon + templ_refresh_icon + '</span>';
		template += 		'<span class="'+widget.key_widget_header_title_class+'">'+title+'</span>';
		template += 	'</div>';
		template += 	'<div class="'+widget.key_widget_content_window+'" style="padding-bottom: 0.5em;background-image:url('+widget.url_image_ajax_loader+');'+templ_widget_state+'">';
		template += 		'<span style="margin-left:5px">'+widget.messages.widget_loading+'</span>';
		template += 	'<br clear="all" /></div>';
		template +=	'</div>';

		// fade out "widget loading information 
		widget.fadeInfo();

		// append widget to corresponding widget tab
		$('#'+widget.key_widgets_tab_id+tab).prepend(template);
		
		// register widget as new widget
		$('#'+widget.key_widgets_tab_id+tab).SortableAddItem(document.getElementById(p_widget));
		
		// add handler to hide/show the widget content
		$('#'+p_widget+' div.'+widget.key_widget_header_class+' img.'+widget.key_widget_header_options_hide_class + ',#'+p_widget+' div.'+widget.key_widget_header_class+' img.'+widget.key_widget_header_options_show_class).bind('click',function(){widget.toggle(p_widget)}).bind('mouseover', widget.changeOptionsIcon).bind('mouseout', widget.changeOptionsIcon);
			
		// add handler to close the widget
		$('#'+p_widget+' div.'+widget.key_widget_header_class+' img.'+widget.key_widget_header_options_close_class).bind('click',function(){widget.removeWidget(p_widget)}).bind('mouseover', widget.changeOptionsIcon).bind('mouseout', widget.changeOptionsIcon);
				
		// slide-in widget
		$('#'+p_widget).slideDown("slow");
		
 	 	// request content via ajax
		$.post(widget.url_get_widgetdata,{
			POSTDATA: '{"method":"get_widget","id":"JsonRpcClient","params":["'+p_widget+'"]}'
		},function(p_obj){
			var obj = eval('('+p_obj+')');
			
			// remove ajax-loader.gif
			$('#'+p_widget+' div.'+widget.key_widget_content_window).css('backgroundImage', '');
			
			// insert html into content-area
			$('#'+p_widget+' div.'+widget.key_widget_content_window).html(obj.result);
			
			// execute widget autostart-function if available
			if(eval("typeof "+p_widget+" != 'undefined'")){
				if(eval("typeof "+p_widget+".autoStart == 'function'")){
					eval(p_widget+".autoStart()")
				}
			}
			
			// check content height and set 
			widget.setHeight(p_widget);
			
			$('#'+p_widget).fadeTo("normal", 1);
					
			// add config-button to widget options, if widget is configurable
			if(widget.isConfigurable(p_widget)){
				widget.config.createConfigLink(p_widget);
				widget.config.addConfigOptions(p_widget);
			}
 	 	});
 	 },
 	 changeOptionsIcon:function(event){
 	 	var target_class = $(event.target).attr("class");
 	 	var active = "";
 	 	

 	 	
 	 	if(event.type == 'mouseover'){
 	 		active += "_active";
 	 	}
 	 	
 	 	var image_url = eval('widget.url_image_widget_'+target_class+active);
 	 	
 	 	$(event.target).attr("src", image_url);
 	 },
 	 /**
 	  * Refresh content of widget
 	  * @param string - widget-id
 	  */
 	 refreshWidget:function(p_widget){
 	 	// set refresh-info on title
 	 	$('#'+p_widget+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' span.'+widget.key_widget_header_options_refresh_class+' span.'+widget.key_widget_header_options_refreshinfo_class).text(widget.messages.info_refresh);
 	 	
 	 	// show refresh-info
 	 	$('#'+p_widget+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' span.'+widget.key_widget_header_options_refresh_class).css('display', 'inline');
 	 	
 	 	// request content via ajax
		$.post(widget.url_get_widgetdata,{
			POSTDATA: '{"method":"get_widget","id":"JsonRpcClient","params":["'+p_widget+'"]}'
		},function(p_obj){
			var obj = eval('('+p_obj+')');
			
			// insert html into content-area
			$('#'+p_widget+' div.'+widget.key_widget_content_window).html(obj.result);
			
			// execute widget autostart-function if available
			if(eval("typeof "+p_widget+" != 'undefined'")){
				if(eval("typeof "+p_widget+".autoStart == 'function'")){
					eval(p_widget+".autoStart()")
				}
			}
			
			// check and set widget height
			widget.setHeight(p_widget);
			
			// hide refresh-icon
			$('#'+p_widget+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' span.'+widget.key_widget_header_options_refresh_class).css('display', 'none');
			
			// add config-button to widget options, if widget is configurable
			if(widget.isConfigurable(p_widget)){
				widget.config.addConfigOptions(p_widget);
			}
 	 	});
 	 },
 	 /**
 	  * Check content height and set widget height
 	  * @param:	string - widget_id
 	  */
 	  setHeight:function(widget_id){
 	  		// get height of content
			var content_height = $('#'+widget_id+' div.'+widget.key_widget_content_window+' .'+widget.key_content_container_class).get(0).scrollHeight;
			if(laconica_config && !laconica_init_once) {
				widget_heights.push(widget);
				setTimeout("setWidgetHeight('" + widget_id + "')", 2000);
			}

			var content_overflow = "hidden";
			
			// check if content-height greater than limit
			if(content_height > widget.key_widget_content_max_height){
				content_height = 400;
				content_overflow = "auto";
			}
			
			// check if a min-Height is set
			if(eval("typeof "+widget_id+" == 'object'")){
				if(eval("typeof "+widget_id+".minHeight  == 'number'"))
					if(eval(widget_id+".minHeight") > content_height)
						content_height = eval(widget_id+".minHeight");
			}
			
			// save content height
			eval("widget.state."+widget_id+".content_height = "+content_height);
			
			// set content overflow handling
			$('#'+widget_id+' div.'+widget.key_widget_content_window+' div.'+widget.key_content_container_class).css({
				overflowY: content_overflow,
				height: (content_height-15)+"px"
			});
			
			// set widget height if widget is opened
			if(widget.checkState(widget_id)){
				$('#'+widget_id+' div.'+widget.key_widget_content_window).animate({
					height: (content_height)+"px"
				}, 500);
			}
 	  },
 	 /**
 	  * Renders a widget tab corresponding to
 	  * the given coordinate
 	  * @param Int counter - X coordinate for widgettab
 	  * @return -
 	  */
 	 renderWidgetTab:function(p_counter){
 	 	var template	= '<div id="'+widget.key_widgets_tab_id+p_counter+'" class="widgettab '+widget.key_widgets_tab_id+p_counter+'">';
 	 	$('#'+widget.key_widget_container_id).append(template);
		widget.initializeMove();
 	 },
 	 /**
 	  * Displays loading information in widget content area
 	  */
 	 loadingInfo:function(){
 	 	$('#'+widget.key_widget_container_id).html('<span id="'+widget.key_loading_element+'">'+widget.messages.loading_info+'</span>').css('z-index','1');
 	 },
 	 /**
 	  * Fades the info box
 	  */
 	 fadeInfo:function(){
 	 	$('#'+widget.key_loading_element).remove();
 	 },
 	 /**
 	  * Callback function to sort lists of objects
 	  * using their y-attribute
 	  * @param: Object a First object
 	  * @param: Object b Second object
 	  * @return signed int
 	  */
 	 callbackSort:function(a,b){
 	 	return (a.y > b.y) ? -1 : 1;
 	 },
 	 /**
 	  * Checks if a widget is configurable by searching for a config area
 	  * @param: String widget_id Widget's ID
 	  * @return: Boolean
 	  */
 	 isConfigurable:function(widget_id){
 	 	return ($('#'+widget_id+' .'+widget.key_config_container_class).is('div')) ? 1 : 0;
 	 },
	 /**
 	  * Initialize plugin to make the widgets moveable
 	  * @param -
 	  * @return -
 	  */
	 initializeMove:function(){
		$('div.widgettab').Sortable(
		{
			accept: 		widget.key_widget_class,
			helperclass: 	'sortHelper',
			opacity:		 0.65,
			handle: 		'div.'+widget.key_widget_header_class,
			tolerance: 		'pointer',
			onChange : function()
			{
				widget.setAllUserWidgets();
			},
			onStart : function()
			{
				$.iAutoscroller.start(this, document.getElementsByTagName('body'));
			},
			onStop : function()
			{
				$.iAutoscroller.stop();
			}
		});
	},
	/**
	  * Toggle view of widget content (slide in/slide out)
	  * @param: String "widget_id" - ID of the widget
	  */
	toggle:function(widget_id){
		// Toggle view of widget content
		if(widget.checkState(widget_id)){
			widget.hide(widget_id);
		}
		else{
			widget.show(widget_id);
		}
	},
	/**
	 * hide widget content
	 * @param: String - widget_id
	 */
	 hide:function(widget_id){
	 	// change icon to class "show" and trigger mouseover
	 	$('#'+widget_id+' .'+widget.key_widget_header_class+' .'+widget.key_widget_header_options_hide_class).removeClass(widget.key_widget_header_options_hide_class).addClass(widget.key_widget_header_options_show_class).trigger('mouseover');
	 	
	 	// hide widget content if it is shown
	 	if(widget.checkState(widget_id)){
	 		
	 		// IE peekaboo-bugfix (set display back to block)
	 		$('#'+widget_id+' div.'+widget.key_widget_content_window).css("display", "block");
	 		
	 		$('#'+widget_id+' div.'+widget.key_widget_content_window).slideUp(500, function(){
	 			// close config dialog if it is shown
			 	if(widget.config.checkState(widget_id)){
						widget.config.hideDialog(widget_id);
				}
	 		});
	 		widget.config.hideConfigLink(widget_id);
	 		// set state of widget
	 		eval("widget.state."+widget_id+".state = 0");
	 	}
		// save widget state
		$.post(widget.url_set_userconfig,{POSTDATA:'{"method":"store_widget_state","id":"JsonRpcClient","params":["'+widget_id+'",0]}'});
	 },
	 /**
	  * show widget content
	  * @param: String - widget_id
	  */
	  show:function(widget_id){
	  	// change icon to class "hide" and trigger mouseover
	  	$('#'+widget_id+' .'+widget.key_widget_header_class+' .'+widget.key_widget_header_options_show_class).removeClass(widget.key_widget_header_options_show_class).addClass(widget.key_widget_header_options_hide_class).trigger('mouseover');
	  	
	 	// show widget content if it is hidden
	 	if(!widget.checkState(widget_id)){
	 		$('#'+widget_id+' div.'+widget.key_widget_content_window).slideDown(500, function(){
	 			widget.config.showConfigLink(widget_id);
	 			// IE peekaboo-bugfix (set display to inline-block)
				if(is_ie) $('#'+widget_id+' div.'+widget.key_widget_content_window).css("display", "inline-block");
	 		});
	 		eval("widget.state."+widget_id+".state = 1");
	 	}
	 	$.post(widget.url_set_userconfig,{POSTDATA:'{"method":"store_widget_state","id":"JsonRpcClient","params":["'+widget_id+'",1]}'});
	 },
	/**
	 * check state of widget, if it is openened or not
	 * @return: boolean - true if widget is opened, false if not
	 */
	checkState:function(widget_id){
		// get state of widget
		eval("var state = widget.state."+widget_id+".state");
		return state
	},
	/**
 	  * Get the tab with the lowest amount of widgets
 	  * @return - Int counter - tab with lowest amount of widgets
 	  */
	getLowestWidgetTab:function(){
		// set first tab and its amount of widgets as initial
		var tab = 1;
		var tab_widgets = $('#'+widget.key_widgets_tab_id+'1 div.'+widget.key_widget_class).length;
		
		// traversing all tabs an compare amount of widgets
		for(i=2;i<=widget.key_tab_amount;i++)
		{
			var widgets = $('#'+widget.key_widgets_tab_id+i+' div.'+widget.key_widget_class);
			if(widgets.length < tab_widgets){
				tab = i;
				tab_widgets = widgets.length;
			}
		}
		
		return tab;
	},
	/**
	 * Menu object for storage of user settings
	 */
	menu:{
		/**
		 * Displays the configuration menu
		 */
		display:function(){
			// bind hide-action to customizer-link
 			widget.menu.bindCustomizerLink(widget.menu.hide);
			
			$('#'+widget.key_menu_id).slideDown('slow');
			widget.menu.hideElements();
			
		},
		/**
		 * Cleans the checkboxes
		 */
		clean:function(){
			$('#'+widget.key_menu_id+' fieldset').children().remove();
		},
		/**
		 * Hides the widget menu
		 */
		hide:function(){
			// bind show-action to customizer-link
 			widget.menu.bindCustomizerLink(widget.menu.display);
			
			$('#'+widget.key_menu_id).slideUp('normal');
			widget.menu.showElements();
		},
		/**
		 * Hides elements with specified class 
		 */
		hideElements:function(){
			$('.'+widget.key_hide_elements_class).slideUp(450);	
		},
		/**
		 * Shows elements with specified class 
		 */
		showElements:function(){
			$('.'+widget.key_hide_elements_class).slideDown('normal');	
		},
		/**
		 * Generates the user menu form
		 */
		generateForm:function(){
			// clean old checkboxes
			widget.menu.clean();
			
			// refill
			for(var i=0;i<widget.environment.available_widget_list.length;i++){
				widget.menu.addCheckbox(widget.environment.available_widget_list[i].identifier,widget.environment.available_widget_list[i].title);
			}
			
			// add function to handle action on change
			$('#'+widget.key_menu_id+' input.form_checkbox').bind('click',widget.menu.onClickCheckbox);
			
		},
		/**
		 * Creates checkboxes for each element
		 * @param: String name Identifier of the widget
		 * @param: String title Widget's title
		 */
		addCheckbox:function(name, title){
			var is_checked	= false;
			var list		= null;
			
			// user configuration exists?
			(widget.environment.user_widget_list.length>0) ? list=widget.environment.user_widget_list : list=widget.default_widgets;
			
			//check if widget is in user's list
			for(var i=0;i<list.length;i++){
				if(list[i].identifier == name){
					is_checked=true;
				}	
			}
			
			// render checkbox & label
			$('#'+widget.key_menu_id+' fieldset').prepend('<div class="entry"><input type="checkbox" class="form_checkbox" name="custom" id="wmenu'+name+'" value="'+name+'"/><label for="wmenu'+name+'">'+title+'</label></div>');
			
			// sets checkbox state
			if(is_checked==true){
				$('#wmenu'+name).attr('checked','true');
			}
		},
		/**
		 * Action-handler for checkboxes to create or close a widget
		 */
		onClickCheckbox:function(){
			if(this.checked)
			{
				// get title 
				var title = $(this).next().text();
				// add an widget state holder if it does not exists
				if(eval("!widget.state."+this.value)){
					eval("widget.state."+this.value+" = {}");
				}
				// set widget state to active (opened)
				eval("widget.state."+this.value+".state = 1");
				// open a new widget on tab with lowest amount of widgets
				widget.renderWidget(this.value, widget.getLowestWidgetTab(), title, 1);
				// save widget config
				widget.setAllUserWidgets();
			}
			else
			{
				// close a widget
				widget.removeWidget(this.value);
			}
		},
		/**
		 * 
		 */
		bindCustomizerLink:function(exec_function){
			// unbind all actions
			$('#'+widget.key_page_customizer_link_id).unbind();
			
			// bind new action
			$('#'+widget.key_page_customizer_link_id).bind('click', exec_function);
		}
	},
	/**
	 * object containing methods to store user specific settings for a single widget
	 */
	config:{
		/**
		 * stores settings for a single widget
		 * @param: String widget_id ID of the widget
		 * @param: keys String[] Array of strings containing the keys
		 * @param: values String[] Array of strings containing the values
		 */
		store:function(widget_id, keys, values){
			// lock form elements to prevent duplicate submission
			widget.config.lock(widget_id);

			// serializing data			
			//var m_keys=keys.toSource();
			//var m_values=values.toSource();
			var m_keys=widget.arraySerialize(keys);
			var m_values=widget.arraySerialize(values);
			
			// set info on refresh icon
			$('#'+widget_id+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' span.'+widget.key_widget_header_options_refresh_class+' span.'+widget.key_widget_header_options_refreshinfo_class).text(widget.messages.info_save_config);
			
			// show refresh-info
			$('#'+widget_id+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' span.'+widget.key_widget_header_options_refresh_class).css('display', 'inline');
			
			// ajax request
			$.post(widget.url_set_userwidget_config,{
				POSTDATA: '{"method":"setWidgetConfig","id":"JsonRpcClient","params":["'+widget_id+'",'+m_keys+','+m_values+']}'
			},
			function(response){
				var json = eval('('+response+')');
				(json.result==1) ? widget.config.showResponse(widget_id,widget.messages.store_success) : widget.config.showResponse(widget_id, widget.messages.store_error);
				
				// hide refresh-icon
				$('#'+widget_id+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' span.'+widget.key_widget_header_options_refresh_class).css('display', 'none');
				
				// hide config-dialog
				widget.config.hideDialog(widget_id, widget.refreshWidget(widget_id));
			});
		},
		/**
		 * toggle the configuration dialog
		 * @param: String widget_id
		 */
		toggleDialog:function(widget_id){
			// look if config-dialog is shown or not
			var state = $('#'+widget_id+' div.'+widget.key_config_container_class).css("display");
			
			if(state == "block")
				widget.config.hideDialog(widget_id);
			else
				widget.config.showDialog(widget_id);
		},
		/**
		 * shows the configuration dialog
		 * @param String widget_id The widget's ID
		 */
		showDialog:function(widget_id){
			// set display of config-window
			$('#'+widget_id+' div.'+widget.key_widget_content_window+' .'+widget.key_config_container_class).css('display', 'block');
			
			// get height/width of widget window
			var contentwidth = $('#'+widget_id+' div.'+widget.key_widget_content_window).width() - 15;
			var contentheight = $('#'+widget_id+' div.'+widget.key_widget_content_window).height() - 15;
			var configheight =  $('#'+widget_id+' div.'+widget.key_config_container_class).get(0).scrollHeight - 15 ;
			
			// calculate offset
			var offset = 0 - configheight;
			
			// set height/width to config-window
			$('#'+widget_id+' div.'+widget.key_widget_content_window+' .'+widget.key_config_container_class).css({
				top: offset + "px",
				width: contentwidth + "px",
				height: configheight + "px"
			});
			
			// slide down config container
			$('#'+widget_id+' div.'+widget.key_widget_content_window+' .'+widget.key_config_container_class).animate({
					top: 0
				}, 500
			);
			
			// ie has to set widget height directly instead to animate it
			if(is_ie){
				$('#'+widget_id+' div.'+widget.key_widget_content_window).css("height", configheight + 15 + "px");
			}
			else{
				$('#'+widget_id+' div.'+widget.key_widget_content_window).animate({
						height: configheight + 15 + "px"
					}, 500
				);
			}
			
			// set widget border color to yellow
			/*$('#'+widget_id).animate({
					borderColor: '#ffce00'
				}, 500
			);*/

		},
		/**
		 * hides the configuration dialog
		 * @param: String widget_id The widget's ID
		 * @param: function callback_function
		 */
		hideDialog:function(widget_id, callback_function){
			// get height of widget window
			var offset = 0 - $('#'+widget_id+' div.'+widget.key_widget_content_window).height()
			// get saved height of widget content
			eval("var content_height = widget.state."+widget_id+".content_height");

			// slide up config container
			$('#'+widget_id+' div.'+widget.key_widget_content_window+' .'+widget.key_config_container_class).animate({
					top: offset + "px"
				}, 500,
				function(){
					$('#'+widget_id+' div.'+widget.key_widget_content_window+' .'+widget.key_config_container_class).css('display', 'none');
					if(callback_function){
						eval(callback_function);
					}
				}
			);
			
			// change widget-height back to orginal size, if widget is active (shown)
			if(widget.checkState(widget_id)){
				// ie have to set widget height directly instead to animate it
				if(is_ie){
					$('#'+widget_id+' div.'+widget.key_widget_content_window).css("height", content_height+"px");
				}
				else{
					$('#'+widget_id+' div.'+widget.key_widget_content_window).animate({
							height: content_height+"px"
						}, 500
					);
				}
			}
			
			// change widget-border to grey
			$('#'+widget_id).animate({
					borderColor: '#D0CFCF'
				}, 500
			);
		},
		/**
		 * Checks state of config-dialog, if it is opened or not
		 */
		checkState:function(widget_id){
			// get state of config dialog
			var state = $('#'+widget_id+' div.'+widget.key_widget_content_window+' div.'+widget.key_config_container_class).css('display');
			
			if(state == 'block'){
				return 1;
			}
			else{
				return 0;
			}
		},
		/**
		 * Shows server response after triggered store event
		 * @param: String widget_id Widget's ID
		 * @param: String response Server response 
		 */
		showResponse:function(widget_id, response){
			// unlock form elements
			widget.config.unlock(widget_id);
			
			// generate function string for delayed execution
			var action='widget.config.hideResponse("'+widget_id+'")';
			
			// shows response text
			$('#'+widget_id+' .'+widget.key_config_container_class).append('<div class="'+widget.key_config_result_class+'">'+response+'</div>');
			
			// delayed fadeout of response text
			window.setTimeout(action,widget.key_config_display_timeout);
		},
		/**
		 * Hides server response dialog container
		 * @param: String widget_id Widget's ID
		 */
		hideResponse:function(widget_id){
			$('#'+widget_id+' .'+widget.key_config_result_class).remove();
		},
		/**
		 * Locks form elements for data submission to prevent duplicate data requests
		 * @param: String widget_id Widget's ID
		 */
		lock:function(widget_id){
			$('#'+widget_id+' .'+widget.key_config_submit_class).attr('disabled','true');
		},
		/**
		 * Unlocks form elements
		 * @param: String widget_id Widget's ID
		 */
		unlock:function(widget_id){
			$('#'+widget_id+' .'+widget.key_config_submit_class).removeAttr('disabled');
		},
		/**
		 * Create and append a config button
		 * @param: String widget_id Widget's ID
		 */
		createConfigLink:function(widget_id){
			// show config-icon in header, if widget is opened
			if(widget.checkState(widget_id)){
				$('#'+widget_id+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' .'+widget.key_widget_header_options_config_class).css("display", "inline");
			}
			// add handler to close/open the widget configuration dialog
			$('#'+widget_id+' div.'+widget.key_widget_header_class+' span.'+widget.key_widget_header_options_class+' .'+widget.key_widget_header_options_config_class).click(function(){
				widget.config.toggleDialog(widget_id);
			}).bind('mouseover', widget.changeOptionsIcon).bind('mouseout', widget.changeOptionsIcon);
		},
		/**
		 * Add config options to a config-dialog
		 * @param: widget_id (string) - ID of the widget 
		 */
		addConfigOptions:function(widget_id){
			// generate options template
			var template = '<div class="'+widget.key_config_options_panel+'">';
			template += '><a class="conf_button" onclick="'+widget_id+'.'+widget.button_functions.submit+'">'+widget.messages.button_submit+'</a>';
			template += '><a class="conf_button" onclick="widget.config.hideDialog(\''+widget_id+'\')">'+widget.messages.button_cancel+'</a>';		
			template += '</div>';
			
			// append options panel to config-window
			$('#'+widget_id+' div.'+widget.key_widget_content_window+' div.'+widget.key_config_container_class).append(template);
		},
		/**
		 * Toggle view of config button
		 */
		toggleConfigLink:function(widget_id){
			// check if widget is configurable
			if(widget.isConfigurable(widget_id)){
				$('#'+widget_id+' div.'+widget.key_widget_header_class+' .'+widget.key_widget_header_options_config_class).toggle();
			}
		},
		/**
		 * Hide the config icon from widget options
		 * @param: widget_id (string) - ID of the widget
		 */
		hideConfigLink:function(widget_id){
			$('#'+widget_id+' div.'+widget.key_widget_header_class+' .'+widget.key_widget_header_options_config_class).hide();
		},
		/**
		 * Show the config icon from widget options
		 * @param: widget_id (string) - ID of the widget
		 */
		showConfigLink:function(widget_id){
			// check if widget is configurable
			if(widget.isConfigurable(widget_id)){
				$('#'+widget_id+' div.'+widget.key_widget_header_class+' .'+widget.key_widget_header_options_config_class).show();
			}
		}
	},
	/**
	 * serialize an array
	 * @param: p_array - array
	 * @return: string - serialized array
	 */
	arraySerialize:function(p_array){
		 var str = '[';
		 for(var i=0;i< p_array.length;i++){
		 	str += '"'+p_array[i]+'"';
		 	if(i<p_array.length-1) str += ', ';
		 }
		 str += ']';
		 return str;
	}
 }

