  ///////////////////////////////////////////////////////////////////////
  // (C) 2006 Mindsnake Information Systems. All Rights Reserved.
  //
  // This software is under license and is not public domain.
  // You are not granted the right to distribute or modify
  // this software for any purposes and never to remove the
  // copyright notice, unless agreed to in writing.
  //
  // Email: info@mindsnake.com
  // Web: http://mindsnake.com
  //
  // Desc: MAP javascript helper functions
  // Modified: 29 aug 2006
  ///////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////
// SAVE SCROLL COORDINATES
//////////////////////////////////////////////////////////////////////
function _saveFWScrollCoordinates(){

	if(document.multipurpose.scx && document.multipurpose.scy){
		var p = _getFWScrollCoordinates();
		document.multipurpose.scx.value = p.x;
		document.multipurpose.scy.value = p.y;
  }
}



function _getFWScrollCoordinates(){
	var p = {x:0,y:0};

		
	if(self.pageYOffset || self.pageXOffset) // all except Explorer
	{
		p.x = self.pageXOffset;
		p.y = self.pageYOffset;
	}
	else if(document.documentElement && (document.documentElement.scrollTop||document.documentElement.scrollLeft))
		// Explorer 6 Strict
	{
		p.x = document.documentElement.scrollLeft;
		p.y = document.documentElement.scrollTop;
	}
	else if(document.body) // all other Explorers
	{
		p.x = document.body.scrollLeft;
		p.y = document.body.scrollTop;
	}
	
	
//	p.x = (document.body)?document.documentElement.scrollLeft:window.pageXOffset;
//	p.y = (document.body)?document.documentElement.scrollTop:window.pageYOffset;
	return p;
}

function _restoreScrollCoordinates(){
	if(document.multipurpose.scx && document.multipurpose.scy){
		window.scrollTo(document.multipurpose.scx.value, document.multipurpose.scy.value);
  }
}

//////////////////////////////////////////////////////////////////////
// NEW CRUD METHODS
//////////////////////////////////////////////////////////////////////
function _createFW(act,id,qs){
	

	if( _validateFWPage('CREATE_' + String(act).toUpperCase(),id) ){
		if(qs!=null && qs!=""){
			document.multipurpose.action = document.multipurpose.action+qs
		}
		
		document.multipurpose.act.value = 'create_' + act;
		if(id)
			document.multipurpose.id.value = id;
		else
			document.multipurpose.id.value = -1;
		_saveFWScrollCoordinates();
		document.multipurpose.submit();
		document.multipurpose.act.value ="";
		document.multipurpose.id.value ="";
		return true;
	}
	return false;
}

function _updateFW(act,id,qs){
	
	if( _validateFWPage('UPDATE_' + String(act).toUpperCase(),id) ){
		if(qs!=null && qs!=""){
			document.multipurpose.action = document.multipurpose.action+qs
		}
		
		document.multipurpose.act.value = 'update_' + act;

		if(id)
			document.multipurpose.id.value = id;
		else
			document.multipurpose.id.value = -1;
		_saveFWScrollCoordinates();
		
		document.multipurpose.submit();
		document.multipurpose.act.value ="";
		document.multipurpose.id.value ="";
		return true;
	}
	return false;
}

function _deleteFW(act,id,qs){
	
	if( _validateFWPage('DELETE_' + String(act).toUpperCase(),id) ){
		if(qs!=null && qs!=""){
			document.multipurpose.action = document.multipurpose.action+qs
		}
		
		document.multipurpose.act.value = 'delete_' + act;
		if(id)
			document.multipurpose.id.value = id;
		else
			document.multipurpose.id.value = -1;
		_saveFWScrollCoordinates();
		document.multipurpose.submit();
		document.multipurpose.act.value ="";
		document.multipurpose.id.value ="";
		return true;
	}
	return false;
}

//////////////////////////////////////////////////////////////////////
// LOGIN
//////////////////////////////////////////////////////////////////////
function _loginFWKeyPress(e,obj){
		
		var characterCode;
		
		if(e && e.which){
				characterCode = e.which ;
		}else if(e && window.event){
				e = window.event;
				characterCode = e.keyCode;
		}else{
			return;
		}

		if(characterCode == 13){
			if(!e) var e = window.event;
			e.cancelBubble = true;
			e.returnValue = false;

			if(e.stopPropagation){
				e.stopPropagation();
				e.preventDefault();
			}
			_loginFW(obj);
		}

}

//NOTE: Change here probably means change in postFWLoginFail also
function _loginFW(obj){
	var bi = $(obj).attr('blockId');
	
	var ref = _getFWQueryString("ref");
	
	_saveFWScrollCoordinates();

	$('#fw_loginusrnam').val($('#CMS_block_'+bi+'_usrnam').val());
	$('#fw_loginusrpas').val($('#CMS_block_'+bi+'_usrpas').val());
	
	$('#SET_block_'+bi).removeClass("SET_cssFail").addClass("SET_cssLoading");
	$('#CMS_block_'+bi+'_usrnam').parents("div.SET_cssBody:first").removeClass("SET_cssFail").addClass("SET_cssLoading");//To cover login in dialogs
	_unmarkSETInvalid($('#CMS_block_'+bi+'_usrnam').get(0));
	_unmarkSETInvalid($('#CMS_block_'+bi+'_usrpas').get(0));

	// Ajax
	_ajaxFWPost("FW_LOGIN",bi,(ref?"ref="+ref:""),"GET_EXEC",null,null,"#fw_loginusrnam,#fw_loginusrpas");
	
	$('#fw_loginusrnam').val('');
	$('#fw_loginusrpas').val('');
}



//////////////////////////////////////////////////////////////////////
// EDITION
//////////////////////////////////////////////////////////////////////

function _changeFWEdition(){
	//alert(_getFWFormObject('fw_edition_id').value)
	_saveFWScrollCoordinates();
	document.multipurpose.act.value = "FW_EDITION";
	document.multipurpose.submit();
	document.multipurpose.act.value = "";
}
//////////////////////////////////////////////////////////////////////
// RESET
//////////////////////////////////////////////////////////////////////

function _resetFW(which,qs,frm){

	if(frm == null || frm == "")
		frm = "multipurpose"
	if(which == null || which == "")
		which = "sel"
	_setFWValue('act',"fw_clr_"+which);

	_submitFW(frm,qs);
}


/////////////////////////////////////////////////////////////////////////////////////////////
// FORM AND OBJECTS TOOLS
// ------------------------------------------------------------------------------------------
// Get an object if it exists
// Retrieve values from checkboxes and radiobuttons
// Etc.
/////////////////////////////////////////////////////////////////////////////////////////////

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _resetFW(frm) DEPRECATED
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	/*function _resetFW(frm){
		if(frm == null || frm == "")
			frm = "mulitpurpose"
		if(document.forms[frm]){
			document.forms[frm].reset();
		}
	}*/
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _submitFW(frm)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	function _submitFW(frm,qs){
		if(frm == null || frm == "")
			frm = "multipurpose"
		if(document.forms[frm]){
			if(qs && qs != "")
				document.forms[frm].action = document.forms[frm].action + qs;
			_saveFWScrollCoordinates();
			document.forms[frm].submit();
		}
	}
	
	function _uploadFW(type,path,filename,qs){
			
		if(type && type != ""){

			if( _validateFWPage('UPLOAD_' + String(type).toUpperCase(),null,null) ){

				if(path == null)
					path = "";
				if(filename == null)
					filename = "";
				if(!qs)
					qs = ""
				document.forms["fileupload"].action = document.forms["fileupload"].action + "&uploadtype=" + type + "&uploadpath=" + escape(path) + "&uploadfilename=" + escape(filename)+qs;
				_submitFW("fileupload");
				
				return true;
			}
		
		}
		return false;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _setFWValue(prop,val)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	function _setFWValue(prop,val){
		var tmp;
		if( prop != '' && val != '' ){
			tmp = _getFWFormObject( prop );
			if( tmp ){
				//###Should take type into account!
				tmp.value = val;
			}
		}
	}
	
	function _setFWVal(prop,val){
			var tmp = _getFWFormObject( prop );
			if( tmp ){
				tmp.value = val;
			}
	}
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _focusFWField(id)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	function _focusFWField( id ){
		//_debug( '_focusFWField(' + id + ')', dbg_level_function );

		var obj = _getFWFormObject( id );
	
		if( obj && !window.fw_firstFocSet ){
		
			obj.focus();

			
			return true;
		}
		return false;
	}
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _getFWFormObject(id)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	function _getFWFormObject(id){
		//_debug( '_getFWFormObject(' + id + ')', dbg_level_function );
		
		// Gecko NN6, IE5+
		if(document.multipurpose){
			//_debug( 'document.getElementById (Gecko NN6, IE5+): ' + document.multipurpose[id], dbg_level_execution );
			//return document.getElementById(id);
			var x = document.multipurpose[id]; 
			if(typeof(x)=="undefined"){
				x = _getFWHTMLObject(id);
			}
			return x;
		}
		// IE4
		else if(document.all){
			//_debug( 'document.all (IE4)', dbg_level_execution );
			return document.all[id];
		}
		// NN4+
		else if(document.layers){
			//_debug( 'document.layers (NN4+)', dbg_level_execution );
			return document.layers[id];
		}
		return null;
	}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _getFWHTMLObject(id) DEPRECATED
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	function _getFWHTMLObject(id){
	//	_debug( '_getFWHTMLObject(' + id + ')', dbg_level_function );
		
		// Gecko NN6, IE5+
		if(document.getElementById){
		//	_debug( 'document.getElementById (Gecko NN6, IE5+): ' + document.getElementById(id), dbg_level_execution );
			return document.getElementById(id);
		}
		// IE4
		else if(document.all){
		//	_debug( 'document.all (IE4)', dbg_level_execution );
			return document.all[id];
		}
		// NN4+
		else if(document.layers){
		//	_debug( 'document.layers (NN4+)', dbg_level_execution );
			return document.layers[id];
		}
		return null;
	}


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// _toggleFWAll(objectname,jumpto)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	function _toggleFWAll(objectname,jumpto,toggleNoChecks){
		try{
		var bal = objectname + '_all';
		var con = $("#"+bal).get(0);
		someChanged = false;
		$("input:checkbox[name='"+objectname+"']").each(function(){
			if(this.checked!=con.checked){
				someChanged=true;
				if(con.checked){
					this.checked = true;
					// If the checkbox is in a tr, give that a class
					$(this).parents("tr.SET_cssListRow:first").addClass("SET_cssListRowSelected");
					if(toggleNoChecks){try{if(this.nextSibling.name.indexOf("_nochk")!=-1){this.nextSibling.value='';}}catch(er){}}
				}else{
					$(this).parents("tr.SET_cssListRow:first").removeClass("SET_cssListRowSelected");
					this.checked = false;
					if(toggleNoChecks){try{if(this.nextSibling.name.indexOf("_nochk")!=-1){this.nextSibling.value=this.value;}}catch(er){}}
				}
			}
				
			
		});
		/*
		if( tmp.length > 0 ){
			
			for(i = 0; i < tmp.length; i++){
				
				if(con.checked){
					tmp[i].checked = true;
					if(toggleNoChecks){		try{if(tmp[i].nextSibling.name.indexOf("_nochk")!=-1){tmp[i].nextSibling.value='';}}catch(er){}}
				}else{
					tmp[i].checked = false;
					if(toggleNoChecks){try{if(tmp[i].nextSibling.name.indexOf("_nochk")!=-1){tmp[i].nextSibling.value=tmp[i].value;}}catch(er){}}
				}
				
			}
		}
		else {
			if(con.checked){
				tmp.checked = true;
				if(toggleNoChecks){try{if(tmp.nextSibling.name.indexOf("_nochk")!=-1){tmp.nextSibling.value='';}}catch(er){}}
			}else{
				tmp.checked = false;
				if(toggleNoChecks){try{if(tmp.nextSibling.name.indexOf("_nochk")!=-1){tmp.nextSibling.value=tmp.value;}}catch(er){}}
			}
		}*/
		
		if( con.checked && jumpto != null){
			_focusFWField(jumpto);
		}
		}catch(e){}
		return someChanged;
	}


// Dual list move function
function _moveFWDualList( srcListA, destListA, moveAll, doNotSort ){
	if(typeof(srcListA)!="object") srcList = _getFWFormObject(srcListA);
	else srcList=srcListA;
	if(typeof(destListA)!="object") destList = _getFWFormObject(destListA);
	else destList=destListA;

  // Do nothing if nothing is selected
  if(  ( srcList.selectedIndex == -1 ) && ( moveAll == false )   )
  {
    return;
  }
  
 // newDestList = new Array( destList.options.length );
  
  var len = destList.options.length;
 /* for( len = 0; len < destList.options.length; len++ )
  {
    if( destList.options[ len ] != null )
    {
    newDestList[ len ] = new Option( destList.options[ len ].text, 
		destList.options[ len ].value, destList.options[ len ].defaultSelected, 
		destList.options[ len ].selected );
		newDestList[ len ].className = destList.options[ len ].className;
		}
  }*/
  
  for( var i = 0; i < srcList.options.length; i++ )
  {
    if( srcList.options[i] != null && ( srcList.options[i].selected || moveAll ) )
    {
      // Statements to perform if option is selected
      // Incorporate into new list
      destList.options[ len ]= new Option( srcList.options[i].text, 
				srcList.options[i].value, srcList.options[i].defaultSelected, 
				srcList.options[i].selected );
/*
			newDestList[ len ] = new Option( srcList.options[i].text, 
				srcList.options[i].value, srcList.options[i].defaultSelected, 
				srcList.options[i].selected );
				newDestList[ len ].className = srcList.options[i].className;*/
			len++;
		}
  }
  // Sort out the new destination list
  //newDestList.sort( compareOptionValues );   // BY VALUES
  //newDestList.sort( compareOptionText );   // BY TEXT
  // Populate the destination with the items from the new array
  
  /*for( var j = 0; j < newDestList.length; j++ )
  {
    if( newDestList[ j ] != null )
    {
    destList.options[ j ] = newDestList[ j ];
  }
  }*/
  if(!doNotSort)
		_sortFWQuickText(destList,false);
  // Erase source list selected elements
  for( var i = srcList.options.length - 1; i >= 0; i-- )
  {
    if( srcList.options[i] != null && ( srcList.options[i].selected || moveAll ) )
    {
      // Erase Source
      //srcList.options[i].value = "";
      //srcList.options[i].text  = "";
			srcList.options[i]       = null;
		}
  }
  //srcList=newDestList;
  srcList.selectedIndex = -1;
  destList.selectedIndex = -1;
} // End of _moveFWDualList()

// For migration boxes with links as "to" list
function _moveFWMigrationLink( name, item, maxToAdd, justFixButtons ){
	sel = $("#"+name+"_from").get(0);
	var mb = $("#"+name+"_wrapper");
	var div = $(sel).parents('div.SET_cssFormMigrationBoxSingle').find('div.SET_cssFormMigrationBoxTo');
	if(!justFixButtons){
		if(!item){
			if(sel.selectedIndex<0) return false;
			var o=sel.options[sel.selectedIndex];
			var template = $("#"+name+"_template");
			var item = template.clone(true);
			item.removeAttr("id").show().append("<input type='hidden' value='"+o.value+"' name='"+name+"'>");
			item.find("span:first").html(o.text);
			template.before(item);
			$(o).remove();
			sel.selectedIndex=0;
			if(sel.options.length<=0){
				if($(sel).attr("textOnEmpty")){ // If sel empty now
					var o = $(document.createElement("option"));
					o.attr("textOnEmpty","true").attr("text",$(sel).attr("textOnEmpty"));
					o.get(0).disabled=true;
					$(sel).append(o);
					sel.selectedIndex=0;
				}
			}
		}else{
			var t=item.find("span:first").html();
			var added=false;
			// Remove textOnEmpty option, if present
			$("option[textOnEmpty='true']",sel).remove();
			var o = $(document.createElement("option"));
			o.val(item.find("input:hidden:first").val());
			o.attr("text",t).html(t);
			sel.selectedIndex=-1;
			o.attr("selected","true");
			$("option",sel).each(function(){
				if(t.toLowerCase()<this.text.toLowerCase()){
					$(this).before(o);
					added=true;
					return false;
				}
			});
			if(!added) $(sel).append(o);
			item.remove();
		}
	}
	maxToAdd = parseInt(maxToAdd,10);
	if((!isNaN(maxToAdd) && $("div.SET_cssFormMigrationBoxToItem:visible",div).length>=maxToAdd) || sel.options.length<=0){
		$("div.SET_cssAddButton:first a:first",mb).hide();
		sel.disabled=true;
	}else{
		$("div.SET_cssAddButton:first a:first",mb).show();
		sel.disabled=false;
	}
	return true;
	
}


/////////////////////////////////////////////////////////////////////////////////////////////
// FORMATTING TOOLS
// ------------------------------------------------------------------------------------------
// 
/////////////////////////////////////////////////////////////////////////////////////////////

	function _padFW(val,len,what){
		val = String(val)
		what = String(what)
		if(what.length > 0){
			while(val.length<len){
				val = what + val;
			}
		}
		return val;
	}
	
function _formatFWCurrency(val,dec_char,thousands_char,num_dec){

	var orig = val;
	try{
		val = parseFloat(val);
		
		if(isNaN(val))
			return orig;
			
		num_dec = parseInt(num_dec);
		if(isNaN(num_dec))
			num_dec = 2;
			
		if(!dec_char)
			dec_char = ",";
			
		if(!thousands_char && thousands_char!="")
			thousands_char = " ";

		var n1="-";
		var x = Math.round(val * Math.pow(10,num_dec));if(x >= 0) n1=n2='';var y = (''+Math.abs(x)).split('');var z = y.length - num_dec; if(z<0) z--; for(var i = z; i < 0; i++) y.unshift('0');y.splice(z, 0, dec_char); if(y[0] == dec_char) y.unshift('0'); while (z > 3){z-=3; y.splice(z,0,thousands_char);}
		var r = n1+y.join('');
		if(num_dec==0){
			return r.replace(dec_char,"");
		}else{
			return r;
		}
	}catch(e){
		return orig;
	}
}
	

/////////////////////////////////////////////////////////////////////////////////////////////
// DHTML AND PAGE NAVIGATION TOOLS
// ------------------------------------------------------------------------------------------
// Changing styles and contents of DHTML tags
/////////////////////////////////////////////////////////////////////////////////////////////
	
function _moveFWSelected (objName, down){
	var objItem = _getFWFormObject(objName);
	var scrollPos = objItem.scrollTop;
	if(objItem.selectedIndex != -1){
		if(down){
			if(objItem.selectedIndex != objItem.options.length - 1)
				var i = objItem.selectedIndex + 1;
			else
				return;
		}
		else {
			if(objItem.selectedIndex != 0)
				var i = objItem.selectedIndex - 1;
			else
				return;
		}
		objItem.selectedIndex = objItem.selectedIndex;
		var swapOption = new Object();
		swapOption.text = objItem.options[objItem.selectedIndex].text;
		swapOption.value = objItem.options[objItem.selectedIndex].value;
		swapOption.selected = objItem.options[objItem.selectedIndex].selected;
		swapOption.defaultSelected = objItem.options[objItem.selectedIndex].defaultSelected;
		var anIndex = objItem.selectedIndex;
		for(var property in swapOption)
			objItem.options[anIndex][property] = objItem.options[i][property];
		for(var property in swapOption)
			objItem.options[i][property] = swapOption[property];
	}

	if(objItem.options[0] && objItem.options[0].clientHeight){
		
		if(down){
		
			objItem.scrollTop = scrollPos+objItem.options[0].clientHeight;
		}else{
			objItem.scrollTop = scrollPos-objItem.options[0].clientHeight;
		}
	}
}

function _selectFWAll(CONTROL){
	for(var i = 0;i < CONTROL.length;i++){
		CONTROL.options[i].selected = true;
	}
}

function _deselectFWAll(CONTROL){
	//alert(control.name);
	for(var i = 0;i < CONTROL.length;i++){
		CONTROL.options[i].selected = false;
	}
}

function _selectFWValue(sel,val){
	sel = _getFWFormObject(sel);
	
	if(sel){
	   for(var i = 0; i < sel.options.length; i++){
       if(sel.options[i].value==val)
					sel.options[i].selected = true;
	   }
	}
}

function _reviseFWQuery(qs,name,value,divider){
	if(!divider)divider = '&';
	// Remove earlier occurrences of the strType
	var splitQs = qs.split(divider);
	var newQs = '';
	name = name + '=';
	for(i=0;i<splitQs.length;i++){
		if( splitQs[i].indexOf(name) != 0 && splitQs[i] != '' ){
			newQs += splitQs[i] + divider;
			
		}
	}
	// Reinsert selected id
	newQs += name + value;
	return newQs;
}

function _reviseFWQueryState(state,name,value){
	var lsRegExp = /\+/g;
	state = unescape(String(state).replace(lsRegExp, " "));
	state = _reviseFWQuery(state,name,value);
	return escape(state);
}



/******************************************
 * STORE CURRENT
 *
 * Stores the current caret position and
 * object.
 ******************************************/
var caret = false;
var currentControl = false;
function _storeFWCurrent(ctrl){
	
	currentctrl = ctrl;
	if(ctrl&&ctrl.createTextRange)
		caret = document.selection.createRange();
}

/******************************************
 * GET SELECTED TEXT
 *
 * Gets the selected text in the
 * current control
 ******************************************/
function _getFWSelectedText(){
	if(currentControl){

		if(currentControl.createTextRange && caret){	// IE code
		
			if(caret.parentElement() == currentControl){
				var isCollapsed = caret.text == '';
				var caretLen = 0; 
				var txt = caret.text;

				while ( txt.substring( txt.length-1, txt.length) == ' '){ 
					 txt = txt.substring(0, txt.length-1); 
				}
				
				if(!txt)
					txt = "";
				return txt;
				
			}
		
		}else if(currentControl.setSelectionRange){	// Mozilla code
			var insertPoint  = currentControl.selectionStart;
			var endPoint     = currentControl.selectionEnd;
			var text         = currentControl.value;
			var selectedText = "";
						
			selectedText = text.substr(insertPoint,endPoint-insertPoint);
			while ( selectedText.substring( selectedText.length-1, selectedText.length) == ' '){ 
				selectedText =  selectedText.substring(0, selectedText.length-1); 
				endPoint -= 1;
			}
			if(!selectedText)
				selectedText="";
			return selectedText;
							
		}
	}
	return "";
}

/******************************************
 * INSERT INTO
 *
 * Inserts text in current control
 ******************************************/
 function _insertFWInCurrent(textBefore,keepSelection,textAfter){
	
	if(currentControl && (textBefore || textAfter)){

		var scrollPos = currentControl.scrollTop;
		if(!textAfter){
			textAfter = ""
		}
		if(!textBefore){
			textBefore = ""
		}
		if(currentControl.createTextRange && caret){	// IE code
		
			if(caret.parentElement() == currentControl){
				var isCollapsed = caret.text == '';
				var caretLen = 0; 
				var txt = caret.text;
				var numSpaces = 0;
				var numSpacesBefore = 0;
				/* Remove trailing space from selection adn add it AFTER everything */
				while ( txt.substring( txt.length-1, txt.length) == ' '){ 
					 txt = txt.substring(0, txt.length-1); 
					 textAfter += ' ';
					 numSpaces++;
				}
				/* Same thing: add prefixing space to BEFORE selection */
				while ( txt.substr(0,1) == ' '){ 
					 txt = txt.substr(1); 
					 textBefore = ' '+textBefore;
					 //numSpaces++;
				}

				
				if(keepSelection){
					caret.text = textBefore + txt + textAfter;
					caretLen = String(textBefore + txt + textAfter).length;
				}else{
					caret.text = textBefore + textAfter;
					caretLen = String(textBefore + textAfter).length;
				}
				
				// selection of changed text
				if(!isCollapsed)  {
					currentControl.focus();
					caret.moveStart('character', -(caretLen));
					//caret.moveStart('character', -numSpaces);
					caret.moveEnd('character', -numSpaces);
					
					caret.select();
				}

			}
		
		}else if(currentControl.setSelectionRange){	// Mozilla code
			var insertPoint  = currentControl.selectionStart;
			var endPoint     = currentControl.selectionEnd;
			var text         = currentControl.value;
			var selectedText = "";
			var sub = 0;
			
			var adjustment = 0;
			
			
			selectedText = text.substr(insertPoint,endPoint-insertPoint);
			/* Trailing spaces are added last */
			while ( selectedText.substring( selectedText.length-1, selectedText.length) == ' '){ 
				selectedText =  selectedText.substring(0, selectedText.length-1); 
				endPoint--;
			}
			/* Same thing: add prefixing space to BEFORE selection */
			while ( selectedText.substr(0,1) == ' '){ 
				 selectedText = selectedText.substr(1); 
				 textBefore = ' '+textBefore;
				 adjustment++;
			}

			if(!keepSelection){
				sub = selectedText.length;
				selectedText = "";
			}
			
			
			currentControl.value = text.substr(0,insertPoint) + textBefore + selectedText + textAfter + text.substr(endPoint);
			currentControl.focus();
			// enable to select entire text
			//currentControl.setSelectionRange(insertPoint,  endPoint + textBefore.length + textAfter.length);
			sub = ((endPoint + textBefore.length + textAfter.length) - sub) - adjustment;
			currentControl.setSelectionRange(insertPoint,  sub);
			// Enable below NOT to select newly select
			// currentControl.setSelectionRange(sub,  sub);
			
			
			
			/*	currentControl.selectionStart = endPoint;
				currentControl.selectionEnd = endPoint;*/
			
		}
		currentControl.scrollTop = scrollPos;
	}//if controls exist
}



/******************************************
 * IS SELECTED TEXT
 *
 * True if any text is selected in current
 * control
 ******************************************/
function _isFWSelectedText(){
	if(currentControl){

		//var scrollPos = currentControl.scrollTop;
		
		if(currentControl.createTextRange && caret){	// IE code
		
			if(caret.parentElement() == currentControl){
				//currentControl.scrollTop = scrollPos;
				return caret.text.length>0;
			}
		
		}else if(currentControl.setSelectionRange){	// Mozilla code
			var insertPoint  = currentControl.selectionStart;
			var endPoint     = currentControl.selectionEnd;
			var text         = currentControl.value;

			//currentControl.scrollTop = scrollPos;
			return text.substr(insertPoint,endPoint-insertPoint).length>0;
			
		}
		
	}//if controls exist
	return false;
}

/******************************************
 * REMOVE OCCURANCES
 *
 * Removes all occurances of reg-exps in 
 * array (of reg exps) @rem from @from
 ******************************************/
function _removeFWOccurances(from,rem){

	for(i=0;i<rem.length;i++){
		try{
		from = from.replace(rem[i],"")
		}catch(e){
			alert(e+"\n"+rem[i]);
		}
	}
	return from;
	
}

/******************************************
 * EXTRACT LINK
 *
 * Returns the url in the value of the field
 * with "id". If the value is splitted with
 * fwDiv (which means it's an internal link),
 * we get the other half, otherwise just
 * get the value
 ******************************************/
function _extractFWLink(id,split){

	return _extractFW(id,split,1);
}

function _extractFW(id,split,pos){
	if(!split || split == "" ||split == null)
		split = "|";
	if(!pos)
		pos = 1;
		
	var temp = document.getElementById(id);
	if(temp && temp.value){
		temp = String(temp.value).split(split);
		
		if(pos < temp.length){
			return temp[pos];
		}
	}
	if(temp[0])
		return temp[0];
	else
		return "";
}
/******************************************
 * RESET CLASS
 *
 * Removes the removeClass from element's 
 * className string (if present).
 ******************************************/ 
function _resetFWClass(element,removeClass,noSpace){
	if(!element)
		return;
	if(!element.className)
		return;
	var sp;
	if(noSpace)
		sp = "";
	else
		sp = " ";
	var className = element.className;
	if(className.indexOf(removeClass)!=-1){
		if(className && className != "" && className.length > removeClass.length){
			className = String(className);
			if(className.substr(className.length-(removeClass.length+sp.length)) == sp + removeClass){
				//alert("1: "+element.className);
				element.className = className.substr(0,className.length-(removeClass.length+sp.length));
				//alert("2: "+element.className);
			}
		}else if(className == removeClass){
			element.className = "";
		
		}
	}
	
}

/******************************************
 * APPEND CLASS
 *
 * Appends appClass to element's className
 ******************************************/ 
function _appendFWClass(element,appClass,noSpace){
	if(!element)
		return;
	if(element.className==null)
		return;	
		
	var sp;
	if(noSpace)
		sp = "";
	else
		sp = " ";
	if(element.className.indexOf(appClass)==-1)
		element.className = element.className+sp+appClass;
}


// Uses Iterative (non-recursive) Quick Sort Algorithm
// from Knuth, D.  The art of computer programming, vol. 3
//                 sorting and searching
//
// usage: _sortFWQuickText(document.formname.selectname, {true|false} )
//        true  = keep selected
//        false = unselect all

function _sortFWQuickText( obj, opt ){ // sort by text
  var Left  = 0, Right = obj.options.length-1, top = 1;
  var lStack = new Array(), rStack = new Array();
      lStack[top] = Left; rStack[top] = Right;
  while (top!=0){
    Left  =  lStack[top]; Right =  rStack[top]; top--;
    while (Left < Right){
      var i = Left, j = Right, n = Left+Right;
      var k = Math.floor(n / 2)
      var x = obj.options[k].text;
      while (i <= j){
        while (obj.options[i].text < x){ i++ }
        while (obj.options[j].text > x){ j-- }
        if(i <= j){
          var i1= (obj.options[i].selected == true ) ? true : false
          var j1= (obj.options[j].selected == true ) ? true : false
          var q1 = obj.options[j].text;
          var q2 = obj.options[j].value;
          obj.options[j].text  = obj.options[i].text;
          obj.options[j].value = obj.options[i].value;
          obj.options[i].text  = q1;
          obj.options[i].value = q2;
          obj.options[i].selected = (j1&opt) ? true : false
          obj.options[j].selected = (i1&opt) ? true : false
          i++; j--
        }
      }
      if((j - Left) < (Right - i)){
        if(i < Right){ top++; lStack[top] = i; rStack[top] = Right }
        Right = j;
      }
      else {
        if(Left < j){ top++; lStack[top] = Left; rStack[top] = j }
        Left = i;
      }
    }
  }
  return true
}

// usage: _sortFWQuickValue(document.formname.selectname, {true|false} )
//        true  = keep selected
//        false = unselect all

function _sortFWQuickValue( obj, opt ){ // sort by value
  var Left  = 0, Right = obj.options.length-1, top = 1;
  var lStack = new Array(), rStack = new Array();
      lStack[top] = Left; rStack[top] = Right;
  while (top!=0){
    Left  =  lStack[top]; Right =  rStack[top]; top--;
    while (Left < Right){
      var i = Left, j = Right, n = Left+Right;
      var k = Math.floor(n / 2)
      var x = obj.options[k].value;
      while (i <= j){
        while (obj.options[i].value < x){ i++ }
        while (obj.options[j].value > x){ j-- }
        if(i <= j){
          var i1= (obj.options[i].selected == true ) ? true : false
          var j1= (obj.options[j].selected == true ) ? true : false
          var q1 = obj.options[j].text;
          var q2 = obj.options[j].value;
          obj.options[j].text  = obj.options[i].text;
          obj.options[j].value = obj.options[i].value;
          obj.options[i].text  = q1;
          obj.options[i].value = q2;
          obj.options[i].selected = (j1&opt) ? true : false
          obj.options[j].selected = (i1&opt) ? true : false
          i++; j--
        }
      }
      if((j - Left) < (Right - i)){
        if(i < Right){ top++; lStack[top] = i; rStack[top] = Right }
        Right = j;
      }
      else {
        if(Left < j){ top++; lStack[top] = Left; rStack[top] = j }
        Left = i;
      }
    }
  }
  return true
}

/*************************************************
 * SUBMIT ON ENTER
 *
 * Submits the form on enter. If act is
 * supplied, validation is performed as well.
 ************************************************/
function _onFWEnter(e,fun,charCode){
	if(!charCode){
		try{
			if(window.event){
				e = window.event;
				charCode = e.keyCode;//
			}else{
				charCode = e.which;
			}
		}catch(er){}
		if(charCode) setTimeout(function(){_onFWEnter(null,fun,charCode);},0);
		if(charCode==13){
			e.cancelBubble = true;
			e.returnValue = false;
			if(e.stopPropagation){
				e.stopPropagation();
				e.preventDefault();
			}
		}
	}else if(charCode==13 && $.isFunction(fun)){
		fun();
	}
	
}

function _submitFWOnEnter(e,act,id,qs){
	
	var characterCode;
	if(window.event){
		e = window.event;
	  characterCode = e.keyCode;//
	}else{
		characterCode = e.which;
	}
	/*if(e && e.which){ //
	alert("0");
	    e = e;
	    characterCode = e.which ;//
	}else{
		alert("1");
	    e = event;
	    characterCode = e.keyCode;//
	}

*/

	setTimeout("var v=_submitFWOnEnterTimeout("+characterCode+",'"+(act?act:"")+"','"+(id?id:"")+"','"+(qs?qs:"")+"')",0);

}

function _submitFWOnEnterTimeout(characterCode,act,id,qs){

	if(characterCode == 13){
		if(act){

			if( _validateFWPage(String(act).toUpperCase(),id) ){
			
			
				if(id)
					document.multipurpose.id.value = id;
				else
					document.multipurpose.id.value = -1;
				_submitFW('',qs);
				return false;
			}
		}else{

			_submitFW('',qs);
			return false;
		}
	}
	
	return true;
}

/************
 * GCD
 */
function _getFWgcd(a, b){
   var r, x, y
   x = a
   y = b
   while (y != 0)
   {
      // Invariant:
      // gcd(a,b)=gcd(x,y) 
      r = x % y
      x = y
      y = r
   }
   return x
}

/************
 * LCM
 */
function _getFWlcm(t1,t2){
  var cm=1;
  var f=hcf(t1,t2);
  cm=t1*t2/f;
  return cm;
}



/****************************************
 * SHOW AT
 * Shows obj at x and y
 * Does not account for how the object
 * is positioned. Assumes "absolute" and
 * with "body" as nearest parent.
 */
function _showFWAt(obj, x, y, styleDisplay,isFixed){
	if(!obj)return;
	//fixed for IE6 is position absolute with expression set in css so just set necessary left + top to use in the css expression
	if(isFixed && $("body").hasClass("PC_IE6")){
		obj.IE6Left = x;
		obj.IE6Top = y;
	}else{
		obj.style.left = x + "px";
		obj.style.top = y + "px";
	}
	if(styleDisplay!=null)
		obj.style.display=styleDisplay;
	else
		_resetFWClass(obj,"hidden");
}

/****************************************
 * SHOW AT ELEMENT
 * Shows obj below el with opts
 * opts may contain combo of:
 * T = above el
 * R = to the right of el
 * O = on top of el (both x and y axis)
 * B = below el
 * L = to the left of el
 * A = askew to the right
 * <null> = below el
 */
 
function _showFWAtElement(obj, el, opts, xmod,ymod, styleDisplay, isFixed, dblPos){
	var iter = 1;

	if(dblPos){
		iter = 2;
		$(obj).css('z-index', '-1000').show(); //hide through z-index instead of display:none so that obj will cause scrollbars if necessary
	}

	for(i=1; i<=iter; i++){
		var p = _getFWAbsolutePos(el);

		//IE6 use position:absolute to simulate position:fixed so that position is set via expression in css
		if(isFixed && !$("body").hasClass("PC_IE6")){
			/*var scr = _getFWScrollCoordinates();
			p.x += scr.x;
			p.y += scr.y;*/
		}

		//p = { x: 937, y: 252 };
		if(!xmod)
			xmod = 0;
		if(!ymod)
			ymod = 0;
			
		p.x += xmod;
		p.y += ymod;

		//alert( p.x+", "+(p.y + el.offsetHeight));
		if(!opts) opts="B";
				
		if(opts.toUpperCase().indexOf("B")!=-1)	p.y += el.offsetHeight;
		if(opts.toUpperCase().indexOf("T")!=-1) p.y -= obj.offsetHeight;
		if(opts.toUpperCase().indexOf("R")!=-1) p.x += el.offsetWidth;
		if(opts.toUpperCase().indexOf("I")!=-1) p.x -= obj.offsetWidth;
		if(opts.toUpperCase().indexOf("L")!=-1) p.x = (p.x - obj.offsetWidth) + el.offsetWidth;
		if(opts.toUpperCase().indexOf("A")!=-1) p.x += parseInt(el.offsetWidth/4,10);

		_showFWAt(obj, p.x, p.y, styleDisplay,isFixed);

		if(i==iter){
			if(dblPos)$(obj).css('z-index', '');
			return;
		}
	}

	if(dblPos){
		$(obj).css('z-index', '');
	}
}
 
 /****************************************
 * GET ABSOLUT POS
 * Returns the absolute position of el
 * as a point object p.x, p.y
 */
function _getFWAbsolutePos(el){
	var r = { x: 0, y: 0 };
	if(el){
		/*
		var o = $(el).offset(); // jQuery method is A LOT faster, but results in ONE too little for left (or rather, it sometimes returns half pixels), maybe use later
		_c(o.left,o.top);
	
		r.x=o.left;r.y=o.top;
		*/
		var SL = 0, ST = 0;
		var is_div = /^div$/i.test(el.tagName);
		if(is_div && el.scrollLeft)
			SL = el.scrollLeft;
		if(is_div && el.scrollTop)
			ST = el.scrollTop;
		r.x = el.offsetLeft - SL;
		r.y = el.offsetTop - ST;
		if(el.offsetParent){
			var tmp = _getFWAbsolutePos(el.offsetParent);
			r.x += tmp.x;
			r.y += tmp.y;
		}
	
		
	}
		
	return r;
}

function _c(){
	var str="";
	for(i=0;i<arguments.length;i++){
		if(i>0) str+=" | ";
		str+=arguments[i];
	}
	try{console.log(str)}catch(er){alert(str);}
}
function _a(){
	var str="";
	for(i=0;i<arguments.length;i++){
		if(i>0) str+=" | ";
		str+=arguments[i];
	}
	alert(str);
}
function _t(){
	var str="";
	for(i=0;i<arguments.length;i++){
		str+=" | ";
		str+=arguments[i];
	}
	if(document.title.length>512) document.title="";
	document.title+=str;
}



function _getFWMouseCoordinates(e){
	var posx = 0;
	var posy = 0;
	if(!e) var e = window.event;
	if(e.pageX || e.pageY) 	{
		posx = e.pageX;
		posy = e.pageY;
	}
	else if(e.clientX || e.clientY) 	{
		posx = e.clientX + document.body.scrollLeft
			+ document.documentElement.scrollLeft;
		posy = e.clientY + document.body.scrollTop
			+ document.documentElement.scrollTop;
	}
	// posx and posy contain the mouse position relative to the document
	// Do something with this information
	return {x:posx,y:posy};
}

/**********************
 * PREVENTS SUBMIT
 */
function _preventFWSubmit(e,chr){
	var characterCode;
	if(!chr){
		chr = 13;
	}
	if(e && e.which){ 
	    characterCode = e.which;
	}else{
	    e = window.event;
	    characterCode = e.keyCode;
	}

	if(characterCode == chr){
		return false;
	}
	return true;
}

/**********************
 * LIMIT WIDTH
 */
function _limitFWWidth(str, perChar, width, dots){
	width = Math.round(parseFloat(width)/parseFloat(perChar));

	var output = "";

	if(str.length > width){
		output = str.substr(0,width) + dots;
	}else{
		output = str;
	}

	return output;
}



/*****************
 * Expand and contract a div with more content
 */

function _expandFW(e,target,str,hoverClass,doReplace,delay){
		e = _initFWieEvent(e);
		if(!target || target.isExpanded || str=="")
			return;

		target.isExpanded = true;	
		target.oldInnerHTML = target.innerHTML;
		if(doReplace){
			target.innerHTML = str;
		}else{
			target.innerHTML += str;
		}
			
		if(hoverClass)
			_appendFWClass(target,hoverClass);

}

function _contractFW(e,target,hoverClass,delay){
	
	e = _initFWieEvent(e);
	
	if(!target)
			return;
	
	if(target.isExpanded){
		
		// Only hide it if the newly gained focus thingy is NOT a child of the hintBox
		if(e){
		
			var mpoint = _getFWMouseCoordinates(e);
			if(_isFWPointWithinTarget(mpoint,target))	
				return;
		}
	
		target.innerHTML = target.oldInnerHTML;
		target.isExpanded = false;
		target.oldInnerHTML = null;
		if(hoverClass)
			_resetFWClass(target,hoverClass);
	}
}

/* Use this method to add events so that IE also understands it */
function _addFWEvent(el, evname, func){
	if(el.attachEvent){ // IE
		el.attachEvent("on" + evname, func);
	} else if(el.addEventListener){ // Gecko / W3C
		el.addEventListener(evname, func, true);
	} else {
		el["on" + evname] = func;
	}
}

function _removeFWEvent(el, evname, func){
	if(el.detachEvent){ // IE
		el.detachEvent("on" + evname, func);
	} else if(el.removeEventListener){ // Gecko / W3C
		el.removeEventListener(evname, func, true);
	} else {
		el["on" + evname] = null;
	}
}


/* This is here to ensure JS 1.5 extended array filter function for non-mozilla browsers*/
if(!Array.prototype.filter){
  Array.prototype.filter = function(fun){
    var len = this.length;
    if(!$.isFunction(fun)) return;

    var res = new Array();
    var thisp = arguments[1];
    for(var i = 0; i < len; i++){
      if(i in this)
      {
        var val = this[i]; // in case fun mutates this
        if(fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}

// Moves caret to end of field
function _setFWCaretToEnd(control){
  if(ctrl.createTextRange){
    var range = ctrl.createTextRange();
    range.collapse(false);
    range.select();
  }else if(ctrl.setSelectionRange){
    ctrl.focus();
    var length = ctrl.value.length;
    ctrl.setSelectionRange(length, length);
  }
}

// Use to initialize standard event handling with ie
function _initFWieEvent(e){
	try{
		if(navigator.userAgent.toLowerCase().indexOf("msie") == -1 || navigator.userAgent.toLowerCase().indexOf("opera") != -1){
			
			// Nada
			
		}else{
			
			if(!e){
				e = window.event;
			}
			
			if(!e.target){
				e.target=e.srcElement;
			}
		
		}
		
		if(e && e.which){
	    e.keyCode = e.which;
		}else if(e && window.event){
	    e.which = e.keyCode;
	  }
	  
	}catch(ev){
	}	
	return e;
}


function _clearFWTimeout(all){
	try{
	if(window.timer){
		clearTimeout(window.timer);
		window.timer = null; 
	}
	if(all==true){
		if(window.timer2){
			clearTimeout(window.timer2);
			window.timer2 = null; 
		}
	}
	
	}catch(e){
	
	}
}

// Replaces a qs attrib in form action
function _reviseFWFormAction(atr,val){
	atr=atr.toLowerCase();
	var act = String(document.multipurpose.action);
	var re = new RegExp("([\?&]"+atr+")=[^&]*","gi");
	if(act.search(re)!=-1)
		act = act.replace(re,"$1="+escape(val));
	else
		act = act + "&"+ atr + "=" + escape(val);
		
	//alert(act.replace(re,"$1="+escape(val)));
		
	document.multipurpose.action = act;
	_setFWValue(atr,val);
}


// Inits side chain submit
function _preFWSideChainSubmit(noUnmark){
	document.multipurpose.target='sidechainIframe';
	if(noUnmark)
		window.fw_noUnmark=true;
}

// Must be done after side chain submit to reset things
function _postFWSideChainSubmit(){
	document.multipurpose.target='_self';
	_getFWFormObject("act").value='';
	window.fw_noUnmark=null;
}




function _getFWWindowSize(){
	var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ){
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ){
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ){
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return {width:myWidth,height:myHeight};




}

// Checks if a specified point is within the bounding box of the object target
function _isFWPointWithinTarget(mpoint,target,adjH,adjW,isFixed,adjustForTargetScroll){
	if(!target) return false;
	var point = _getFWAbsolutePos(target);
	if(isFixed){
		var scr = _getFWScrollCoordinates();
		point.x += scr.x;
		point.y += scr.y;
	}
	if(adjustForTargetScroll){
		target = $(target);
	
		point.x += target.scrollLeft();
		point.y += target.scrollTop();
		target = target.get(0);
		
	}

	//IE requires +2px for some values, Safari for others
	var adj=0;
	if(adjH==null) adjH=0;
	if(adjW==null) adjW=0;
	if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
		adj=1;
	}else if(navigator.userAgent.toLowerCase().indexOf("safari") != -1){
		//adjW=-1;
	}
	
	// If mouse pointer is within menu OR within field, don't continue
	//document.title = "mouse: "+mpoint.x+" "+mpoint.y+" - left/top:"+point.x+" "+point.y+" - right/bottom:"+(point.x+target.offsetWidth)+" "+(point.y+target.offsetHeight);
	if(!(mpoint.x > ((point.x+target.offsetWidth)+adjW) || mpoint.x <= (point.x+adj)
		|| mpoint.y > ((point.y+target.offsetHeight)+adjH) || mpoint.y <= (point.y+adj))){
		//alert("mouse: "+mpoint.x+" "+mpoint.y+"\nleft/top:"+point.x+" "+point.y+"\nright/bottom:"+(point.x+window.menuBox.offsetWidth)+" "+(point.y+window.menuBox.offsetHeight));
		return true;
	}
	return false;
}


// Takes a string of field names, extracts and sums values of those fields and puts in target field
function _sum(flds,tar,doRound){
	flds = String(flds).split(",");
	var sum = 0;
	for(i=0;i<flds.length;i++){
		f = _getFWFormObject(flds[i]);
		if(f&&f.value!=null&&!isNaN(parseFloat(f.value.replace(/,/,".")))){
			sum += parseFloat(f.value.replace(/,/,"."));
		}
	}
	if(doRound)
		sum = Math.round(sum);


	if(tar){
		tarDisp = _getFWHTMLObject(tar+"_display");
		tar = _getFWFormObject(tar);
		
		if(tar&&tar.value!=null){
			if(sum>0)
				tar.value = sum;
			else
				tar.value = "";
		}
		if(tarDisp){
			// Note: no format of value
			if(sum>0)
				tarDisp.innerHTML=sum;
			else
				tarDisp.innerHTML="";
		}
	}
	return sum;
}


function _getFWViewportSize(){
	var p={x:0,y:0};
	if(self.innerHeight) // all except Explorer
	{
		p.x = self.innerWidth;
		p.y = self.innerHeight;
	}
	else if(document.documentElement && document.documentElement.clientHeight)
		// Explorer 6 Strict Mode
	{
		p.x = document.documentElement.clientWidth;
		p.y = document.documentElement.clientHeight;
	}
	else if(document.body) // other Explorers
	{
		p.x = document.body.clientWidth;
		p.y = document.body.clientHeight;
	}
	return p;
}

/***********************************************
 * COMPARE VERSIONS
 *
 * -1 if v1 is newer/greater than v2
 * 0 if v1 is the same version as v2
 * 1 if v1 is older/smaller than v2
 * Ex:
 * 2.5.1 , 1.6.0.1	= -1
 * 4.0.0 , 4				= 0
 * 3.0.1.5 , 3.0.2	= 1
 **********************************************/
function _compareFWVersions(v1,v2){
	if(v1==null)
		return 1;
	if(v2==null)
		return -1;

	v1 = String(v1).split(".");
	v2 = String(v2).split(".");
	
	var max;
	var ub1 = v1.length;
	var ub2 = v2.length;
	if(ub1>ub2)
		max = ub1;
	else
		max = ub2;
	
	//Start comparing from left to right
	for(ix=0;ix<max;ix++){
		if(ix<=ub1 && ix<=ub2){
			
			if(isNaN(parseInt(v1[ix],10)))
				return 1;
			if(isNaN(parseInt(v2[ix],10)))
				return -1;
				
			if(parseInt(v1[ix]) > parseInt(v2[ix],10))
				return -1;
			else if(parseInt(v1[ix]) < parseInt(v2[ix],10))
				return 1;
				
		}else if(ix<=ub1){
			if(parseInt(v1[ix],10) > 0)
				return -1;
		}else{
			if(parseInt(v2[ix],10) > 0)
				return 1;
		}
	}
	return 0;
}


function _getFWFlash(id,src,width,height,quality,xtras,moreParams){
	//Opera executes this twice from a single asp call sometimes (always?)
	//Thus we check if an object with same id already exists
	var x = _getFWHTMLObject(id);
	if(x) return;

	var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
	var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
	var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;
  var str = '';
  if(isIE && isWin && !isOpera)
  {
  	str += '<object align="middle" type="application/x-shockwave-flash" width="'+width+'" height="'+height+
  				 '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="'+id+'" '+xtras+'>';
  	str += '<param name="movie" value="' + src + '" /> ';
  	str += '<param name="allowScriptAccess" value="sameDomain" /> ';
  	if(quality)
  		str += '<param name="quality" value="' + quality + '" /> ';
  		
  	if(moreParams){
  		var wmode="";
  		str += '<param name="flashvars" value="';
  		for(i=0;i<moreParams.length;i++){
  			if(moreParams[i].name!="wmode"){
  				if(i>0)
  					str += '&amp;';
  				str += moreParams[i].name+'=' + moreParams[i].value;
  			}else{
  				wmode=moreParams[i].value;
  			}
  		}
  		str += '" />';
  		
  		if(wmode){
  			str += '<param name="wmode" value="'+wmode+'" />';
  		}

  	}
  	str += '</object>';
  } else {
  	str += '<embed align="middle" allowScriptAccess="sameDomain" quality="'+quality+'" type="application/x-shockwave-flash" width="'+width+'" height="'+height+
  				 '" src="'+src+'" id="'+id+'" name="'+id+'" '+xtras;
  	 if(moreParams){
  		var wmode="";
  		str += ' flashvars="';
  		for(i=0;i<moreParams.length;i++){
  			if(moreParams[i].name!="wmode"){
  				if(i>0)
  					str += '&amp;';
  				str += moreParams[i].name+'=' + moreParams[i].value;
  			}else{
  				wmode=moreParams[i].value;
  			}
  		}
  		str += '"';
  		
  		if(wmode){
  			str += ' wmode="'+wmode+'"';
  		}
  	}
  	str += '></embed>';
  }
	return str;
}

function _createFWKeyboardShortcut(shortcut,callback,opt){
	//Provide a set of default options
	var default_options = {
		'type':'keydown',
		'propagate':false,
		'target':document
	}
	if(!opt) opt = default_options;
	else {
		for(var dfo in default_options){
			if(typeof(opt[dfo]) == 'undefined') opt[dfo] = default_options[dfo];
		}
	}

	var ele = opt.target
	if(typeof(opt.target) == 'string') ele = document.getElementById(opt.target);
	var ths = this;

	//The function to be called at keypress
	var func = function(e){
		e = e || window.event;
		
		//Find Which key is pressed
		if(e.keyCode) code = e.keyCode;
		else if(e.which) code = e.which;
		var character = String.fromCharCode(code).toLowerCase();

		var keys = shortcut.toLowerCase().split("+");
		//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
		var kp = 0;
		
		//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
		var shift_nums = {
			"`":"~",
			"1":"!",
			"2":"@",
			"3":"#",
			"4":"$",
			"5":"%",
			"6":"^",
			"7":"&",
			"8":"*",
			"9":"(",
			"0":")",
			"-":"_",
			"=":"+",
			";":":",
			"'":"\"",
			",":"<",
			".":">",
			"/":"?",
			"\\":"|"
		}
		//Special Keys - and their codes
		var special_keys = {
			'esc':27,
			'escape':27,
			'tab':9,
			'space':32,
			'return':13,
			'enter':13,
			'backspace':8,

			'scrolllock':145,
			'scroll_lock':145,
			'scroll':145,
			'capslock':20,
			'caps_lock':20,
			'caps':20,
			'numlock':144,
			'num_lock':144,
			'num':144,
			
			'pause':19,
			'break':19,
			
			'insert':45,
			'home':36,
			'delete':46,
			'end':35,
			
			'pageup':33,
			'page_up':33,
			'pu':33,

			'pagedown':34,
			'page_down':34,
			'pd':34,

			'left':37,
			'up':38,
			'right':39,
			'down':40,

			'f1':112,
			'f2':113,
			'f3':114,
			'f4':115,
			'f5':116,
			'f6':117,
			'f7':118,
			'f8':119,
			'f9':120,
			'f10':121,
			'f11':122,
			'f12':123
		}


		for(var i=0; k=keys[i],i<keys.length; i++){
			//Modifiers
			if(k == 'ctrl' || k == 'control'){
				if(e.ctrlKey) kp++;

			} else if(k ==  'shift'){
				if(e.shiftKey) kp++;

			} else if(k == 'alt'){
					if(e.altKey) kp++;

			} else if(k.length > 1){ //If it is a special key
				if(special_keys[k] == code) kp++;

			} else { //The special keys did not match
				if(character == k) kp++;
				else {
					if(shift_nums[character] && e.shiftKey){ //Stupid Shift key bug created by using lowercase
						character = shift_nums[character]; 
						if(character == k) kp++;
					}
				}
			}
		}

		if(kp == keys.length){
			callback(e);

			if(!opt['propagate']){ //Stop the event
				//e.cancelBubble is supported by IE - this will kill the bubbling process.
				e.cancelBubble = true;
				e.returnValue = false;

				//e.stopPropagation works only in Firefox.
				if(e.stopPropagation){
					e.stopPropagation();
					e.preventDefault();
				}
				return false;
			}
		}
	}

	//Attach the function with the event	
	if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
	else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
	else ele['on'+opt['type']] = func;
}


function _hideFWShield(callback,onlyIfNoDialogs){
	if(onlyIfNoDialogs && $("div.ui-dialog:visible:first").length>0) return; // Do not remove shield if any dialogs exist

	var dis = _getFWHTMLObject("SET_shield");
	if(dis){
		//_removeFWEvent(window, "Resize", _resizeFWShield);
		dis.parentNode.removeChild(dis);
		dis = null;
	}
	if(callback)
		callback.call();
}


//disableObject - the object that should be disabled. If null then disable viewport
//disableOutsideObject - true if everything except disableObject should be disabled, false if only disableObject
function _showFWShield(callback,silent,disableObject,disableOutsideObject,topOffset,bottomOffset,leftOffset,rightOffset,style){
	//init offsets
	if(!topOffset) topOffset = 0;
	if(!bottomOffset) bottomOffset = 0;
	if(!leftOffset) leftOffset = 0;
	if(!rightOffset) rightOffset = 0;
	
	var css = "SET_cssShield";
	var dis = _getFWHTMLObject("SET_shield");
	if(silent && !dis){
		if(String(silent).toLowerCase()=="true") css+=" SET_cssShieldSilent";
		else{
			css+=" "+silent;
		}
	}

	//if there's already a shield at this level, then we shouldn't add another one, and also NOT change it to silent
	if(dis){
		dis.className=css; // Change classes
		return;
	}
	
	if(style){
		css+=" "+style;
	}
	dis = document.createElement("div");
	/*$(dis).css({"position":"fixed",
		"top":"0",
		"left":"0",
		"width":"100%",
		"height":"100%",
		"z-index":"10000",
		"opacity":"0",
		"padding":"0",
		"margin":"0"});*/

	dis.className=css;
	dis.id="SET_shield";
		
	if(navigator.userAgent.toLowerCase().indexOf("msie") != -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1){
		var ifObj = document.createElement("iframe");
		//ifObj.src = "/st/stNothing.asp";
		ifObj.name = "SET_shieldIframe";
		dis.appendChild(ifObj);
	}

	if(disableObject){
		if(disableOutsideObject){
		}else{
			disableObject.appendChild(dis);
			_resizeFWShieldForObject(disableObject,topOffset,bottomOffset,leftOffset,rightOffset)
		}
	}else{
		document.body.appendChild(dis);

		var v = _getFWHTMLObject('SET_container');
		if(!v)	var v = window.parent._getFWHTMLObject('SET_container');
		try{
			if(v && !isNaN(parseInt(v.clientWidth))){ dis.minWidth = v.clientWidth + 4;
			}else{ dis.minWidth = 0;}
		}catch(err){}

		_resizeFWShield();

		//add a resize event
		_addFWEvent(window,"resize",_resizeFWShield);
	}

	if(callback) callback.call();	
}

function _resizeFWShieldForObject(disableObject,topOffset,bottomOffset,leftOffset,rightOffset){
	var v = _getFWHTMLObject('SET_shield');
	if(v){
		_setFWShieldXForObject(v,disableObject,leftOffset,rightOffset);
		_setFWShieldYForObject(v,disableObject,topOffset,bottomOffset);
	}
}

function _setFWShieldXForObject(dis,target,leftOffset,rightOffset){	
	dis.style.left = leftOffset + 'px';
	dis.style.width = target.offsetWidth - leftOffset - rightOffset + 'px';
}

function _setFWShieldYForObject(dis,target,topOffset,bottomOffset){
	dis.style.top = topOffset + 'px';
	dis.style.height = target.offsetHeight - topOffset - bottomOffset + 'px';
}

function _resizeFWShield(){
	var v = _getFWHTMLObject('SET_shield');
	if(v){
		_setFWShieldWidth(v,document);
		_setFWShieldHeight(v,document);
		_setFWShieldWidth(v,document);
	}
}

function _setFWShieldWidth(dis,doc,extrawidth){
	//only FF/NN/IE6 are unable to use width:100%
	if((navigator.userAgent.toLowerCase().indexOf("msie 6.0") == -1) && (navigator.userAgent.toLowerCase().indexOf("firefox") == -1) )
		return;

	var width = 0;

	if(dis){
		if(!extrawidth) extrawidth = 0;

		if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
			width = doc.documentElement.clientWidth;
			if(width < 996) width = 1016;
		}
		else {			
			if(doc.body.offsetWidth > doc.documentElement.clientWidth) 
				width = doc.documentElement.clientWidth;
			else {
				width = doc.documentElement.clientWidth;
				if(navigator.userAgent.toLowerCase().indexOf("safari") != -1){
					if(width < 996) width = 1016;
				}
			}
		}
		
		if(dis.minWidth && width<dis.minWidth)
			width=dis.minWidth;
	}
	
	dis.style.width = width + 'px';
}

function _setFWShieldHeight(dis,doc,extraheight){
	//only use this for firefox and netscape, due to the bug with the disappearing input caret when placed above something
	//that has position:fixed
	if(navigator.userAgent.toLowerCase().indexOf("firefox") == -1) 
		return;

	var height = 0;

	if(dis){
		if(!extraheight) extraheight = 0;

		if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
			height = doc.body.offsetHeight + extraheight + 23;
		}
		else {
			if(doc.body.offsetHeight > doc.documentElement.clientHeight)  {
				height = doc.body.offsetHeight + 16 + extraheight;
			} else {
				height = doc.documentElement.clientHeight + doc.body.scrollTop + extraheight;
			}
		}

		//at least cover visible area even if page is smaller
		var v = _getFWViewportHeight();
		if(height < v)
			height = v;
	}
	
	dis.style.height = height + 'px';
}

function _setFWDisableContentHeight(dis,doc,extraheight){
	//only use this for firefox and netscape, due to the bug with the disappearing input caret when placed above something
	//that has position:fixed
	if(navigator.userAgent.toLowerCase().indexOf("firefox") == -1) 
		return;

	var height = 0;

	if(dis){
		if(!extraheight) extraheight = 0;

		if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
			height = doc.body.offsetHeight + extraheight + 23;
		}
		else {
			if(doc.body.offsetHeight > doc.documentElement.clientHeight)  {
				height = doc.body.offsetHeight + 16 + extraheight;
			} else {
				height = doc.documentElement.clientHeight + doc.body.scrollTop + extraheight;
			}
		}

		//at least cover visible area even if page is smaller
		var v = _getFWViewportHeight();
		if(height < v)
			height = v;
	}
	
	dis.style.height = height + 'px';
}

function _getFWViewportHeight(){
	var viewportheight;

	// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
	if(typeof(window.innerWidth) != 'undefined')	  
		viewportheight = window.innerHeight;

	// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
	else if(typeof(document.documentElement) != 'undefined' && typeof(document.documentElement.clientWidth) != 'undefined' && document.documentElement.clientWidth != 0)
		viewportheight = document.documentElement.clientHeight;

	return viewportheight;
}

/************************************
 * _openFWIframeWindow
 * Created : oct 24 Stefan Lisper
 *
 * id - id of iframe object
 * url - page to load in iframe
 * css - ,-delimited list of any css classes of the iframe. Will be prefixed with fw_iframe_<classname>
 * autoSize - if true then iframe will initially be sized according to css, but resized according to content once that's done loaded
 * isPreload - if true then the iframe will not be shown, but the content will be loaded into it. Later it can be shown by using _showFWIframeWindow()
 *
 * returns the generated iframe object
 ***********************************/
function _openFWIframeWindow(id,url,css,autoSize,isPreload,storePrevScroll,posY){
	// Close old window
	window.parent._closeFWIframeWindow(id);

	var ifrm = document.createElement("IFRAME");
	
	//iframe content always is always bare, otherwise the framework redirects to startpage
	if(url.indexOf('bare=true')==-1) 
		url=url + '&bare=true';

	ifrm.src = url;
	
	// Determine CSS	
	css = css.split(",");

	ifrm.className = "dyniFrame"

	for(i=0; i<css.length; i++){
		ifrm.className = ifrm.className + " dyniFrameType" + css[i].substring(0,1).toUpperCase() + css[i].substring(1,css[i].length);
	}

	var className = ifrm.className;
	// Autosize
	if(autoSize){
		//since we can't cascade css starting with the iframe we add the iframe's classes to the iframe's body element 
		_addFWEvent(ifrm, "load", function(event){ifrm.style.height = _getFWIframeHeight(ifrm) + "px"; }); 
		ifrm.scrolling="no";
	} else { 
		ifrm.scrolling="yes"; 
	}

	ifrm.id = id;
	ifrm.name = id;
	ifrm.allowTransparency = "true";
	ifrm.frameBorder = 0;
	document.body.appendChild(ifrm);

	if(!isPreload){_showFWIframeWindow(ifrm,storePrevScroll,posY);}

	return ifrm;
}

function _showFWIframeWindow(ifrm,storePrevScroll,posY){
	if(ifrm){
		// Gray out
		_showFWShield();
		
		ifrm.style.display = "block";

		// Store scroll position (always of upper most parent! only handles max one parent for now)
		if(storePrevScroll){
			if(window.parent)
				ifrm.previousScrollCoordinates = window.parent._getFWScrollCoordinates();
			else
				ifrm.previousScrollCoordinates = _getFWScrollCoordinates();
		}else{
			ifrm.previousScrollCoordinates = null;
		}

		if(posY)
			ifrm.style.top = (_getFWScrollCoordinates().y + posY) + "px"
	}
}

function _getFWIframeHeight(ifrm){
	if(ifrm.contentDocument && ifrm.contentDocument.body.offsetHeight){ 
		return ifrm.contentDocument.body.offsetHeight; }
	else if(ifrm.document && ifrm.document.body.scrollHeight){
		return ifrm.document.body.scrollHeight; }

	return 0;
}

function _closeFWIframeWindow(id){
	var ifrm = _getFWHTMLObject(id);
	if(ifrm){
	
		// Restore previous scroll position (always of upper most parent! only handles max one parent for now)
		if(ifrm.previousScrollCoordinates){
			if(window.parent)
				window.parent.scrollTo(ifrm.previousScrollCoordinates.x, ifrm.previousScrollCoordinates.y);
			else
				window.scrollTo(ifrm.previousScrollCoordinates.x, ifrm.previousScrollCoordinates.y);
		}
		
		// Remove iframe
		document.body.removeChild(ifrm);
		
		// Remove gray out
		_hideFWShield();
	}
}


/**********************************
 * Shows popup (much stabler
 * than showHintbox - always to 
 * be preferred!). Also handles
 * safari stop automatically.
 * e = event
 * con = the object from which the popup gets its content (by cloning unless attribute noClone="true" is present in object),
 *			 or a html text string which comprises the content
 * conTransformFun = a handle to a function called when the popup has been shown. The function takes the popup itself as argument.
 * hideFun = a handle to a function called when the popup has been hidden. The function takes the popup itself as argument.
 * adjX = adjustment of popup position x
 * adjY = adjustment of popup position y
 * css = css class(es) besides popup (always added)
 * explicitHide = if true, the box NEVER hides on an event (like clicking or moving mouse outside of box), only on direct command
 *								if string "click", the box only hides on click outside of box (unless on trigger)
 *                if string "clickany", the box only hides on click, anywhere outside of box (even on trigger)
 * align = align in relation to position object
 * del = delay until popup is shown
 * positionAt = if true the popup is positioned at coordinates adjX and adjY
 * hideDel = delay until popup is hidden
 * childId = id if this popup is a child to an already opened popup
 * isFixed = position fixed (needed so that positioning is done correctly for fixed elements)
 * attemptHideFun = function that is called when attempting to hide a popup. The function takes an event and the popup itself as argument.
 *                  The function must return true if hide is ok, else false.
 **********************************/
function _showFWPopup(e,con,conTransformFun,hideFun,adjX,adjY,css,explicitHide,align,del,positionAt,hideDel,childId,isFixed,attemptHideFun){
	
	e = _initFWieEvent(e);
	
	// Init previous object (if any)
	var fw_popup;
	if(childId && window.fw_popup){
		if(window.fw_popup.fw_children)
			fw_popup = window.fw_popup.fw_children[childId];
		else 
		  fw_popup = null;
	}else{
		fw_popup = window.fw_popup;
		childId = "";
	}
	var posAtObj;
	if(_getFWTypeOf(positionAt)=="object"){
		posAtObj=positionAt;
		positionAt=false;
	}else{
		posAtObj=e.target;
	}
	// If no element to position at, make target the same as the con-object
	if(positionAt)
		e = {target:con};

	// If menu already open
	if(fw_popup){
		
		// If same menu, don't retrigger, and don't hide either (unless explicitHide=="clickany")
		if(fw_popup.trigger == posAtObj){
			if(String(explicitHide).toLowerCase()=="clickany"){
				_hideFWPopup(null,true,0,childId);
			}else{
				// Clear hide timeout though
				_clearFWTimeout(false);
			}
			return;
		//Else if the menu is NOT an onlyHide
		}else{
			// Hide existing menu first, no delay
			_hideFWPopup(null,true,0,childId);
		}
	}
	
	_clearFWTimeout(true);
	
	if(!con)
		return;
	
	// Initiate menu	
	fw_popup = null;
	
	if(typeof(con)=='object'){
		if(String(con.getAttribute("noClone")).toLowerCase()=="true"){
			var originalParent = con.parentNode;
			if(originalParent){
				fw_popup = originalParent.removeChild(con);
				fw_popup.originalParent = originalParent;
			}else{
				fw_popup = con;
			}
			fw_popup.originalClassName = fw_popup.className;
			fw_popup.originalId = fw_popup.id;
			fw_popup.originalName = fw_popup.name;
			fw_popup.noClone = true;
		}else{
			fw_popup = con.cloneNode(true);
			fw_popup.noClone = false;
		}
	}else{
		fw_popup = document.createElement("div");
		fw_popup.innerHTML = con;
		fw_popup.noClone = true;
	}
	 
	if(childId){
		fw_popup.id = childId;
		fw_popup.name = childId;
		if(!window.fw_popup.fw_children) window.fw_popup.fw_children = new Object();
		if(!window.fw_popup.fw_childrenArr) window.fw_popup.fw_childrenArr = new Array();
		window.fw_popup.fw_children[childId] = fw_popup;
		window.fw_popup.fw_childrenArr[window.fw_popup.fw_childrenArr.length] = fw_popup;
	}else{
		fw_popup.id = "fw_popup";
		fw_popup.name = "fw_popup";
		window.fw_popup = fw_popup;
	}
	fw_popup.className= "fw_popup "+fw_popup.className;
	if(css)	fw_popup.className+=" "+css;
	fw_popup.hideFun = hideFun;
	fw_popup.hideDel = hideDel;
	fw_popup.attemptHideFun = attemptHideFun;
	fw_popup.isFixed = isFixed;
		
	// Loop through children and fix id's (if any have a T-prefix)
	if(!fw_popup.noClone){
		try{
			for(i=0;i<fw_popup.childNodes.length;i++){
				if(fw_popup.childNodes[i].id&&fw_popup.childNodes[i].id.substr(0,1)=="T"){
					fw_popup.childNodes[i].id=fw_popup.childNodes[i].id.substr(1);
				}
			}
		}catch(er){}
	}
	
	
	// Add menu to DOM
	document.body.appendChild(fw_popup);

	// Add events
	if(String(explicitHide).toLowerCase().substr(0,5)=="click"){
		_removeFWEvent(document,"mouseup",_hideFWPopupNoDel);
	  _addFWEvent(document,"mouseup",_hideFWPopupNoDel);
		if(childId){ // Add for parent as well
			_addFWEvent(window.fw_popup,"mouseup",function(event){_hideFWPopup(event,false,hideDel,childId)});
		}
	}else if(explicitHide!=true){
		_addFWEvent(fw_popup,"mouseout",function(event){_hideFWPopup(event,false,hideDel,childId)});
		posAtObj.originalOnMouseOut = posAtObj.onmouseout;
		_addFWEvent(posAtObj,"mouseout",function(event){_hideFWPopup(event,false,hideDel,childId)});
		_removeFWEvent(document,"mouseup",_hideFWPopupNoDel);
		_addFWEvent(document,"mouseup",_hideFWPopupNoDel);
	}
	_addFWEvent(fw_popup,"mouseover",_clearFWTimeout);
	
	// Set globals
	fw_popup.trigger = posAtObj;
	
	if(adjX==null)
		adjX = 4;
	if(adjY==null)
		adjY = -5;
		
	// Show menu
	if(del==null||del==0){
		if(positionAt)
			_showFWAt(fw_popup,adjX,adjY);
		else
			_showFWAtElement(fw_popup,fw_popup.trigger,(align==null?'B':align),adjX,adjY,null,false,true);
		fw_popup.style.display="block";
	}else{
		
		if(isNaN(del))
			del=200;
		
		if(positionAt)
			window.timer = setTimeout("var fw_popup=window.fw_popup"+(childId?"["+childId+"]":"")+";_showFWAt(fw_popup,"+adjX+","+adjY+",'block');",del);
		else
			window.timer = setTimeout("var fw_popup=window.fw_popup"+(childId?"["+childId+"]":"")+";_showFWAtElement(fw_popup,fw_popup.trigger,'"+(align==null?'B':align)+"',"+adjX+","+adjY+",'block',fw_popup.isFixed,true);",del);
	}
	
		
	// Content transform
	if(conTransformFun){
		conTransformFun(fw_popup);
	}

	return fw_popup;
}

/**********************************
 * Hides popup. If noEvent is 
 * true, the hide is done even if
 * mouse is over menu or trigger.
 * Optional delay inidicates time
 * from call of this method until
 * actual hide. Default: 200ms
 **********************************/

function _hideFWPopupNoDel(e){
	_hideFWPopup(e,false,0);
}
 
 
function _hideFWPopup(e,noEvent,delay,childId){
	if(noEvent!=true)
		e = _initFWieEvent(e);
	else
		e = null;
		
	
	
	// Init previous object (if any)
	var fw_popup;
	if(childId && window.fw_popup){
		if(window.fw_popup.fw_children)
			fw_popup = window.fw_popup.fw_children[childId];
		else 
		  fw_popup = null;

	}else{
		fw_popup = window.fw_popup;
		childId = "";
	}

	if(!fw_popup){
		return;
	}

	_clearFWTimeout();	


	// No hide if mouse is over the menu
	if(e){
		if(fw_popup.preventHide)
			return;
		
		if(fw_popup.attemptHideFun){
			if(!fw_popup.attemptHideFun(e,fw_popup))
				return;
		}

		var mpoint = _getFWMouseCoordinates(e);

		// Make sure mouse is not within popup och popup's trigger
		if(_isFWPointWithinTarget(mpoint,fw_popup,-1,-1,fw_popup.isFixed==true,true)||_isFWPointWithinTarget(mpoint,fw_popup.trigger,null,null,fw_popup.isFixed==true))	
			return;

		// Make sure mouse is not within any children either
		if(fw_popup.fw_childrenArr){
			var children = fw_popup.fw_childrenArr;
			for(i=0;i<children.length;i++){
				if(children[i] && children[i].trigger){
					if(_isFWPointWithinTarget(mpoint,children[i],-1,-1,fw_popup.isFixed==true)||_isFWPointWithinTarget(mpoint,children[i].trigger,null,null,fw_popup.isFixed==true))	
						return;
				}
			}
		}
		
				
//		alert("mouse: "+mpoint.x+" "+mpoint.y+"\nleft/top:"+point2.x+" "+point2.y+"\nright/bottom:"+(point2.x+e.target.offsetWidth)+" "+(point2.y+e.target.offsetHeight));
		
		// Timeout hide, so that the user has a grace period if he accidentally moves the mouse out
		if(delay==null){
			delay = fw_popup.hideDel;
			if(delay==null){
				delay=3000;
			}
		}
		if(delay==0){
			_hideFWPopup(null,true,0,childId);
		}else{
			window.timer = setTimeout("_hideFWPopup(null,true,0,'"+childId+"');",delay);
		}
		
		return;	
		
	}else{

		fw_popup.style.display="none";

	
			// Remove events
			_removeFWEvent(document,"mouseup",_hideFWPopupNoDel);
			
			if(fw_popup.trigger && fw_popup.trigger.originalOnMouseOut){
				fw_popup.trigger.onmouseout = fw_popup.trigger.originalOnMouseOut;
			}

			// Call function on hide (for ajax:ing, unlocking etc)
			if(fw_popup.hideFun){
				fw_popup.hideFun(fw_popup);
			}
					
			// Hide
			var con = (fw_popup.parentNode?fw_popup.parentNode.removeChild(fw_popup):null);//document.body.removeChild(fw_popup);

			// Hide all children
			if(fw_popup.fw_childrenArr){
				var children = fw_popup.fw_childrenArr;
				for(i=0;i<children.length;i++){
					if(children[i] && children[i].id){
						_hideFWPopup(null,true,0,children[i].id);
					}
				}
			}

			// If original parent exists, insert at parent again, and hide
			if(con && con.originalParent){
				con.style.display="none";
				con.style.top="";
				con.style.left="";
				con.className = con.originalClassName;
				con.id = con.originalId;
				con.name = con.originalName;
				con.originalParent.appendChild(con);
				con.originalParent = null;
				con.onmouseout = null;
			}else{
			}
			fw_popup.trigger = null;
			
			if(childId && window.fw_popup.fw_children){
				window.fw_popup.fw_children[childId] = null;
				if(fw_popup.fw_childrenArr){
					for(i=0;i<fw_popup.fw_childrenArr.length;i++){
						if(fw_popup.fw_childrenArr[i] && fw_popup.fw_childrenArr[i].id && String(childId)==String(fw_popup.fw_childrenArr[i].id)){
							fw_popup.fw_childrenArr[i]=null;
						}
					}
				}
			}else{
				window.fw_popup = null;
			}	
	}
}

/******************************************************
 * _determineFWTimezoneOffset
 * Oct 2007 - Linus Lövholm
 *
 * Calcs timezone offset of client computer and submits
 * it to the server via the sidechain.
 ******************************************************/
function _determineFWTimezoneOffset(sh,so){
	var tz = parseInt(new Date().getTimezoneOffset(),10);
	var h = parseInt(new Date().getHours(),10);
	so = parseInt(so,10);
	sh = parseInt(sh,10);
	
	/*tz = 0;
	h = 8;
	sh = 10;
	so = 60;*/
	
	//60
	sh*=60;
	h*=60;

	// tz will be incorrect if summer time (60 minutes less than it should be), account for this here
	if((so+tz)<(sh-h)){
		tz += 60;
	}
	
	// "reverse" tz since it is a negative value when it should be positive
	tz*=-1;
	
	window.fw_timezoneOffset = tz;

}


/******************************************************
 * _showFWDate
 * Oct 2007 - Linus Lövholm
 *
 * Shows a date in a certain format, takes client timezone
 * into account
 ******************************************************/
function _showFWDateQuick(dat,format,months,days){ // Just shows a js date in specified format
	return _showFWDate(null,null,null,null,null,null,null,format,months,days,null,null,dat);
}
function _showFWDate(y,m,d,ho,mi,se,wd,str,months,days,sh,so,dat,keepUpdatedSelector){
	if(window.fw_timezoneOffset=null && sh && so)
		_determineFWTimezoneOffset(sh,so);
	var origStr = str;
	months = String(months).split(",");
	days = String(days).split(",");
	
	// Month in js starts from 0
	if(!dat){
		y=parseInt(y,10);
		m=parseInt(m,10);
		d=parseInt(d,10);
		ho=parseInt(ho,10);
		mi=parseInt(mi,10);
		se=parseInt(se,10);
		wd=parseInt(wd,10);
		dat = new Date(y,m-1,d,ho,mi,se);
	}
	
	y=dat.getFullYear();
	m=dat.getMonth()+1;
	d=dat.getDate();
	ho=dat.getHours();
	mi=dat.getMinutes();
	se=dat.getSeconds();
	wd=dat.getDay();
	var nextDate = new Date(y,m-1,d,ho,mi,se+1);

	str = str.replace("YYYY",y);
	str = str.replace("YY",String(y).substr(2));
	
	str = str.replace("DDDD",days[wd-1]);
	str = str.replace("DD",_padFW(d,2,0));
	str = str.replace("D",d);
	
	str = str.replace("WWWW",days[wd-1]);
	
	str = str.replace("MMMM",months[m-1]);
	str = str.replace("MMM",String(months[m-1]).substr(0,3));
	str = str.replace("MM",_padFW(m,2,0));
	
	str = str.replace("hh",_padFW(ho,2,0));
	str = str.replace("mm",_padFW(mi,2,0));
	str = str.replace("ss",_padFW(se,2,0));

	if(ho < 12){
		str = str.replace("AMPM","AM");
		if(ho == 0)
			ho = 12;
	}else{
		if(ho > 12)
			ho = ho - 12;
		str = str.replace("AMPM","PM");
	}
		
	str = str.replace("HH",_padFW(ho,2,0));
	str = str.replace("SUF","");

	if(keepUpdatedSelector){
		var ku=$(keepUpdatedSelector);
		ku.html(str);
		var tim =ku.data("timer");
		if(tim)clearTimeout(tim);
		var timerId = new Date().getTime();//Make sure this timer only triggers if timerId is the same
		ku.data("timerId",timerId);
		ku.data("timer",setTimeout(function(){
			if(timerId!=ku.data("timerId")) return;
			_showFWDate(null,null,null,null,null,null,null,origStr,months,days,sh,so,nextDate,keepUpdatedSelector);
		},1000));
	}

	return str;
		/*
		y = Year(dat)
		m = Month(dat)
		d = Day(dat)
		wd = WeekDay(dat,2)
		str = Replace(str,"DDDD",application("fw_edition_"&sess("edition_id")&"_date_days")(wd-1),1,1,0)

		str = Replace(str,"MMMM",application("fw_edition_"&sess("edition_id")&"_date_months")(m-1),1,1,0)
		str = Replace(str,"WWWW",application("fw_edition_"&sess("edition_id")&"_date_days")(wd-1),1,1,0)
		str = Replace(str,"MMM",left(application("fw_edition_"&sess("edition_id")&"_date_months")(m-1),3),1,1,0)
		*/
}

// Parses a string to a date object according to a certain format
// Only parses YYYY, YY, MM, M, DD, D, hh, mm
function _parseFWDate(str,format){
	
	var y;
	var m;
	var d;
	var ho;
	var mi;
	
	function _extractFWAtom(str,format,atm){
		p = format.indexOf(atm);
		if(p>-1 && p < str.length){
			return parseInt(str.substr(p,atm.length),10);
		}
		return null;
	}
	
	
	
	
	// YEAR
	y = _extractFWAtom(str,format,"YYYY");
	if(y==null||isNaN(y)){
		y = _extractFWAtom(str,format,"YY");
		if(y==null||isNaN(y)){
			y = new Date().getFullYear();
		}else{
			// Add correct century, same as current if below 70, else same as previous
			var c = parseInt(String(new Date().getFullYear()).substr(0,2),10);
			
			if(y<70)
				y = parseInt(String(c)+""+_padFW(y,2,0),10);
			else{
				y = parseInt(String(c-1)+""+_padFW(y,2,0),10);
			}
			//alert(y);
		}
	}

	
	// MONTH
	m = _extractFWAtom(str,format,"MM");
	if(m==null||isNaN(m)){
		m = _extractFWAtom(str,format,"M");
		if(m==null||isNaN(m)){
			m = new Date().getMonth();
		}else{
			m--;
		}
	}else{
		m--;
	}
	
	
	// DAY
	d = _extractFWAtom(str,format,"DD");
	if(d==null||isNaN(d)){
		d = _extractFWAtom(str,format,"D");
		if(d==null||isNaN(d)){
			d = new Date().getDate();
		}
	}
	
	
	// HOUR
	ho = _extractFWAtom(str,format,"hh");
	if(ho==null||isNaN(ho)){
		ho = new Date().getHours();
	}
	
	// MINUTE
	mi = _extractFWAtom(str,format,"mm");
	if(mi==null||isNaN(mi)){
		mi= new Date().getMinutes();
	}

	return new Date(y,m,d,ho,mi);
}

/***********************************************
 * IS NOTHING
 *
 * True if value is null, uninstantiated, empty
 * string or -1, else false
 ***********************************************/
function _isFWNothing(value){
	//alert("value="+(!value || value == null || value == "" || value == -1 || value == "-1"));
	return (!value || value == null || value == "" || value == -1 || value == "-1");
}



//////////////////////////////////////////////////////////////////////
// VALID STRING
// -------------------------------------------------------------------
// A valid string is non-empty and non-numeric
//////////////////////////////////////////////////////////////////////

	function _validFWString(in_param, hardcore){
		if( hardcore ){
			if((in_param == '') ||
				(isNaN(in_param) == false)){
				return false;
			}
		}
		else {
			if( in_param == '' ){
				return false;
			}
		}
		
		return true;
	}

//////////////////////////////////////////////////////////////////////
// VALID INTEGER
// -------------------------------------------------------------------
// A valid integer is non-empty and numeric
// A valid integer can be zero but not contain any ',' or '.'
// If hardcore is true it may not be zero
//////////////////////////////////////////////////////////////////////

	function _validFWInteger(in_param, hardcore){
	
		if( (in_param == '') || (isNaN(in_param) == true) || in_param.toString().indexOf( '.' ) >= 0 || in_param.toString().indexOf( ',' ) >= 0 ){
			return false;
		}
		if( hardcore && parseInt(in_param,10) <= 0 ){
			return false;
		}
		return true;
	}

//////////////////////////////////////////////////////////////////////
// VALID REAL
// -------------------------------------------------------------------
// A valid real is non-empty and numeric
// A valid real can be zero and contain one ',' or '.'
// If hardcore is true it may not be zero
//////////////////////////////////////////////////////////////////////

	function _validFWReal(in_param, hardcore){
		in_param = in_param.toString().replace( /,/g,'.' );
		if( (in_param == '') || (isNaN(in_param) == true) ){
			return false;
		}
		if( hardcore && in_param <= 0 ){
			return false;
		}
		return true;
	}

//////////////////////////////////////////////////////////////////////
// VALID DATE
// -------------------------------------------------------------------
// Inparameter may be in format 'yyyymmdd' or 'yymmdd'
// A valid date has year, month and day that meets the demands on:
//	- 28/29 days in February
//	- 
//////////////////////////////////////////////////////////////////////

	function _validFWDate(in_param){
		
	    var dd;
	    var mm;
	    var yyyy;
		in_param = String(in_param).replace(/-/gi,"");

		// Check valid input
		switch ( parseInt(in_param.toString().length,10) ){
			case 6:
				yyyy = '20' + in_param.toString().substr(0,2);
				mm = in_param.toString().substr(2,2);
				dd = in_param.toString().substr(4,2);
				return _isFWDate(yyyy,mm,dd);
				break;
			case 8:
				yyyy = in_param.toString().substr(0,4);
				mm = in_param.toString().substr(4,2);
				dd = in_param.toString().substr(6,2);
				return _isFWDate(yyyy,mm,dd);
				break;
			default:
				//alert("Detta datumformat känner inte _validDate() till. Metoden måste skrivas om för att hantera detta format.");
				return false;
		}
		
		return false;
	}

	function getYear(d){ 
		return (d < 1000) ? d + 1900 : d;
	}

	function _isFWDate( year, month, day ){
		// month argument must be in the range 1 - 12
		month = month - 1;  // javascript month range : 0- 11
		var tempDate = new Date(year,month,day);
		if( (getYear(tempDate.getYear()) == year) &&
			(month == tempDate.getMonth()) &&
			(day == tempDate.getDate()) )
			return true;
		else {
			return false;
		}
	}





	function _setFWOnlyFirstFocus( obj ){
	
		if( !window.fw_firstFocSet ){
			window.fw_firstFocSet = true;
			if(obj && obj.focus)
				obj.focus();
		}
	}
	

function _someFWSelected(sel,maxAllowed){
	try{
		if(!maxAllowed)
				maxAllowed = -1;
		if(sel.length){
			var numSel = 0;
			for(i=0;i<sel.length;i++){
				if(sel[i].checked)
					numSel++;
			}
			if(numSel>0 && (maxAllowed == -1 || numSel <= maxAllowed)){
				return true;
			}else{
				return false;
			}
		}else{
			try{
				if(!sel.checked){
					return false;
				}else{
					return true;
				}
			}catch(e){
				return false;
			}
		}
		
	}catch(e){
		
		try{
			if(!sel.checked){
				return false;
			}else{
				return true;
			}
		}catch(e){
			return false;
		}
	}
}


/*******************
/* _preloadFWImages
/* Created dec 12 2007 Stefan Lisper
/*
/* idea taken from http://www.webreference.com/programming/javascript/gr/column3/
/* but much simplified here
/*******************/
function _preloadFWImages(images){
	var imgArr = new Array;

	for( var i = 0; i < images.length; i++ ){
		var img = new Image;
		imgArr.push(img);
		img.src = images[i];
	}
}

/********************************************************
 * _autoFWComplete
 * Created 10 mar 2008 Linus Lövholm
 *
 * Enables auto-completion for an input field.
 * fieldObj = the field to enable auto-completion for.
 * handle = handle used in communication with server as strPageACT, i.e. UPDATE_<handle>.
 * cssClasses = css class string for the match list. If null, no classes are applied.
 * numCharsToAutoComplete = number of chars required before fetch request to server is done and match list is shown. If null, set to 3.
 * numMaxHitsToShow = number of hits to show as a maximum in the match list. Null = all (but this is NOT recommended).
 * messWorking = message to show in match list while retrieving data from server (if any). Can be HTML.
 * messNoHits = message to show in match list if no hits are found. Can be HTML.
 * messMaxHitsExceeded = message to show at the end of the list if number of hits exceed numMaxHitsToShow. Can be HTML.
 * onSelectFunction = function that is called when an item is selected. The fieldObj, the selected object and the charcode
 *                    (if the select was triggered by a keyboard key) is sent as arguments to this method.
 *										The list HTML object can be reached with selectedObj.
 *                    The source object can be reached with fieldObj.autoCompleteCurrentSource,
 *                    and the value of that by fieldObj.autoCompleteCurrentSource.value,
 *                    the id by fieldObj.autoCompleteCurrentSource.id and the data VO by fieldObj.autoCompleteCurrentSource.data (etc)
 *                    Thus, the signature of the onSelectFunction should be: function onSelectFunction(fieldObj,selectedObj,charCode,wasAutoSelect)
 * onDeselectFunction = function that is called when a complete match is no longer found (on erase of char, or equiv).
 *										The fieldObj is sent as argument.
 *										Thus, signature of onDeselectFunction should be: function onDeselectFunction(fieldObj)
 * enablePropagation = if true, enter and tab key presses will be propagated, else they will be stopped (for browsers where this is possible)
 * hideOnExactMatch = if true, the match list is not shown if only one match and that match is matched exactly (char-by-char) and that match
 *                    is the currently selected match (via autoselect, keyboard, or mouse)
 * autoSelectOnExactMatch = if true, if only one match and that match matches exactly (char-by-char), it is selected automatically
 * showAtObj = object to show the match list below. If null, list will be shown below fieldObj.
 * showAtAlign = alignment string that is passed to the _showFWAtElement()-method. If null, align will be "B".
 * qs = querystring to use on ajax submit
 * showInObj = object to show match list INSIDE of (i.e. match list is not shown as popup)
 * neverBlur = If true, the match list is never hidden on blur of fieldObj (i.e. even when fieldObj is not focused, the matchlist is shown).
 *             This also means a search is performed on init of autocomplete (if num chars and other conditions are met of course)
 * noMoveUpSelection = If true, the text of selected item in match list is NOT moved to the fieldObjs search text.
 *                     Also the match list is not hidden on select of item.
 * autoSearchDelay = Numeric. Milliseconds to wait after typing before submitting search to server. If this is present, a refetch to the server
 *                   is done with EVERY change of filter and NO client side filtering is performed. This is especially useful when searching using 
 *                   searchtags, when the JS-filtering would become slow due to the amount of text to filter for in matchValue.
 *                   Extra qs-parameters sent to server when searching like this: fw_limit = numMaxHitsToShow+1 (for limiting search results)
 *                   Note: A LOT of autocomplete functionality is bypassed when using this - only the visual and navigational properties of the gui
 *                   control remain
 * storeTermInSession = Bool. Every change of filter leads to an ajaxFWGet that submits search term as qs attribute fw_ac, for storing in session.
 * noAutoSearchOnEnter = Bool. If true, enter does not perform a "re-search" if autoSearch is enabled, instead selection will continue as if autosearch was not enabled.
 *
 * Note that the objects in the list can use special classes instead
 * of the default _autoFWCompleteClass.
 ********************************************************/
 
 
 /* Example usage:
 
 	'In pgPrepare where sidechain handling is performed:
	'-------------------------------------------------------------------
	select case strPageACT
		
		case "UPDATE_ACTEST"
		%><script language="javascript">
			// Normally, these posts would be retrieved dynamically based on request.form("data"), but here we hard code them
			var ar = [new window.parent._autoFWCompleteClass(1,"linus lövholm","NAME","Linus Lövholm",true,"mark"),
								new window.parent._autoFWCompleteClass(2,"linus linusson","NAME","Linus Linusson",true,"mark"),
								new window.parent._autoFWCompleteClass(3,"lina svensson","NAME","Lina Svensson",true,"mark"),
								new window.parent._autoFWCompleteClass(4,"arne jonsson","NAME","Arne Jonsson",true,"mark")];
			// Note the need to include sendId (request.form("id")) in the call to _autoCompleteComplete, so that only the latest sidechain call
			// is handled
			window.parent._getFWFormObject('acTest')._autoCompleteComplete('<%=request.Form("id")%>',ar);
		</script><%

		fwCleanUp
		response.end
		
	end select
 
 
	'In pgRenderContent where the field is to be rendered:
	'-------------------------------------------------------------------
	%><input type="text" id="acTest" name="acTest" value="lin"><%
	fwpostrender "_autoFWComplete(_getFWFormObject('acTest'),'ACTEST','actest',3,10"&_
							 ",'Arbetar...','Inga träffar','<a href=\'\'>Fler träffar...</a>',_onAcTestSelect,_onAcTestDeselect,true,true,true);"


	'JS handler function for when selecting:
	'-------------------------------------------------------------------	
	%><script language="javascript">
	function _onAcTestSelect(fieldObj,selectedObj,charCode,wasAutoSelect){
		// Do something fun here instead of just showing the selection as window title, for example filling out other fields
		window.document.title=fieldObj.autoCompleteCurrentSource.value;
		
		// If wasAutoSelect is true, the item was automatically selected (not by click etc by user)
	}
	
	function _onAcTestDeselect(fieldObj){
		window.document.title="Something was selected, but is now no longer selected";
	}
	
	
	</script><%


	'CSS classes used in this example:
	'-------------------------------------------------------------------
	%><style>
		div.actest{
			background-color:red;
			z-index:1001;
			width:200px;
			position:absolute;
		}

		div.actest div.SET_cssSelected
		{
			color:white;
			background-color:green;
			cursor:pointer;
		}

		div.actest div span.mark{
			background-color:#77bb77;
		}

		div.actest div.SET_cssFooter{
			<css for footer of list>
		}

	</style><%

	'To preselect an item on creation of autocomplete (from for example page memory):
	'-------------------------------------------------------------------
	fwPostRender "_getFWFormObject('acTest')._autoCompletePreselect("&_
		"new window.parent._autoFWCompleteClass("""&getPageRegProp("acTest_id")&""","""&getPageRegProp("acTest")&""",""NAME"")"&_
			");"
			
	// I.e. do a post render where a "dummy" _autoFWCompleteClass instance is created. This instance need only fulfil the equality comparison in _autoFWCompleteClass
	// On a preselect, the messWorking is not shown as preselection is loading content

*/
function _autoFWComplete(fieldObj,handle,cssClasses,numCharsToAutoComplete,numMaxHitsToShow
											,messWorking,messNoHits,messMaxHitsExceeded,onSelectFunction,onDeselectFunction
											,enablePropagation,hideOnExactMatch,autoSelectOnExactMatch,showAtObj,showAtAlign,qs,showInObj,neverBlur,noMoveUpSelection
											,autoSearchDelay,storeTermInSession,noAutoSearchOnEnter){
	
		
	// Check if auto complete object enabled
	if(!fieldObj.autoCompleteEnabled){
		fieldObj.storeTermInSession = storeTermInSession;
		fieldObj.autoSearchDelay = parseInt(autoSearchDelay,10);
		fieldObj.autoSearch = !isNaN(fieldObj.autoSearchDelay);
		fieldObj.noAutoSearchOnEnter = noAutoSearchOnEnter;

		// If no specific showAtObj, set fieldObj as showAtObj
		if(!showAtObj){
			showAtObj = fieldObj;
		}
		
		// Default align
		if(!showAtAlign){
			showAtAlign = "B";
		}
		
		// Default num chars
		if(!numCharsToAutoComplete){
			numCharsToAutoComplete = 3;
		}

		fieldObj.qs = qs;
		
		// *** FUNCTION ***
		// Add function to handle complete of autocomplete submit
		fieldObj._autoCompleteComplete = function (sendId,sourceList){
			
//			_clearFWTimeout(false);
			
			if(fieldObj.autoCompleteInProgress && String(fieldObj.sendId)==String(sendId)){
				fieldObj.sourceList = sourceList;
				fieldObj._autoCompleteRenderList();
				fieldObj.autoCompleteInProgress = false;
			}
		}
	
		// *** FUNCTION ***
		// Add function to handle click on element in list
		fieldObj._autoCompletePreselect = function(sourceObj){
			
			fieldObj.noBlur=false;
			fieldObj.value=sourceObj.value;
			
			// Store source as the selected source
			fieldObj.autoCompleteCurrentSource = sourceObj;
			
			// Hide match list
			fieldObj._autoCompleteHideList();
			
			// Hide messWorking on the next load, since we have a preselection and do not want to see the message
			fieldObj.autoCompleteHideMessWorking = true;
			
			// Call on select function, if present (no list object can be sent along though)
			if(onSelectFunction)
				onSelectFunction(fieldObj,null,null,true);
		}
	
		// *** FUNCTION ***
		// Add function to handle click on element in list
		fieldObj._autoCompleteSelect = function(listObj,charCode,wasAutoSelect){

			fieldObj.noBlur=false;
			if(!noMoveUpSelection) fieldObj.value=listObj.source.value; // No move up if not selected
			
			// If listObj is not selected visually, do this
			if(fieldObj.autoCompleteCurrent!=listObj){
				// Reset previous autocomplete
				if(fieldObj.autoCompleteCurrent){
					fieldObj.autoCompleteCurrent.className=fieldObj.autoCompleteCurrent.origClassName;
				}
				// Store listObj as current	
				fieldObj.autoCompleteCurrent = listObj;
				fieldObj.autoCompleteCurrent.className = fieldObj.autoCompleteCurrent.origClassName+" SET_cssSelected";
			}
			
			// Store listObj's source as the selected listObj source
			fieldObj.autoCompleteCurrentSource = listObj.source;
			
			// Hide match list (unless noMoveUpSelection is on)
			if(!noMoveUpSelection)
				fieldObj._autoCompleteHideList();
			
			// Call on select function, if present	
			if(onSelectFunction)
				onSelectFunction(fieldObj,listObj,charCode,wasAutoSelect);
		}

		// *** FUNCTION ***
		// Add function to handle hide/destroy of autocomplete list
		fieldObj._autoCompleteHideList = function (destroy){
			
			if(!fieldObj.autoCompleteList){
				return;
			}
			
			if(destroy){
				// Remove list
				if(fieldObj.autoCompleteList.parentNode){
					fieldObj.autoCompleteList.parentNode.removeChild(fieldObj.autoCompleteList);
				}
				fieldObj.autoCompleteList=null;
			}else{
				// Hide list
				fieldObj.autoCompleteList.visible=false;
				fieldObj.autoCompleteList.style.display="none";
			}
			if(showInObj){
				$(showInObj).hide();
			}
			

		}
		
		// *** FUNCTION ***
		// Add function to show list
		fieldObj._autoCompleteShowList = function(){
			if(fieldObj.autoCompleteList){
				if(!fieldObj.autoCompleteList.lastChild || fieldObj.autoCompleteList.lastChild.className!="SET_cssFooter"){
					var footer = document.createElement("div");
					footer.className = "SET_cssFooter";
					fieldObj.autoCompleteList.appendChild(footer);
				}
				if(fieldObj.autoCompleteList.showable){
					if(!fieldObj.autoCompleteList.visible){
						if(showInObj){
							$(showInObj).html("").show().append($(fieldObj.autoCompleteList).show());
						}else{
							_showFWAtElement(fieldObj.autoCompleteList, showAtObj, showAtAlign,0,0,"block",$(fieldObj).attr("fixed"));
						}
						fieldObj.autoCompleteList.visible = true;
						//fieldObj.autoCompleteList.style.display="block";
					}
				}else{
					fieldObj._autoCompleteHideList();
				}
			}
			
			if(fieldObj.doFocus && !fieldObj.focused){
				fieldObj.focus();
				fieldObj.select();
				fieldObj.focused=true;
			}
			fieldObj.doFocus=false;
			
			//if(navigator.userAgent.toLowerCase().indexOf("msie") != -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1)
			//	_setFWCaretToEnd(fieldObj);

			// Click on document, outside of list and field = close list
			$(document).click(fieldObj._autoCompleteHideListIfOutside);
			
		}

		// *** FUNCTION ***
		// Add function to handle rendering/filtering of autocomplete list
		fieldObj._autoCompleteRenderList = function (){
			var sourceList = fieldObj.sourceList;
			var filterVal = fieldObj.value.toLowerCase();
			var filterChanged = true;
			
			// Determine if filter has changed. Filter is regarded as changed also when there is a selected item.
			// This is because we need to re-render the list in this case, so that hideOnExactMatch etc takes effect.
			// Since the list is so small when something is selected, this is ok.
			if(fieldObj.lastFilterVal && String(fieldObj.lastFilterVal)==String(filterVal) && !fieldObj.autoCompleteCurrentSource){
				filterChanged = false;
			}


			// If list already exists
			if(fieldObj.autoCompleteList){
				// Clear list if filter vals differ
				if(filterChanged){
					fieldObj.autoCompleteList.innerHTML="";
				}
			}else{
				// Create list
				fieldObj.autoCompleteList = document.createElement("div");
				if(cssClasses){
					fieldObj.autoCompleteList.className = cssClasses;
					// NOTE: The class must have position absolute,as well as apropriate z-index values and width
				}else{
					fieldObj.autoCompleteList.style.position="absolute";
				}
				fieldObj._autoCompleteHideList();
				document.body.appendChild(fieldObj.autoCompleteList);
				
				// Add events to prevent list from hiding when the fieldObj blurs (on click of list)
				_addFWEvent(fieldObj.autoCompleteList, "mouseover", function(){fieldObj.noBlur=true;});
				_addFWEvent(fieldObj.autoCompleteList, "mouseout", function(){fieldObj.noBlur=false;if(fieldObj.autoCompleteCurrent){fieldObj.autoCompleteCurrent.className=fieldObj.autoCompleteCurrent.origClassName;fieldObj.autoCompleteCurrent=null;}});
			}


			// If source list present
			if(sourceList){
				if(filterChanged){
					var numHits = 0;
					var lastHit;
					var currentExists = false;
					var re=new RegExp(_escapeFWRegExp(filterVal), "i"); //Pre-compile reg exp for matching
					re=re.compile(re);

					// Render list based on source list and filterval
					for(i=0;i<sourceList.length;i++){
						//If matches filter OR if autoSearch, include this hit. Observe the lazy evaluation optimization (autoSearch MUST be checked before filter match)
						if(sourceList[i] && (fieldObj.autoSearch || sourceList[i].matchesFilter(filterVal,re))){
							numHits++;
							if(numHits>numMaxHitsToShow){
								break;
							}
							
							
							// Render item
							ai = sourceList[i].render(filterVal);
							ai.source = sourceList[i];
							
							// Add events for setting this item as current in list
							$(ai).unbind('click').click(function(event){var self=this;event.preventDefault();	event.stopPropagation();_stopFWEvents(event,function(){fieldObj._autoCompleteSelect(self);});});
							ai.onmouseover = function(){if(fieldObj.autoCompleteCurrent){fieldObj.autoCompleteCurrent.className=fieldObj.autoCompleteCurrent.origClassName;}this.className=this.origClassName+" SET_cssSelected";fieldObj.autoCompleteCurrent=this;};
							ai.onmouseout = function(){this.className=this.origClassName;fieldObj.autoCompleteCurrent=null;};
							
							// If item equals the autocompletecurrent item, preselect it
							if(ai.source.equals(fieldObj.autoCompleteCurrentSource)){
								ai.className = ai.origClassName+" SET_cssSelected";
								currentExists = true;
								fieldObj.autoCompleteCurrent=ai;
							}
							
							// Append item to list
							fieldObj.autoCompleteList.appendChild(ai);
							
							// Store item as last hit
							lastHit = ai;
						}
					}
					
					// If current does not exist in filtered list, clear current
					if(!currentExists && fieldObj.autoCompleteCurrentSource){
						if(fieldObj.autoCompleteCurrent) fieldObj.autoCompleteCurrent.className=fieldObj.autoCompleteCurrent.origClassName;
						fieldObj.autoCompleteCurrent = null;
						// No longer any current selected item, clear source var for this
						fieldObj.autoCompleteCurrentSource = null;
						
						// If deselect function ("not a complete match") present, call it
						if(onDeselectFunction){
							onDeselectFunction(fieldObj);
						}
					}

					// If no hits, show no hits message
					if(numHits == 0){
						if(messNoHits){
							fieldObj.autoCompleteList.innerHTML = "<div class='SET_cssTextItem'>"+messNoHits+"</div>";
							fieldObj.autoCompleteList.showable = true;
						}else{
							// Hide
							fieldObj.autoCompleteList.showable = false;
						}
					
					}else{
						
						fieldObj.autoCompleteList.showable = true;
						
						// If auto select on exact match OR if autoSearch, auto select if just one hit
						if(autoSelectOnExactMatch){
							if(numHits==1 && (fieldObj.autoSearch || lastHit.source.matchesExactly(filterVal))){
								// Select last hit
								fieldObj._autoCompleteSelect(lastHit,null,true);
							}
						}
						
						// If a selected item exists
						if(fieldObj.autoCompleteCurrentSource){
							// If last hit (which on the cases where this is useful is the one and only match) matches the selected item
							// NOTE: Match is done with equals if autoSearch
							if((fieldObj.autoSearch && fieldObj.autoCompleteCurrentSource.equals(lastHit.source))
									|| lastHit.source.matchesExactly(filterVal)){
								// If hideOnExactMatch is true and only one hit (since even if complete match and many hits, we want to show this fact),
								// do not show list
								if(hideOnExactMatch && numHits==1 && fieldObj.autoCompleteCurrentSource.equals(lastHit.source)){
									fieldObj.autoCompleteList.showable = false;
								}
							// Last hit is not selected item, but we have previously made a selection that should be "reset" now
							}else{
								
								// No longer any current selected item, clear source var for this
								fieldObj.autoCompleteCurrentSource = null;
								
								// If deselect function ("not a complete match") present, call it
								if(onDeselectFunction){
									onDeselectFunction(fieldObj);
								}
							}
						}else{
							// If any hits, preselect top item
							if(numHits>0){
								if(fieldObj.autoCompleteList.firstChild){
									fieldObj.autoCompleteCurrent = fieldObj.autoCompleteList.firstChild;
									fieldObj.autoCompleteCurrent.className = fieldObj.autoCompleteCurrent.origClassName+" SET_cssSelected";
								}
							}
						}
						
						// If more hits than allowed, and message for hits exceeded exists, add message
						if(numHits>numMaxHitsToShow && messMaxHitsExceeded){
							var maxHitsMess = document.createElement("div");
							maxHitsMess.className = "SET_cssAdditionalHits"; //This class is used to indicate to the keyboard navigator that it should not move past this item
							maxHitsMess.innerHTML = messMaxHitsExceeded.replace(/\#NUM\#/gi,numMaxHitsToShow);
							fieldObj.autoCompleteList.appendChild(maxHitsMess);
						}
						
					}
					
					fieldObj.lastFilterVal=filterVal;	
				}
				

			// If no list, render empty container with messWorking
			}else if(messWorking){
				fieldObj.autoCompleteList.innerHTML = "<div class='SET_cssTextItem SET_cssWorking'>"+messWorking+"</div>";
				// Only show if message present and no explicit flag is set to hide message
				if(!fieldObj.autoCompleteHideMessWorking)
					fieldObj.autoCompleteList.showable = true;
				fieldObj.lastFilterVal=null;

			}else{
				// Hide list
				fieldObj.autoCompleteList.showable = false;
				fieldObj.lastFilterVal=null;
			}
			
			// Reset explicit flag to hide message
			fieldObj.autoCompleteHideMessWorking = false;
			
			
			// Attempt show of list. If showable is nothing or field is not focused, the list won't be shown
			fieldObj._autoCompleteShowList();

		}
		
		
		// *** FUNCTION ***
		// Add function for handling keyboard navigation
		fieldObj._autoCompleteKeyboardHandler = function(e){
			e = _initFWieEvent(e);
						
			var characterCode;
	
			if(e && e.which){ 
					characterCode = e.which ;
			}else if(e && window.event){
					e = window.event;
					characterCode = e.keyCode;
			}else{
				return;
			}
				
			// Enter or tab = select current (if any)
			if(characterCode == 13 || characterCode == 9){
				var forceProp = false;
				// If autosearch perform search forcibly on enter always (never select on enter)
				if(characterCode == 13 && fieldObj.autoSearch && !fieldObj.noAutoSearchOnEnter){
					if(fieldObj.autoSearchTimer){
						clearTimeout(fieldObj.autoSearchTimer);
						fieldObj.autoSearchTimer = null;
					}
					// If submit in progress, cancel it
					if(fieldObj.autoCompleteInProgress && fieldObj.xmlHttp) fieldObj.xmlHttp.abort();
					if(fieldObj._autoCompleteSearchCallback) fieldObj._autoCompleteSearchCallback();

				}else	if(fieldObj.autoCompleteList && fieldObj.autoCompleteList.visible && fieldObj.autoCompleteCurrent){
					fieldObj._autoCompleteSelect(fieldObj.autoCompleteCurrent,characterCode);
				}else{
					// Nothing matching exists, but call onselectfunction anyway (with null values)
					if(onSelectFunction)
						onSelectFunction(fieldObj,null,characterCode);
					if(characterCode == 9)forceProp = true;
				}

				// If no propagation wanted, try to prevent propagation (good luck)
				if(!enablePropagation && !forceProp){
					if(e && e.preventDefault && e.stopPropagation)
					{
						e.stopPropagation();
						e.preventDefault();
					}else{
						e.returnValue=false;
						e.cancelBubble=true;
					}
				}
				return false;
			
			}
			if(!fieldObj.autoCompleteList || !fieldObj.autoCompleteList.visible) return;

			// Arrow down = go to next in list (if any, otherwise stop)
			if(characterCode == 40){
			
				// If item selected
				if(fieldObj.autoCompleteCurrent){

					// Goto next if next exists (and next is not "morehits" message div), else keep selection
					if(fieldObj.autoCompleteCurrent.nextSibling && fieldObj.autoCompleteCurrent.nextSibling.className!="SET_cssAdditionalHits"
							&& fieldObj.autoCompleteCurrent.nextSibling.className!="SET_cssFooter"){
						// Reset old class
						fieldObj.autoCompleteCurrent.className = fieldObj.autoCompleteCurrent.origClassName;
						fieldObj.autoCompleteCurrent = fieldObj.autoCompleteCurrent.nextSibling;
					}
				
				// No item selected, if at least one item exists
				}else if(fieldObj.autoCompleteList.firstChild){
					fieldObj.autoCompleteCurrent = fieldObj.autoCompleteList.firstChild;
					
				// No items exist
				}else{
					fieldObj.autoCompleteCurrent = null;
				}
				
				// Set class of current to hover state
				if(fieldObj.autoCompleteCurrent){
					fieldObj.autoCompleteCurrent.className = fieldObj.autoCompleteCurrent.origClassName+" SET_cssSelected";
				}
				
				return false;
							
			// Arrow up = go to previous in list (if any, otherwise unmark current)
			}else if(characterCode == 38){
				
				// If item selected
				if(fieldObj.autoCompleteCurrent){

					fieldObj.autoCompleteCurrent.className = fieldObj.autoCompleteCurrent.origClassName;

					// If previous exists, else clear selection
					if(fieldObj.autoCompleteCurrent.previousSibling){
						// Reset old class
						fieldObj.autoCompleteCurrent = fieldObj.autoCompleteCurrent.previousSibling;
					}else{
						fieldObj.autoCompleteCurrent = null;
					}
				
				// No item selected or no items exist, empty selection
				}else{
					fieldObj.autoCompleteCurrent = null;
				}
				
				// Set class of current to hover state
				if(fieldObj.autoCompleteCurrent){
					fieldObj.autoCompleteCurrent.className = fieldObj.autoCompleteCurrent.origClassName+" SET_cssSelected";
				}
				
				return false;
			}
						
			return true;
		}
		
		fieldObj.sendId = 0;
		fieldObj.numCharsToAutoComplete = numCharsToAutoComplete;
		fieldObj.numMaxHitsToShow = numMaxHitsToShow;
		fieldObj.autoCompleteEnabled = true;
		
		// *** EVENT ***
		// Add onBlur that hides the list (nothing else)
		//_addFWEvent(fieldObj, "blur", function(event){if(!fieldObj.noBlur){fieldObj._autoCompleteHideList();}});
		$(fieldObj).bind("blur",function(event){if(!fieldObj.noBlur && !neverBlur){fieldObj._autoCompleteHideList();}this.doFocus=false;this.focused=false});

		// *** EVENT ***
		// Add onFocus that shows the list
		//_addFWEvent(fieldObj, "focus", function(){_autoFWComplete(fieldObj,handle);});
		$(fieldObj).bind('focus', function(event){var self=this;setTimeout(function(){self.doFocus=true;_autoFWComplete(fieldObj,handle);},0);});
		
		// *** EVENT ***
		// Add onChange event that handles when one has used context menu or mouse to modify content of field
		_addFWEvent(fieldObj, "change", function(){_autoFWComplete(fieldObj,handle);});
			
		// *** EVENT ***
		// Add onKeyUp event that handles writing on the object (but only do on type)
		_addFWEvent(fieldObj, "keyup", function(event){this.doFocus=false;_onFWType(event,function(){_autoFWComplete(fieldObj,handle);})});
		
		// *** EVENT ***
		// Add onKeyDown event that handles keyboard selection of item in list
		_addFWEvent(fieldObj, "keydown", function(event){return fieldObj._autoCompleteKeyboardHandler(event);});

		// *** EVENT ***
		// Handler for closing if outside of field or list
		fieldObj._autoCompleteHideListIfOutside = function(ev){
			var mpoint = _getFWMouseCoordinates(ev);
			if( !(fieldObj.autoCompleteList && _isFWPointWithinTarget(mpoint,fieldObj.autoCompleteList)) && 
					!_isFWPointWithinTarget(mpoint,fieldObj)){
				$(document).unbind("click",fieldObj._autoCompleteHideListIfOutside);
				fieldObj._autoCompleteHideList();
			}
		}

		fieldObj.lastFilterVal="";
		
		if(neverBlur){ // Perform search on load if never blur is true (so that list is prefilled onload)
			$(function(){_autoFWComplete(fieldObj,handle);}); //On DOM complete only
		}

		return; // Return, since this is only an init-call
	}


	// If too few chars to submit
	if(fieldObj.value.length<fieldObj.numCharsToAutoComplete){
				
		// Cancel submit + make sure return of submit does nothing
		fieldObj.autoCompleteInProgress = false;
		if(fieldObj.xmlHttp) fieldObj.xmlHttp.abort();

		// Hide list if visible
		fieldObj._autoCompleteHideList(true);

		// Clear source list
		fieldObj.sourceList = null;

		if(fieldObj.doFocus) fieldObj.focused=true;

		// Update search term session var
		if(fieldObj.storeTermInSession && String(fieldObj.lastFilterVal)!=String(fieldObj.value.toLowerCase()))
			_ajaxFWGet(String(handle).toUpperCase(),fieldObj.sendId,"fw_ac="+escape(fieldObj.value.toLowerCase())+(fieldObj.qs?"&"+fieldObj.qs:""),"GET_DATA",function(){},30000,true);
	
	// If submit in progress AND not autoSearch (which doesn't care if submit is ongoing)
	}else if(fieldObj.autoCompleteInProgress && !fieldObj.autoSearch){
		// Only update search term session var
		if(fieldObj.storeTermInSession && String(fieldObj.lastFilterVal)!=String(fieldObj.value.toLowerCase()))
			_ajaxFWGet(String(handle).toUpperCase(),fieldObj.sendId,"fw_ac="+escape(fieldObj.value.toLowerCase())+(fieldObj.qs?"&"+fieldObj.qs:""),"GET_DATA",function(){},30000,true);
		
	// If JS list already present, no auto search and filter prefix unchanged, re-render
	}else if(!fieldObj.force && !fieldObj.autoSearch && fieldObj.sourceList && 
		String(fieldObj.lastFilterVal).substr(0,fieldObj.numCharsToAutoComplete)
		==String(fieldObj.value.toLowerCase()).substr(0,fieldObj.numCharsToAutoComplete)){
		
		// Update search term session var
		if(fieldObj.storeTermInSession && String(fieldObj.lastFilterVal)!=String(fieldObj.value.toLowerCase()))
			_ajaxFWGet(String(handle).toUpperCase(),fieldObj.sendId,"fw_ac="+escape(fieldObj.value.toLowerCase())+(fieldObj.qs?"&"+fieldObj.qs:""),"GET_DATA",function(){},30000,true);

		// Filter and render list based on JS list and fieldObj value
		fieldObj._autoCompleteRenderList();

	// If JS list already present, auto search and filter COMPLETELY unchanged, re-render
	}else if(!fieldObj.force && fieldObj.autoSearch && fieldObj.sourceList && 
		String(fieldObj.lastFilterVal)==String(fieldObj.value.toLowerCase())){

		// Render list based on JS list and fieldObj value
		fieldObj._autoCompleteRenderList();
	
	// Submit AJAX request
	}else{

		// Define inline wrapper function for the actual search request. When using autoSearch, this will be called after a delay,
		// for normal search it will be called directly
		fieldObj._autoCompleteSearchCallback = function(){
			fieldObj.force = false;
			
			// Indicate submit in progress
			fieldObj.autoCompleteInProgress = true;
			
			// Increment send id to make sure all cases of autocomplete submits are kept apart
			fieldObj.sendId++;

			// Clear source list
			fieldObj.sourceList = null;
			
			// If auto search, take entire search term (not x first chars)
			if(fieldObj.autoSearch)
				_getFWFormObject("data").value=String(fieldObj.value.toLowerCase());
			else
				_getFWFormObject("data").value=String(fieldObj.value.toLowerCase()).substr(0,fieldObj.numCharsToAutoComplete);
			
			// Define fail function 
			var _autoCompleteOnFail = function(){
				 _getFWHTMLObject(fieldObj.id)._autoCompleteComplete(fieldObj.sendId,[]);
			}
			// Submit: handle (act) + value of field (data) + sendId (id) are included in the submit
			fieldObj.xmlHttp=_ajaxFWSubmit(String(handle).toUpperCase(),fieldObj.sendId,30000,_autoCompleteOnFail,1,null,false,
					"fw_limit="+(fieldObj.numMaxHitsToShow+1)+"&fw_ac="+escape(fieldObj.value.toLowerCase())+(fieldObj.qs?"&"+fieldObj.qs:""),
					_autoCompleteOnFail,"GET_EXEC","#data"+(fieldObj.submitFieldsSelector?","+fieldObj.submitFieldsSelector:""));

			_getFWFormObject("data").value="";
			_getFWFormObject("id").value="";
			
			// Show list with messWorking in it
			fieldObj._autoCompleteRenderList();
		}

		// If autoSearch, use delays before searching, but not when focusing field OR on enter
		if(fieldObj.autoSearch && !fieldObj.doFocus){
			// Reset any existing timer
			if(fieldObj.autoSearchTimer){
				clearTimeout(fieldObj.autoSearchTimer);
				fieldObj.autoSearchTimer = null;
			}

			// If submit in progress, cancel current request first
			if(fieldObj.autoCompleteInProgress && fieldObj.xmlHttp) fieldObj.xmlHttp.abort();
			
			fieldObj._autoCompleteRenderList();

			// Make new timer
			fieldObj.autoSearchTimer = 
				setTimeout(function(){
					fieldObj.autoSearchTimer = null;
					fieldObj._autoCompleteSearchCallback();
				},fieldObj.autoSearchDelay);
		
		// Normal search, just call the search immediately
		}else{
			fieldObj._autoCompleteSearchCallback();
		}
	}
}


// Default class for objects in a auto complete list. This interface must be implemented for all custom auto complete list object classes.
function _autoFWCompleteClass(id,value,type,content,matchAny,markClass,data,matchValue,markOnlyFirstHit,css,markWithinSelector){
	// The value that a match is made against, for this row
	this.value = value;
	
	// Match value is the value used when matching. This may differ to value (which is used to fill out the field on a match)
	if(!matchValue)
		matchValue = value;
		
	this.matchValue = matchValue.toLowerCase();
	
	// Use the id variable to store a unique identifier for this row
	this.id = id;
	
	// Use the data variable to store a VO-like structure with extra data (a JS-object or equiv),
	// for example for filling out other fields when this item is selected
	this.data = data;
	
	// Content is set to value if no conten present
	if(!content)
		content = value;
	
	// Content var contains the displayed value in the match list
	this.content = content;
	
	// Type var determines the type of autocomplete class, useful when having different type of items in a list
	this.type = type;
	
	// Create element here in constructor to speed things up
	var el = document.createElement("div");
	
	// Split each class in markClass
	var markClasses = markClass.split(",");

	if(markOnlyFirstHit==null)
		markOnlyFirstHit = !matchAny
	
	// Called when this item is to be rendered
	// The function must return a DOM object that can be added to the autocomplete list with appendChild
	this.render = function(filterVal){
		el.origClassName = "SET_cssItem " + (css?css:'');
		el.className = "SET_cssItem " + (css?css:'');
		el.innerHTML = this.content;
	
		// Parameter filterVal can for example be used to mark the filterVal text in the object's rendering.
		if(markClass){
			if(markWithinSelector){
				var tmp = filterVal.replace(/>/gi,"&gt;");
				tmp = tmp.replace(/</gi,"&lt;");
				var ta = tmp.split(" ");
				var al=$(markWithinSelector,el);
				for(ti=0;ti<ta.length;ti++){
					if(String(ta[ti]).replace(/[ ]*/gi,"")!=""){
						var re = new RegExp("("+_escapeFWRegExp(ta[ti])+")",(!markOnlyFirstHit?"g":"")+"i");
						al.html(al.html().replace(re,"\013$1\037"));
					}
				}
				al.html(al.html().replace(/\013/gi,"<span>"));
				al.html(al.html().replace(/\037/gi,"</span>"));

				$("span", al).each(function(){
					for(ai=1; ai<=ta.length;ai++) {
						if(ta[ai-1].toLowerCase() == $(this).html().toLowerCase()){
							if(ai <= markClasses.length){
								markerClass = markClasses[ai-1];
							}else{
								markerClass = markClasses[0];
							}
							$(this).addClass(markerClass);
						}
					}
				});
			}else{
				// If filterval contains < > these must be replaced by &gt;
				var tmp = filterVal.replace(/>/gi,"&gt;");
				tmp = tmp.replace(/</gi,"&lt;");
				var oldTmp=tmp;
				var pos = Math.round(tmp.length/2);
				var tmpLeft = tmp.substr(0,pos);
				var tmpRight = tmp.substr(pos);
				if(tmp.length<2){
					tmpLeft = tmp;
					tmpRight = "";
				}else{
					tmpRight = _escapeFWRegExp(tmpRight);
				}
				tmpLeft = _escapeFWRegExp(tmpLeft);
				tmp = _escapeFWRegExp(tmp);

				var re1 = new RegExp("(<.*?)("+tmpLeft+")("+tmpRight+")(.*?>)",(!markOnlyFirstHit?"g":"")+"i");re1 = re1.compile(re1);
				var re2 = new RegExp("("+tmp+")",(!markOnlyFirstHit?"g":"")+"i");re2 = re2.compile(re2);
				var re3 = new RegExp("(<.*?)("+tmpLeft+")>><<("+tmpRight+")(.*?>)",(!markOnlyFirstHit?"g":"")+"i");re3 = re3.compile(re3);

				// This advanced recursive replacing is required to ensure no HTML tags are messed up			
				function _autoFWCompleteReplace(al){
					var ch = al.children();
					if(ch.length>0){
						ch.each(function(){_autoFWCompleteReplace($(this))});
					}
					var tmpStr = al.html().replace(re1,"$1$2>><<$3$4");
					tmpStr = tmpStr.replace(re2,"<span class='"+markClass+"'>$1</span>");
					tmpStr = tmpStr.replace(re3,"$1$2$3$4");
					al.html(tmpStr);
				}
				_autoFWCompleteReplace($(el));
			}
		}
		return el;
	}
	
	// Called to check if this item should be included in match list
	this.matchesFilter = function(filterVal,re){
		if(!matchAny){
			return (String(this.matchValue).substr(0,String(filterVal).length).toLowerCase() == String(filterVal).toLowerCase());
		}else if(re){
			return re.test(this.matchValue);
		}else{
			return new RegExp(_escapeFWRegExp(String(filterVal).toLowerCase()), "i").test(String(this.matchValue).toLowerCase());
		}
	}
	
	// Called to check if this item matches the filterval EXACTLY char-by-char
	this.matchesExactly = function(filterVal){
		return (String(this.matchValue).toLowerCase() == String(filterVal).toLowerCase());
	}
	
	// Determines equality between different _autoFWCompleteClass instances
	this.equals = function(obj){
		try{
			return (String(this.matchValue)==String(obj.matchValue) && String(this.id)==String(obj.id) && String(this.type)==String(obj.type));
		}catch(e){
			return false;
		}
	}
	
}




/********************************************************
 * _escapeFWRegExp
 * Created 10 mar 2008 Linus Lövholm
 *
 * Escapes any reg exp characters in s so that they can be
 * used as literals in a subsequent reg exp
 ********************************************************/
function _escapeFWRegExp(s){
  return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
}

/********************************************************
 * _getFWTypeOf
 *
 * A type of that works for arrays etc. Returns 
 * different strings depending on the type
 ********************************************************/ 
function _getFWTypeOf(value){
    var s = typeof(value);
    if(s === 'object'){
        if(value){
            if(typeof(value.length) === 'number' &&
                    !(value.propertyIsEnumerable('length')) &&
                    typeof(value.splice) === 'function'){              
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

/********************************************************
 * _getFWQueryString
 *
 * Returns specific query string variable, empty string if
 * not found.
 ********************************************************/ 
function _getFWQueryString(variable,query){
	if(!query) query = window.location.search.substring(1);
	var vars = query.split("&");
	for(var i=0;i<vars.length;i++){
		var pair = vars[i].split("=");
		if(pair[0] == variable){
			return pair[1];
		}
	}
	return "";
} 


/********************************************************
 * FWAjaxRequest
 *
 * Object for handling advanced AJAX requests. NEVER USE
 * DIRECTLY.
 ********************************************************/ 
function FWAjaxRequest(){var req =new Object(); req.requestType=null;req.act=null;req.timeout =null; req.generateUniqueUrl =true; req.url =window.location.href; req.method ="GET"; req.async =true; req.username =null; req.password =null; req.ajaxId=null;req.parameters =new Object(); req.fieldSelector=""; req.requestIndex =FWAjaxRequest.numAjaxRequests++; req.responseReceived =false; req.groupName =null; req.queryString =""; req.responseText =null; req.responseXML =null; req.status =null; req.statusText =null; req.aborted =false; req.xmlHttpRequest =null; req.onTimeout=null; req.onLoading=null; req.onLoaded=null; req.onInteractive=null; req.onComplete=null; req.onSuccess=null; req.onError=null; req.onGroupBegin=null; req.abort=null;req.onGroupEnd=null; req.xmlHttpRequest =FWAjaxRequest.getXmlHttpRequest(); if(req.xmlHttpRequest==null){return null;}var t=function(){if(req==null || req.xmlHttpRequest==null){return;}if(req.xmlHttpRequest.readyState==1){req.onLoadingInternal(req);}if(req.xmlHttpRequest.readyState==2){req.onLoadedInternal(req);}if(req.xmlHttpRequest.readyState==3){req.onInteractiveInternal(req);}if(req.xmlHttpRequest.readyState==4){req.onCompleteInternal(req);}};if($.browser.mozilla){req.xmlHttpRequest.onload=t}else{req.xmlHttpRequest.onreadystatechange=t};req.onLoadingInternalHandled=false; req.onLoadedInternalHandled=false; req.onInteractiveInternalHandled=false; req.onCompleteInternalHandled=false; req.onLoadingInternal= function(){if(req.onLoadingInternalHandled){return;}FWAjaxRequest.numActiveAjaxRequests++; if(FWAjaxRequest.numActiveAjaxRequests==1 && typeof(window['AjaxRequestBegin'])=="function"){AjaxRequestBegin();}if(req.groupName!=null){if(typeof(FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName])=="undefined"){FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName] =0;}FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName]++; if(FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName]==1 && typeof(req.onGroupBegin)=="function"){req.onGroupBegin(req.groupName);}}if(typeof(req.onLoading)=="function"){req.onLoading(req);}req.onLoadingInternalHandled=true;}; req.onLoadedInternal= function(){if(req.onLoadedInternalHandled){return;}if(typeof(req.onLoaded)=="function"){req.onLoaded(req);}req.onLoadedInternalHandled=true;}; req.onInteractiveInternal= function(){if(req.onInteractiveInternalHandled){return;}if(typeof(req.onInteractive)=="function"){req.onInteractive(req);}req.onInteractiveInternalHandled=true;}; req.onCompleteInternal= function(){if(req.onCompleteInternalHandled || req.aborted){return;}req.onCompleteInternalHandled=true; FWAjaxRequest.numActiveAjaxRequests--; if(FWAjaxRequest.numActiveAjaxRequests==0 && typeof(window['AjaxRequestEnd'])=="function"){AjaxRequestEnd(req.groupName);}if(req.groupName!=null){FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName]--; if(FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName]==0 && typeof(req.onGroupEnd)=="function"){req.onGroupEnd(req.groupName);}}req.responseReceived =true; req.status =req.xmlHttpRequest.status; req.statusText =req.xmlHttpRequest.statusText; req.responseText =req.xmlHttpRequest.responseText; req.responseXML =req.xmlHttpRequest.responseXML; if(typeof(req.onComplete)=="function"){if(!req.onComplete(req)) return;}if(req.xmlHttpRequest.status==200 && typeof(req.onSuccess)=="function"){req.onSuccess(req);}else if(typeof(req.onError)=="function"){req.onError(req);}delete req.xmlHttpRequest['onreadystatechange']; req.xmlHttpRequest =null;if(req.act && FWAjaxRequest.requests[req.act]){FWAjaxRequest.requests[req.act]=null;}}; req.onTimeoutInternal= function(){
if(req!=null && req.xmlHttpRequest!=null && !req.onCompleteInternalHandled){req.abort();if(typeof(req.onTimeout)=="function"){req.onTimeout(req);}}}; req.process = function(){if(req.xmlHttpRequest!=null){if(req.generateUniqueUrl){req.ajaxId=new Date().getTime() + "" + req.requestIndex;req.url +=((req.url.indexOf("?")>-1)?"&":"?") + "fw_ajaxid="+req.ajaxId;}var content =null; for(var i in req.parameters){if(req.queryString.length>0){req.queryString +="&";}req.queryString +=escape(i) + "=" + escape(req.parameters[i]);}if(req.method=="GET"){if(req.queryString.length>0){req.url +=((req.url.indexOf("?")>-1)?"&":"?") + req.queryString;}}
req.xmlHttpRequest.open(req.method,req.url,req.async,req.username,req.password);
if(req.method=="POST"){if(typeof(req.xmlHttpRequest.setRequestHeader)!="undefined"){req.xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;');}content =req.queryString;}else{
	/*if(req.xmlHttpRequest.overrideMimeType){req.xmlHttpRequest.overrideMimeType('text/html; charset=iso-8859-1')}*/
req.xmlHttpRequest.setRequestHeader('Content-type', 'text/html; charset=iso-8859-1');
}if(req.timeout>0){setTimeout(req.onTimeoutInternal,req.timeout);}req.xmlHttpRequest.send(content);}if(req.act){FWAjaxRequest.requests[req.act]=req;}}; req.handleArguments = function(args){for(var i in args){if(typeof(req[i])=="undefined"){req.parameters[i] =args[i];}else{req[i] =args[i];}}}; req.getAllResponseHeaders = function(){if(req.xmlHttpRequest!=null){if(req.responseReceived){return req.xmlHttpRequest.getAllResponseHeaders();}alert("Cannot getAllResponseHeaders because a response has not yet been received");}}; req.getResponseHeader = function(headerName){if(req.xmlHttpRequest!=null){if(req.responseReceived){return req.xmlHttpRequest.getResponseHeader(headerName);}alert("Cannot getResponseHeader because a response has not yet been received");}}; req.abort =function(){if(req!=null && req.xmlHttpRequest!=null && !req.onCompleteInternalHandled){req.aborted =true; req.xmlHttpRequest.abort();FWAjaxRequest.numActiveAjaxRequests--; if(FWAjaxRequest.numActiveAjaxRequests==0 && typeof(window['AjaxRequestEnd'])=="function"){AjaxRequestEnd(req.groupName);}if(req.groupName!=null){FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName]--; if(FWAjaxRequest.numActiveAjaxGroupRequests[req.groupName]==0 && typeof(req.onGroupEnd)=="function"){req.onGroupEnd(req.groupName);}}delete req.xmlHttpRequest['onreadystatechange']; req.xmlHttpRequest =null;if(req.act && FWAjaxRequest.requests[req.act]){FWAjaxRequest.requests[req.act]=null;}}
}; return req;}FWAjaxRequest.getXmlHttpRequest =function(){if(window.XMLHttpRequest){return new XMLHttpRequest();}else if(window.ActiveXObject){try{return new ActiveXObject("Msxml2.XMLHTTP");}catch(e){try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(E){return null;}}}else{return null;}}; FWAjaxRequest.isActive =function(){return(FWAjaxRequest.numActiveAjaxRequests>0);}; FWAjaxRequest.get =function(args){return FWAjaxRequest.doRequest("GET",args);}; FWAjaxRequest.post =function(args){return FWAjaxRequest.doRequest("POST",args);}; FWAjaxRequest.doRequest =function(method,args){if(typeof(args)!="undefined" && args!=null){var myRequest =new FWAjaxRequest(); myRequest.method =method; myRequest.handleArguments(args); myRequest.process();return myRequest;}return null;}; FWAjaxRequest.submit =function(theform, args){var myRequest =new FWAjaxRequest(); if(myRequest==null){return null;} myRequest.method =theform.method.toUpperCase(); myRequest.url =theform.action; myRequest.handleArguments(args); var serializedForm =FWAjaxRequest.serializeForm(theform,myRequest); myRequest.queryString =serializedForm; myRequest.process(); return myRequest;}; 
FWAjaxRequest.serializeForm =function(theform,req){var els =(req.fieldSelector!=""?$.unique($(req.fieldSelector+",#id:first,#data:first,#act:first,#scy:first,#scx:first",document.body).get())		:$(":input",document.body).get()); var len=els.length; var queryString =""; this.addField = function(name,value){if(queryString.length>0){queryString +="&";}queryString +=escape(name) + "=" + escape(value).replace(/\+/gi,"%2B").replace(/&/gi,"%26")}; for(var i=0;i<len;i++){var el =els[i]; if(!el.disabled){switch(el.type){case 'text': case 'password': case 'hidden': case 'textarea': this.addField(el.name,el.value); break; case 'select-one': if(el.selectedIndex>=0){this.addField(el.name,el.options[el.selectedIndex].value);}break; case 'select-multiple': for(var j=0;j<el.options.length;j++){if(el.options[j].selected||el.getAttribute("submitAll")){this.addField(el.name,el.options[j].value);}}break; case 'checkbox': case 'radio': if(el.checked){this.addField(el.name,el.value);}break;}}}return queryString;}; FWAjaxRequest.numActiveAjaxRequests =0; FWAjaxRequest.numActiveAjaxGroupRequests =new Object(); FWAjaxRequest.numAjaxRequests =0;FWAjaxRequest.requests=new Object();

/********************************************************
 * _ajaxFWSubmit
 *
 * Use this when submitting a form via AJAX.
 * By default (if no funcOnDone is provided) response text
 * will be executed as JS.
 * Returns the FWAjaxRequest object or null if fail.
 ********************************************************/ 
function _ajaxFWSubmit(act,id,timeout,funcOnTimeout,numRetries,funcOnDone,isSingleton,qs,funcOnFail,requestType,fieldSelector){
	
	if(!qs) qs=""; //Always build qs from scratch, since every ajax call may have different requestType
	else qs=String(qs);

	if(!requestType) requestType = window.location.fw_rt; //Default rt = get from window.location (i.e. last full page load request's type)
	qs = _reviseFWQuery(qs,"fw_rt",String(requestType));
	
	// Add certain qs pars if missing
	switch(requestType){
		case "GET_PAGETEMPLATE":
			if(window.location.ptid){if(("&"+qs).indexOf("&ptid=")==-1) qs += "&ptid="+String(window.location.ptid)}
			if(window.location.ptvs){if(("&"+qs).indexOf("&ptvs=")==-1) qs += "&ptvs="+String(window.location.ptvs)}
			break;
		case "GET_PAGE":
			if(window.location.pid){if(("&"+qs).indexOf("&pid=")==-1) qs += "&pid="+String(window.location.pid)}
			if(window.location.vs){if(("&"+qs).indexOf("&vs=")==-1) qs += "&vs="+String(window.location.vs)}
			break;
	}
	
	if(("&"+qs).indexOf("&gvs=")==-1)	qs += "&gvs="+String(window.location.gvs);
	if(window.location.fw_pt){if(("&"+qs).indexOf("&fw_pt=")==-1) qs += "&fw_pt="+String(window.location.fw_pt)}
	if(window.location.fw_th){if(("&"+qs).indexOf("&fw_th=")==-1) qs += "&fw_th="+String(window.location.fw_th)}
	if(window.location.fw_ps){if(("&"+qs).indexOf("&fw_ps=")==-1) qs += "&fw_ps="+String(window.location.fw_ps)}
	if(window.fw_noAjaxIncludes){if(("&"+qs).indexOf("&fw_noinc=")==-1) qs += "&fw_noinc=true"}
	var oldAction = document.multipurpose.action;document.multipurpose.action = "index.asp?"+qs;
	
	if(act){try{if(_validateFWPage && !_validateFWPage(String(act).toUpperCase(),id)){return null;}}catch(er){}
		document.multipurpose.act.value=act;
		// If is singleton = cancel any existing requests for same act
		if(isSingleton && FWAjaxRequest.requests[act]) FWAjaxRequest.requests[act].abort();
	}
	if(id)document.multipurpose.id.value = id;
	var args = {'act':act,'requestType':requestType};
	if(funcOnFail){args.onError=funcOnFail;}
	else{args.onError = function(){_hideFWShield(null,true);document.body.style.cursor = 'auto';};}
	args.onSuccess=(funcOnDone?funcOnDone:function(req){/*_hideFWShield();*/
		switch(requestType){
			case "GET_PAGE":case "GET_PAGETEMPLATE":$(document.body).html(req.responseText);break;
			case "GET_EXEC":jQuery.globalEval(req.responseText);break;
		}});
	if(!timeout)timeout=window.fw_ajaxDefaultTimeout;
	timeout = parseInt(timeout,10);
	if(timeout>0){
		args.timeout=timeout;
		if(funcOnTimeout){args.onTimeout=funcOnTimeout;}
		else{args.onTimeout = function(){_hideFWShield(null,true);document.body.style.cursor = 'auto';};}
	}
	numRetries = parseInt(numRetries,10)
	if(numRetries>1){
		args.onError=function(req){_ajaxFWSubmit(act,id,timeout,funcOnTimeout,numRetries-1,funcOnDone,isSingleton,qs,funcOnFail,requestType,fieldSelector)};
		args.onTimeout=args.onError;
	}
	args.onComplete = function(req){return _ajaxFWOnComplete(req,requestType,funcOnFail)};
	if(fieldSelector) args.fieldSelector=fieldSelector;
	
	var ret = FWAjaxRequest.submit(document.multipurpose,args);
	document.multipurpose.id.value = "";
	document.multipurpose.act.value ="";
	if(oldAction)document.multipurpose.action = oldAction;
	return ret;
}

/* Helper used by both ajax handlers */
function _ajaxFWOnComplete(req,requestType,funcOnFail){
	if(req.responseText.indexOf("<!--FW_RELOAD-->")!=-1){
		location.href=location.href;
		return false;
	}

	if(req.responseText.substr(0,9)=="<!DOCTYPE"){
		if(req.responseText.indexOf("<!--FW_AJAX-->")==-1){
			if($.isFunction(funcOnFail)) funcOnFail(req);
			return false;
		}
	}else if(requestType=="GET_MARKUP"){
		_resizeFWIfInIframe();
	}
	var newTxt = req.responseText;
	newTxt = newTxt.replace(/\<\!--FW\_LOG\:(.*?)--\>/,function(s,p1){
		var l = $("#SET_ajaxMessageLog");
		if(l.length==0){
			// Ej dialog, istället ha en liten liten div som visas som ikon nere i högra hörnet bara, som kan expandera att ta upp hela viewporten + ha scrollbars
			l=$("<div id='SET_ajaxMessageLog' style='display:none;'>Loading...</div>");
			$(document.body).append(l);
		}else{
			l.html("Loading...");
		}
		_renderFWLogIndicator(p1);
		return "";
	});

	if(!window.fw_noAjaxIncludes){
		if(!window.fw_dynAddedJs) window.fw_dynAddedJs=",";
		newTxt=newTxt.replace(/\<\!--FW\_JSINCLUDES\:(.*?)--\>/,function(s,p1){
				$.each(p1.split(","),function(i){
					var s = this;
					if(s.substr(0,1)!="/") s="/mind_setup/scripts/"+s;
					if($("head > script[src*='"+s+"']:first").length==0 && window.fw_dynAddedJs.indexOf(","+s+",")){
						$("head:first").append('<script src="'+s+'?v='+window.fw_systemVersion+'" type="text/javascript"/>');
						window.fw_dynAddedJs += s+",";
					}
				});
				return "";
			});
		newTxt = newTxt.replace(/\<\!--FW\_CSSINCLUDES\:(.*?)--\>/,function(s,p1){
				$.each(p1.split(","),function(i){
					var s = this;
					if(s.substr(0,1)!="/") s=window.location.path+"/css/"+s;
					if($("head > link[href^='"+s+"']:first").length==0){
						$('<link rel="stylesheet" href="'+s+'?v='+window.fw_systemVersion+'" type="text/css"/>').appendTo("head:first");
					}
				});
				return "";
			});
	}

	newTxt = newTxt.replace(/\<\!--FW\_VALIDATION\:(.*?)--\>/,function(s,p1){
			var pr=$("#SET_postRenders");
			if(p1)pr.data("additionalValidation","switch(act){"+p1+"}");
			return "";
	});
	
	newTxt = newTxt.replace(/\<\!--FW\_CHECKMESSAGES(?:\:((?:INFO|WARNING|ERROR)\|.*?))?--\>/,function(s,p1){
			if(p1){
				p1 = p1.split("|");
				_showFWSystemMessage(p1[1],p1[0]);
			}else _checkFWSystemMessages();
			return "";
		});

	//switch(answerFormat){case "HTML":break;default: newTxt = newTxt.replace(/\<\!--FW\_AJAX\--\>/,"");}
	req.responseText = newTxt;
	
	newTxt = null;
	return true;
}

function _resizeFWIfInIframe(){
	if(window!=window.parent && window.name.indexOf('SET_iframe')!=-1){
		var callbackURL=(String(window.name)+'|').split('|')[1];
		if(callbackURL){
			var height = Math.max( document.body.offsetHeight, document.body.scrollHeight );
			callbackURL+=height;
			// Create an iframe with url like callbackURL
			var name = 'resize_iframe';
			var iframe = document.getElementById(name);
			if(!iframe){
				iframe = document.createElement("iframe");
				iframe.style.display="none";
				iframe.id=name;
				iframe.name=name;
				document.body.appendChild(iframe);
			}
			iframe.src=callbackURL;
		}
	}
}

/********************************************************
 * _ajaxFWRequest
 *
 * Use this when performing a simple GET AJAX request.
 * By default (if no funcOnDone is provided) response text
 * will be executed as JS.
 * Returns the FWAjaxRequest object or null if fail.
 ********************************************************/ 
function _ajaxFWRequest(act,id,timeout,funcOnTimeout,numRetries,funcOnDone,isSingleton,qs,funcOnFail,requestType){
	
	if(!qs) qs="";
	else qs=String(qs);
	
	if(!requestType) requestType = window.location.fw_rt; //Default rt = get from window.location (i.e. last full page load request's type)
	qs = _reviseFWQuery(qs,"fw_rt",String(requestType));

	switch(requestType){
		case "GET_PAGETEMPLATE":
			if(window.location.ptid){if(("&"+qs).indexOf("&ptid=")==-1) qs += "&ptid="+String(window.location.ptid)}
			if(window.location.ptvs){if(("&"+qs).indexOf("&ptvs=")==-1) qs += "&ptvs="+String(window.location.ptvs)}
			break;
		case "GET_PAGE":
			if(window.location.pid){if(("&"+qs).indexOf("&pid=")==-1) qs += "&pid="+String(window.location.pid)}
			if(window.location.vs){if(("&"+qs).indexOf("&vs=")==-1) qs += "&vs="+String(window.location.vs)}
			break;
	}

	if(("&"+qs).indexOf("&gvs=")==-1) qs += "&gvs="+String(window.location.gvs);
	if(window.location.fw_pt){if(("&"+qs).indexOf("&fw_pt=")==-1) qs += "&fw_pt="+String(window.location.fw_pt)}
	if(window.location.fw_th){if(("&"+qs).indexOf("&fw_th=")==-1) qs += "&fw_th="+String(window.location.fw_th)}
	if(window.location.fw_ps){if(("&"+qs).indexOf("&fw_ps=")==-1) qs += "&fw_ps="+String(window.location.fw_ps)}
	if(window.fw_noAjaxIncludes){if(("&"+qs).indexOf("&fw_noinc=")==-1) qs += "&fw_noinc=true"}

	if(qs!=null){
		qs = String(qs);
		if(qs.substr(0,1)=="?") qs = qs.substr(1);
		var splQs = qs.split("&");
		var newQs = "";
		for(i=0;i<splQs.length;i++){
			var pair = String(splQs[i]).split("=");
			if(pair.length==2){
				newQs += (newQs==""?"":"&") + pair[0] + "=" + escape(pair[1]);
			}
		}
		qs = newQs;
		if(act){
			qs = _reviseFWQuery(qs,"act",escape(act));
			if(isSingleton && FWAjaxRequest.requests[act]) FWAjaxRequest.requests[act].abort();
		}
		if(id)	qs = _reviseFWQuery(qs,"id",escape(id));
	}
	var args = {'act':act,'url':'','queryString':qs};
	if(funcOnFail){args.onError=funcOnFail;}
	else{args.onError = function(){_hideFWShield(null,true);document.body.style.cursor = 'auto';};}
	args.onSuccess=(funcOnDone?funcOnDone:function(req){/*_hideFWShield();*/
		switch(requestType){
		case "GET_PAGE":case "GET_PAGETEMPLATE":$(document.body).html(req.responseText);break;
		case "GET_EXEC":jQuery.globalEval(req.responseText);break;
		}});
	if(!timeout)timeout=window.fw_ajaxDefaultTimeout;
	timeout = parseInt(timeout,10);
	if(timeout>0){
		args.timeout=timeout;
		if(funcOnTimeout){args.onTimeout=funcOnTimeout;}
		else{args.onTimeout = function(){_hideFWShield(null,true);document.body.style.cursor = 'auto';};}
	}
	numRetries = parseInt(numRetries,10)
	if(numRetries>1){
		args.onError=function(req){_ajaxFWRequest(act,id,timeout,funcOnTimeout,numRetries-1,funcOnDone,isSingleton,qs,funcOnFail,requestType)};
		args.onTimeout=args.onError;
	}
	args.onComplete = function(req){return _ajaxFWOnComplete(req,requestType,funcOnFail)};
	var ret = FWAjaxRequest.get(args);
	return ret;
}


// Wrapper functions for simpler ajax calls
// Example: _ajaxFWGet("UPDATE_STEP",17,"mod=CMSbid=239","GET_DATA",function(req){...},30000,true);
function _ajaxFWGet(act,id,qs,requestType,funcOnDone,timeout,notSingleton){
	return _ajaxFWRequest(act,id,timeout,null,1,funcOnDone,!(notSingleton),qs,null,requestType);
}
function _ajaxFWPost(act,id,qs,requestType,funcOnDone,timeout,fieldSelector,notSingleton){
	return _ajaxFWSubmit(act,id,timeout,null,1,funcOnDone,!(notSingleton),qs,null,requestType,fieldSelector);
}



/* 
	Strip and post process content.
	Post processes string by converting MAP bb-code to HTML (and also ensures no HTML injections).
	Updates of these methods MUST mean updates of fwRtnStrings.asp methods fwPostProcessContent and/or fwStripContent
*/

function _stripFWContent(str){
	if(!str) return "";
	str = String(str);	
	str = str.replace(/\</gi,"&lt;").replace(/\>/gi,"&gt;").replace(/\n/gi," ").replace(/\[\/?[BIUM]\]/gi,"");
	str = str.replace(/\[(?:(?:LINK)|(?:EMAIL))[^\]]*\](.*?)\[\/(?:(?:LINK)|(?:EMAIL))\]/gi,"$1");
	return str;
}

function _postProcessFWContent(str){

	if(!str) return "";
	str = str.replace(/\</gi,"&lt;").replace(/\>/gi,"&gt;").replace(/\n/gi,"<br>")
	
	str = str.replace(/\[(\/)?[M]\]/gi,"<$1em>")
	str = str.replace(/\[(\/?[BIU])\]/gi,"<$1>")

	//[LINK]url[/LINK] => <a href="url">url</a>
	str = str.replace(/\[LINK\](.*?)\[\/LINK\]/gi,"<a href=\"$1\">$1</a>")
		
	//[LINK=url]title[/LINK] => <a href="url">title</a>
	str = str.replace(/\[LINK=(https?:\/\/[^\]]+?)\](.*?)\[\/LINK\]/gi,"<a href=\"$1\" target=\"_blank\">$2</a>")
	str = str.replace(/\[LINK=((?:\/|javascript)?[^\]]+?)\](.*?)\[\/LINK\]/gi,"<a href=\"$1\">$2</a>")

	//str = str.replace(/\[LINK=([^\]]+)\]([^\[]+)\[\/LINK\]","<a href=""http://$1"" target=""_blank"">$2</a>")

	//[EMAIL]url[/EMAIL] => <a href="url">url</a>
	str = str.replace(/\[EMAIL](.*?)\[\/EMAIL]/gi,"<a href=\"mailto:$1\">$1</a>")

	//[EMAIL=url]title[/EMAIL] => <a href="url">title</a>
	str = str.replace(/\[EMAIL([^\]]+?)\](.*?)\[\/EMAIL]/gi, "<a href=\"mailto:$1\">$2</a>")
		
	return str;
}


/* $ Dynamic select */

// Toggles between close and show select expander
function _toggleFWDynamicSelect(id,onlyShow,e){
	var s=$("#"+id+"___select");
	if(s.attr("notVisible")) return;
	if(_hasFWStateCSS(s,'DISABLED')) return;

	if(!s.attr("isExpanded") || onlyShow){
		//_closeFWDynamicSelect();
		_showFWDynamicSelect(s);
	}else{
		_closeFWDynamicSelect(s);
	}
	_stopFWEvents(e);
}
// Toggles between close and show select sub expander
function _toggleFWDynamicSubSelect(dynOptionA,onlyShow,e){
	dynOptionA = $(dynOptionA);
	var cur = dynOptionA.parents("div.SET_cssFormSelectOptionParent:first").find("div.SET_cssFormSelectSubExpander:first");
	dynOptionA.parents("div.SET_cssFormSelectExpander:first").find("div.SET_cssFormSelectSubExpander").not(cur.get(0)).hide(); //Hide other subs first
	if(!onlyShow){
		if(cur.is(":visible")) cur.hide(); //Hide current as well if visible
		else cur.show();
	}else{
		cur.show();
	}
	_stopFWEvents(e);
}

// Shows a select expander
function _showFWDynamicSelect(s){
	
	if(typeof(s) != "object") s = $("#"+s+"___select");
	if(!s||s.length<1) return;
	
	var id = s.attr("id").replace("___select","");
	var d = $("#"+id+"___expander");
	var group = s.attr("group");
	if(typeof(group)=="undefined")group="";
	
	// Hide all siblings
	setTimeout(function(){
	$("div.SET_cssFormSelect[group='"+group+"'][isExpanded='true']:not(#"+id+"___select)").each(function(i){
		_closeFWDynamicSelect($(this)); // Handles hide of sibling's children as well
	});},10);

	// Append to body and show
	d.appendTo(document.body);
	
	var isFixed = (String(s.css("position")).toLowerCase()=="fixed") || s.attr("fixed");

	_showFWAtElement(d.get(0),s.get(0),"B",0,0,"block",isFixed);
	
	if(isFixed)	d.addClass("SET_cssFormSelectExpanderFixed");
	else d.removeClass("SET_cssFormSelectExpanderFixed");

	s.attr("isExpanded",true); //Indicate expanded, with attribute and class
	var classStr = s.attr("class");
	if(classStr){
		s.data("oldClass",classStr);
		classStr += " "+classStr.split(" ").join("Expanded ")+"Expanded";
		s.attr("class",classStr);
	}else{s.addClass("SET_cssFormSelectExpanded");}

	// If not keep open, the select is closed on click almost anywhere on document
	if(!s.attr("keepOpen")){
		var _okFWToHideDynamicSelect = function(e){
			var mpoint = _getFWMouseCoordinates(e);
			var doHide = true;
			d.add(s.find("div.SET_cssFormSelectTop [isTrigger='true']")).add(d.find("div.SET_cssFormSelectSubExpander")).each(function(i){
				if(_isFWPointWithinTarget(mpoint,this,-1,null,isFixed)){
					doHide = false;
					return false;
				}else{
					if(s.attr("dontCloseOn")){
						$(s.attr("dontCloseOn")).each(function(i){
							if(_isFWPointWithinTarget(mpoint,this,-1,null,isFixed,true)){
								doHide = false;
								return false;
							}
						});
					}
				}
			});
			return doHide;
		}
		// Store close handler in window, so it can be removed later
		window["fw_dynamicSelectCloseHandler_"+id]=function(e){
			if(s.data("okToHide")){
				s.removeData("okToHide");
				if(_okFWToHideDynamicSelect(e))_closeFWDynamicSelect(s,e);
			}
		};
		window["fw_dynamicSelectMouseDownHandler_"+id]=function(e){
			if(_okFWToHideDynamicSelect(e)){s.data("okToHide",true)}
		};
		$(document).mousedown(window["fw_dynamicSelectMouseDownHandler_"+id]);
		$(document).click(window["fw_dynamicSelectCloseHandler_"+id]);
	}

	// On open?
	if(s.attr("onOpen")){
		eval("var f="+s.attr("onOpen")+";");
		if($.isFunction(f)) f(id,s,d);
		//if(typeof(f)=="function") f(id,s,d);
	}
}

// Closes a select expander
function _closeFWDynamicSelect(s,e,notRecursive){
	if(s==null){
		// Close all open dyn selects
		$("div.SET_cssFormSelect[isExpanded='true']").each(function(i){
			_closeFWDynamicSelect($(this),e,true); // Handles hide of sibling's children as well
		});
		return;
	}
	if(typeof(s) != "object")s = $("#"+s+"___select");
	if(!s||s.length<1||!s.attr("isExpanded")) return;
	var id = s.attr("id").replace("___select","");
	var d = $("#"+id+"___expander");
	var group = s.attr("group");
	if(typeof(group)=="undefined")group="";
	// Hide all children, and childrens children (etc), if not recursive
	if(!notRecursive){
		$("div.SET_cssFormSelect[group^='"+group+".'][isExpanded='true']:not(#"+id+"___select)").each(function(i){
			_closeFWDynamicSelect($(this),e,true);
		});
	}
	s.removeAttr("isExpanded");
	s.removeData("okToHide");
	var classStr = s.data("oldClass");
	if(classStr){
		s.attr("class",s.data("oldClass"));
		s.removeData("oldClass");
	}else{s.removeClass("SET_cssFormSelectExpanded");}
	
	// Hide expander and append it to original position (after s)
	d.hide().insertAfter(s);
	if(window["fw_dynamicSelectCloseHandler_"+id]){
		$(document).unbind("click",window["fw_dynamicSelectCloseHandler_"+id]);
		window["fw_dynamicSelectCloseHandler_"+id]=null;
	}
	if(window["fw_dynamicSelectMouseDownHandler_"+id]){
		$(document).unbind("mousedown",window["fw_dynamicSelectMouseDownHandler_"+id]);
		window["fw_dynamicSelectMouseDownHandler_"+id]=null;
	}
	// Hide all sub expanders
	$("div.SET_cssFormSelectSubExpander",d).hide();
	// On close?
	if(s.attr("onClose")){
		eval("var f="+s.attr("onClose")+";");
		if($.isFunction(f)) f(id,s,d,e);
		//if(typeof(f)=="function") f(id,s,d,e);
	}
	_stopFWEvents(e);
	
}

// Selects an option
function _selectFWDynamicSelectOption(e,s,value,html,data){
	if(typeof(s) != "object") s = $("#"+s+"___select");
	var id = s.attr("id").replace("___select","");
	$("#"+id).val(value);
	html = $(html).clone(true);
	if(html.length>0){
		var top = $("div.SET_cssFormSelectTopOption:first",s);
		if(top.length>0){
			top.replaceWith(html.show());
		}else{
			$("div.SET_cssFormSelectTop:first",s).prepend(html.show());
		}
	}
	// Trigger onchange if there is one
	if(s.attr("onChange")){
		eval("var f="+s.attr("onChange")+";");
		if($.isFunction(f)) f(e,s,value,data);
		//if(typeof(f)=="function") f(e,s,value);
	}
}

/* Copies font styles from one jQuery object to another */
function _copyFWFontStyles(from,to,alsoPaddingsEtc){
	to.css("font",from.css("font"));
	to.css("font-weight",from.css("font-weight"));
	to.css("text-decoration",from.css("text-decoration"));
	to.css("font-style",from.css("font-style"));
	if(parseInt(from.css("font-size"),10)>0) to.css("font-size",from.css("font-size"));
	to.css("font-family",from.css("font-family"));
	to.css("font-variant",from.css("font-variant"));
	if(parseInt(from.css("line-height"),10)>0) to.css("line-height",from.css("line-height"));
	to.css("letter-spacing",from.css("letter-spacing"));
	to.css("text-align",from.css("text-align"));
	to.css("text-transform",from.css("text-transform"));
	to.css("word-spacing",from.css("word-spacing"));
	to.css("color",from.css("color"));
	to.css("direction",from.css("direction"));
	if(alsoPaddingsEtc){
		to.css("padding",from.css("padding"));
		to.css("padding-left",from.css("padding-left"));
		to.css("padding-right",from.css("padding-right"));
		to.css("padding-top",from.css("padding-top"));
		to.css("padding-bottom",from.css("padding-bottom"));
		to.css("border-width",from.css("border-width"));
		to.css("border-left-width",from.css("border-left-width"));
		to.css("border-right-width",from.css("border-right-width"));
		to.css("border-top-width",from.css("border-top-width"));
		to.css("border-bottom-width",from.css("border-bottom-width"));
		to.css("border-left-style",from.css("border-left-style"));
		to.css("border-right-style",from.css("border-right-style"));
		to.css("border-top-style",from.css("border-top-style"));
		to.css("border-bottom-style",from.css("border-bottom-style"));
	}
}

function _autoGrowFWTextArea(textareas){
	$(textareas).each(function(){
			var $this = $(this);
			if($this.attr("autogrow")=="inited") return;
			var mh=$this.css("min-height");
			var minHeight = $this.height(),
					lineHeight = $this.css('lineHeight');
			var shadow = $('<div></div>').css({
					position: 'absolute',
					top: -10000,
					left: -10000,
					width: $(this).width() - parseInt($this.css('paddingLeft')) - parseInt($this.css('paddingRight')),
					fontSize: $this.css('fontSize'),
					fontFamily: $this.css('fontFamily'),
					lineHeight: $this.css('lineHeight'),
					resize: 'none'
			}).appendTo(document.body);
			$this.attr("autogrow","inited");
			var first=true;
			var update = function(ev){
					var times = function(string, number){
							for(var i = 0, r = ''; i < number; i ++) r += string;
							return r;
					};
					var val = this.value.replace(/</g, '&lt;')
															.replace(/>/g, '&gt;')
															.replace(/&/g, '&amp;')
															.replace(/\n$/, '<br/>&nbsp;')
															.replace(/\n/g, '<br/>')
															.replace(/ {2,}/g, function(space){ return times('&nbsp;', space.length -1) + ' ' });
					
					if(!val && ((ev && ev.type=="blur") || first)){
						shadow.html(val);
						$(this).css('height', (mh?mh:minHeight))
					}else{
						if(!val) val="i"; //Always assume at least ONE char (not space) in val, so that there's no jump when writing first char (ugly)
						shadow.html(val);
						$(this).css('height', Math.max(shadow.height() + 20, minHeight));
					}
			}
			$(this).change(update).keyup(update).keydown(update).focus(update).blur(update);
			update.apply(this);
			var first=false;
	});
 }

/* Makes sure link is valid */
function _ensureFWLink(li,disallowJs){
	if(!li || li=="")return li;
	if(disallowJs){
		li = String(li).replace(/javascript:/gi,"");
	}
	if(String(li).search(/^(mailto:)|(ftp:\/\/)|(https?:\/\/)|(\/)/gi)==-1){
		return "http://"+li;
	}
  return li; 
}

/* Helper to retrieve a template, via ajax if necessary */
function _getFWTemplate(templateId,ajaxHandle,id,callback,qs,requestType){
	var d = $("#"+templateId); // Attempt retrieve of template
	if(d.length==0){ // No template found
		// Fill div with data via ajax and do callback
		if(!requestType) requestType="GET_MARKUP";
		_ajaxFWGet(ajaxHandle,id,"fw_tid="+templateId+(qs?"&"+qs:""),requestType,function(req){
		$(document.body).append(req.responseText);
		if(callback)callback($("#"+templateId));},120000);
	}else{
		if(callback)callback(d);
	}
}

function _openFWTabbedDialog(srcObj,css,onClose,buttons,dialogWidth,dialogHeight,onBack,position,isFixed){

	if(!dialogWidth) 
		dialogWidth = 'auto';
	else
		dialogWidth = dialogWidth + 'px';

	if(!dialogHeight) 
		dialogHeight = 'auto';
	else
		dialogHeight = dialogHeight + 'px';

	dialogWidth = dialogWidth.replace('pxpx','');
	dialogHeight = dialogHeight.replace('pxpx','');

	var onCloseTitle="";
	if(onClose){
		if(!$.isFunction(onClose)){
			onCloseTitle = onClose.title;
			onClose = onClose.action;
		}
	}
	if(!$.isFunction(onClose)) return;
	//_showFWShield(null,true);

	position = _initFWPosition(position,"center",true);
	
	$(srcObj).unbind("close").bind("close",srcObj,function(ev){onClose(ev,ev.data)});
	var openFun = function(event,ui){
		$(srcObj).css("width",dialogWidth);
		$(srcObj).css("height",dialogHeight);
		var diag = $(this).parents(".ui-dialog:first");	

		var diagCont = $(".ui-dialog-container",diag);
		if(diagCont.length==0){
			diagCont=$("<div class='ui-dialog-container'></div>");
			diagCont.appendTo(diag);
		}
		$(".ui-dialog-titlebar",diag).appendTo(diagCont);
		$(srcObj).appendTo(diagCont);

		_fillFWAdminDialogFooter(srcObj,buttons,dialogWidth,dialogHeight);
		
		var b=diag.find(".ui-dialog-titlebar-close");
		b.attr("href","javascript:void(0)").html(onCloseTitle);
		b.unbind();
		b.bind("click",srcObj,function(ev){onClose(ev,ev.data)});
		
		var btns = '<div class="SET_cssFunctionButtons">';
				//btns += '<a href="javascript:void(0);" class="SET_cssMinimize" onmousedown="_setFWStateCSS(this,\'ACTIVATED\');" onmouseup="_removeFWStateCSS(this,\'ACTIVATED\');"></a>';
				//btns += '<a href="javascript:void(0);" class="SET_cssMaximize" onmousedown="_setFWStateCSS(this,\'ACTIVATED\');" onmouseup="_removeFWStateCSS(this,\'ACTIVATED\');"></a>';
				//btns += '<a href="javascript:void(0);" class="SET_cssRestore" onmousedown="_setFWStateCSS(this,\'ACTIVATED\');" onmouseup="_removeFWStateCSS(this,\'ACTIVATED\');"></a>';
				btns += '<a href="javascript:void(0);" class="SET_cssClose" onmousedown="_setFWStateCSS(this,\'ACTIVATED\');" onmouseup="_removeFWStateCSS(this,\'ACTIVATED\');_closeFWDynamicSelect();"></a>';
		btns += '</div>';

		diag.find('div.ui-dialog-titlebar').append(btns);

		var b=diag.find(".SET_cssFunctionButtons .SET_cssClose");
		b.html(onCloseTitle);
		b.unbind();
		b.bind("click",srcObj,function(ev){onClose(ev,ev.data)});

		if($.isFunction(onBack)){
			var bb = $("<a href='javascript:void(0)' class='ui-dialog-titlebar-back'></a>)");
			bb.bind("click",srcObj,function(ev){onBack(ev,ev.data)});
			$("div.SET_cssAdminDialogTitle",srcObj).addClass("SET_cssAdminDialogTitleWithBack");
			b.before(bb);    
		}
		
		$(srcObj).trigger("open");
	};

	$(srcObj).show().dialog({
		height:dialogHeight,
		width:dialogWidth,
		zIndex:10000,
		"position":position,
		resizable:false,
		dialogClass:css,
		stack:false,
		closeOnEscape:false,
		autoOpen:false,
		open:($().jquery.indexOf("1.3")==0?null:openFun)
	});

	$(srcObj).bind('dialogopen',openFun);

	$(srcObj).dialog("open");
	if(!position){

		var tb = $('div#CMS_toolbar');
		var y = 8 + parseInt(_getFWScrollCoordinates().y);

		if(tb.hasClass('CMS_cssExpanded')){
			$(srcObj).parents(".ui-dialog:first").css('top',tb.outerHeight()+y+'px');
		}else{
			$(srcObj).parents(".ui-dialog:first").css('top',y+'px');
		}
	}	
}

// Fills footer of mind dialog with buttons, status area etc
function _fillFWAdminDialogFooter(dialogObj,contents,dialogWidth,dialogHeight){
//	var footerHeight	
	var diag = $(dialogObj).parents(".ui-dialog:first");
	var idBase = $(dialogObj).attr("id");
/*
	if(!(dialogHeight)){
		dialogHeight=parseInt($(dialogObj).dialog('option','height'),10);
	}
	if(!(dialogWidth)){
		dialogWidth=parseInt($(dialogObj).dialog('option','width'),10);
	}
*/
	var show=false;
	if(contents){
		var b = $(dialogObj).find("div.SET_cssAdminDialogFooterContent:first");
		b.html("");
		function _createFWSingleButton(t,ac,id,css){
			css = css?' '+css:'';
			//TODO:remove display:none once migration to new dialog is complete
			var div = $('<div class="SET_cssLinkButtonWrapper'+css+'" style="display:none;"><a id="'+id+'"href="javascript:void(0);" class="SET_cssLinkButton"><div>'+t+'</div></a></div>');
			
			var a=$('a:first',div);
			a.bind("click",dialogObj,function(ev){if(_hasFWStateCSS(a,'DISABLED'))return;ac(ev,ev.data)}).bind('mousedown',function(){if(_hasFWStateCSS(a,'DISABLED'))return;_setFWStateCSS(this, 'ACTIVATED')}).bind('mouseup', function(){if(_hasFWStateCSS(a,'DISABLED'))return;_removeFWStateCSS(this, 'ACTIVATED')});

			b.append(div);

			a = document.createElement("a");
			div = document.createElement("div");
			a.href="javascript:void(0);";
			if(id)$(a).attr("id",id);
			a.className = "SET_cssButton"+(css?" "+css:"");
			div.innerHTML = t;
			a.appendChild(div);
			b.append(a);
			$(a).bind("click",dialogObj,function(ev){if(_hasFWStateCSS(a,'DISABLED'))return;ac(ev,ev.data)}).bind('mousedown',function(){if(_hasFWStateCSS(a,'DISABLED'))return;_setFWStateCSS(this, 'ACTIVATED')}).bind('mouseup', function(){if(_hasFWStateCSS(a,'DISABLED'))return;_removeFWStateCSS(this, 'ACTIVATED')});
			show = true;
		}
		// Determine revert action
		var tabDiv = dialogObj.find("div.SET_cssAdminDialogSections:first");
		var ix=0; //Determine selected tab's index
		$('> li',tabDiv).each(function(j){
			if($(this).hasClass("ui-tabs-selected")){ix=j;return false;}
		});
		var revertAction = function(ev){
			var ix2=0;
			$('div.SET_cssAdminDialogSectionTabs:first li',dialogObj).each(function(j){
				if($(this).hasClass("ui-tabs-selected")){ix2=j;return false;}
			});
			var osf=tabDiv.data("onSelect");if($.isFunction(osf))osf(ev,{indexSectionTab:ix2,index:ix});
		};

		if(_getFWTypeOf(contents)=="array"){
			for(i=0;i<contents.length;i++){
				switch(String(contents[i].type).toUpperCase()){
					case "SAVE":
						_createFWSingleButton(contents[i].title,contents[i].action,idBase+"___SAVE",contents[i].css);
						break;
					case "CANCEL":
						_createFWSingleButton(contents[i].title,(contents[i].action?contents[i].action:function(ev){dialogObj.trigger("close");}),idBase+"___CANCEL",contents[i].css);
						break;
					case "REVERT":
						_createFWSingleButton(contents[i].title,(contents[i].action?contents[i].action:revertAction),idBase+"___REVERT",contents[i].css);
						break;
					case "STATUS":
						b.append("<div id='"+idBase+"___STATUS' timeoutSaved='"+(contents[i].timeoutSaved?contents[i].timeoutSaved:3000)+"' style='display:none'"+
							" class='SET_cssAdminDialogStatus'>"+
							"<div class='SET_cssAdminDialogStatusChanged'>"+(contents[i].titleChanged?contents[i].titleChanged:"")+
							(contents[i].titleRevert?"<a class='SET_cssAdminDialogStatusRevert' href='javascript:void(0)'>"+contents[i].titleRevert+"</a>":"")+"</div>"+
							"<div class='SET_cssAdminDialogStatusSaving'>"+contents[i].titleSaving+"</div>"+
							"<div class='SET_cssAdminDialogStatusSaved'>"+contents[i].titleSaved+"</div>"+
							"<div class='SET_cssAdminDialogStatusFailedForm'>"+contents[i].titleFailedForm+"</div>"+
							"<div class='SET_cssAdminDialogStatusFailedSave'>"+contents[i].titleFailedSave+"</div></div>");
						var revertActionLocal;
						if(contents[i].revertAction) revertActionLocal=contents[i].revertAction;
						else revertActionLocal=revertAction;
						$("a.SET_cssAdminDialogStatusRevert:first",b).bind("click",function(ev){revertActionLocal(ev,ev.data)});
						show = true;
						break;
					default:
						if(contents[i].action) _createFWSingleButton(contents[i].title,contents[i].action,(contents[i].id?contents[i].id:""),(contents[i].css?contents[i].css:""));
						else{
							b.append(contents[i].title);
							show = true;
						}
						break;
				}
			}
		}else{ // Only for simplets possible button/HTML creation
			for(prop in contents){
				if(contents[prop]) _createFWSingleButton(prop,contents[prop]);
				else{
					b.append(prop);
					show = true;
				}
			}
		}
	}

	if(show){
		$("div.SET_cssAdminDialogFooter",dialogObj).show();
		//footerHeight=$("div.SET_cssAdminDialogFooter",dialogObj).height();
		$("div.SET_cssAdminDialogContent",dialogObj).removeClass("SET_cssNoFooter");
	}else{
		$("div.SET_cssAdminDialogFooter",dialogObj).hide();
		$("div.SET_cssAdminDialogContent",dialogObj).addClass("SET_cssNoFooter");
		//footerHeight=0;
	}

	/*var titleHeight=$(".ui-dialog-titlebar",diag).height();
	var padding =($("div.CMS_cssAdminDialogContent",dialogObj).outerHeight()-$("div.SET_cssAdminDialogContent",dialogObj).height());
	var contentHeight=(dialogHeight-titleHeight-footerHeight-padding-10);
	$(".ui-dialog-container",diag).css({"width":(dialogWidth-10)+"px","height":(dialogHeight-10)+"px","position":"relative"});
	$("div.CMS_cssAdminDialogContent",dialogObj).css({"width":(dialogWidth-30)+"px","height":contentHeight+"px"});*/
}
				
function _closeFWTabbedDialog(dialogObj,ev){
	// Hide srcObj
	$(dialogObj).parents("div.ui-dialog:first").hide();
	_hideFWShield(null,true);
	if(ev)_stopFWEvents(ev,null,true);
	setTimeout(function(){
		$("div.SET_cssAdminDialogFooterContent:first",dialogObj).html(""); // Clean up everything in content
		if(window.fw_popup){ // Close all popups opened by the dialog (check z-index to determine this)
			var pi=parseInt($(window.fw_popup).css("z-index"),10);
			var di;
			try{di=parseInt($(dialogObj).parents("div.ui-dialog:first").css("z-index"),10)}catch(er){}
			var cl=false;
			if(!isNaN(pi) && !isNaN(di)){
				if(pi>=di) cl=true;
			}else{
				cl=true;
			}
			if(cl){
				window.fw_popup.preventHide=null;
				_hideFWPopupNoDel();
			}
			
		}
		$(dialogObj).dialog("destroy");
	},0);
	
}

function _openFWAdminDialog(dialogHandle,act,itemId,qs,selectedSection,selectedSectionTab,size,position,onClose,titleClose,css,onOpen,onBack,footerContent, isFixed){
	document.body.style.cursor = 'wait';
	_closeFWDynamicSelect();
	_hideFWPopupNoDel();
	_showFWShield(null,"SET_cssShieldLoading");
	if(!selectedSectionTab) selectedSectionTab="";
	
	if(isFixed){
		css += ' SET_cssFixed';
	}

	var dialogId = "SET_dialog_"+dialogHandle;
	
	if($("#"+dialogId).length){ // Diag exists, append stuff to ID
		var ord=0;
		while($("#"+dialogId+"_"+ord).length){
			ord++;
		}
		dialogId += "_"+ord;
	}
	if(!qs || qs=="") qs="did="+dialogHandle;
	else qs="did="+dialogHandle+"&"+qs;

	// Get requested template via ajax
	_getFWTemplate(dialogId,act,itemId,function(template){ // Function to call when template has been retrieved
		_playFWSound("opendialog")	
		if(template.length==0){
			document.body.style.cursor = 'auto';
			_hideFWShield(null,true);
			return;
		}
		template.attr("dialogHandle",dialogHandle);
		template.attr("itemAdditionals","");
		template.attr("itemId","");
		// If itemId is a composite, only store first part as itemId, second part will be stored as itemAdditionals
		if(itemId){
			itemId = String(itemId).split("_");
			template.attr("itemId",itemId[0]);
			if(itemId.length>1){
				itemId.splice(0,1);
				template.attr("itemAdditionals",itemId.join("_"));
			}
		}
		// If footercontent supplied by method, use that
		template.data("footerContent",footerContent);
		
		// Init tabs, incl function to call when selecting a tab (which retrieves tab content via ajax)
		var son;
		try{eval("son="+template.attr("sectionOnChange"))}catch(er){son=null;}
		if(!$.isFunction(son)) son = null;
		_initFWTabs(template,selectedSection,(template.attr("renderAllSections")?son:function(ev,ui){
			if(ui.index==null) return false;
			if(!ui.indexSectionTab) ui.indexSectionTab=0;
			
			// Clear content in tab and only show loading indicator	
			var tab = $("#"+dialogId+"_section"+(ui.index+1));
			tab.html("").parent().addClass("SET_cssLoadingIndicator");
			// Also clear footer
			_fillFWAdminDialogFooter(template,null);
			// Get new content
			_ajaxFWGet(act+"_SECTION",template.attr("itemId")+(template.attr("itemAdditionals")?"_"+template.attr("itemAdditionals"):""),
					(qs?qs+"&":"")+"fw_tid="+dialogId+"&fw_ss="+(ui.index+1)+"&fw_sst="+(ui.indexSectionTab+1),
				"GET_DIALOG",function(req){
				// Insert new content in correct tab
				tab.html(req.responseText).parent().removeClass("SET_cssLoadingIndicator");
				_fillFWAdminDialogFooter(template,template.data("footerContent"));
			},120000);
		}));

		// Close function: cleans up and closes admin window
		var onCloseActual = function(ev){
			var template = ev.data;
			document.body.style.cursor = 'wait';
			//$(template).parents("div.ui-dialog:first").hide(); //Hide to make closing seem quicker
			_closeFWTabbedDialog(template);
			$(template).remove();
			document.body.style.cursor = 'auto';
		};
		//The close functions must always be available for overriding close-functions to use
		template.bind("closeActual",template,function(ev){onCloseActual(ev)});

		var onCloseLocal; //This binds the function that is actually called when pressing close/cancel
		if(titleClose) onCloseLocal = {title:titleClose,action:($.isFunction(onClose)?onClose:onCloseActual)};
		else onCloseLocal = ($.isFunction(onClose)?onClose:onCloseActual); 

		if(!size) size = [840,530];

		// Open dialog
		_openFWTabbedDialog(template,css,onCloseLocal,template.data("footerContent"),size[0],size[1],onBack,position);
		document.body.style.cursor = 'auto';

		if(isFixed){
			$('.ui-dialog').css('margin-left','-' + size[0]/2 + 'px');
		}
	
		if($.isFunction(onOpen)) onOpen(template);
		_showFWShield();
	},(qs?qs+"&":"")+"fw_ss="+selectedSection+"&fw_sst="+selectedSectionTab,"GET_DIALOG");
}

// Change action when a field in a form in a mind dialog is changed
function _changeFWAdminDialogField(ev,fld,dialogObj){
	fld = $(fld);
	var af = function(){
		dialogObj = $(dialogObj);
		if(dialogObj.length==0)dialogObj=fld.parents("div.ui-dialog-content:first");
		if(dialogObj.length==0)return;
		var mds = $("div.SET_cssAdminDialogStatus:first",dialogObj);
		if(mds.length>0){
			if(mds.data("timer")) clearTimeout(mds.data("timer"));
			$("div",mds).hide();
			$("div.SET_cssAdminDialogStatusChanged",mds).show();
			mds.show();
		}
	};
	if(fld.is(":text,:password"))	_onFWType(ev,af);
	else af();
}

// Fails a form in a mind dialog
function _failFWAdminDialogForm(ok,failed,dialogObj){
	document.body.style.cursor = 'auto';
	dialogObj = $(dialogObj);
	var mds = $("div.SET_cssAdminDialogStatus:first",dialogObj);
	$("ul.SET_cssAdminDialogSectionTabs li",dialogObj).removeClass("SET_cssTabFail"); // Remove fail classes of tabs
	if(mds.length>0){
		if(!ok){
			if(mds.data("timer")) clearTimeout(mds.data("timer"));
			$('div',mds).hide();$('div.SET_cssAdminDialogStatusFailedForm',mds).show();mds.show();
			$(failed).each(function(){
				if(this && String(this).replace(/\s/gi,"")!=""){ // Add fail class to tabs of failed fields
					$("#"+$("#"+this).parents("div.ui-tabs-panel:first").attr("id")+"li").addClass("SET_cssTabFail");
				}
			});
		}
	}
}

// Call this before saving, when in a dialog
function _beforeFWAdminDialogSave(dialogObj,doValidationAct,doValidationId){
	document.body.style.cursor = 'wait';
	dialogObj = $(dialogObj);
	var mds=$("div.SET_cssAdminDialogStatus:first",dialogObj);
	if(mds.length>0){
		if(mds.data("timer")) clearTimeout(mds.data("timer"));
		$("div",mds).hide();
		$("div.SET_cssAdminDialogStatusSaving",mds).show();
		mds.show();
	}
	if(doValidationAct){
		try{if(_validateFWPage && !_validateFWPage(String(doValidationAct).toUpperCase(),doValidationId)){_failFWAdminDialogForm(false,setValidationFailedFields.split(','),dialogObj);return false;}}catch(er){}
		return true;
	}
}

// Call this after saving, when in a dialog
function _afterFWAdminDialogSave(req,dialogObj,noSuccMess){
	document.body.style.cursor = 'auto';
	dialogObj = $(dialogObj);
	var mds=$("div.SET_cssAdminDialogStatus:first",dialogObj);
	var data;
	try{eval("data="+req.responseText);}catch(er){data={success:true}};
	dialogObj.attr("itemId",data.itemId);
	if(!data.success){
		if(data.failed && data.failed.length>0){
			for(i=0;i<data.failed.length;i++){
				if(data.failed[i])_markSETInvalid( $("#"+data.failed[i]).get(0) );
			}
			_failFWAdminDialogForm(false,data.failed,dialogObj);
		}else{
			$("div",mds).hide();
			$("div.SET_cssAdminDialogStatusFailedSave",mds).show();
		}
	}else{ // Show success mess, timeout for hide
		$("div",mds).hide();
		if(!noSuccMess){
			$("div.SET_cssAdminDialogStatusSaved",mds).show();
			mds.data("timer",setTimeout(function(){mds.fadeOut("slow");},parseInt(mds.attr("timeoutSaved"),10)));
		}
	}
	if(data.debug)alert(data.debug);
	return data;
}

// Inits tabs
function _initFWTabs(srcObj,selectedTab,onSelect,onShow){
	
	srcObj = $(srcObj);
	if(!srcObj.attr("initedTabs")){ //Init tabs
		var tabDiv;
		if(srcObj.is('div.SET_cssTabs')) tabDiv=srcObj;
		else tabDiv=$('div.SET_cssTabs:first',srcObj);
		var disTabs=[];
		var j=0;
		$('li',tabDiv).each(function(i){
			if($(this).hasClass("SET_cssTabDisabled")) disTabs[j++]=i;
		});

				/*navClass: prefix+'_cssTabbed',*/
				/*selectedClass: prefix+'_cssTabSelected',*/
				/*unselectClass: prefix+'_cssTabUnselected',*/
				/*disabledClass: prefix+'_cssTabDisabled',*/
				/*panelClass: prefix+'_cssTabPanel',*/
				/*hideClass: prefix+'_cssTabHide',*/
				/*loadingClass: prefix+'_cssTabLoading',*/
		tabDiv.tabs({ // Parse tabs in template
				spinner:'',
				disabled:disTabs,
				selected:(selectedTab?(selectedTab-1):0),
				select:($().jquery.indexOf("1.3")!=0 && $.isFunction(onSelect)?onSelect:null),
				show:($.isFunction(onShow)?onShow:null)
			});


		if($.isFunction(onSelect)){
			tabDiv.data("onSelect",onSelect); //Store onselect in data, for easy manual triggering
			tabDiv.bind('tabsselect',onSelect);
		}
		srcObj.attr("initedTabs",true);
		
	}

}

function _enableFWTabs(srcObj,tabIndexes){//Tabindexes first tab has index 1
	var tabDiv;
	if(srcObj.is('div.SET_cssTabs')) tabDiv=srcObj;
	else tabDiv=$('div.SET_cssTabs:first',srcObj);
	var lis=$("li",tabDiv);
	for(i=0;i<tabIndexes.length;i++){
		tabDiv.tabs('enable', tabIndexes[i]-1);
		lis.eq(tabIndexes[i]-1).removeClass("SET_cssTabDisabled").removeClass("ui-tabs-disabled");
	}
}

function _selectFWTab(srcObj,tabIndex){//tabIndex first tab has index 1
	var tabDiv;
	if(srcObj.is('div.SET_cssTabs')) tabDiv=srcObj;
	else tabDiv=$('div.SET_cssTabs:first',srcObj);
	tabDiv.tabs('select',tabIndex-1); 
}

// Sets loading indicator for checked or supplied list rows and RETURNS these rows
function _beforeFWListFun(listId,rowIds){
	var rows;
	if(!rowIds){// If no row ids, gets all checked rows
		rowIds = $("table#SET_listTable_"+listId+" td.SET_cssCellCheck input:checkbox:checked").map(function(){
		  return this.value;
		}).get().join(',');
	}
	if(rowIds){
		if(_getFWTypeOf(rowIds)=="object"){ //rowIds contains the row objects
			rows = rowIds;
		}else{ //Ids specified, get all rows by ids
			rowIds = "#SET_list_"+listId+"_row_"+String(rowIds).replace(/\,/gi,",#SET_list_"+listId+"_row_");
			rows = $(rowIds);
		}
	}
	if(rows){
		rows.addClass("SET_cssListLoading");
	}
	return rows;
}
// Removes loading indicator for checked or supplied list rows
function _afterFWListFun(listId,rowIds){
	var rows;
	if(!rowIds){// If no row ids, gets all checked rows
		rowIds = $("table#SET_listTable_"+listId+" td.SET_cssCellCheck input:checkbox:checked").map(function(){
		  return this.value;
		}).get().join(',');
	}
	if(rowIds){
		if(_getFWTypeOf(rowIds)=="object"){ //rowIds contains the row objects
			rows = rowIds;
		}else{ //Ids specified, get all rows by ids
			rowIds = "#SET_list_"+listId+"_row_"+String(rowIds).replace(/\,/gi,",#SET_list_"+listId+"_row_");
			rows = $(rowIds);
		}
	}
	if(rows){
		rows.removeClass("SET_cssListLoading");
	}
	return rows;
}

//Checks if list filter is active and sets classes accordingly
function _checkFWListFilterActive(listId,specificField,justRemove,onlySearch,noDelay,forceSearch){
	var asf;
	if(specificField || forceSearch){
		// Check if this should even be enabled
		asf=(noDelay?$("#SET_listAutoSearch_"+listId).attr("autoSearchNoDelay"):$("#SET_listAutoSearch_"+listId).attr("autoSearch"));
		if(asf)eval(asf);
		else return false;
	}
	setTimeout(function(){
		// THEN activate/inactivate filter icon
		if(!onlySearch){
			var sel = $("#SET_listSearchFilter_"+listId+":first div.SET_cssToggleFilterMakeVisible:first"+
						",#SET_listSearchFilter_"+listId+":first div.SET_cssToggleFilterMakeHidden:first");
			var sel2 = $("#SET_listSearchFilter_"+listId+":first div.SET_cssFilter:first");
			var exit = false;
			if(!justRemove){
				var f=function(self){
					var self=$(self);
					switch(self.attr("type")){
						case "checkbox":
						case "radio":
							if( (self.val()!=self.attr("initValue") && self.get(0).checked)
							 || (self.val()==self.attr("initValue") && !self.get(0).checked) ){
								sel.addClass("SET_cssToggleFilterActive");
								sel2.addClass("SET_cssFilterActive");
								return true;
							}
							break;
						default:
							if(self.val()!="" && self.val()!=self.attr("initValue")){
								sel.addClass("SET_cssToggleFilterActive");
								sel2.addClass("SET_cssFilterActive");
								return true;
							}
					}
					return false;
				}
				
				if(specificField){if(f(specificField)){return;}}
				$("#SET_listSearchFilter_"+listId+" div.SET_cssFilter :input:not(.SET_cssNoAutoSearch)").each(function(i){
					if(f(this)){exit=true;return false;};
				});
			}
			if(!exit){sel.removeClass("SET_cssToggleFilterActive");sel2.removeClass("SET_cssFilterActive");}
		}
		// Also make sure searchText is correctly masked/not masked
		if($("#SET_listSearchFilter_"+listId+":first div.SET_cssSearchCtrls:first :input:first").val()!=""){
			$("#SET_listSearchFilter_"+listId+":first div.SET_cssSearchCtrls:first").addClass("SET_cssSearchCtrlsActive");
		}else{
			$("#SET_listSearchFilter_"+listId+":first div.SET_cssSearchCtrls:first").removeClass("SET_cssSearchCtrlsActive");
		}
	},1);
}
// Auto searches, after a certain delay
function _autoFWListSearch(ev,listId,delay,searchCallback){
	var f = function(){
		
		// Reset any existing timer
		if(window["fw_list_"+listId+"_autoSearchTimer"]){
			clearTimeout(window["fw_list_"+listId+"_autoSearchTimer"]);
			window["fw_list_"+listId+"_autoSearchTimer"] = null;
		}

		// Cancel any loads in progress
		$("#SET_listLoadingIndicator_"+listId+" div.SET_cssListLoading").find("a:first").click();

		// Make new timer
		if(delay){
			delay = parseInt(delay,10);
			window["fw_list_"+listId+"_autoSearchTimer"] = 
				setTimeout(function(){
					window["fw_list_"+listId+"_autoSearchTimer"] = null;
					searchCallback();
				},delay);
		}else{
			searchCallback();
		}
	};

	if(ev) _onFWType(ev,f);
	else f();
}


// Opens row function menu for certain list/row
function _showFWListRowFunctions(event,trigger,listId,itemId){
	isIE = $.browser.msie;

	_showFWPopup(event,$("#SET_listRowFunctions_"+listId).attr("itemId",itemId).get(0),
		function(){$(trigger).addClass('SET_cssListRowFunctionsActive')},
		function(){$("#SET_listRowFunctions_"+listId).removeAttr("itemId");$(trigger).removeClass('SET_cssListRowFunctionsActive')},
		isIE?-2:1,isIE?1:-2,null,'click','R',0,false,0);
}

// Clears fields for a certain list id
function _clearFWListSearchFilter(listId,onlyFilter,closeFilter){
	var sel = "#SET_listSearchFilter_"+listId+":first div.SET_cssFilter:first :input:not(.SET_cssNoClear)";
	if(!onlyFilter) sel+=",#SET_listSearchFilter_"+listId+":first div.SET_cssSearchCtrls:first :input";
	$(sel).each(function(i){
		var self=$(this);
		switch(self.attr("type")){
			case "checkbox":
			case "radio":
				self.get(0).checked = (self.val()==self.attr("initValue"));
				break;
			case "select-multiple": //Selects may have multi-select mouseup handling (for setting num checked), trigger that
				if(self.attr("initValue")) self.val(self.attr("initValue"));
				else self.val("");
				self.trigger("mouseup");
				break;
			default:
				if(self.attr("initValue")) self.val(self.attr("initValue"));
				else self.val("");
				self=self.get(0);self.focus();self.blur();
		}
	});
	// Also remove all visible divs with class SET_cssSelected (special controls use this)
	$("#SET_listSearchFilter_"+listId+" div.SET_cssSelected").remove();
	_checkFWListFilterActive(listId,null,true);
	if(closeFilter){
		var lst=$("#SET_listSearchFilter_"+listId);
		var filt = $("div.SET_cssFilter",lst);
		if(filt.attr("showFilter")!="ALWAYS"){
			$("div.SET_cssToggleFilterMakeVisible",lst).show();
			$("div.SET_cssToggleFilterMakeHidden",lst).hide();
			filt.hide();
		}
	}
	return true;
}

// Submits certain list id via ajax
// NOTE: act must lead to a rendering of what is INSIDE of listBody
function _submitFWListSearch(listId,act,qs,callback){
	// Cancel any pending auto searches
	if(window["fw_list_"+listId+"_autoSearchTimer"]){
		clearTimeout(window["fw_list_"+listId+"_autoSearchTimer"]);
		window["fw_list_"+listId+"_autoSearchTimer"] = null;
	}

	$("#SET_listTable_"+listId).addClass("SET_cssListLoading");

	// First set the sel props hidden, including pagenumber 1
	$("#SET_list_"+listId+"_pageNum").val("1");
	if(!$("#SET_list_"+listId+"_sel_props").val()){
		var selProps="pageNum";
		var len = ("SET_list_"+listId+"_").length;
		$("#SET_listSearchFilter_"+listId+":first :input").each(function(){
			if((","+selProps+",").indexOf(","+this.name.substr(len)+",")==-1) selProps+=(selProps==""?"":",")+this.name.substr(len);
		});
		$("#SET_list_"+listId+"_sel_props").val(selProps);
	}
	_hideFWPopupNoDel();
	var f = function(){
		xmlHttp=_ajaxFWPost("FW_SET_PROPS","SET_list_"+listId+"_","fw_search=true&fw_lstid="+listId+"&fw_go=true&fw_act="+act+(qs?"&"+qs:""),
			"GET_MARKUP",function(req){
			// Check that responsetext contains a list
			if(req.responseText.indexOf("class=\"SET_cssListRows")==-1)_failFWListLoadingIndicator(listId);
			else{
				$("#SET_listBody_"+listId).html(req.responseText);// Replace list body content
				if($.isFunction(callback)) callback(listId,act,qs,req);
			}
			$("#SET_listTable_"+listId).removeClass("SET_cssListLoading");
		},60000,"#SET_listSearchFilter_"+listId+":first :input,#SET_list_"+listId+"_pageNum");
		_showFWListLoadingIndicator(listId,xmlHttp,f); // Show loading indicator
		$("#SET_listSearchNoHits_"+listId).hide();
	}
	f();
}

// Refreshes a list
function _refreshFWList(listId,callback,keepExpansions){
	var f=$("#SET_listTable_"+listId).attr("refreshCallback");
	try{if(f){var prop="";
	var val;
	if(keepExpansions){
		// Store expanded rows
		var expIds = $("#SET_listTable_"+listId+" tr.SET_cssListRowExpanded.SET_cssListRow").map(function(){
			return this.getAttribute("itemId");
		}).get();
		// Add expand again to val
		val = function(){
			for(j=0;j<expIds.length;j++) $("#SET_list_"+listId+"_row_"+expIds[j]).click();
			if($.isFunction(callback)) callback();
		};
	}else if($.isFunction(callback)){
		val = callback;
	}
	eval(f);}}catch(er){}
}

// Changes a page num or per page for a list
// NOTE: does not update sel props for search or filter, simply changes page via get
function _changeFWListProp(listId,act,qs,prop,value,noHidePopup){
	switch(prop.toUpperCase()){
		case "PAGENUM":
			if(parseInt(value,10)<1) value=1;
			prop = "pageNum";
			break;
		case "PERPAGE":
			if(parseInt(value,10)<1) value=1;
			prop = "perPage";
			break;
		case "ORDERBY":
			prop = "orderBy";
			break;
		default:
			prop = null;
	}
	if(!noHidePopup)_hideFWPopupNoDel();
	var f = function(){
		if(prop){
			xmlHttp=_ajaxFWGet("FW_SET_SEL_PROP","SET_list_"+listId+"_|"+prop+"|"+value,"fw_lstid="+listId+"&fw_go=true&fw_act="+act+(qs?"&"+qs:""),
				"GET_MARKUP",function(req){
				// Check that responsetext contains a list
				if(req.responseText.indexOf("class=\"SET_cssListRows")==-1)_failFWListLoadingIndicator(listId);
				else $("#SET_listBody_"+listId).html(req.responseText);// Replace list body content
			},60000,true);
		}else{ // If no prop present, just refresh list. If value is something still, it contains callback
			xmlHttp=_ajaxFWGet(act,"","fw_lstid="+listId+(qs?"&"+qs:""),
				"GET_MARKUP",function(req){
				// Check that responsetext contains a list
				if(req.responseText.indexOf("class=\"SET_cssListRows")==-1)_failFWListLoadingIndicator(listId);
				else{$("#SET_listBody_"+listId).html(req.responseText);if($.isFunction(value)){value();}}// Replace list body content
			},60000,true);
		}
		_showFWListLoadingIndicator(listId,xmlHttp,f); // Show loading indicator
	}
	f();
}

// Shows loading indicator row
function _showFWListLoadingIndicator(listId,xmlHttp,retryFun,rowId,expRow){
	var realRetryFun = function(){
		if(rowId) $("#"+rowId+"_expanded div.SET_cssListLoadingRowFailure").hide().prev().show();
		else{
			_showFWLoading("PREPEND",$("#SET_listFunctions_"+listId),"","",{http:xmlHttp},null,"SET_listLoading_"+listId);
			$("#SET_listLoadingIndicator_"+listId).show().find(" div.SET_cssListLoadingFailure:not(div.SET_cssListLoadingRowFailure)").hide();
		}
		setTimeout(retryFun,1);
	}
	if(rowId || expRow){//Copy the loading divs to the forRow-id
		var ll=$("#SET_listLoadingIndicator_"+listId);
		if(ll.length==0) return;
		if(!expRow)	expRow = $("#"+rowId+"_expanded");
		expWrap = expRow.find("div.SET_cssExpandedInfoWrapper:first");
		expWrap.html("");
		cl=$("div.SET_cssListLoadingRow",ll).clone(true);
		cl.show().appendTo(expWrap);
		clf=$("div.SET_cssListLoadingRowFailure",ll).clone(true);
		clf.hide().appendTo(expWrap);
		expRow.show(); 
		/*cl.find("a:first").unbind("click").bind("click",function(){
			xmlHttp.abort(); // Bind abort
			expRow.remove();
			$("#"+rowId).removeClass("SET_cssListRowExpanded");
		});*/
		clf.find("a:first").unbind("click").bind("click",function(){
			// Bind retry
			realRetryFun();
		});
		$("#"+rowId).addClass("SET_cssListRowExpanded");
	}else{
		_showFWLoading("PREPEND",$("#SET_listFunctions_"+listId),"","",{http:xmlHttp},null,"SET_listLoading_"+listId);

		$("div.SET_cssListLoadingFailure:not(div.SET_cssListLoadingRowFailure)","#SET_listLoadingIndicator_"+listId).hide().find("a:first").unbind("click").bind("click",function(){
			// Bind retry
			realRetryFun();
		});
	}
}
function _failFWListLoadingIndicator(listId,rowId){
	_hideFWLoading("#SET_listLoading_"+listId);
	if(rowId) $("#"+rowId+"_expanded div.SET_cssListLoadingRowFailure").show().prev().hide();
	else $("#SET_listLoadingIndicator_"+listId).show().find(" div.SET_cssListLoadingFailure:not(div.SET_cssListLoadingRowFailure)").show();
}

// Click checkbox for row or checkall. Either way, submits all checkboxes in this list and adds/removes accordingly from sel prop. Can also clear sel prop.
function _checkFWListItems(rowChk,listId,doClear,checkAllAct,checkAllQs){
	setTimeout(function(){
		if(rowChk){
			if((rowChk.checked && rowChk.nextSibling.value=="")
				|| (!rowChk.checked && rowChk.nextSibling.value!="")) return; //Nothing if no change
			if(rowChk.checked){
				rowChk.nextSibling.value="";
			}else{
				rowChk.nextSibling.value=rowChk.value;
			}
		}
		if(doClear){
			_ajaxFWGet("FW_CHECK_ITEMS","SET_list_"+listId+"_|SET_listCheck_"+listId+"|SET_listCheck_"+listId+"_nochk",
						"fw_lstid="+listId+(checkAllAct?"&fw_act="+checkAllAct:"")+(checkAllQs?"&"+checkAllQs:"")+(doClear?"&fw_clr=true":""),"GET_DATA",function(req){
				// Update nummarked on return
				var numMarked = parseInt(req.responseText,10);
				if(isNaN(numMarked)) numMarked = 0;
				$("#SET_listNumMarked_"+listId).html(String(numMarked));
			},60000,false);//false = singleton
		}else{
			_ajaxFWPost("FW_CHECK_ITEMS","SET_list_"+listId+"_|SET_listCheck_"+listId+"|SET_listCheck_"+listId+"_nochk",
						"fw_lstid="+listId+(checkAllAct?"&fw_act="+checkAllAct:"")+(checkAllQs?"&"+checkAllQs:"")+(doClear?"&fw_clr=true":""),"GET_DATA",function(req){
				// Update nummarked on return
				var numMarked = parseInt(req.responseText,10);
				if(isNaN(numMarked)) numMarked = 0;
				$("#SET_listNumMarked_"+listId).html(String(numMarked));
			},60000,"#SET_listTable_"+listId+":first td.SET_cssCellCheck :input",false);//false = singleton
		}
	},0);
}




// Makes sure only li's there is room for are shown
function _normalizeFWListPaging(listId,pagingIndicator,nonList){
	//setTimeout(function(){
	var par;
	if(nonList){
		par=$("#"+listId);
	}else{
		if(pagingIndicator=="POST") par=$("#SET_listPostPaging_"+listId);
		else par=$("#SET_listPaging_"+listId);
	}

	if(par.length==0) return;
	prePivotPage=parseInt(par.attr("prePivotPage"),10);
	if(isNaN(prePivotPage)) prePivotPage=0;
	
	var ulw=$("div.SET_cssListPagingUlWrapper:first",par);
	var perPageWidth =$("div.SET_cssListPerPage:first",par).outerWidth(true); //Include margins,padding,border
	if(!perPageWidth)perPageWidth=0;
	var curtain = (par.width()-(!perPageWidth?0:perPageWidth))-(ulw.outerWidth(true)-ulw.width());
	
	// Subtract 10px to cover various browser miscalculations
	curtain -= 10;
	//ulw.width(curtain);

	var last = $("li.SET_cssListGotoLast:first",ulw);
	if(!last.length) last = $("li.SET_cssListGotoNext:first",ulw);
	var lastPos = (last.offset().left-ulw.offset().left)+last.outerWidth(); //Do not include margins, but do include border+padding
	
	var ixAfter=0,ixBefore=0,li;
	var liBefore=$("li.SET_cssListPageBeforeCurrent:hidden",ulw).get().reverse();
	var liAfter=$("li.SET_cssListPageAfterCurrent:hidden",ulw).get();
	// Start showing
	while(lastPos<curtain){
		if(li) li.show(); //Show li from last iteration
		li=null;
		if(ixAfter<=ixBefore && ixAfter<liAfter.length){ //More or equal before than after = show a new tab after
			li=$(liAfter[ixAfter++]);
		}else if(ixBefore<prePivotPage && ixBefore<liBefore.length){ //Less before than prePivotPage = show a new tab before
			li=$(liBefore[ixBefore++]);
		}else if(ixAfter<liAfter.length){ //More after tabs exist = show a new tab after
			li=$(liAfter[ixAfter++]);
		}else if(ixBefore<liBefore.length){ //If any pre tabs still exist, now it is ok to show them
			li=$(liBefore[ixBefore++]);
		}else{
			lastPos=curtain; //This case is to capture if no more befores or afters exist, to prevent eternal looping
		}
		if(li)lastPos+=li.outerWidth(true); //Do include margins+border+padding
	}
	//},1);
	//Call for post paging automatically if no forWhat specified
	if(!pagingIndicator && !nonList) _normalizeFWListPaging(listId,"POST");
}

// Expand an extra row for a row in a list
function _toggleFWListExpandedRow(listId,rowItems,act,id,qs,forceRefresh,forceClose){
	
	var f = function(){
		xmlHttp=_ajaxFWGet(act,id,qs,"GET_MARKUP",function(req){
			
			var isFail=(req.responseText.indexOf("<!--FW_LISTEXPANSION-->")==-1);
			rowItems.each(function(){ // Update each expansion
				var rowId = $(this).attr("id");
				var expRow = $("#"+rowId+"_expanded");
				if(expRow.length){
					if(isFail)_failFWListLoadingIndicator(listId,rowId);
					else{
						expRow.show().find(".SET_cssExpandedInfoWrapper").html(req.responseText);
						$(this).addClass("SET_cssListRowExpanded");
					}
				}
			});
		},60000,true);
	}
	
	if(_getFWTypeOf(rowItems)=="string" || _getFWTypeOf(rowItems)=="number") rowItems = $("#SET_list_"+listId+"_row_"+rowItems);
	var some = false;
	rowItems.each(function(){
		var rowId = $(this).attr("id");
		expRow = $("#"+rowId+"_expanded");
		if(expRow.length && (!forceRefresh || forceClose)){
			$(this).removeClass("SET_cssListRowExpanded");
			expRow.remove();
		}else if(!forceClose){
			// Force refresh only refreshes if row already expanded
			if(forceRefresh && !expRow.length) return;
			var colspans = $("td",this).length;
			some = true;
			if(!expRow.length){
				expRow = $('<tr id="'+rowId+'_expanded" class="SET_cssListRowExpanded" style="display:none"><td colspan="'+colspans+'" class="SET_cssCellExpandedInfo"><div class="SET_cssExpandedInfoWrapper"></div></td></tr>');
				$(this).after(expRow);
			}
			 _showFWListLoadingIndicator(listId,null,f,rowId,expRow); // Show loading indicator
		}
	});
	setTimeout(function(){if(some)f()},1);
}

// Stops propagation of events on callback
function _stopFWEvents(e,callback,all){
	var event = e || window.event;

	if(!e)return;

	if(callback)callback.call();

	if(event.stopPropagation){
		event.stopPropagation();
	} else {
		event.cancelBubble = true;
	} 
	if(all){if(event.preventDefault){event.preventDefault();}else{event.returnValue=false;}}
}

// Only performs action if something was typed (not on arrow keys etc)
function _onFWType(ev,callback){
	var charCode;
	try{
		if(window.event){
			ev = window.event;
			charCode = ev.keyCode;
		}else{
			charCode = ev.which;
		}
	}catch(er){}
	switch(charCode){//Disallow auto-search for the following keycodes
		case 9: case 13: case 16: case 17: case 18: case 19: case 20: case 27: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 44: case 91: case 92: case 93: case 144: case 145: case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: return; break;
	}
	callback.call();
}


// Shows a system confirm popup dialog with text and buttons
// Utökning: skicka in ett nytt argument sist i funkitionen som är ett id på ett template som har renderats på sidan
// flytta in templatet i funktionen istället för header, question. Detta ger oss möjlighet att mer flexibelt rendera innehåll för systemdialogs.
// måste renderaas som template för att kunna innehålla dynsels m.m
function _showFWSystemDialog(id,header,question,description,buttons,css,position,hideOtherSysDiags,noShield,silentShield,width){
	if(hideOtherSysDiags) _hideFWSystemDialog(null,!noShield);
	else _hideFWSystemDialog(id,!noShield);//Regardless, hide THIS dialog if it was previously visible

	if(!noShield){
		_showFWShield(null,silentShield);
	}
	s="<div id='"+id+"' class='SET_cssSystemDialogContainer' style='display:none'>"+
		"<div class='SET_cssSystemDialogHeader'><div></div></div>"+
		"<div class='SET_cssSystemDialogRight'><div></div></div>"+
		"<div class='SET_cssSystemDialogLeft'><div></div></div>"+
		"<div class='SET_cssSystemDialogBody'>"+
		"<div class='SET_cssSystemDialogLoadingIndicator' style='display:none'></div>"+
		(header?"<h1>"+header+"</h1>":"")+
		(question?"<div class='SET_cssSystemDialogQuestion'>"+question+"</div>":"")+
		(description?"<div class='SET_cssSystemDialogDescription'>"+description+"</div>":"");
	s+="</div>"+
		"<div class='SET_cssSystemDialogFooter'><div></div></div>"+
		"</div>";
	s = $(s);
	var bs;
	if(buttons){
		bs = $("<div class='SET_cssSystemDialogButtons'></div>");
		if(_getFWTypeOf(buttons)=="array"){
			for(i=0;i<buttons.length;i++){
				b=$("<div class='SET_cssLinkButtonWrapper'><a class='SET_cssLinkButton' href='javascript:void(0);'><div>" + buttons[i].title + "</div></a></div>");
				b.click(buttons[i].action);
				b.appendTo(bs);
			}
		}else{
			for(prop in buttons){
				b=$("<div class='SET_cssLinkButtonWrapper'><a class='SET_cssLinkButton' href='javascript:void(0);'><div>" + prop + "</div></a></div>");
				b.click(buttons[prop]);
				b.appendTo(bs);
			}
		}
	}
	if(!width){
		width="300px";
	}else{
		width=width+"px";
	}
	s.appendTo(document.body);
	if(bs)$("div.SET_cssSystemDialogBody",s).append(bs).append("<div class='breaker'></div>");
	position=_initFWPosition(position,"center",true);
	s.show().dialog({
		"position":position,
		height:"auto",
		width:width,
		draggable:true,
		resizable:false,
		zIndex:10000,
		closeOnEscape:false,
		open:function(){
			$(this).parents(".ui-dialog:first")
				.attr("class","ui-dialog ui-draggable SET_cssSystemDialog "+css)
				.find(".ui-dialog-titlebar-close").remove();
			s.css({
				'height' : 'auto',
				'min-height' : '0'
			});
		}
	});
	_playFWSound("alert");
	return s;
}
function _hideFWSystemDialog(id,hideShield){
	var d;
	if(!id){
		d = $("div.SET_cssSystemDialog");
	}else{
		if(typeof(id)=="object") d=$(id);
		else d=$("#"+id);
	}
	d.hide();
	setTimeout(function(){ //Threading
		d.dialog("destroy").remove();
		if(hideShield){
			// Only enable content if there are NO MORE DIALOGS now
			if($("div.SET_cssSystemDialog:first").length==0){
				_hideFWShield(null,true);
			}
		}
	},1);
}
// Makes sure a position is returned for a pos obj, or a pos array
// Extends jQuerys positioning with "topthird" and position at equivalents
function _initFWPosition(position,defaultPos,skipScrollAdjust){
  if(position){
		if(_getFWTypeOf(position)!="array"){ //Position is another object
			posOff = position.offset();
			position = [posOff.left,posOff.top];
		}else{
			var vps=_getFWViewportSize();
			var sc=_getFWScrollCoordinates();
			if(skipScrollAdjust) sc.y=0;
			if(String(position[1]).toLowerCase()=="topthird"){position[1]=parseInt(vps.y/5,10)+sc.y;
			}else if(!isNaN(parseInt(position[1],10))){ //Check if any parameter is in px, which then should be adjusted with viewport height
				position[1] = parseInt(position[1],10)+sc.y;
			}
		}
	}else{
		position = defaultPos;
	}
	return position;
}

////////////////////////////////////////////////////////////
//
//	_checkFWSystemMessages()
//
//	wrapperfunction called from ajax-actions etc. 
//	for systemmessage blocks to update themselves
/////////////////////////////////////////////////////////////

function _checkFWSystemMessages(extras){
	try{_getCMSSystemMessages(extras)}catch(er2){};
	var dialogId = $("div.ui-dialog-content[isAdminDialog='true']:first").attr("id");
	if(dialogId) _refreshFWSystemMessages($("#"+dialogId+"___messages"),null,null,null,null,"div.ui-dialog-content:first",true);
	else try{_refreshSystemMessagesCMS_SYSTEM8(null,extras);}catch(er1){};
}
function _showFWSystemMessage(str,typ,doClear){
	var dialogId = $("div.ui-dialog-content[isAdminDialog='true']:first").attr("id");
	if(dialogId) _refreshFWSystemMessages($("#"+dialogId+"___messages"),$("#"+dialogId+"___messageTemplate"),str,doClear,typ,"div.ui-dialog-content:first",true);
	else try{_refreshSystemMessagesCMS_SYSTEM8(str,doClear,typ);}catch(er1){};
}
function _clearFWSystemMessages(){
	_showFWSystemMessage(null,null,true);
}
function _refreshFWSystemMessages(msgContainer,msgTemplate,str,doClear,typ,parentContainerSelector,noBodyClass){
	var f = function(st,fromAjax){
		if(!st){
			msgContainer.html("").addClass('SET_cssNoMessages').hide();
			if(parentContainerSelector)msgContainer.parents(parentContainerSelector).addClass('SET_cssNoMessages');
			$(document.body).removeClass("SET_cssHasSystemMessage");
		}else{
			if(!fromAjax){
				var t = msgTemplate.clone(true);
				t.removeClass("SET_cssMessageTemplate").find("div.SET_cssContent:first").append(st);
				switch(typ){
				case "INFO":t.addClass("SET_cssSystemMessageInfo");break;
				case "WARNING":t.addClass("SET_cssSystemMessageWarning");break;
				case "ERROR":t.addClass("SET_cssSystemMessageError");break;
				}
				msgContainer.html("").append(t.show());
			}else{
				msgContainer.html(st);
			}
			msgContainer.removeClass('SET_cssNoMessages').show();
			if(parentContainerSelector)msgContainer.parents(parentContainerSelector).removeClass('SET_cssNoMessages');
			if(!noBodyClass) $(document.body).addClass("SET_cssHasSystemMessage");
			else $(document.body).removeClass("SET_cssHasSystemMessage");
		}
		_playFWSound("systemmessage")
	}
				
	if(str || doClear){
		f(str);
	}else{
		_ajaxFWGet("FW_GET_SYSTEMMESSAGES","","","GET_MARKUP",function(req){
			f(req.responseText,true);
		});
	}
}

// Creates an iframe to perform a file download request in
function _getFWFile(aObj,href){
	var inhref=href;
	if(!href && aObj){
		href=aObj.href;
		aObj.href="javascript:void(0)";
	}
	var iframe=$("#SET_getFileIframe");
	if(iframe.length==0){
		iframe=$("<iframe id=\"SET_getFileIframe\" src=\""+href+"\"></iframe>").hide();
		$(document.body).append(iframe);
	}else{
		iframe.attr("src",href);
	}
	if(!inhref && aObj) aObj.href=href;
	return false;
}



//////////////////////////////////////////////////////////
//	_updateFWDynamicCheckbox
//
//	updates submittable value of a checkbox
//  used in conjunction with sub renderFWDynamicCheckbox(...)
//////////////////////////////////////////////////////////
function _updateFWDynamicCheckbox(chkbox){
	chkbox=$(chkbox);
	var input = chkbox.parent().next();
	
	if(chkbox.attr('ischecked').toLowerCase().indexOf('true') != -1){
		_removeFWStateCSS(chkbox.parent(),"SELECTED");
		input.val('');
		chkbox.attr('ischecked','False');
	}else{
		_setFWStateCSS(chkbox.parent(),"SELECTED");
		input.val(chkbox.attr('value'));
		chkbox.attr('ischecked','True');
	}
}


//////////////////////////////////////////////////////////
//	_updateFWDynamicRadioGroup
//
//	updates submittable value of a group of radiobuttons.
//  used in conjunction with sub renderFWDynamicRadiobutton(...)
//////////////////////////////////////////////////////////
function _updateFWDynamicRadioGroup(radio,name,val){
	radio = $(radio);

	if(!radio.attr('ischecked')=='False') return; //nothing happens if already checked radio is clicked

	var a;

	$('input#'+name).attr('value',val); //set hidden field

	var radios = $('a[radiogroup*='+name+']'); //select all radios in the group

	for(var i=0; i<radios.length; i++){
		a = radios[i];
		if($(a).attr('value')==val){
			$(a).attr('ischecked','True');
			_setFWStateCSS(a,"SELECTED");
		}else{
			$(a).attr('ischecked','False');
			_removeFWStateCSS(a,"SELECTED");
		}
	}
}


//////////////////////////////////////////////////////////
//	_clickFWInnerCheckRadio
//
//	activates all dynamic checkboxes/radiobuttons inside obj
//	used to get an effect similar to a label coupled with for="an_id" to a normal radio/checkbox with id="an_id"
//////////////////////////////////////////////////////////
function _clickFWInnerCheckRadio(obj){
	obj = $(obj);
	var chkradio = obj.find('a.SET_cssRadiobutton, div.SET_cssCheckbox a');

	while(chkradio.length==0 && obj.parent().length==1){
		obj = obj.parent();
		chkradio = obj.find('a.SET_cssRadiobutton, div.SET_cssCheckbox a');
	}

	if(chkradio.length == 0){
		return;
	}

	chkradio.trigger('mousedown').trigger('mouseup').trigger('click');
}


//////////////////////////////////////////////////////////
//	_setFWStateCSS
//
//	Used to set a standard class for a state
//  obj can be either an id string or the object itself
//
//  NOTE! UPDATE CLASSNAMES OF sub getFWState(), _setFWStateCSS(), _removeFWStateCSS, _resetFWStatesCSS AND _hasFWStateCSS IF YOU UPDATE THESE CLASSNAMES!!!
//////////////////////////////////////////////////////////
function _setFWStateCSS(obj,state){
	obj = $(obj);

	switch(state.toUpperCase()){
		case 'HOVERED':
			obj.addClass('SET_cssHovered');
			break;
		case 'ACTIVATED':
			obj.addClass('SET_cssActivated');
			break;
		case 'SELECTED':
			obj.addClass('SET_cssSelected');
			break;
		case 'HIGHLIGHTED':
			obj.addClass('SET_cssHighlighted');
			break;
		case 'DISABLED':
			obj.addClass('SET_cssDisabled');
			break;
		case 'DRAGGED':
			obj.addClass('SET_cssDragged');
			break;
		case 'DROPPED':
			obj.addClass('SET_cssDropped');
			break;
		case 'ERROR':
			obj.addClass('SET_cssError');
			break;
		case 'DELETED':
			obj.addClass('SET_cssDeleted');
			break;
	}
}


//////////////////////////////////////////////////////////
//	_removeFWStateCSS
//
//	Used to remove a standard class for a state
//  obj can be either an id string or the object itself
//
//  NOTE! UPDATE CLASSNAMES OF sub getFWState(), _setFWStateCSS(), _removeFWStateCSS, _resetFWStatesCSS AND _hasFWStateCSS IF YOU UPDATE THESE CLASSNAMES!!!
//////////////////////////////////////////////////////////
function _removeFWStateCSS(obj,state){
	obj = $(obj);

	switch(state.toUpperCase()){
		case 'HOVERED':
			obj.removeClass('SET_cssHovered');
			break;
		case 'ACTIVATED':
			obj.removeClass('SET_cssActivated');
			break;
		case 'SELECTED':
			obj.removeClass('SET_cssSelected');
			break;
		case 'HIGHLIGHTED':
			obj.removeClass('SET_cssHighlighted');
			break;
		case 'DISABLED':
			obj.removeClass('SET_cssDisabled');
			break;
		case 'DRAGGED':
			obj.removeClass('SET_cssDragged');
			break;
		case 'DROPPED':
			obj.removeClass('SET_cssDropped');
			break;
		case 'ERROR':
			obj.removeClass('SET_cssError');
			break;
		case 'DELETED':
			obj.removeClass('SET_cssDeleted');
			break;
	}
}




//////////////////////////////////////////////////////////
//	_resetFWStatesCSS
//
//	Used to remove all standard classes for states
//  obj can be either an id string or the object itself
//
//  NOTE! UPDATE CLASSNAMES OF sub getFWState(), _setFWStateCSS(), _removeFWStateCSS, _resetFWStatesCSS AND _hasFWStateCSS IF YOU UPDATE THESE CLASSNAMES!!!
//////////////////////////////////////////////////////////
function _resetFWStatesCSS(obj){
	obj = $(obj);

	obj.removeClass('SET_cssHovered');
	obj.removeClass('SET_cssActivated');
	obj.removeClass('SET_cssSelected');
	obj.removeClass('SET_cssHighlighted');
	obj.removeClass('SET_cssDisabled');
	obj.removeClass('SET_cssDragged');
	obj.removeClass('SET_cssDropped');
	obj.removeClass('SET_cssError');
	obj.removeClass('SET_cssDeleted');
}




//////////////////////////////////////////////////////////
//	_hasFWStateCSS
//
//	Returns true if obj has
//  obj can be either an id string or the object itself
//
//  NOTE! UPDATE CLASSNAMES OF sub getFWState(), _setFWStateCSS(), _removeFWStateCSS, _resetFWStatesCSS AND _hasFWStateCSS IF YOU UPDATE THESE CLASSNAMES!!!
//////////////////////////////////////////////////////////
function _hasFWStateCSS(obj,state){
	obj = $(obj);

	switch(state.toUpperCase()){
		case 'HOVERED':
			if(obj.hasClass('SET_cssHovered')) return true;
			break;
		case 'ACTIVATED':
			if(obj.hasClass('SET_cssActivated')) return true;
			break;
		case 'SELECTED':
			if(obj.hasClass('SET_cssSelected')) return true;
			break;
		case 'HIGHLIGHTED':
			if(obj.hasClass('SET_cssHighlighted')) return true;
			break;
		case 'DISABLED':
			if(obj.hasClass('SET_cssDisabled')) return true;
			break;
		case 'DRAGGED':
			if(obj.hasClass('SET_cssDragged')) return true;
			break;
		case 'DROPPED':
			if(obj.hasClass('SET_cssDropped')) return true;
			break;
		case 'ERROR':
			if(obj.hasClass('SET_cssError')) return true;
			break;
		case 'DELETED':
			if(obj.hasClass('SET_cssDeleted')) return true;
			break;
	}

	return false;
}

//////////////////////////////////////////////////////////
//	_getFWStateCSS
//
//	Used to get the standard classname for a state
//  
//
//  NOTE! UPDATE CLASSNAMES OF sub getFWState(), _setFWStateCSS(), _removeFWStateCSS, _resetFWStatesCSS AND _hasFWStateCSS IF YOU UPDATE THESE CLASSNAMES!!!
//////////////////////////////////////////////////////////
function _getFWStateCSS(state){
	var val = '';

	switch(state.toUpperCase()){
		case 'HOVERED':
			val = 'SET_cssHovered';
			break;
		case 'ACTIVATED':
			val = 'SET_cssActivated';
			break;
		case 'SELECTED':
			val = 'SET_cssSelected';
			break;
		case 'HIGHLIGHTED':
			val = 'SET_cssHighlighted';
			break;
		case 'DISABLED':
			val = 'SET_cssDisabled';
			break;
		case 'DRAGGED':
			val = 'SET_cssDragged';
			break;
		case 'DROPPED':
			val = 'SET_cssDropped';
			break;
		case 'ERROR':
			val = 'SET_cssError';
			break;
		case 'DELETED':
			val = 'SET_cssDeleted';
			break;
	}

	return val;
}

/* Show an image in a popup */
function _showFWImage(e,imgUrl,posAlign,css,explicitHide){

	e = _initFWieEvent(e);
	if(window.fw_popup && window.fw_popup.trigger==e.target){
		_stopFWEvents(e,function(){_hideFWPopupNoDel()});
	}else{
		var mpoint;
		var doAdjust=false;
		if(posAlign=="center"){
			var vps=_getFWViewportSize();
			var sc=_getFWScrollCoordinates();
			//mpoint = {x:Math.round((((vps.x-20)/2)+sc.x)-(0.025*vps.x)),y:Math.round((((vps.x-20)/2)+sc.y)-(0.025*vps.y))};
			mpoint = _getFWMouseCoordinates(e);
			posAlign=null;
			doAdjust=true;
		}else{
			mpoint = (posAlign?{x:0,y:0}:_getFWMouseCoordinates(e));
		}
		_showFWPopup(e,"<img src='"+imgUrl+"' "+(doAdjust?"style='display:none' onload='_adjustFWImagePosition(this)'":"")+
				"><a class='SET_cssClose' href='javascript:_hideFWPopupNoDel()'></a>",function(popup){
		$(popup).draggable({opacity:0.6});	
		},null,mpoint.x,mpoint.y,"SET_cssImagePopup "+(css?css:""),(explicitHide!=null?explicitHide:"click"),posAlign,0,!(posAlign),0);

	}
}

function _adjustFWImagePosition(img){
	$(img).show();
	var p = $(img).parents("div.SET_cssImagePopup:first");
	var vps=_getFWViewportSize();
	var sc=_getFWScrollCoordinates();
	p.css("left",Math.round((((vps.x-p.width())/2)+sc.x)-(0.025*vps.x))+"px");
	p.css("top",Math.round((((vps.y-p.height())/2)+sc.y)-(0.025*vps.y))+"px");
}

/* Renders indicator that log is present */
function _renderFWLogIndicator(status){

	var l = $("#SET_ajaxMessageLog");
	var li = $("#SET_ajaxMessageLogIndicator");
	if(li.length==0){
		li=$("<div id='SET_ajaxMessageLogIndicator'>L</div>");
		li.click(function(){if(l.is(":visible")){l.hide()}else{l.show();window.scrollTo(0, 0);
			if(li.attr("refreshLog")){
				_ajaxFWGet("FW_GET_LAST_LOG",null,null,"GET_MARKUP",function(req){
					l.html(req.responseText);	
					li.removeAttr("refreshLog");
				},60000)}}
			}
		);
		$(document.body).append(li);
	}

	li.attr("refreshLog",true);

	setTimeout(function(){li.fadeOut(200)
		setTimeout(function(){li.fadeIn(200)
			setTimeout(function(){li.fadeOut(200)
				setTimeout(function(){li.fadeIn(200)}
				,100);}
			,100);}
		,100);}
	,100);
						
	li.attr("class","SET_cssAjaxMessageLogIndicatorStatus"+status);
	l.attr("class","SET_cssAjaxMessageLogStatus"+status);
}

// Enables micro editor for field with id (should be a hidden field)
function _initFWMicroEditor(id,editorType,onSave,css){
	var str;
	var h=$("#"+id);
	var disabled = h.attr("disabled");


	str = "<div noClone='true' id='"+id+"___template'>"
		str += "<div class='SET_cssMicroEditorHeader'><div></div></div>"
		str += "<div class='SET_cssMicroEditorBody'>"
			if(h.attr("editorTitle")){
				str += "<h1>"+h.attr("editorTitle")+"</h1>"
			}
	
			str += "<div class='SET_cssMicroEditorContent'></div>";
		
			switch(editorType){
				case "DATE":
					str +="<input type='hidden' id='"+id+"___datehidden' name='"+id+"___datehidden'>";
					break;
				case "TEXT":
					if(!disabled){
						if(h.attr("rte")){
							str +="<div class='SET_cssMicroEditorRTE' style='display:none' id='"+id+"___rte'></div>";
							str +="<input type='hidden' id='"+id+"___rtehidden' name='"+id+"___rtehidden'>"
						} else {
							str +="<textarea class='SET_cssMicroEditorTextarea' style='display:none' id='"+id+"___textarea' name='"+id+"___textarea'></textarea>";
						}
					}
					break;
				case "PRIV":
					// Render nothing prematurely
					break;
			}

			if(!disabled){
				str +="<div style='display:none' class='SET_cssMicroEditorLoadingIndicator'>"+(h.attr("savingTitle")?h.attr("savingTitle"):"")+"</div>";
				str +="<div class='SET_cssButtons'>";
					str += "<div style='display:none' class='SET_cssMicroEditorFailed'>"+(h.attr("failTitle")?h.attr("failTitle"):"")+"</div>";
					str += "<div class='SET_cssLinkButtonWrapper' style='display:none'>"
						str += "<a class='SET_cssMicroEditorBtn SET_cssMicroEditorSaveBtn' href='javascript:void(0);'>"
							str += "<div>" + h.attr("saveBtnTitle") + "</div>"
						str += "</a>"
					str += "</div>";

					str += "<div class='SET_cssLinkButtonWrapper' style='display:none'>"
						str += "<a class='SET_cssMicroEditorBtn SET_cssMicroEditorCancelBtn' href='javascript:void(0);'>"
							str += "<div>" + h.attr("cancelBtnTitle") + "</div>"
						str += "</a>"
					str += "</div>";

					str += "<div class='SET_cssLinkButtonWrapper'>"
						str += "<a class='SET_cssMicroEditorBtn SET_cssMicroEditorEditBtn' href='javascript:void(0);'>"
							str += "<div>" + h.attr("editBtnTitle") + "</div>"
						str += "</a>"
					str += "</div>";
				str +="</div>";
			}
		str += "</div>"; //end div.SET_cssMicroEditorBody

		str +="<div class='SET_cssMicroEditorFooter'><div></div></div>";
	str += "</div>";			
	//str += "</div>";

	str = $(str);

	var co=$("div.SET_cssMicroEditorContent:first",str);
	var ta=$("textarea.SET_cssMicroEditorTextarea:first",str); //Will not find anything if disabled OR if RTE
	var rte=$("div.SET_cssMicroEditorRTE:first",str); //Will not find anything if disabled OR if not RTE
	if(rte.length) ta=rte.next('input'); //Will not find anything if disabled OR if not RTE
				
	if(!disabled || editorType=="PRIV"){
		var li = $("div.SET_cssMicroEditorLoadingIndicator:first",str);
		var fail = $("div.SET_cssMicroEditorFailed:first",str);
		var canbtn = $("a.SET_cssMicroEditorCancelBtn:first",str); //Will not find anything if disabled
		var savbtn = $("a.SET_cssMicroEditorSaveBtn:first",str); //Will not find anything if disabled
		var edtbtn = $("a.SET_cssMicroEditorEditBtn",str); //Will not find anything if disabled
	}

	var openFun;
	var cal;

	switch(editorType){
		case "DATE":
			ta=$("#"+id+"___datehidden",str);
			if(!disabled){
				
				/*** DATE save function ***/
				savbtn.click(function(e){ // Bind click events
					if(window.fw_popup){
						window.fw_popup.preventHide=null;
						$(window.fw_popup).removeClass("SET_cssMicroEditorFail").addClass("SET_cssMicroEditorSaving");
					}
					li.show();fail.hide();
					h.val(ta.val());
					cal.setDisabled(true);
					if($.isFunction(onSave)){onSave(h);}
					else h.trigger("close");
				});
				

				/*** DATE cancel function ***/
				canbtn.click(function(e){
					h.trigger("close");
				});

				/*** DATE edit function ***/
				edtbtn.click(function(e){
					ta.val(h.val());
					if(cal){
						cal.setDisabled(false);
						cal.setDate(_parseFWDate(ta.val(),h.attr("dateFormatExpanded")));
					}
					//Hide edit btn, show other btns
					edtbtn.parent().hide();canbtn.parent().show();savbtn.parent().show();
					if(window.fw_popup) window.fw_popup.preventHide=true;
					/*** DATE refresh function ***/
					h.unbind("refresh").bind("refresh",function(e){
						li.hide();
						fail.hide();
						if(window.fw_popup)	$(window.fw_popup).removeClass("SET_cssMicroEditorSaving").removeClass("SET_cssMicroEditorFail");
						
						canbtn.parent().hide();savbtn.parent().hide(); // Hide any loading indicators, textareas, buttons etc
						edtbtn.parent().show();
						if(cal){
							cal.setDate(_parseFWDate(ta.val(),h.attr("dateFormatExpanded")));
							cal.setDisabled(true);
						}
					});
					
				});

				/*** DATE fail function ***/
				h.unbind("fail").bind("fail",function(e){
					h.val(h.attr("oldVal"));
					if(cal)cal.setDisabled(false);
					if(window.fw_popup) $(window.fw_popup).removeClass("SET_cssMicroEditorSaving").addClass("SET_cssMicroEditorFail");
					li.hide();fail.show();
					
				});
			}
			str = str.get(0);
			/*** DATE close function ***/
			h.unbind("close").bind("close",function(e,popup){
				if(window.fw_popup && !popup){
					window.fw_popup.preventHide=null;
					_hideFWPopup(e,true,0,h.attr("childId"));
				}
				
				_initFWMicroEditor(id,editorType,onSave,css);//Re-enable with new bindings
				e.stopPropagation();
				e.preventDefault();
			});

			/*** DATE open function ***/
			openFun = function(ev,trigger,toEdit){
				ta.val(h.val());
				h.attr("oldVal",h.val());

				_showFWPopup(ev,str,function(popup){
						
						cal=_showFWFlatCalendar(ta.get(0),h.attr("dateFormatExpanded"),String(h.attr("showTime")).toLowerCase()=="true",
							String(h.attr("showDateFields")).toLowerCase()=="true",true,co.get(0),"",true);
						if(toEdit){edtbtn.click();}$(popup).css("cursor","move").draggable({
							cancel:":input,a,table",cursorAt:false
						});$(":input,a,table",popup).css("cursor","");
					},function(popup){h.trigger("close",[popup])},0,0,"SET_cssMicroEditor "+(css?css:""),"clickany","R",0,
					(h.attr("positionAt")?$(h.attr("positionAt")).get(0):trigger),0,h.attr("childId"));
			}
			
			break;
		case "TEXT":

			if(!disabled){

				/*** TEXT save function ***/
				savbtn.click(function(e){ // Bind click events
					if(window.fw_popup){
						window.fw_popup.preventHide=null;
						$(window.fw_popup).removeClass("SET_cssMicroEditorFail").addClass("SET_cssMicroEditorSaving");
					}
					li.show();
					fail.hide();
					if(rte.length){
						rte.wysiwyg("disable");
					}else{
						ta.attr("disabled","true");
					}
					h.val(ta.val());
					
					if($.isFunction(onSave)){onSave(h);}
					else h.trigger("close");
				});

				/*** TEXT cancel function ***/
				canbtn.click(function(e){
					h.trigger("close");
				});

				/*** TEXT edit function ***/
				edtbtn.click(function(e){
					edtbtn.parent().hide();
					var editFun = function(){ // Inline fun to be called on ajax get complete OR immediately if no ajax
						co.hide(); //Hide content and edit btn
						canbtn.parent().show();savbtn.parent().show(); // Show textareas, btns etc
						if(rte.length){ // Enable RTE (on each open)
							rte.html(ta.val());
							rte.show();
							rte.wysiwyg({
								css : {padding:"2px",margin:0},
								cssColorPicker : (css?String(css).split(" ")[0]+"ColorPicker":"SET_cssMicroEditorColorPicker"),
								copyFontStylesFrom : co,
								linkDialogCss : (css?String(css).split(" ")[0]+"LinkDialog":"SET_cssMicroEditorDialog"),
								original : ta.attr("id"),
								onSave : function(wysi){}
							 });
							 rte.wysiwyg("focus");
						}else{
							ta.show();
							ta.get(0).focus();
						}
						if(window.fw_popup) window.fw_popup.preventHide=true;
						/*** TEXT refresh function ***/
						h.unbind("refresh").bind("refresh",function(e){
							li.hide();
							fail.hide();
							if(window.fw_popup)	$(window.fw_popup).removeClass("SET_cssMicroEditorSaving").removeClass("SET_cssMicroEditorFail");
							if(rte.length){
								rte.wysiwyg("enable");
								rte.wysiwyg("destroy");
								rte.html("");
								
							}else{
								ta.removeAttr("disabled");
								ta.hide();
							}
							canbtn.parent().hide();savbtn.parent().hide(); // Hide any loading indicators, textareas, buttons etc
							// Update content and show it, along with edit butn
							edtbtn.parent().show();
							if(h.attr("ajaxGet")){
								co.html("");
							}else{
								if(h.attr("rte")) co.html(ta.val()).show();
								else co.html(_postProcessFWContent(ta.val())).show();
							}
						});
					}
					if(h.attr("ajaxGet")){
						//Show loading icon and do not switch over until loading is done
						if(li.html())li.html((h.attr("loadingTitle")?h.attr("loadingTitle"):""));
						li.show();
						// NOTE: Do NOT update the "shown" text, since we cannot update the row behind it anyways, so just update the hidden field so that when editing everything is edited on the "latest" thing
						_ajaxFWGet(h.attr("ajaxAct"),h.attr("ajaxId"),h.attr("ajaxQs"),"GET_DATA",function(req){
							ta.val(req.responseText);
							// When done, hide li and set its content to savingTitle
							li.hide();
							if(li.html())li.html((h.attr("savingTitle")?h.attr("savingTitle"):""));
							editFun();
						});
					}else{
						ta.val(h.val());
						editFun();//Call immediately
					}
				});

				/*** TEXT fail function ***/
				h.unbind("fail").bind("fail",function(e){
					h.val(h.attr("oldVal"));
					if(rte.length){
						rte.wysiwyg("enable");
					}else{
						ta.removeAttr("disabled");
					}
					if(window.fw_popup) $(window.fw_popup).removeClass("SET_cssMicroEditorSaving").addClass("SET_cssMicroEditorFail");
					li.hide();fail.show();
					
				});
			}

			str = str.get(0);

			/*** TEXT close function ***/
			h.unbind("close").bind("close",function(e,popup){
				if(rte.length && rte.attr("rteInited") && !popup) rte.wysiwyg('destroy');
				if(window.fw_popup && !popup){
					window.fw_popup.preventHide=null;
					_hideFWPopup(e,true,0,h.attr("childId"));
				}
				
				if(!popup) _initFWMicroEditor(id,editorType,onSave,css);//Re-enable with new bindings
				e.stopPropagation();
				e.preventDefault();
			});
			
			/*** TEXT open function ***/
			openFun = function(ev,trigger,toEdit){
				h.attr("oldVal",h.val());
				if(!h.attr("ajaxGet") || !toEdit){
					if(h.attr("rte")) co.html(h.val());
					else co.html(_postProcessFWContent(h.val()));
				}

				_showFWPopup(ev,str,
					function(popup){
						if(toEdit){
							edtbtn.click();
						}
						$(popup).css("cursor","move").draggable({
							cancel:":input,a,iframe",
							cursorAt:false
						});
						$(":input,a,iframe",popup).css("cursor","");
					},
					function(popup){h.trigger("close",[popup])},
					0,
					0,
					"SET_cssMicroEditor "+(css?css:""),
					"clickany",
					"R",
					0,
					(h.attr("positionAt")?$(h.attr("positionAt")).get(0):trigger),
					0,
					h.attr("childId")
				);
			}
			break; //end TEXT case
		
		case "PRIV":
			var disableElSel = "div.SET_cssCheckbox,a.SET_cssRadiobutton"
			if(!disabled){

				/*** PRIV save function ***/
				savbtn.click(function(e){ // Bind click events
					if(window.fw_popup){
						window.fw_popup.preventHide=null;
						$(window.fw_popup).removeClass("SET_cssMicroEditorFail").addClass("SET_cssMicroEditorSaving");
					}
					li.show();
					fail.hide();
					_setFWStateCSS($(disableElSel,co),"DISABLED");
					

					// DETERMINE PRIVSTR
					var privStr="";
					var privIdStr="";
					
					// Determine levels
					var levsAndGroups = $("div.SET_cssLevelsAndGroups:first",co);
					privStr += $("div.SET_cssLevel div.SET_cssSelected",levsAndGroups).nextAll("label").map(function(){
						return this.innerHTML+levsAndGroups.attr("langLevel");
					}).get().join(", ");
					privIdStr += $("div.SET_cssLevel div.SET_cssSelected a",levsAndGroups).map(function(){return $(this).attr("value");}).get().join(",")+"|";

					// Determine groups
					var tmp=$("div.SET_cssGroup div.SET_cssSelected",levsAndGroups).nextAll("label").map(function(){
						return this.innerHTML+levsAndGroups.attr("langGroup");
					}).get().join(", ");
					if(tmp)	privStr += (privStr?", ":"")+tmp;
					if(privStr) privStr += "&nbsp;";
					privIdStr += $("div.SET_cssGroup div.SET_cssSelected a",levsAndGroups).map(function(){return $(this).attr("value");}).get().join(",")+"|";

					// Determine group type
					if($("div.SET_cssLockType:first a.SET_cssRadiobutton.SET_cssSelected:first",co).attr("value")=="ALL"){
						privStr = h.attr("langLockTypeAll")+"&nbsp;|&nbsp;"+privStr;
						privIdStr = "ALL|"+privIdStr;
					}else{
						privStr = h.attr("langLockTypeOne")+"&nbsp;|&nbsp;"+privStr;
						privIdStr = "ONE|"+privIdStr;
					}
					
					// Set privStr to privStr-span (if present)
					$("#"+id+"___privstr").html(privStr);
					// Set privIdStr to hiddens value
					h.val(privIdStr);

					if($.isFunction(onSave)) onSave(h,privStr);
					else h.trigger("close");
				});

				/*** PRIV cancel function ***/
				canbtn.click(function(e){
					h.trigger("close");
				});

				/*** PRIV edit function ***/
				edtbtn.click(function(e){
					edtbtn.parent().hide();
					var editFun = function(){ // Inline fun to be called on ajax get complete OR immediately if no ajax
						canbtn.parent().show();savbtn.parent().show(); // Show fields, btns etc
						_removeFWStateCSS($(disableElSel,co),"DISABLED");
							
						if(window.fw_popup) window.fw_popup.preventHide=true;
						/*** PRIV refresh function ***/
						h.unbind("refresh").bind("refresh",function(e){
							li.hide();
							fail.hide();
							if(window.fw_popup)	$(window.fw_popup).removeClass("SET_cssMicroEditorSaving").removeClass("SET_cssMicroEditorFail");
							
						
							canbtn.parent().hide();savbtn.parent().hide(); // Hide any loading indicators, textareas, buttons etc
							// Show  edit butn
							edtbtn.parent().show();
						});
					}
					editFun();//Call immediately
				});

				/*** PRIV fail function ***/
				h.unbind("fail").bind("fail",function(e){
					h.val(h.attr("oldVal"));
					_removeFWStateCSS($(disableElSel,co),"DISABLED");
					if(window.fw_popup) $(window.fw_popup).removeClass("SET_cssMicroEditorSaving").addClass("SET_cssMicroEditorFail");
					li.hide();fail.show();
					
				});
			}

			str = str.get(0);

			/*** PRIV close function ***/
			h.unbind("close").bind("close",function(e,popup){
				if(window.fw_popup && !popup){
					window.fw_popup.preventHide=null;
					_hideFWPopup(e,true,0,h.attr("childId"));
				}
				
				_initFWMicroEditor(id,editorType,onSave,css);//Re-enable with new bindings
				e.stopPropagation();
				e.preventDefault();
			});
			
			/*** PRIV open function ***/
			openFun = function(ev,trigger,toEdit){
				h.attr("oldVal",h.val());

				_showFWPopup(ev,str,
					function(popup){

						if(toEdit){
							edtbtn.click();
							savbtn.hide();
						}

						// AJAX LOAD	

						//Show loading icon and do not switch over until loading is done
						if(li.html())li.html((h.attr("loadingTitle")?h.attr("loadingTitle"):""));
						li.show();
						_ajaxFWGet(h.attr("ajaxAct"),h.attr("ajaxId"),"fw_lang="+h.attr("langHandle")+"&fw_id="+h.attr("id")+"&fw_val="+h.val()+
								(h.attr("ajaxQs")?"&"+h.attr("ajaxQs"):""),"GET_DATA",function(req){
							co.html(req.responseText);
							if(!toEdit)	_setFWStateCSS($(disableElSel,co),"DISABLED");//Always set disabled first if not toEdit
							else savbtn.show();
							// When done, hide li and set its content to savingTitle
							li.hide();
							if(li.html())li.html((h.attr("savingTitle")?h.attr("savingTitle"):""));
							
						});
						
						$(popup).css("cursor","move").draggable({
							cancel:":input,a,iframe",
							cursorAt:false
						});
						$(":input,a,iframe",popup).css("cursor","");
						
						
					},
					function(popup){h.trigger("close",[popup])},
					0,
					0,
					"SET_cssMicroEditor "+(css?css:""),
					"clickany",
					"R",
					0,
					(h.attr("positionAt")?$(h.attr("positionAt")).get(0):trigger),
					0,
					h.attr("childId")
				);
			}
			break; // End PRIV case
	}

	h.unbind("open").bind("open",openFun);
	h.unbind("openEdit").bind("openEdit",function(ev,trigger){openFun(ev,trigger,true)});

	
}

// Extension of date with function for getting week
Date.prototype.getWeek = function (){ //ISO 8601
	// Local helper functions	
	function DoWoJ1(Y){
			return 1 + (--Y + (Y / 4 | 0) - (Y / 100 | 0) + (Y / 400 | 0)) % 7;
	}

	function DoYoW11(Y){
			return (11 - DoWoJ1(Y)) % 7 - 2;
	}

	function DaysBeforeMonth(Y, M){
			return M-- < 3 ? M * 31 : (Y % 4 == 0 && (Y % 100 != 0 || Y % 400 == 0)) + (M * 306 - 17) / 10 | 0;
	}
	var Y=this.getFullYear();
	var M=this.getMonth()+1;
	var D=this.getDate();
	var DoY, DN, WN;
	DoY = DaysBeforeMonth(Y, M) + D;
	DN = 1 + (DoWoJ1(Y) + DoY - 2) % 7;
	WN = 1 + (DoY - DoYoW11(Y)) / 7 | 0;
	if(WN == 0){
		return new Date(Y - 1, 11, D + 31).getWeek();
	}
	if(WN == 53 && DoYoW11(Y + 1) < 3){
			WN = 1;
			Y++;
	}
	return WN;
 
}  

function _getFWNumWeeksOfYear(y){ //ISO 8601
	var w=new Date(y,11,31).getWeek();
	if(w<52) w=new Date(y,11,24).getWeek();//For years where final week is next years first week
	return w;
}

function _initFWTree(listId,maxlevels,afterMoveCallback,noDragClass,disableDrag){
	var simpleTreeCollection;
	$(document).ready(function(){
		simpleTreeCollection = $('table#SET_list_'+listId+' ul:first').simpleTree({
			drag:(disableDrag?false:true),
			autoclose: false,
			hideDraggedNode:false,
			docToFolderConvert:true,
			animate:false,
			toggleOnDblClick:false,
			eventSelector:'div.CMS_cssName,div.CMS_cssLink,div.CMS_cssCtrls',
			afterClick:function(node){},
			noDragOnClass:noDragClass,
			onOpenParent:function(node){
				$('[id^="SET_list_menuTree_isopen_"]', node).val('True');
			},
			onCloseParent:function(node){
				$('[id^="SET_list_menuTree_isopen_"]', node).val('False');				
			},
			onNodeMouseOver:function(node){
				var wrapper = $('div.SET_cssWrapper:first', node);
				if($('.SET_cssListRowDragged').length != 0 && !_hasFWStateCSS(wrapper, 'DELETED')){
					_setFWStateCSS(wrapper, 'ACTIVATED');
					
					_startMenuExpansion(node,wrapper);
				}
			},
			onNodeMouseOut:function(node){
				var wrapper = $('div.SET_cssWrapper:first', node);
				if($('.SET_cssListRowDragged').length != 0){
					_removeFWStateCSS(wrapper, 'ACTIVATED');
				}
			},
			afterMove:function(destination, source, pos){
				var id=($(source).attr('itemId'));

				if(destination.hasClass("SET_cssTarget")){ // Nota node, get parent node of target
					destination = destination.parents("li:first");
				}

				source = $(source);

				//Update node's parent
				source.attr('parentId',destination.attr('itemId'));
				$("#SET_list_menuTree_parent_id_"+id).val(destination.attr('itemId'));

				//Update node levels
				var destLevel = parseInt(destination.attr('level')) + 1;
				source.attr('level',destLevel);
				$("#SET_list_menuTree_level_"+id).val(destLevel);

				var temp, currLvl = destLevel + 1;
				do{
					source = source.find('li.SET_cssLI');
					
					if(source.length>0){
						source.attr('level',currLvl);
						$("ul .CMS_cssLinkLevel",source).val(currLvl);
						currLvl++;
					}else{
						break;
					}
				}while(true);
				if($.isFunction(afterMoveCallback)) afterMoveCallback(destination, source, pos);
			},
			doOnDragStart:function(sourcenode){//set number of levels being dragged
				var sourceLvl = lowestLvl = $(sourcenode).attr('level'), temp = 0;

				do{
					temp = $(sourcenode).find('li.SET_cssLI').filter(function(index){return $(this).attr('level')>lowestLvl}).length;
					if(temp>0){
						lowestLvl++;
					}else{
						break;
					}
				}while(lowestLvl <= maxlevels);
				
				var numlevels = lowestLvl - sourceLvl + 1;
				
				$('#SET_draggedTreeviewItem').attr('numlevels',numlevels);
				
				$(document.body).css('cursor','move');
			},
			doOnDragEnd:function(){
				$(document.body).css('cursor','');
			},
			okToDrop:function(destination,source){
				var parents,level;
				var numlevels = parseInt($('#SET_draggedTreeviewItem').attr('numlevels'));
				
				//okToDrop is also used when adding a node, i.e. not dragging, which results in numlevels never having been set. 
				//In these cases it's okToDrop
				if(!numlevels){
					return true;
				}

				destination = $(destination);
				var dest = destination.get(0);
				source = $(source);

				if(destination.is('li.SET_cssLI')){//is node
					//if dropping on sourcenode
					if(destination.get(0) == source.get(0)){
						return false;
					}

					level = parseInt(destination.attr('level'));
				}else{//is target
					//if dropping on targets that are immediately before/after the sourcenode
					if((dest == source.prev().get(0)) || (dest == source.next().get(0))){
						return false;
					}

					level = parseInt(destination.siblings('li.SET_cssLI[level]:first').attr('level'))-1;
				}
				
				//if trying to build branch with too many levels
				if(!((level + numlevels) <= maxlevels)){
					return false;
				}

				//if trying to drop in a sublevel of the source node
				var parents = destination.parents('li.SET_cssLI');				
				if(parents.index(source.get(0)) != -1){ //if we find source node in the parent nodes of destination
					return false;
				}

				//get all the immediate wrappers of the parents that are nodes
				parents = parents.children('div.SET_cssWrapper');
				//check that no parents are deleted
				if(_hasFWStateCSS(parents,'DELETED') || _hasFWStateCSS($('div.SET_cssWrapper:first', destination), 'DELETED')){
					return false;
				}

				return true;
			},
			afterAjax:function(){}
		});
	});
}


function _startMenuExpansion(node,wrapper){
	var tree = $("table#SET_list_menuTree ul:first").get(0);
	
	_clearMenuExpansion(tree);

	if(!wrapper.hasClass("SET_cssOpen")){
		tree.timer = setTimeout(
			function(){tree.nodeToggle(node,true);}
			,1000); 
	}
}


function _clearMenuExpansion(tree){
	clearTimeout(tree.timer);
	tree.timer = null;
}

/**********************************************
/* _openFWTooltip
/* 
/* Created: Stefan Lisper 2009-Nov-23
/* 
/* ev				- event
/* opts				- JSON-object defining any/all of the following
/*		context			-	string. name of context. ignoreShowOn only activates for tooltips of the same context
/*		showOn			-	delay in ms before tooltip is shown
/*		hideOn			-	time in ms/string. 
/*							0 = close asap
/*							null = keep open until other tooltip of same context is shown or click anywhere
/*							'CLICK' = only close on click anywhere
/*							'CLOSE' = only close on click on tooltip's close-button. a.SET_cssCloseBtn will be automatically included and appended 
/*								to the div.SET_cssTooltip
/*		ignoreShowOn	-	time in ms. Time during which tooltips of same context will open asap, instead of after showOn
/*		closeOnClick	-	true/false. Should tooltip be closed on click anywhere? This is only meaningful if hideOn is not null
/*		onShow			-	function to call immediately after showing the tooltip
/*		onHide			-	function to call immediately after removing the tooltip
/*		align			-	string. horizontal align.
/*								LEFT	= align left side of tooltip with left side of positionObjAt
/*								RIGHT	= align right side of tooltip with right side of positionObjAt
/*								AUTO	= automatically choose from above values to make the tooltip show as close as possible to center of viewport
/*		valign			-	string. vertical align.
/*								ABOVE	= align bottom of tooltip with top of positionObjAt
/*								BELOW	= align top of tooltip with bottom of positionObjAt
/*								AUTO	= automatically choose from above values to make the tooltip show as close as possible to center of viewport
/*		adjPos			-	JSON-object containing x/y-values to add to the tooltip's calculated position
/*		positionObjAt	-	node where the tooltip should align to. defaults to ev.target
/*		followMouse		-	true/false. should the tooltip follow the mouse above positionObjAt
/*		width			-	pixels. Will be inserted in style="width:<x>" for the div.SET_cssTooltip
/*		content			-	html string/object. will be appended to div.SET_cssTooltip
/*		css				-	string. will be written as is to the div.SET_cssTooltip class-attribute
/*		isFixed			-	true/false. does positionObj or any of its ancestors have position:fixed?
/*/
function _openFWTooltip(ev, opts){
//OK
	//init stuff
	ev = _initFWieEvent(ev);
	if(!opts){
		opts = {};
	}

	if(!opts.positionObjAt){
		opts.positionObjAt = ev.target;
	}

	opts.positionObjAt = $(opts.positionObjAt);
	
	if(isNaN(opts.showOn)){
		opts.showOn = 0;
	}

	if(!opts.adjPos){
		opts.adjPos = {x:0,y:0};
	}

	if(!opts.context || opts.context==''){
		opts.context = 'default';
	}

	if(!opts.ignoreShowOn || isNaN(opts.ignoreShowOn)){
		opts.ignoreShowOn = 0;
	}

	if(opts.align){
		opts.align = opts.align.toUpperCase();
	}

	if(opts.valign){
		opts.valign = opts.valign.toUpperCase();
	}

	if(!opts.closeOnClick){
		opts.closeOnClick = true;
	}

	if(!window.fw_tooltipsinitialized){
		$(document.body).bind('click', _triggerFWdocbodyclickedtooltip);
		window.fw_tooltipsinitialized = true;
	}
	//end init of stuff


	//if this object has already begun showing its tooltip then stop executing. 
	//Example of this happening is the CMS toolbar's logo-button in the top left corner of the viewport
	//When the mouse enters the logo-button the tooltip process is started, but at the same time div.CMS_cssBase is hidden
	//by div.CMS_cssHighlight, thus triggering onmouseover on div.CMS_cssHighlight and this event bubbles up to logo-button, thereyby trying yet
	//again to show the same tooltip. By this time, however, the ignoreShowOn state has been activated thereby showing the tooltip without waiting //for opts.showOn milliseconds
	if(opts.positionObjAt.get(0).alreadyShowingTooltip){
		return;
	}


	//get the new tooltip and add it to the DOM
	var tt = _getFWTooltip(opts);
	
	//position tooltip
	_positionFWTooltip(tt,ev,opts);

	//bind event if tt should follow mouse across target
	if(opts.followMouse){
		opts.positionObjAt.bind('mousemove',function(e){_positionFWTooltip(tt, e, opts);});
	}

	if(opts.closeOnClick){
		//use special event to not run risk of unbinding non-tooltiprelated click-event
		$(document.body).bind('docbodyclickedtooltip', function(){opts.positionObjAt.trigger('onclose');_removeFWIgnoreShow(opts);});
	}

	if(opts.hideOn != null){
		if(_getFWTypeOf(opts.hideOn)=='string'){
			if(opts.hideOn.toUpperCase() == 'CLICK' && !opts.closeOnClick){
				//hide tooltip on click on body
				$(document.body).bind('docbodyclickedtooltip', function(){opts.positionObjAt.trigger('onclose');_removeFWIgnoreShow(opts);});
			}else if(opts.hideOn.toUpperCase() == 'CLOSE'){//bind onclose. will be triggered by the close button
				opts.positionObjAt.bind('onclose', function(){_doFWCloseTooltip(tt,opts);opts.positionObjAt.unbind('onclose')});
			}
		
		}else if(_getFWTypeOf(opts.hideOn) == 'number'){
			var time = parseInt(opts.hideOn);
			if(time > 0){
				//bind close function so that we can easily execute it once tooltip wants to close
				opts.positionObjAt.bind('onclose', function(){
					setTimeout(function(){_doFWCloseTooltip(tt,opts)},time);
				});	
			}else{
				opts.positionObjAt.bind('onclose', function(){_doFWCloseTooltip(tt,opts);});
			}
		
			//x.mouseisover-variables are used to stop closing tooltip as long as mouse is over either opts.positionObjAt or tooltip
			//Turned out to be difficult to get event for mouse coordinates so decided to simply use variables instead
			opts.positionObjAt.bind('mouseleave', 
				function(){
					_clearFWShowTooltipTimer(opts);
					eval('var ignoreshowIsActive = window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimeout;');
					if(!ignoreshowIsActive){
						_clearFWIgnoreShowTimer(opts)
					}
					opts.positionObjAt.get(0).mouseisover=false;
					opts.positionObjAt.trigger('onclose');
				}
			).bind('mouseover', 
				function(){
					opts.positionObjAt.get(0).mouseisover=true;
				}
			);

			tt.bind('mouseleave', 
				function(){
					_clearFWShowTooltipTimer(opts);
					eval('var ignoreshowIsActive = window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimeout;');
					if(!ignoreshowIsActive){
						_clearFWIgnoreShowTimer(opts)
					}
					tt.get(0).mouseisover=false;
					opts.positionObjAt.trigger('onclose');
				}
			).bind('mouseover', 
				function(){
					tt.get(0).mouseisover=true;
				}
			);
		}
	}else{
		opts.positionObjAt.bind('onclose', function(){
			_doFWCloseTooltip(tt,opts);
		});
		$(document.body).bind('docbodyclickedtooltip', function(){
			opts.positionObjAt.trigger('onclose');
			_removeFWIgnoreShow(opts);
		});
	}

	//set timers and stuff
	_showFWTooltipAndSetIgnoreShowOnTimeout(tt,opts);

	//store array of all the objects that should be hidden when another tooltip is opened in the same context
	if(opts.hideOn == null){
		opts.positionObjAt.attr('context',opts.context);
	}

	//safeguard against reinitialization of tooltip same object
	opts.positionObjAt.get(0).alreadyShowingTooltip = true;
}


function _clearFWShowTooltipTimer(opts){
	eval('clearTimeout(window.fw_tooltiptimer_context_'+opts.context+');');
	eval('window.fw_tooltiptimer_context_'+opts.context+' = null;');
}


function _removeFWIgnoreShow(opts){
	_clearFWIgnoreShowTimer(opts);
	eval('window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimeout = false;');
}


function _clearFWIgnoreShowTimer(opts){
	eval('clearTimeout(window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimer);');
	eval('window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimer = null;');
}


function _setFWIgnoreStateShowStateAndTimer(opts){
	//set ignore show state and timer
	if(opts.ignoreShowOn > 0){
		_clearFWIgnoreShowTimer(opts);
		eval('window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimeout = true;');
		eval('window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimer = setTimeout(function(){window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimeout = false;}, '+opts.ignoreShowOn+');');
	}
}

function _showFWTooltipAndSetIgnoreShowOnTimeout(tt,opts){
	_clearFWShowTooltipTimer(opts);

	//show tooltip
	eval('var ignoreShowTimeout = window.fw_tooltiptimer_context_'+opts.context+'_ignoreShowTimeout;');
	if(ignoreShowTimeout || (opts.showOn <= 0)){
		_showFWTooltip(tt,opts);
		_setFWIgnoreStateShowStateAndTimer(opts);
	}else{
		eval('window.fw_tooltiptimer_context_'+opts.context+' = setTimeout(function(){_showFWTooltip(tt,opts);_setFWIgnoreStateShowStateAndTimer(opts);},'+opts.showOn+');');
	}
}


//shows tooltip and resets array of other tooltips to hide if such an array exists
function _showFWTooltip(tt,opts){
	$('[context="'+opts.context+'"]').filter(
		function(){
			if($(this).get(0) == opts.positionObjAt.get(0)){
				return false;
			} 
			
			return true;
		}
	).trigger('onclose');

	tt.show();
	
	if(_getFWTypeOf(opts.onShow) == 'function'){
		opts.onShow();
	}
}


//helper function that can be used when trying to close a tooltip from an event, i.e. can only get the target
function _closeFWTooltip(obj){
	$(obj).trigger('onclose');
}


//helper to _closeFWTooltip
function _doFWCloseTooltip(tt,opts){
	//don't close if pointer is within tooltip
	if(tt.get(0).mouseisover){
		return;
	}

	if(_getFWTypeOf(opts.onHide) == 'function'){
		opts.onHide();
	}

	tt.remove();

	//clean up
	opts.positionObjAt.get(0).alreadyShowingTooltip = false;

	opts.positionObjAt.unbind('onclose');
}


function _triggerFWdocbodyclickedtooltip(){
	$(document.body).trigger('docbodyclickedtooltip').unbind('docbodyclickedtooltip');
}


//creates a tooltip from opts.content
function _getFWTooltip(opts){
	var tt = $('<div class="SET_cssTooltip' + (opts.css?' '+opts.css:'') + '" style="'+(opts.width?'width:'+opts.width+';':'')+'"></div>').hide();
	
	//try to create a node
	var cont = $(opts.content);
	if(cont.length!=0){ //if we managed to create a node
		tt.append(cont);
	}else{//otherwise just add the straight string
		tt.html(opts.content);
	}

	//include that close button if 'CLOSE' hideOn
	if(opts.hideOn && _getFWTypeOf(opts.hideOn)=='string' && (opts.hideOn.toUpperCase() == 'CLOSE')){
		var btn = $('<a class="SET_cssCloseBtn"></a>');
		btn.bind('click', function(){opts.positionObjAt.trigger('onclose')});
		tt.append(btn);
	}

	tt.hide();
	$(document.body).append(tt);
	return tt;
}


function _positionFWTooltip(tt, ev, opts){
	if(opts.align){
		opts.align = opts.align.toUpperCase();
	}else{
		opts.align = 'AUTO';
	}
	
	if(opts.valign){
		opts.valign = opts.valign.toUpperCase();
	}else{
		opts.valign = 'AUTO';
	}

	var scroll;

	//scroll position will be deducted from the position later on and if position:fixed we're only interested in the viewport position
	if(opts.isFixed){
		tt.css('position','fixed');
		scroll = _getFWScrollCoordinates();
	}else{
		scroll = {x:0,y:0};
	}

	var ttdims = {x:tt.outerWidth(), y:tt.outerHeight()};
	var target = opts.positionObjAt;
	var targetdims = {x:target.outerWidth(), y:target.outerHeight()};
	var targetpos = _getFWAbsolutePos(target.get(0));
	var vpsize = _getFWViewportSize();

	//AUTO works like this: 
	//1. the viewport is divided into four equal parts
	//2. the tooltip alignment is switched so that it moves towards the centre of the screen
	if(opts.align=='AUTO'){
		if(targetpos.x > ((vpsize.x/2) + scroll.x)){
			opts.align = 'RIGHT';
		}else{
			opts.align = 'LEFT';
		}
	}
	
	//set new valign as above
	if(opts.valign=='AUTO'){
		if(targetpos.y > ((vpsize.y/2) + scroll.y)){
			opts.valign = 'ABOVE';
		}else{
			opts.valign = 'BELOW';
		}	
	}
	//ej ok
	if(opts.followMouse){
		var coords = _getFWMouseCoordinates(ev);
		tt.addClass('SET_cssFollowMouse');

		//position horizontally
		switch(opts.align){
			case 'LEFT':
				tt.addClass('SET_cssLeft').css('left', coords.x - scroll.x + opts.adjPos.x);
				break;
			case 'RIGHT':
				tt.addClass('SET_cssRight').css('left', coords.x - ttdims.x - scroll.x + opts.adjPos.x);
				break;
			case 'CENTER':
				break;
		}

		//position vertically
		switch(opts.valign){
			case 'ABOVE':
				tt.addClass('SET_cssAbove').css('top', coords.y - ttdims.y - scroll.y + opts.adjPos.y);
				break;
			case 'BELOW':
				tt.addClass('SET_cssBelow').css('top', coords.y - scroll.y + opts.adjPos.y);
				break;
			case 'CENTER':
				break;
		}
	}else{
		//position horizontally
		switch(opts.align){
			case 'LEFT':
				tt.addClass('SET_cssLeft').css('left', targetpos.x - scroll.x + opts.adjPos.x);
				break;
			case 'RIGHT':
				tt.addClass('SET_cssRight').css('left', targetpos.x + (targetdims.x - ttdims.x) - scroll.x + opts.adjPos.x);
				break;
			case 'CENTER':
				break;
		}

		//position vertically
		switch(opts.valign){
			case 'ABOVE':
				tt.addClass('SET_cssAbove').css('top', targetpos.y - ttdims.y - scroll.y + opts.adjPos.y);
				break;
			case 'BELOW':
				tt.addClass('SET_cssBelow').css('top', targetpos.y + targetdims.y - scroll.y + opts.adjPos.y);
				break;
			case 'CENTER':
				break;
		}
	}
}

function _showFWMessage(messagelang,closelang){
	//Skapa nya klasser till fwmessage och lägg dessa i CMS_cssDefault.asp, SET_cssBrowserDetection --> CMS_cssBrowserDetection
	$("body").prepend("<div class='CMS_cssBrowserDetection'><a onclick='$(\"div.CMS_cssBrowserDetection\").remove();' class='SET_cssBrowserDetectionClose'>"+closelang+"</a><div class='CMS_cssBrowserDetectionInfo'>"+messagelang+"</div></div>");
}

function _selectFWWeek(weekDiv,doNotSort){
	weekDiv = $(weekDiv).toggleClass("SET_cssMarked");
	setTimeout(function(){//Threading for speed
		var wsel = weekDiv.parents("div.SET_cssWeekSelector:first"); 
		var h=wsel.prev("input:hidden:first");
		var hv = h.val();
		var wk = weekDiv.attr("week");

		// If NOW has class SET_cssMarked, it means it was unmarked before and should now be added to string, else removed from str
		if(weekDiv.hasClass("SET_cssMarked")){
			var a=hv.split(",");
			a.push(wk);
			if(!doNotSort){
				a.sort(function(c,d){
					c=c.split("-");
					d=d.split("-");
					if(parseInt(c[0],10)>parseInt(d[0],10) || (c[0]==d[0] && parseInt(c[1],10)>parseInt(d[1],10))) return 1;
					return -1
				});
			}
			hv = a.join(",");
		}else{
			hv = ","+hv+",";
			hv = hv.replace(","+wk+",",",");
		}
		if(hv.substr(0,1)==",") hv = hv.substr(1);
		if(hv.substr(hv.length-1,1)==",") hv = hv.substr(0,hv.length-1);
		h.val(hv);
		// Trigger onchange
		if(wsel.attr("onChange")){
			try{eval(wsel.attr("onChange"))}catch(er){}
		}
	},2);
}

function _selectFWWeeks(id,weekExpr){
	$("#"+id).val(weekExpr);
	var weekWr = $("#"+id+"___weekSelector");
	var a = weekExpr.split(",");
	$("div.SET_cssWeek",weekWr).removeClass("SET_cssMarked");
	for(i=0;i<a.length;i++){
		$("div.SET_cssWeek[week='"+a[i]+"']:first",weekWr).addClass("SET_cssMarked");
	}
}

function _gotoFWYear(id,yea){
	var o=$("#"+id+"___weekSelector");
	o.addClass("SET_cssLoading");
	var sh = o.find("div.SET_cssBody:first div.SET_cssLoadingShield:first");
	if(sh.length==0) sh = o.find("div.SET_cssBody:first").append("<div class='SET_cssLoadingShield'></div>");
	var dateFormat=o.attr("dateFormat");
	if(!dateFormat)dateFormat="";
	var weekFormat=o.attr("weekFormat");
	if(!weekFormat)weekFormat="";
	var numWeeksPerRow=o.attr("numWeeksPerRow");
	if(!numWeeksPerRow)numWeeksPerRow="";
	$("#data").val(o.prev("input:hidden:first").val());
	_ajaxFWPost("FW_GOTO_WEEKSELECTOR_YEAR",id,"fw_year="+yea+"&fw_dateFormat="+escape(dateFormat)+"&fw_weekFormat="+escape(weekFormat)+"&fw_numWeeksPerRow="+numWeeksPerRow,"GET_MARKUP",function(req){
		if(req.responseText.indexOf("<!--FW_SUCCESS-->")) o.html(req.responseText);
		o.removeClass("SET_cssLoading");
		sh.remove();
	},null,"#data");
}

function _showFWLoading(insertAtHow,insertAt,str,css,cancel,onHide,id){
	var l=$("<div "+(id?"id='"+id+"'":"")+" isLoading='true' class='SET_cssLoading "+(css?css:"")+"'>"+(str?str:"")+"</div>");
	if(cancel){
		if(cancel.html) l.append(cancel.html);
		else{
			var a = $("<a href='javascript:void(0)'>"+cancel.text+"</a>");
			a.click(function(){
				if(cancel.http) cancel.http.abort();
				if($.isFunction(cancel.callback)) callback();
				_hideFWLoading(l);
			});
		}
	}
	if($.isFunction(onHide)) l.bind("hide",onHide);
	if(insertAt){
		// If there already is a loading indicator, remove it first
		switch(insertAtHow.toUpperCase()){
			case "PREPEND":case "APPEND":case "HTML":
				_hideFWLoading($("div.SET_cssLoading[isLoading='true']",insertAt));break;
			default: //AFTER, BEFORE
				_hideFWLoading($("div.SET_cssLoading[isLoading='true']",$(insertAt).parent()));break;
		}
		eval("$(insertAt)."+insertAtHow.toLowerCase()+"(l)");
	}
	return l;
}

function _hideFWLoading(l){
	if(!l) l = $("div.SET_cssLoading[isLoading='true']");
	l = $(l);
	if(!l.is("div.SET_cssLoading[isLoading='true']")) l=$("div.SET_cssLoading[isLoading='true']",l); 
	l.trigger("hide");
	l.remove();
}

function _loadFWBlockInDialog(dialogId,mod,bv,bid,tab,itemId,secIx,jqtIx){
	_closeFWDynamicSelect();
	_hideFWPopupNoDel();
	var template=$("#"+dialogId);
	if(itemId) template.attr("itemId",itemId);
	// Clear content in tab and only show loading indicator	
	if(!tab){
		if(secIx && jqtIx) tab = $("#"+dialogId+"_"+secIx+"_tab"+jqtIx);
		else tab = $("#SET_block_"+bid).parents("div.ui-tabs-panel:first");
	}
	tab.html("");
	tab.parents("div.SET_cssAdminDialogContent:first").addClass("SET_cssLoadingIndicator");

	// Get new content (NOTE: act FW_RENDER_BLOCK does nothing here, is needed since ajax requires an act)
	_ajaxFWGet("FW_RENDER_BLOCK",itemId,"fw_render=true&mod="+mod+"&bv="+bv+(bid?"&bid="+bid:""),"GET_MARKUP",function(req){
		// Insert new content in correct tab
		tab.html(req.responseText).parents("div.SET_cssAdminDialogContent:first").removeClass("SET_cssLoadingIndicator");
		_fillFWAdminDialogFooter(template,template.data("footerContent"));
	},60000);
}

function _initFWGantt(listId,unit,callback){
	var listT	= $("#SET_listTable_"+listId);
	var bc = $("div.SET_cssBarContainer",listT);
	_initFWGanttBars($("div.SET_cssBar",listT),listT,bc,listId,unit,callback);
}

function _initFWGanttBars(bars,listT,bc,listId,unit,callback){
	var zindex				= 100; //Start z-index för kontroll av högstligande projekt
	var startDateCell		= $("td.SET_cssDate:first",listT);
	var endDateCell			= $("td.SET_cssDate:last",listT);
	var cellStep			= startDateCell.outerWidth(); //Bredden för varje steg
	var firstStartDate		= new Date(startDateCell.attr("date")); //Startdagen för tabellen
	var padding				= null;

	var pos					= startDateCell.position();
	var endPos				= endDateCell.position();
	var endDateCellLeft		= endPos.left-pos.left;
	bc.width(endDateCellLeft+cellStep);
	if(!$.isFunction(callback)) callback=bc.data("callback");
	else bc.data("callback",callback);
	if(!unit) unit=bc.data("unit");
	else bc.data("unit",unit);

	var f = function(bar,action){
		var startPos			= bar.css("left");
		    startPos			= Number(startPos.slice(0, -2))
		var endPos				= bar.width();
		var oldStart			= bar.attr("startdate");
		var oldEnd				= bar.attr("enddate");
		var cellsFromStart		= startPos/cellStep;
		var newStartDate		= $("td.SET_cssDate:eq("+cellsFromStart+")",listT).attr("date");
		
		if(newStartDate == undefined){
			startDate = new Date(startDateCell.attr("date"));
			startDate.setDate(startDate.getDate()+cellsFromStart)
			newStartDate = _showFWDateQuick(startDate,"YYYY-MM-DD",null,null)	
		}
		bar.attr("startdate", newStartDate);
		
		var daysToEndFromStart	= 0;
		newEndDate				= new Date(newStartDate);

		if(action=="RESIZED" || !bar.attr("dateDiff")){
			daysToEndFromStart = Math.round(endPos/cellStep);
			bar.attr("dateDiff",daysToEndFromStart+1);
		}else{
			daysToEndFromStart = Number(bar.attr("dateDiff")-1);
		}

		newEndDate.setDate(newEndDate.getDate()+daysToEndFromStart);
		endDate = _showFWDateQuick(newEndDate,"YYYY-MM-DD",null,null)
		bar.attr("enddate", endDate);
		// Only call callback if actual change
		if($.isFunction(callback) && (endDate!=oldEnd || newStartDate!=oldStart)) callback(listId,bar,action,oldStart,oldEnd);
	} //END f()

	var eachBar = function(self, action){
		var startDate		= new Date(self.attr("startDate"));
		var endDate			= new Date(self.attr("endDate"));
		endDate.setDate(endDate.getDate()+1);
		
		// RÄKNAR UT ANTAL DAGAR TILL SLUTET
		var daysToEnd = endDate-startDate
		daysToEnd = new String(daysToEnd/86400000)
		var point=daysToEnd.indexOf(".")
		if(points = -1){
		}else{
			daysToEnd=daysToEnd.substring(0,point)+1
		}
		self.attr("dateDiff",daysToEnd);
		
		// RÄKNAR UT ANTAL DAGAR TILL START
		daysToStart = startDate-firstStartDate;
		daysToStart = new String(daysToStart/86400000)
		point=daysToStart.indexOf(".")
		if(points = -1){
		}else{
			daysToStart=daysToStart.substring(0,point)
		}
		
		// SÄTTER VARIABLEN PADDING
		if(padding==null) padding = self.outerWidth(true)-self.width();
		
		var left = Number(daysToStart)*Number(cellStep)
		var width = (Number(daysToEnd)*Number(cellStep))-padding;

		// OM DEN SKA POSITIONERA UT KÖRS DETTA
		if(action == "POSITION"){
			self.css("left", left)
			self.css("width", width);
		}
		
		// RÄKNAR UT IFALL "BAREN" SYNS
		var daysWidth = Number($("div.SET_cssGantt").outerWidth())-Number(pos.left);
		var barRightPos = left+width+padding;

		if(left >= Number(daysWidth)){
			indicatorPos = daysWidth - 23;
			self.parent().append("<div class='SET_cssOverflow right' style='left: "+indicatorPos+"px'></div>")
		}

		if(barRightPos <= 0){
			indicatorPos = 5;
			self.parent().append("<div class='SET_cssOverflow left' style='left: "+indicatorPos+"px'></div>")
		}
		
		self.show();
	}

	// Begin init
	$("div.SET_cssBar",listT).each(function(){
		eachBar($(this), "POSITION")
	}).draggable({ 
		grid: [cellStep,cellStep],	
		distance: cellStep,
		//containment: 'parent',
		drag: function(event, ui){

		},
		stop: function(){
			f($(this),"MOVED");
			$("div.SET_cssBar",listT).each(function(){
				eachBar($(this), "RESIZE")
			});
		}
	}).resizable({
		grid: cellStep,
		handles: 'e, w',
		stop: function(){	
			f($(this),"RESIZED");
			$("div.SET_cssBar",listT).each(function(){
				eachBar($(this), "RESIZE")
			});
		}
	}).click(function(){
		$(this).css("z-index", zindex)
		zindex++;
	});

	setTimeout(function(){ // Threading for responsiveness
		bc.each(function(){ // Display add bar button where applicable (if multibars or no bar)
			var self = $(this);
			if(self.parents("td.SET_cssBarCell:first").attr("multiBars") || $("div.SET_cssBar:first",this).length==0)
				$("div.SET_cssAddBar:first",this).show();
		});

		/*$(window).resize(function() {
			$("div.SET_cssGantt div.SET_cssOverflow").remove();
			$("div.SET_cssBar",listT).each(function(){
				eachBar($(this), "RESIZE")
			});
		});*/
	},1)


}

function _addFWGanttBar(listId,itemId,textInBar,barExtras,barCss){
	var listT	=$("#SET_listTable_"+listId);
	// Extract start date
	var startDateCell = $("td.SET_cssDate:first",listT);

	if(startDateCell.length){
		// Get the important bar container
		var bc = $("#SET_list_"+listId+"_"+itemId+"_barcontainer");

		// Hide button
		var addBarDiv = $("div.SET_cssAddBar:first",bc).hide();

		// Loading indicator for row
		var row = bc.parents("tr.SET_cssListRow:first").addClass("SET_cssListLoading");

		setTimeout(function(){
			// Make dates
			var startDate = new Date(startDateCell.attr("date"));
			startDate = _showFWDateQuick(startDate,"YYYY-MM-DD");
			var endDate = startDate; // Same date to indicate one day bar
			/*var endDate = new Date(startDate); OLD CODE that makes a two day bar
			endDate.setDate(endDate.getDate()+1);
			endDate = _showFWDateQuick(endDate,"YYYY-MM-DD");*/

			// Init various stuff
			if(!textInBar) textInBar = bc.next().html();
			var bo=$("div.SET_cssBar",bc).length;

			// Create bar div
			var bar = $("<div itemId='"+itemId+"' "+(barExtras?barExtras:"")+
					" id='SET_list_"+listId+"_"+itemId+"_bar_"+bo+"'"+
					" startDate='"+startDate+"' endDate='"+endDate+"' class='SET_cssBar"+
					(barCss?" "+barCss:"")+"'>"+textInBar+"</div>");

			// Add bar div to container
			bc.append(bar);

			// Trigger the bar change method
			var callback = bc.data("callback");
			if($.isFunction(callback)) callback(listId,bar,"ADDED");
			
			// Init bar div
			_initFWGanttBars(bar,listT,bc,listId);

			if(!$.isFunction(callback)) row.removeClass("SET_cssListLoading");
		},1);
				
	}
}


function _createFWOption(sel,text,val,firstHasValue,noSelect){
	var o = $(document.createElement("option"));
	o.val(val);
	o.attr("text",text).html(text);
	if(!noSelect){
		sel.get(0).selectedIndex=-1;
		o.attr("selected","true");
	}
	text = String(text).toLowerCase();
	var added=false;
	$("option",sel).each(function(i){
		if(i>0 || firstHasValue){//Leave first one alone (blank), unless firstHasValue=true
			if(text<this.text.toLowerCase()){
				$(this).before(o);
				added=true;
				return false;
			}
		}
	});
	if(!added) $(sel).append(o);
}

/*******************************
 * Play sound
 *******************************/
function _playFWSound(type){
	var src = '';
	switch(type){
		case "alert":
			src = "fw_alert";
			break;
		case "drop":
			src = "fw_drop";
			break;
		case "grab":
			src = "fw_grab";
			break;
		case "login":
			src = "fw_login";
			break;
		case "logout":
			src = "fw_logout";
			break;
		case "logoutwarning":
			src = "fw_logoutwarning";
			break;
		case "opendialog":
			src = "fw_opendialog";
			break;
		case "preview":
			src = "fw_preview";
			break;
		case "publish":
			src = "fw_publish";
			break;
		case "save":
			src = "fw_save";
			break;
		case "systemmessage":
			src = "fw_systemmessage";
			break;
	}
	

	var disableSound = false;
	if($.browser.safari){
		src = src+".wav"
	}else if($.browser.mozilla){
		src = src+".wav"
	}else if($.browser.opera){
		src = src+".wav"
	}else if($.browser.chrome){
		src = src+".mp3"
	}else{
		disableSound = true;
	}

	if(!disableSound){
		var audioElement	= document.createElement('audio');
		audioElement.setAttribute('src', '/mind_setup/sound/default/'+src);
		audioElement.load();

		audioElement.play();
	}

	return false;
}

/**
 *
 * VISA RTE-DIALOG
 * ------------------------------------------------
 * Visar RTE-dialogen och bindar klick på "Ok"-knappen
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _showFWRTELinkDialog(linkDiag,sText,sUrl,sTitle,sTarget,rteControl,rteEditor){

	var c = $(linkDiag);
	var id = c.attr("id");

	$("#"+id+"Url_EXTERNAL").val("");
	$("#"+id+"Url_EMAIL").val("");
	$("#"+id+"Text").val(sText);
	$("#"+id+"Title").val(sTitle);

	var handle = _showFWLinkSelector(id,sUrl,sTarget);

	$(linkDiag).draggable({
		cursor:"move",
		distance:0,
		opacity:0.8,
		handle:"h3"
	});

	_showFWAtElement(linkDiag, rteControl, "B", 0,0, "block", false);

	$("#"+id+"Cancel",linkDiag).one("click",function(){$(linkDiag).trigger("close");});
	$("#"+id+"Ok",linkDiag).unbind("click").bind("click",function(){ //kolla mot hiddenfält
		handle = $(".SET_cssLinkOptionMenu input:checked",c).val();
		var url = $("#SET_blockcontent_"+id+"_url").val();
		var linkName;

		// SÄTT FELCLASS OM DET BEHÖVS OCH HÄMTA LÄNKNAMN UTIFALL TEXT SAKNAS
		switch(handle){
			case "INTERNAL":
				linkName = $("#"+id+"Url_INTERNAL___select .SET_cssFormSelectTopOption .SET_cssOptionLink").text();
				break;
			case "DOC":
				if(url == "" || url == "/?fid="){
					$("#"+id+"Url_DOC___select").addClass("SET_cssFail");
					url = "";
					return;
				}
				
				linkName = $("#"+id+"Url_DOC___select .SET_cssFormSelectTopOption .SET_cssOptionLink").text();

				break;
			case "EMAIL":
				if(url == "" || url == "mailto:"){
					$("#"+id+"Url_EMAIL").addClass("SET_cssFail");
					url = "";
					return;
				}
				linkName = $("#"+id+"Url_EMAIL").val();
				break;
			case "EXTERNAL":
				if(url == "" || url == "http://"){
					$("#"+id+"Url_EXTERNAL").addClass("SET_cssFail");
					url = "";
					return;
				}
				linkName = $("#"+id+"Url_EXTERNAL").val();
				break;
		}

		if($("#SET_blockcontent_"+id+"_url").val()){
			
			var text = $("#"+id+"Text").val();
			var title = $("#"+id+"Title").val();
			var target = $("#SET_blockcontent_"+id+"_target").val();

			url = _ensureFWLink(url);

			if(!text){
				text = linkName;
			}

			//(String(li).search(/^(\/)|(javascript:)/gi)!=-1?null:"_blank")
			rteEditor.insertLink(url,text,title,target);
			$(linkDiag).trigger("close");
		}else{
			// Unlink if no URL
			rteEditor.insertLink("","","","");
			$(linkDiag).trigger("close");
		}
	});
}

/**
 *
 * SWITCHA MELLAN LÄNKALTERNATIVEN
 * ------------------------------------------------
 * Använd för att hoppa mellan dom olika 
 * länkalternativen. Uppdaterar samtidigt hidden-
 * fälten.
 * ------------------------------------------------
 * @param id - Huvud-idet för hela länkrutan.
 * @param sUrl - Typ av länkalternativ
 *		- INTERNAL (Tom, /?pid=)
 *		- EXTERNAL (Övriga)
 *		- EMAIL (mailto:)
 *		- DOC (/?fid=)
 * @param sTarget - Ifall target-rutan ska vara 
 *					checked. if(sTarget=="_blank")
 * @param showNone - Ifall den ska börja visa "NONE"
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _showFWLinkSelector(id,sUrl,sTarget,showNone){
	sUrl = sUrl.toLowerCase();
	if(showNone && sUrl==""){
		_switchFWLinkSelectorOption("NONE",id);
		return "NONE"
	}else if(sUrl.indexOf("/?pid=") >= 0 || sUrl == "/" || sUrl == ""){
		var pId="";
		
		if(sUrl){
			sUrl.replace(/\/\?pid=(\d+)/gi,function(s,p1){
				pId=p1;
			});
		}
		
		$("#"+id+"Url_INTERNAL___opt_"+pId).trigger("click");

		if(sTarget=="_blank"){
			$("#"+id+"Target_INTERNAL").attr("checked", "true");
		}else{
			$("#"+id+"Target_INTERNAL").removeAttr("checked");
		}

		_switchFWLinkSelectorOption("INTERNAL", id)

		$("#"+id+"Url_INTERNAL").change(function(){
			_updateFWHiddenLinkOption("INTERNAL", id);
		});

		return "INTERNAL"
	}else if(sUrl.indexOf("mailto:") >= 0){

		var email = sUrl.substr(7);
		$("#"+id+"Url_EMAIL").val(email).unbind("keyup").bind("keyup", function(){
			_updateFWHiddenLinkOption("EMAIL", id);
		});
		
		_switchFWLinkSelectorOption("EMAIL", id)

		return "EMAIL"
	}else if(sUrl.indexOf("/?fid=") >= 0){

		var fId;
		sUrl.replace(/\/\?fid=(\d+)/gi,function(s,p1){
			fId=p1;	
		});
		if(fId) $("#"+id+"Url_DOC___opt_"+fId).click();
		/*var f = aobj.attr("onclick");

		f = String(f).replace(/\$\(this\)/gi,"aobj");
		var event=null;
		alert(aobj.length + " - " + fId + " - " + id);
		eval("f="+f);

		if($.isFunction(f)) f();*/

		_switchFWLinkSelectorOption("DOC", id)

		return "DOC"
	}else{
		$("#"+id+"Url_EXTERNAL").val(sUrl).unbind("keyup").bind("keyup", function(){
			_updateFWHiddenLinkOption("EXTERNAL", id);
		});

		if(sTarget=="_blank"){
			$("#"+id+"Target_EXTERNAL").attr("checked", "true");
		}else{
			$("#"+id+"Target_EXTERNAL").removeAttr("checked");
		}

		_switchFWLinkSelectorOption("EXTERNAL", id)

		return "EXTERNAL"
	}
}

/**
 *
 * SWITCHA MELLAN LÄNKALTERNATIVEN
 * ------------------------------------------------
 * Används för att hoppa mellan dom olika 
 * länkalternativen, uppdatera hiddenvärden och
 * binda olika saker vid click och keyup.
 * ------------------------------------------------
 * @param handle - Typ av länkalternativ
 *		- NONE
 *		- INTERNAL
 *		- EXTERNAL
 *		- EMAIL
 *		- DOC
 * @param id - Huvud-idet för hela länkrutan.
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _switchFWLinkSelectorOption(handle,id){
	// THE CONTAINER
	var c = $("#"+id+"_LinkSelector");
	
	// CHECK THE SELECTED OPTION
	$("#"+id+"_option_"+handle).get(0).checked = true;

	// BIND CLICK-UPDATE FOR TARGET_INTERNAL-CHECKBOX
	$("#"+id+"Target_INTERNAL",c).unbind("click").bind("click", function(){
		_updateFWHiddenLinkOption("INTERNAL", id);
	});

	// BIND CLICK-UPDATE FOR TARGET_EXTERNAL-CHECKBOX
	$("#"+id+"Target_EXTERNAL",c).unbind("click").bind("click", function(){
		_updateFWHiddenLinkOption("EXTERNAL", id);
	});

	// BIND KEYUP-UPDATE FOR URL_EXTERNAL-INPUT
	$("#"+id+"Url_EXTERNAL",c).unbind("keyup").bind("keyup", function(){
		_updateFWHiddenLinkOption("EXTERNAL", id);
	});

	// BIND KEYUP-UPDATE FOR URL_EMAIL-INPUT
	$("#"+id+"Url_EMAIL",c).unbind("keyup").bind("keyup", function(){
		_updateFWHiddenLinkOption("EMAIL", id);
	});

	// UPDATE HIDDENFIELDS
	_updateFWHiddenLinkOption(handle,id)

	// HIDE ALL DIVS
	if(handle == "NONE"){
		$("#"+id+"_option_container > div",c).hide();
	
	// SHOW THE LINK SELECTOR BY HANDLE
	}else{
		$("#"+id+"_option_container > div",c).show();
		$("#"+id+"_option_container > div.SET_cssLinkOption",c).hide();
		$("#"+id+"_"+handle,c).show();

		// ENABLE AJAXUPLOAD FOR DOCS
		if(handle == "DOC"){
			setTimeout(function(){
				if($("#"+id+"Upload_DOC").attr("isEnabled") != "true"){
					$("#"+id+"Upload_DOC").ajaxUpload("enable").attr("isEnabled", "true")
				}
			},20);
		}
	}

	var scrollTarget = $('#'+id+'_LinkSelector').closest(".SET_cssAdminDialogContent");
	if(!scrollTarget.length < 1)	scrollTarget.scrollTop(scrollTarget[0].scrollHeight);
}

/**
 *
 * VID FÄRDIG UPPLADDNING AV DOKUMENT
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _uploadFWDialogDocComplete(name,data){
	var imageFilename = String(data.filename);
	var imageId = String(data.id);
	var dialogId = String(data.dialogid);

	// UPPDATERAR DYNSELEN MED DET NYA VÄRDET
	_ajaxFWGet("CMS_UPDATE_DIALOG_DOC_DYNSEL",imageId,"mod=CMS&dialogId="+dialogId,"GET_MARKUP",function(req){
		$("#"+dialogId+"_DOC___select").remove();
		$("#"+dialogId+"_DOC___expander").remove();
		$("#"+dialogId+"_DOC .SET_cssFormContainer12.SET_cssFormContainerUpload").html(req.responseText);
		$("#SET_blockcontent_"+dialogId+"_url").val("/?fid="+imageId);
	},"","");
}

/**
 *
 * UPPDATERAR HIDDENFÄLT FÖR LÄNKALTERNATIV
 * ------------------------------------------------
 * @param handle - Typ av länkalternativ
 *		- NONE
 *		- INTERNAL
 *		- EXTERNAL
 *		- EMAIL
 *		- DOC
 * @param id - Huvud-idet för hela länkrutan.
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _updateFWHiddenLinkOption(handle,id){
	switch(handle){
		// RESET HIDDENFIELDS
		case "NONE":
			$("#SET_blockcontent_"+id+"_url").val('');
			$("#SET_blockcontent_"+id+"_target").val('');
			break;
		
		// ADD /?pid= TO URL AND SET URL AND TARGET TO HIDDENFIELDS
		case "INTERNAL":
			var target = $("#"+id+"Target_INTERNAL").get(0).checked;
			var url = $("#"+id+"Url_INTERNAL").val();
			
			if (url){
				url = "/?pid="+url;
			}else{
				url = "/"
			}
				
	
			if(target==true) target = "_blank"
			else target = ""

			$("#SET_blockcontent_"+id+"_target").val(target)
			$("#SET_blockcontent_"+id+"_url").val(url);
			break;

		// SET URL AND TARGET TO HIDDENFIELDS
		case "EXTERNAL":
			var target = $("#"+id+"Target_EXTERNAL").get(0).checked;
			var url = $("#"+id+"Url_EXTERNAL").val();

			if(target==true) target = "_blank"
			else target = ""

			$("#SET_blockcontent_"+id+"_target").val(target)
			$("#SET_blockcontent_"+id+"_url").val(url);
			break;

		// ADD mailto: TO URL AND SET TO HIDDENFIELD
		case "EMAIL":
			var url = $("#"+id+"Url_EMAIL").val();
				url = url.replace(/mailto:/gi, "")
				url = "mailto:"+url;

			$("#SET_blockcontent_"+id+"_target").val('');
			$("#SET_blockcontent_"+id+"_url").val(url);
			break;

		// ADD /?fid= TO URL AND SET TO HIDDENFIELD
		case "DOC":
			var url = $("#"+id+"Url_DOC").val();
				url = "/?fid="+url;

			$("#SET_blockcontent_"+id+"_target").val('');
			$("#SET_blockcontent_"+id+"_url").val(url);
			break;
	}
	$("#SET_blockcontent_"+id+"_url").trigger("change");

}

/**
 *
 * ÖPPNA BILDDIALOG
 * ------------------------------------------------
 * Öppnar en bilddialog för att välja bilder till
 * mediaväljaren.
 * ------------------------------------------------
 * @param e - Event
 * @param id - Huvud-idet för hela mediaväljaren.
 * @param currpic - Nuvarande valda bild
 * @param flash - Ska flash visas? (true/false)
 * @param pagenum - Vilken sida som ska visas
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _openFWImageDialog(e,id,currpic,flash,pagenum,strSearch,dia){
	var firstTime = false;

	if(!pagenum && !strSearch) firstTime = true;
	
	if(firstTime){
		var k=$("<div class='CMS_cssImageDialog SET_cssLoading'></div>");
		e = _initFWieEvent(e);
		var posAlign = "";
		if(window.fw_popup && window.fw_popup.trigger==e.target){
			_stopFWEvents(e,function(){_hideFWPopupNoDel()});
		}else{

			if(!dia) dia = $("#"+id+"_image_picker").parents("div.ui-dialog:first");

			var pos = {x:0,y:0};
			pos.x = parseInt(dia.css("left"),10);
			var t = (dia.outerWidth()-parseInt(k.css("width"),10))/2;
			if(!isNaN(t)) pos.x+=t;
			pos.y = parseInt(dia.css("top"),10)+120;

			var mpoint = (posAlign?{x:0,y:0}:_getFWMouseCoordinates(e));
			_showFWPopup(e,k.get(0),function(popup){
				$(popup).draggable({opacity:0.6,cancel:"a,div.CMS_cssBody",handle: "h3"});	
			},null,pos.x,pos.y,"CMS_cssImageDialog ",true,posAlign,0,!(posAlign),0);
		}
	}else{
		$("#"+id+"_paging_images").addClass("SET_cssLoading").html('');
	}

	_ajaxFWGet("FW_GET_IMAGEDIALOG",id,"mod=CMS&fw_showFlash="+flash+"&fw_pagenum="+pagenum+"&fw_search="+strSearch,"GET_MARKUP",function(req){
		if(firstTime) $("#fw_popup").removeClass("SET_cssLoading").html(req.responseText)
		else $("#"+id+"_paging_images").removeClass("SET_cssLoading").html(req.responseText)
	},"","");
}

/**
 *
 * UPPDATERA PREVIEWBILD I MEDIAVÄLJAREN
 * ------------------------------------------------
 * Uppdaterar previewbild och sätter nya värden
 * till hiddenfälten.
 * ------------------------------------------------
 * @param id - Huvud-idet för hela mediaväljaren.
 * @param fileid - Filens id
 * @param filename - Filens namn
 * @param filetype - Filens typ
 * @param isFirstTime - Ifall det är första gången
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _updateFWPreviewImage(id,fileid,filename,filetype,isFirstTime){
	if(!isFirstTime)_hideFWPopup(null,true,0);
	if(!filename){
		filename="";
		$("#"+id+"_image_picker").addClass("SET_cssNoPic");
		$("#"+id+"_image_preview").attr("src","/mind_content/media/"+filename).parent().hide();
		$("#"+id+"_image_preview_name").html(filename).hide().next("a:first").hide();;
		$("#SET_blockcontent_"+id+"_title").parent().hide();
		$("#"+id+"_link_LinkSelector").hide();
		$("#SET_blockcontent_"+id+"_title").val("");

	}else{
		$("#"+id+"_image_picker").removeClass("SET_cssNoPic");
		$("#"+id+"_image_preview").attr("src","/mind_content/media/"+filename).parent().show();
		$("#"+id+"_image_preview_name").html(filename).show().next("a:first").show();
		$("#SET_blockcontent_"+id+"_title").parent().show();
		$("#"+id+"_link_LinkSelector").show();
	}
	$("#"+id+"_flash_settings").hide();
	
	if(filetype == "FLASH"){
		$("#"+id+"_flash_settings").show();
		$("#"+id+"_image_title").hide();
		$("#"+id+"_image_preview").attr("src","/mind_modules/cms/gui/default/default/img/media_flash.png").parent().show();
	}
	
	$("#SET_blockcontent_"+id+"_filename").val(filename);
	$("#SET_blockcontent_"+id+"_type").val(filetype);
	$("#SET_blockcontent_"+id+"_id").val(fileid);

	if(!isFirstTime)$("#SET_blockcontent_"+id+"_filename").trigger("change");
}

/**
 *
 * VID FÄRDIG UPPLADDNING AV BILD
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _uploadFWImagePickerComplete(name,data){
	var imageFilename = String(data.filename);
	var imageId = String(data.id);
	var filetype = String(data.filetype);
	var mediapickerId = String(data.mediapickerid);

	_updateFWPreviewImage(mediapickerId,imageId,imageFilename,filetype)
}

/**
 *
 * OM BILDEN INTE HITTAS
 * ------------------------------------------------
 * Om bilden inte hittas så byts bilden ut och 
 * onclick-eventet töms.
 * ------------------------------------------------
 * @param obj - Objeket som du klickat på ($(this))
 * ------------------------------------------------
 * TODO: 
 *
 **/
function _CMSRemoveImageDialogImage(obj){
	obj.attr("src", "/mind_modules/cms/gui/default/default/img/cms_btn_stop.gif")
		.parent()
			.removeAttr("onclick")
			.css("cursor", "default");
}

/*function _stripFWTags(strMod){
    if(arguments.length<3) strMod=strMod.replace(/<\/?(?!\!)[^>]*>/gi, '');
    else{
        var IsAllowed=arguments[1];
        var Specified=eval("["+arguments[2]+"]");
        if(IsAllowed){
            var strRegExp='</?(?!(' + Specified.join('|') + '))\b[^>]*>';
            strMod=strMod.replace(new RegExp(strRegExp, 'gi'), '');
        }else{
            var strRegExp='</?(' + Specified.join('|') + ')\b[^>]*>';
            strMod=strMod.replace(new RegExp(strRegExp, 'gi'), '');
        }
    }
    return _stripFWTags;
}*/
function _stripFWTags(){
	for (i=0; i < arguments.length; i++)
	arguments[i].value=arguments[i].value.replace(/(<([^>]+)>)/gi, "")
}

