

/*===================================================================   Scripts.js   ===================================================================*/

// Impersonation alternatives
var impersonationTimeOut = 0;
var divImpersonation = 'divImpersonation';

// Preload menu background
var subMenuBackgroundImage = new Image(1, 1);
subMenuBackgroundImage.src = "VirtualResources/Images.MasterPage.bg-subnav.png"; 

function showImpersonationAlternatives() {
    clearTimeout(impersonationTimeOut);
    document.getElementById(divImpersonation).style.display = 'block';
}

function hideImpersonationAlternatives() {
    impersonationTimeOut = setTimeout("document.getElementById(" + divImpersonation + ").style.display = 'none';", 500);
}

// Login functions

function showLoginSelections(element)
{
    doc = document.getElementById(element);
    doc.style.display = doc.style.display == 'block' ? 'none' : 'block';
};
	
function hideLoginSelections(elementname){
	document.getElementById(elementname).style.display = 'none';
	return false;
};

var activeMenu = null;
var activeElement = null;

// Preload the sub menu background image
var preloadSubMenuBackgroundImage = new Image();
preloadSubMenuBackgroundImage.src = "VirtualResources/Images.MasterPage.submenu_shadow.png";

function showThis(element){
	element.style.display = 'inline';	
	var tagElement = element.tagElement;
	tagElement.className = tagElement.originalClass + " " + tagElement.originalClass + "_over";	
}


function hideThis(element){	
	element.style.display = 'none';	
	var tagElement = element.tagElement;
	tagElement.className = tagElement.originalClass;
}

function showSubMenu(eventElement){
	// Get the sub_ div
	var div = document.getElementById('sub_' + eventElement.id);	
	div.tagElement = eventElement;
	if(div != activeMenu && activeMenu != undefined){
		// Hide active
		hideSubMenu();
	}
	
	// If this menu is already visible: hide and return.
	if (div.style.display == 'inline') {
	    hideSubMenu();
	    return;
    }

	// Reset class
	if(activeElement != null) activeElement.className = activeElement.originalClass;
	eventElement.originalClass = eventElement.className;
	
	// We don't want under underlined on click!
	//eventElement.style.background = 'url(VirtualResources/Images.MasterPage.bg-marked-topitem-right.gif) top right no-repeat';
	//eventElement.parentNode.style.background = 'url(VirtualResources/Images.MasterPage.bg-marked-topitem-left.gif) top left no-repeat';
	//eventElement.style.color = '#000000';
	
	// Blur to hide selection box.
	eventElement.blur();

	// Make this one active and show it.
	activeMenu = div;
	activeElement = eventElement;
	div.style.display = 'inline';
}

function hideSubMenu() {
	// Don't bother if not showing
	if(activeMenu == undefined) return;
			
	// Hide and remove active reference
	activeMenu.style.display = 'none';
	activeMenu = undefined;
	
	activeElement.className = activeElement.originalClass;
    
    for (var i = 0; i<100; i++) {
        var a = document.getElementById('menu_' + i);
        try {
            a.style.background = '';
            a.parentNode.style.background = '';
            a.style.color = '';
        } catch(err) {
            break;
        }
    }
}

/*================================================================   CheckPassword.js   ================================================================*/

var numberChars = "0123456789";
var upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ";
var lowerChars = "abcdefghijklmnopqrstuvwxyzåäö";
var specialUpperChars = "ËÏÜÂÊÎÔÛÃÑÕÁÉÍÓÚÝÀÈÌÒÙÇÆ";
var specialLowerChars = "ëïüÿâêîôûãñõáéíóúýàèìòùçæ";
var otherChars = "`\´~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/? ¤§½£¨µ	"; // The second whitespace is a TAB character
var extendedOtherChars = "¼ªº¿«»ß÷°·²"; // Note: These extended ascii codes might vary a little depending on what character-set is used. However, they are NOT Unicode characters.
var specialChars = specialUpperChars + specialLowerChars + otherChars + extendedOtherChars;
var colors = new Array("#FF0000", "#FF0000","#FEA0A5","#FFFF00","#A0FEA5","#00FF00");
var imgBullerRedSrc = 'VirtualResources/Images.Icons.Bullets.red.gif';
var imgBullerGreenSrc = 'VirtualResources/Images.Icons.Bullets.green.gif';
var currentPasswordOK = false;

function UpdateStrengthInfo(password) {
    var passLength = password.length;
    var hasEnoughLength = passLength >= 8;
    var hasNumber = false;
    var hasLower = false;
    var hasUpper = false;
    var hasSpecial = false;

    // Check password
    for (var i=0; i<passLength; i++) {
        var thisChar = password.charAt(i);
        if (!hasNumber) hasNumber = numberChars.indexOf(thisChar) > -1;
        if (!hasLower) hasLower = lowerChars.indexOf(thisChar) > -1;
        if (!hasUpper) hasUpper = upperChars.indexOf(thisChar) > -1;
        if (!hasSpecial) hasSpecial = specialChars.indexOf(thisChar) > -1;
    }

    // Set images
    document.getElementById('imgPasswordStrengthNumber').setAttribute('src', (hasNumber ? imgBullerGreenSrc : imgBullerRedSrc));
    document.getElementById('imgPasswordStrengthLower').setAttribute('src', (hasLower ? imgBullerGreenSrc : imgBullerRedSrc));
    document.getElementById('imgPasswordStrengthUpper').setAttribute('src', (hasUpper ? imgBullerGreenSrc : imgBullerRedSrc));
    document.getElementById('imgPasswordStrengthSpecial').setAttribute('src', (hasSpecial ? imgBullerGreenSrc : imgBullerRedSrc));
    document.getElementById('imgPasswordStrengthLength').setAttribute('src', (hasEnoughLength ? imgBullerGreenSrc : imgBullerRedSrc));
    
    // Compute the score
    var score = 
        (hasNumber  ? 1 : 0) +
        (hasLower   ? 1 : 0) +
        (hasUpper   ? 1 : 0) +
        (hasSpecial ? 1 : 0);
    
    // Update the global variable
    currentPasswordOK = hasEnoughLength && score >= 2;
}

function CheckNewPassword(language) {
    if (!currentPasswordOK) {
        var title = language == 1
            ? 'Ditt lösenord är för svagt'
            : 'Your password is to weak';
            
        var mess = language == 1
            ? 'Vänligan välj ett starkare lösenord.<br /><br />Titta på punkterna i listan till höger om textfälten. Där kan du se om ditt lösenord uppfyller kraven för att klassas som starkt.'
            : 'Please choose a stronger password..<br /><br />Look at the points in the list to the right of the text fields. There you can see if your password meets the security requirements.';
    
        AlertPopupMessage(title, mess, 400);
    }
    return currentPasswordOK;
}

/*==================================================================   AddEvent.js   ===================================================================*/

function addEvent(elm, evType, fn, useCapture) {
    // addEvent cross-browser event handling for IE5+, NS6 and Mozilla
    // By Scott Andrew
	if (elm.addEventListener){
		elm.addEventListener(evType, fn, useCapture);
		return true;
	} else if (elm.attachEvent){
		var r = elm.attachEvent("on"+evType, fn);
		return r;
	} else {
		alert("Handler could not be removed");
	}
}

function copyToClipboard(s) {
    if (window.clipboardData && clipboardData.setData) {
        clipboardData.setData("Text", s);
    }
    else {
        // You have to sign the code to enable this or allow the action in about:config by changing user_pref("signed.applets.codebase_principal_support", true);
        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

        var clip = Components.classes['@mozilla.org/widget/clipboard;[[[[1]]]]'].createInstance(Components.interfaces.nsIClipboard);
        if (!clip) return;

        // create a transferable
        var trans = Components.classes['@mozilla.org/widget/transferable;[[[[1]]]]'].createInstance(Components.interfaces.nsITransferable);
        if (!trans) return;

        // specify the data we wish to handle. Plaintext in this case.
        trans.addDataFlavor('text/unicode');

        // To get the data from the transferable we need two new objects
        var str = new Object();
        var len = new Object();

        var str = Components.classes["@mozilla.org/supports-string;[[[[1]]]]"].createInstance(Components.interfaces.nsISupportsString);

        var copytext = meintext;

        str.data = copytext;

        trans.setTransferData("text/unicode", str, copytext.length * [[[[2]]]]);

        var clipid = Components.interfaces.nsIClipboard;

        if (!clip) return false;

        clip.setData(trans, null, clipid.kGlobalClipboard);
    }
}


/*===================================================================   Opacity.js   ===================================================================*/

/**
 * From: http://brainerror.net/scripts/javascript/blendtrans/
 */
function fadeOpacity(id, opacStart, opacEnd, millisec) {
    // speed for each frame 
    var speed = Math.round(millisec / 100); 
    var timer = 0; 

    // determine the direction for the blending, if start and end are the same nothing happens 
    if(opacStart > opacEnd) { 
        for(i = opacStart; i >= opacEnd; i--) { 
            setTimeout("changeOpac(" + i + ",'" + id + "')",(timer * speed)); 
            timer++; 
        } 
    } else if(opacStart < opacEnd) { 
        for(i = opacStart; i <= opacEnd; i++) 
            { 
            setTimeout("changeOpac(" + i + ",'" + id + "')",(timer * speed)); 
            timer++; 
        } 
    }
}

/**
 * From: http://brainerror.net/scripts/javascript/blendtrans/
 */
function changeOpac(opacity, id) { 
    var element = document.getElementById(id);
    element.style.opacity = (opacity / 100); 
    element.style.MozOpacity = (opacity / 100); 
    element.style.KhtmlOpacity = (opacity / 100); 
    element.style.filter = "alpha(opacity=" + opacity + ")"; 
}

/**
 * From: http://brainerror.net/scripts/javascript/blendtrans/
 */
function shiftOpacity(id, millisec) {
    if(document.getElementById(id).style.opacity == 0) { 
        fadeOpacity(id, 0, 100, millisec); 
    } else { 
        fadeOpacity(id, 100, 0, millisec); 
    } 
}

/*==================================================================   BlackDiv.js   ===================================================================*/

var BlackDiv_BlackDivId = 'BlackDiv_BlackDivId';
var BlackDiv_ClassName = 'DivBlack';
var BlackDiv_showDiv = false;
var BlackDiv_divBlackExists = false;
var BlackDiv_loadingAnimationURL = 'VirtualResources/Images.Animations.Loading.gif';
var BlackDiv_PreventOnSubmitAnimationOnce = false;

function ShowBlackDiv(clickfunction) {
    var blackDivExists = document.getElementById(BlackDiv_BlackDivId);
    if (blackDivExists == null) {
        var divBlack = document.createElement('div');

        divBlack.className = BlackDiv_ClassName;
        divBlack.setAttribute('id',BlackDiv_BlackDivId);

        if (typeof (clickfunction) != 'undefined') {
            try {
                divBlack.onclick = clickfunction;
            } catch (Error) { }
        }
        
        GetFirstDiv().appendChild(divBlack);
        BlackDiv_divBlackExists = true;

        divBlack.onscroll = function() { return false; }
        
        // Gör genomskinligt
        changeOpac(50, BlackDiv_BlackDivId);
    }
}

function ShowLoadingDiv(forceShow) {
    if (BlackDiv_showDiv || forceShow == true) {
        BlackDiv_showDiv = false;
        ShowBlackDiv();

        var divBlack = document.getElementById(BlackDiv_BlackDivId);
        divBlack.style.backgroundImage = 'url(\'' + BlackDiv_loadingAnimationURL + '\')';
        divBlack.style.backgroundRepeat = 'no-repeat';
        divBlack.style.backgroundPosition = '50% 50%';
        divBlack.style.cursor = 'progress';
        divBlack.style.zIndex = 1000000;
        
        if (forceShow == true) {
            divBlack.onclick = function() { return false; }
        }
    }
}

function HideBlackDiv() {
    BlackDiv_showDiv = false;
    BlackDiv_divBlackExists = document.getElementById(BlackDiv_BlackDivId) != null
    while (BlackDiv_divBlackExists) {
        var blackDiv = document.getElementById(BlackDiv_BlackDivId);
        blackDiv.parentNode.removeChild(blackDiv);
        BlackDiv_divBlackExists = document.getElementById(BlackDiv_BlackDivId) != null;
    }
}

function GetFirstDiv() {
    var divs = document.getElementsByTagName('div');
    if (divs.length == 0) { throw('There must be at least one div in the document body.'); }
    return divs[0];
}


/*==============================================================   AlertPopupMessage.js   ==============================================================*/

var AlertPopupMessage_NrOfExistingPopups = 0;
var AlertPopupMessage_ClassName = 'FloatingPanel';

function AlertPopupMessage(title, message, width, isAWarning) {
    ShowAlertPopupDiv(title, message, width, isAWarning);
    return false;
}

function HideAlertPopupDiv(id) {
    HideFloatingPanel(id);
    GetFirstDiv().removeChild(document.getElementById(id));
    return false;
}

function ShowAlertPopupDiv(title, message, width, isAWarning) {
    if (typeof width == 'undefined' || width == '') width = 400;
    if (typeof title == 'undefined' || title == null) title = '';
    if (typeof isAWarning == 'undefined' || isAWarning == null) isAWarning = false;

    title = title.replace("\'", "\\'");
    message = message.replace("\'", "\\'");

    var id = 'AlertPopupMessage' + AlertPopupMessage_NrOfExistingPopups;
    var divAlertPopup = document.createElement('div');
    var html = "<div class=\"TopBar\">" +
                "   <div class=\"CloseButtonContainer\">" +
                "      <span class=\"btn_small\">" +
                "         <a onclick=\"HideFloatingPanel('" + id + "'); return false;\" href=\"#\">X</a>" +
                "      </span>" +
                "   </div>" +
                "   <span>" + title + "</span>" +
                "</div>" +
                "<div style=\"padding: 10px; background-color: #ffffff;\">" +
                "<img src=\"VirtualResources/Images/WebControls/FloatingPanelShadow.png\" class=\"DropShadow\">" +
                (isAWarning
                    ? "<img src=\"VirtualResources/Images.Icons.Warning.png\" style=\"float: right; margin: 5px;\" />" + 
                      message + "<br class=\"clear\" />"
                    : message)
                "</div>";

    divAlertPopup.setAttribute('id', id);
    divAlertPopup.innerHTML = html;
    divAlertPopup.className = AlertPopupMessage_ClassName;
    divAlertPopup.style.display = 'block';
    divAlertPopup.style.width = width + 'px';
    divAlertPopup.style.marginLeft = Math.round(-width/2) + 'px';
    GetFirstDiv().appendChild(divAlertPopup);
    
    AlertPopupMessage_NrOfExistingPopups++;

    ShowFloatingPanel(id, false, true, false);
}


/*===============================================================   RequestHandler.js   ================================================================*/

var RequestHandler_timeBeforeShowingProgressBar = 500;
var RequestHandler_OnEndRequest = new Object();

function AjaxInUse() {
    var ajaxInUse =  
        typeof(Sys) != 'undefined' &&
        typeof(Sys.WebForms) != 'undefined' &&
        typeof(Sys.WebForms.PageRequestManager) != 'undefined' &&
        typeof(Sys.WebForms.PageRequestManager.getInstance()) != 'undefined';
    return ajaxInUse;
}

function SetRequestHandlers(delay) {
    if (AjaxInUse()) {
        if (IsAnInteger(delay)) {
            RequestHandler_timeBeforeShowingProgressBar = delay;
        }

        // Preload loading animation
        image1 = new Image();
        image1.src = BlackDiv_loadingAnimationURL;

        Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
    } else {
        // Add sortables_init function to the window.load event.
        addEvent(window, "unload", sortables_init);
    }
}

function BeginRequestHandler(sender, args) {
    if (!BlackDiv_showDiv && !BlackDiv_PreventOnSubmitAnimationOnce) { // Vi kör endast denna om BlackDiv_showDiv är false. Detta förhindrar parallella körningar.
        BlackDiv_showDiv = true;
        setTimeout('ShowLoadingDiv()', RequestHandler_timeBeforeShowingProgressBar);
    }
    
    // if we have loaded the tinymce stuff we have to unload all the textboxes before
    // submitting the request. TinyMCE code genereates "access denied" if the DOM is altered
    // for an editor.
    if(typeof(tinymce) != 'undefined') {
        if(typeof(tinymce.EditorManager) != 'undefined') {
            if(typeof(tinymce.EditorManager.editors) != 'undefined') {
                for(var edId in tinymce.EditorManager.editors) {
                    tinyMCE.execCommand('mceRemoveControl',false,edId);
                }
            }
        }
    }
}

function EndRequestHandler(sender, args) {
    // run all the registered scripts
    for(var v in RequestHandler_OnEndRequest) {
        eval(RequestHandler_OnEndRequest[v]);
        RequestHandler_OnEndRequest[v] = null;
    }

    HideBlackDiv();
    if (GetVisibleFloatingPanels().length > 0) {
        ShowBlackDiv(true);
    }

    BlackDiv_PreventOnSubmitAnimationOnce = false;
    sortables_init();
}


/*============================================================   OpenNewBrowserWindow.js   =============================================================*/

// Standardscript för att öppna nya browserfönster.
function openNewBrowserWindow(url, title, width, height) {
    return openNewBrowserWindow(url, title, width, height, 50, 50, 1);
}

function openNewBrowserWindow(url, title, width, height, fromLeft, fromTop) {
    return openNewBrowserWindow(url, title, width, height, fromLeft, fromTop, 1);
}

function openNewBrowserWindow(url, title, width, height, fromLeft, fromTop, scrolling) {
    var w = window.open(url,title,'scrollbars=' + scrolling + ',resizable=1,toolbar=0,location=0,directories=0,status=0,menubar=0,width=' + width + ',height=' + height);
    w.focus();
    w.moveTo(fromLeft, fromTop);
    return false;
}


/*================================================================   SafeClassName.js   ================================================================*/

function SafeClassNameAdd(element, classNameToAdd) {
    if (typeof element.className == 'undefined') {
        element.className = "";
    }
    if (element.className.indexOf(classNameToAdd) == -1) {
        element.className += (element.className.length > 0 ? ' ' : '') + classNameToAdd;
    }
}

function SafeClassNameRemove(element, classNameToRemove) {
    if (typeof element.className == 'undefined') {
        element.className = "";
    }
    if (element.className.indexOf(classNameToRemove) > -1) {
        element.className = element.className.replace(classNameToRemove, '');
        element.className = element.className.replace('  ', ' ');
    }
}


/*==========================================================   MakeElementFollowPointer.js   ===========================================================*/

/**
 * Follow Mouse Script
 * (c) Söderberg & Partners
 * Joakim Jamte
 */
var elementId; // The ID of the element that follows the mouse
var offX = 16; // X offset from mouse position
var offY = 16; // Y offset from mouse position

function mouseX(evt) {
	if (!evt)
		evt = window.event; 
	if (evt.pageX)
		return evt.pageX; 
	else if (evt.clientX)
		return evt.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft);
	else
		return 0;
}

function mouseY(evt) {
	if (!evt)
		evt = window.event;
	if (evt.pageY)
		return evt.pageY;
	else if (evt.clientY)
		return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
	else
		return 0;
}

function follow(evt) {
	if (document.getElementById) {
		var objStyle = document.getElementById(elementId).style;
		objStyle.left = (parseInt(mouseX(evt))+offX) + 'px';
		objStyle.top = (parseInt(mouseY(evt))+offY) + 'px';
	}
}

function MakeElementFollowPointer(theElementId) {
	// Save in global variable
	elementId = theElementId;
	
	// Get object, set absolute position and high z-index.
	var o = document.getElementById(elementId);
	o.style.position = 'absolute';
	o.zIndex = 999;
	
	// Set the onmousemove function.
	document.onmousemove = follow;
}


/*===============================================================   NumberFunctions.js   ===============================================================*/

function IsAnInteger(nr) {
    return (new RegExp(/^[+-]?\d*[\.\,]?\d*$/)).test(nr);
}

/*===================================================================   Cookies.js   ===================================================================*/

function setCookie(name, value, expire) {
	document.cookie = name + "=" + escape(value)   
	+ "; expires=" + expire.toGMTString();
}

function getCookie(name) {
	if(!document.cookie) return false;
	var cookie, cookies = document.cookie.split(';');
	for(var i=0; i<cookies.length; i++) {
		cookie = cookies[i].split('=');
		if(cookie[0] == name) { 
			return unescape(cookie[1]);
		}
	}	return false;
}

/*==================================================================   SendMail.js   ===================================================================*/

function SendMail(m, d, td) {
    document.location = 'mailto:' + m + '@' + d + '.' + td;
    return false;
}

/*===================================================================   domdrag.js   ===================================================================*/

/**************************************************
 * dom-drag.js
 * 09.25.2001
 * www.youngpup.net
 * Script featured on Dynamic Drive (http://www.dynamicdrive.com) 12.08.2005
 **************************************************
 * 10.28.2001 - fixed minor bug where events
 * sometimes fired off the handle, not the root.
 **************************************************/

var Drag = {

	obj : null,

	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
	{
		o.onmousedown	= Drag.start;

		o.hmode			= bSwapHorzRef ? false : true ;
		o.vmode			= bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},

	start : function(e)
	{
		// Tillägg av Joakim, specialanpassat för Söderberg & Partners divPopup:
		try {
			var divIFrame = document.getElementById(currentIFrameId);
			if (typeof divIFrame != "undefined") divIFrame.style.visibility = "hidden";
		} catch(err) {}
		// Slut på tillägget.
	
		var o = Drag.obj = this;
		e = Drag.fixE(e);
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		o.root.onDragStart(x, y);

		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;

		if (o.hmode) {
			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}

		if (o.vmode) {
			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}

		document.onmousemove	= Drag.drag;
		document.onmouseup		= Drag.end;

		return false;
	},

	drag : function(e)
	{
		e = Drag.fixE(e);
		var o = Drag.obj;

		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;

		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

		if (o.xMapper)		nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)

		Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
		Drag.obj.lastMouseX	= ex;
		Drag.obj.lastMouseY	= ey;

		Drag.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function()
	{
		// Tillägg av Joakim, specialanpassat för Söderberg & Partners divPopup:
		try {
			var divIFrame = document.getElementById(currentIFrameId);
			if (typeof divIFrame != "undefined") divIFrame.style.visibility = "visible";
		} catch(err) {}
		// Slut på tillägget.
		
		document.onmousemove = null;
		document.onmouseup   = null;
		Drag.obj.root.onDragEnd(	parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
									parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
		Drag.obj = null;
	},

	fixE : function(e)
	{
		if (typeof e == 'undefined') e = window.event;
		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
};

/*=================================================================   BalloonTip.js   ==================================================================*/

/*
 * Popup Help
 * (c) Söderberg & Partners, 2006
 * Joakim Jamte
 */

// Det element som just nu har focus.
var PopupHelpTargetElement;
// Vi döper nya element till PopupHelpDefaultDivPopupIdPrefix + det klickade elementets ID.
var PopupHelpDefaultDivPopupIdPrefix = 'divPopupHelp';


/*
 * Användning:
 * <element
 *     id="theId"
 *     onfocus="JavaScript:showHelp(event, 'Här skriver man den text man vill att användaren ska se.');"
 *     onblur="JavaScript:hideHelp(event);" />
 * id - viktigt! Måste sättas för att funktionen ska fungera.
 * texten - viktig! Annars ser ju användaren inget...
 */
 var popElementIsHiding = false;
 
function showHelp(e, text) {
	try {
	    // Om avfryande element saknar id: skapa ett slumpat.
	    var t = GetFiringElement(e);
	    if (t.id == null || t.id.length == 0) {
	        t.id = Math.random()*100000000;
	        t.id = t.id.toString().replace('.', '');
	    }
	
		// Sätt PopupHelpTargetElement.	
		setPopupHelpTargetElement(e);

		// Lägger första gången till en div med själva popupen efter PopupHelpTargetElement.
		insertPopupDivAfterPopupHelpTargetElement(text);
	} catch(err) {}
}

function hideHelp(e) {
	try {

	    document.getElementById(PopupHelpDefaultDivPopupIdPrefix + PopupHelpTargetElement.id).style.visibility = 'hidden';
	} catch(err) {}
}

function setPopupHelpTargetElement(e) {
	try {
		if (typeof e == 'string') {
			PopupHelpTargetElement = document.getElementById(e);
		} else {
			if (!e) var e = window.event;
			if (e.target) PopupHelpTargetElement = e.target;
			else if (e.srcElement) PopupHelpTargetElement = e.srcElement;
			if (PopupHelpTargetElement.nodeType == 3) PopupHelpTargetElement = PopupHelpTargetElement.parentNode; // Kringgå Safari-bugg
		}
	} catch(err) {}
}

function insertPopupDivAfterPopupHelpTargetElement(text) {
	try {
		// Dölj fönstret
		if (typeof PopupHelpTargetElement != 'undefined' && text.length > 0) {
			if (document.getElementById(PopupHelpDefaultDivPopupIdPrefix + PopupHelpTargetElement.id) == null) { // Första anropet är den inte initierad.
				// Skapa en ny div.
				theDiv = document.createElement('div');

				// Om placeringen ska göras relativt det klickade elementet, måste diven ha position=absolute.
				theDiv.style.position = 'absolute';

				// För att diven ska lägga sig efter det klickade elementet, måste display vara inline.
				theDiv.style.display = 'inline';

				// Sätt dess inre HTML.
				/*theDiv.innerHTML =  "<div " +
										"id=\"" + PopupHelpDefaultDivPopupIdPrefix + PopupHelpTargetElement.id + "\" " + 
										"onmouseover=\"this.style.visibility = 'hidden';\" " + 
										"class=\"BalloonTextTheDiv\">\n" + 
											"<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">" + 
												"<tr>" + 
													"<td class=\"BalloonTextTD1\">&nbsp;" + 
													"</td>" + 
												"<td class=\"SmallText BalloonTextTD2\">\n" + 
													text +
												"</td>" + 
											"</tr>" + 
										"</table>" + 
									"</div>\n";*/
									
				// Sätt dess inre HTML.
				theDiv.innerHTML =  "<div " +
										"id=\"" + PopupHelpDefaultDivPopupIdPrefix + PopupHelpTargetElement.id + "\" " + 
										"onmouseover=\"this.style.visibility = 'hidden';\" " + 
										"style=\"" + 
												"position: absolute;" + 
												"left: 5px; " + 
												"top: 5px; " + 
												"width: 250px;" + 
												"z-index: 1000;" + 
												"text-align: left; " + 
												"white-space: normal; " + 
											"\">\n" + 
											"<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">" + 
												"<tr>" + 
													"<td style=\"" + 
														"background-image: url('VirtualResources/Images.Arrows.BalloonText.PopupHelpTargetPointer.png');" + 
														"background-repeat: no-repeat;" + 
														"background-color: transparent;" + 
														"width: 22px;" + 
														"border-top: 1px solid #999999; " + 
														"border-bottom: 0px; " + 
														"border-left: 0px; " + 
														"border-right: 0px; " + 
														"text-align: left; " + 
														"padding: 0px; " + 
														"white-space: normal; " + 
													"\">&nbsp;" + 
													"</td>" + 
												"<td class=\"SmallText\" style=\"" + 
													"background-color: rgb(249,249,249); " + 
													"border-top: 1px solid #999999; " + 
													"border-bottom: 1px solid #999999; " + 
													"border-right: 1px solid #999999; " + 
													"border-left: 0px; " + 
													"color: #000000; " + 
													"padding: 5px; " + 
													"text-align: left; " + 
													"white-space: normal; " + 
													"font-weight: normal;" + 
													"\">\n" + 
													text +
												"</td>" + 
											"</tr>" + 
										"</table>" + 
									"</div>\n";
									
				// Sätt in diven efter PopupHelpTargetElement.
				PopupHelpTargetElement.parentNode.insertBefore(theDiv, PopupHelpTargetElement.nextSibling);
			} else {
				document.getElementById(PopupHelpDefaultDivPopupIdPrefix + PopupHelpTargetElement.id).style.visibility = 'visible';
			}
		}
	} catch(err) {}
}

/*==================================================================   CheckBox.js   ===================================================================*/

/*
 * Checkbox
 * (c) Söderberg & Partners, 2009
 */

function CheckBox_ToggleGroup(group, checked, toggleRowMarking) {
    var cbxs = document.getElementsByTagName('input');
    for(var i = 0; i < cbxs.length; i++) {
        if (cbxs[i]['Group' + group] == 'true') {
            cbxs[i].checked = checked;
            if (toggleRowMarking) {
                ToggleRowMarking(cbxs[i])
            }
        } 
    }
}


/*=================================================================   FileBrowser.js   =================================================================*/

var fileBrowserIEMessageShown = false;
function filterAccessRights(searchTextBox, tblName, rowClassName) {
    var isOldIE = navigator.appName.indexOf('Internet Explorer') > -1 && navigator.appVersion.indexOf('MSIE 8.0') == -1;
    if (isOldIE) {
        if (!fileBrowserIEMessageShown) {
            AlertPopupMessage(
                    'Din webbläsare stöder inte filtreringen',
                    'Denna filtreringsfunktion stöds inte av din webbläsare. Vänligen uppdatera till Internet Explorer 8 eller byt till Firefox.',
                    400,
                    true);
            fileBrowserIEMessageShown = true;
            searchTextBox.value = '';
            searchTextBox.disabled = true;
            searchTextBox.parentNode.style.display = 'none';
        }
        return;
    }

    var searchString = searchTextBox.value;
    var trs = document.getElementById(tblName).getElementsByTagName('tr');

    for (var i = 0; i < trs.length; i++) {
        var tr = trs[i];
        if (tr.className == rowClassName) {
            var text = tr.getElementsByTagName('td')[0].innerHTML.toLowerCase();
            var hits = 0;
            var words = searchString.split(' ');
            for (var j = 0; j < words.length; j++) {
                if (text.indexOf(words[j]) > -1) {
                    hits++;
                }
            }

            // Set to visible if match, hidden else.
            tr.style.display = hits == words.length ? 'table-row' : 'none';
        }
    }
}

/*================================================================   FloatingPanel.js   ================================================================*/

var FloatingPanel_Parents = new Object();

function ShowFloatingPanel(divId, clickBackgroundToHide, fadePage, moveToFirstDiv, useAjax) {
    if (useAjax) {
        RequestHandler_OnEndRequest[divId] = 'DoShowFloatingPanel(\'' + divId + '\',' + clickBackgroundToHide + ',' + fadePage + ',' + moveToFirstDiv + ')';
    } else {
        DoShowFloatingPanel(divId, clickBackgroundToHide, fadePage, moveToFirstDiv);
    }
}

function DoShowFloatingPanel(divId, clickBackgroundToHide, fadePage, moveToFirstDiv) {
    var visibleFloatingPanels = GetVisibleFloatingPanels();
    var element = document.getElementById(divId);
    element.style.display = 'block';
    element.style.marginTop = Math.round(-element.offsetHeight / 2) + 'px';
    element.style.zIndex = 11000 + (visibleFloatingPanels.length * 1000);

    FloatingPanel_Parents[divId] = element.parentNode;
    if (moveToFirstDiv) {
        element.parentNode.removeChild(element);
        GetFirstDiv().appendChild(element);
    }

    if (fadePage) {
        if (visibleFloatingPanels.length > 0) {
            ShowBlackDiv(
                function() {
                    return false;
                }
            );
        } else if (clickBackgroundToHide) {
            ShowBlackDiv(
                function() {
                    eval('HideFloatingPanel(\'' + divId + '\');');
                    return false;
                }
            );
        } else {
            ShowBlackDiv();
        }
    }

    // If the FloatingPanel is a FloatingIFrame, it has an iframe inside.
    // We then want to get the iframe and set the src to the value of the url property.
    // This is made to make the page in the iframe load only if the FloatingPanel is shown.
    LoadIframesInFloatingPanel(element);
}

function HideFloatingPanel(divId) {
    var element = document.getElementById(divId);

    // If the FloatingPanel is a FloatingIFrame, it has an iframe inside.
    // We then want to remove the src value.
    UnloadIframesInFloatingPanel(element);

    if (typeof (element) == 'undefined') {
        return;
    }
    element.style.display = 'none';
    if (FloatingPanel_Parents[divId] != element.parentNode) {
        try {
            GetFirstDiv().removeChild(element);
            FloatingPanel_Parents[divId].appendChild(element);
        } catch (Error) { }
    }

    if (GetVisibleFloatingPanels().length == 0) {
        HideBlackDiv();
    }
}

function LoadIframesInFloatingPanel(element) {
    LoadOrUnloadIframesInFloatingPanel(element, true);
}

function UnloadIframesInFloatingPanel(element) {
    LoadOrUnloadIframesInFloatingPanel(element, false);
}

function LoadOrUnloadIframesInFloatingPanel(element, load) {
    var iframes = element.getElementsByTagName('iframe');
    for (var i = 0; i < iframes.length; i++) {
        try { // Some kind of problem in IE...
            var iframe = iframes[i];
            var url = iframe.getAttribute('url');

            if (typeof url == 'string' && url.length > 0) {
                iframe.src = load ? url : '';
            }
        } catch (err) { }
    }
}

function GetFloatingPanels() {
    var divs = document.getElementsByTagName("div");
    var floatingPanels = new Array();
    for (var id in divs) {
        var div = divs[id];
        if (div && div.className == 'FloatingPanel') {
            floatingPanels[floatingPanels.length] = div;
        }
    }
    return floatingPanels;
}

function GetVisibleFloatingPanels() {
    var floatingPanels = GetFloatingPanels();
    var visibleFloatingPanels = new Array();
    for (var idx in floatingPanels) {
        if (floatingPanels[idx].style && floatingPanels[idx].style.display == 'block') {
            visibleFloatingPanels[visibleFloatingPanels.length] = floatingPanels[idx];
        }
    }
    return visibleFloatingPanels;
}

function HideVisibleFloatingPanels() {
    var floatingPanels = GetVisibleFloatingPanels();
    for (var idx in floatingPanels) {
        HideFloatingPanel(floatingPanels[idx].id);
    }
}


/*===============================================================   FloatingIFrame.js   ================================================================*/

// To be used by a page that is shown in an iframe to reload its parent with a postback.
function ReloadPage() {
	document.forms[0].submit();
}

// To be used by a page that is shown in an iframe to reload its parent without a postback.
function ReloadPageNoPostback() {
	document.location = document.location;
}


/*==================================================================   GridView.js   ===================================================================*/

/*
Table sorting and row repetion script by Joakim Jamte, Söderberg & Partners (http://www.soderbergpartners.se).
Based on a script by Joost de Valk (http://www.joostdevalk.nl/code/sortable-table/).
Joost de Valk based his script on a script by Stuart Langridge (http://www.kryogenix.org/code/browser/sorttable/).
Distributed under the MIT license (http://www.kryogenix.org/code/browser/licence.html).

Copyright (c) 1997-2007 Stuart Langridge, Joost de Valk, Joakim Jamte (Söderberg & Partners)
*/

/* Settings. *************************************************************************/
var ALTERNATE_ROW_COLORS = true;
var MAX_TABLE_SIZE = 500;
var LARGE_TABLE_LIMIT = 250;
var SET_CSS_IF_NOT_SET = true;
/* Constants. ************************************************************************/
var CSS_CLASS_EDIT_ROW = 'selected';
var CSS_CLASS_EVEN_ROW = 'RowNormal';
var CSS_CLASS_HEADER_ROW = '';
var CSS_CLASS_ODD_ROW = 'RowAlterned';
var CSS_CLASS_REPEAT_HEADER_ROW = 'CSS_PSEUDO_CLASS_INDICATING_REPEATED_HEADER_ROW';
var CSS_PSEUDO_CLASS_INDICATING_SORTABLE = 'CSS_PSEUDO_CLASS_INDICATING_SORTABLE';
var CSS_PSEUDO_CLASS_INDICATING_SORTBOTTOM = 'CSS_PSEUDO_CLASS_INDICATING_SORTBOTTOM';
var CSS_PSEUDO_CLASS_INDICATING_REPEAT_HEADER = 'CSS_PSEUDO_CLASS_INDICATING_REPEAT_HEADER';
var CSS_PSEUDO_CLASS_INDICATING_TABLE_IS_SORTABLE = 'CSS_PSEUDO_CLASS_INDICATING_TABLE_IS_SORTABLE';
var CSS_PSEUDO_CLASS_INDICATING_TABLE_GOT_REPEATED_HEADERROWS = 'CSS_PSEUDO_CLASS_INDICATING_TABLE_GOT_REPEATED_HEADERROWS';
var IMAGE_PATH = 'VirtualResources/Images.Arrows.Sortable.';
var IMAGE_ARROW_DOWN = 'arrow-down.gif';
var IMAGE_ARROW_NONE = 'arrow-none.gif';
var IMAGE_ARROW_UP = 'arrow-up.gif';
/************************************************************************************/

// Add sortables_init function to the window.load event.
addEvent(window, "load", sortables_init);

// Global variables.
var currectSortColumnIndex;
var thead = false;
var headerRows = new Array();
var informationAboutLargeTableShown = false;

// The init function. Searched the DOM thread for tables.
function sortables_init() {
    // The browser cannot handle DOM.
	if (!document.getElementsByTagName) return;

	// Find all tables with class sortable and make them sortable.
	tbls = document.getElementsByTagName('table');
	for (ti=0;ti<tbls.length;ti++) {
		thisTbl = tbls[ti];
		
		//thisTbl.style.visibility = 'hidden';
		
		// If the table has the pseudo CSS class indicating sortable:
        ts_makeSortable(thisTbl);

		// The function knows if to give the table repeated header rows or not.
		repeatHeaderRows(thisTbl);
		
		//thisTbl.style.visibility = 'visible';
	}
	
	// Preload images.
	picUp = new Image(); 
    picUp.src = IMAGE_PATH + IMAGE_ARROW_DOWN;
	picDown = new Image(); 
    picDown.src = IMAGE_PATH + IMAGE_ARROW_UP;
}

function ts_makeSortable(t) {
	// If the table dowsn't have the pseudo CSS class indicating sortable or to few rows: return.
	if (t.className.indexOf(CSS_PSEUDO_CLASS_INDICATING_SORTABLE) == -1 || 
	        t.rows.length <= 3 || 
	        t.className.indexOf(CSS_PSEUDO_CLASS_INDICATING_TABLE_IS_SORTABLE) > -1) {
		return;
	}
		
    // If the table has more lines than we accept: return.
	if (t.rows && t.rows.length > 0 && t.rows.length > MAX_TABLE_SIZE) {
	    return;
	}

    // Try to get the first row.
	if (t.tHead && t.tHead.rows.length > 0) {
		var firstRow = t.tHead.rows[t.tHead.rows.length-1];
		thead = true;
	} else {
		var firstRow = t.rows[0];
	}
	
	// If we don't have a first row, we cannot make the table sortable. Sorry. We return.
	if (!firstRow) return;
	
	// If the headerrow is missing the correct CSS:
	if (SET_CSS_IF_NOT_SET && firstRow.className.indexOf(CSS_CLASS_HEADER_ROW) == -1) {
	    firstRow.className += ' ' + CSS_CLASS_HEADER_ROW;
	}
	
	// If the table is missing an ID: set one!
	if (t.id == null || t.id.length == 0) {
	    t.id = 'tbl' + Math.floor(Math.random()*1000000000);
	}
	
	// We create a standard header row for this table.
	var repHeaderrow = document.createElement('TR');
	repHeaderrow.className = CSS_CLASS_HEADER_ROW + ' ' + CSS_CLASS_REPEAT_HEADER_ROW;
	
	// We have a first row: assume it's the header, and make its contents clickable links.
	for (var i = 0; i < firstRow.cells.length; i++) {
		var cell = firstRow.cells[i];
		var txt = ts_getInnerText(cell);

		// Make a nice clickable link in the cell if the column is sortable and has a column name.
		if (cell.className != 'unsortable' && cell.className.indexOf('unsortable') == -1 && txt.replace(' ', '').replace('&nbsp;', '').replace(String.fromCharCode(160), '').length > 0) { 
		    var alertText = '';
            if (t.rows.length > LARGE_TABLE_LIMIT) {
                alertText = 'if (!informationAboutLargeTableShown) { alert(\'Denna tabell är ganska stor (' + t.rows.length + ' rader). Din webbläsare kan behöva några sekunder på sig för att sortera stora tabeller.\'); informationAboutLargeTableShown = true; } ';
            }
			cell.innerHTML = '<a id="headerLinkRow0Cell' + i + '" onmouseover="this.style.textDecoration=\'underline\';" onmouseout="this.style.textDecoration=\'none\';" style="text-decoration: none; white-space: nowrap;" href="#" class="sortheader" onclick="' + alertText + 'ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow">&nbsp;<img src="'+ IMAGE_PATH + IMAGE_ARROW_NONE + '" alt="&darr;" border="0"/></span></a>';
		}
		
		// Create a new cell and add it to the repeated headerrow.
		var repCell = document.createElement('TH');
		repCell.innerHTML = txt; 
		repHeaderrow.appendChild(repCell);
	}
	
	// Set the general header row for this table.
	headerRows[t.id] = repHeaderrow;
	
	// Set CSS pseudo class indicating that this table has been sortable.
	t.className += ' ' + CSS_PSEUDO_CLASS_INDICATING_TABLE_IS_SORTABLE;
	
	// Eventually alternate thw row colours.
	if (ALTERNATE_ROW_COLORS) {
		alternate(t);
	}
}

function ts_getInnerText(el) {
	if (typeof el == "string") return el;
	if (typeof el == "undefined") { return el };
	if (el.innerText) return el.innerText;	//Not needed but it is faster
	var str = "";
	
	var cs = el.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: // It's an element node.
			    // If the element is hidden or is not displayed: return.
			    if (cs[i].style != null && (
			            cs[i].style.display != null && cs[i].style.display == 'none' || 
			            cs[i].style.visibility != null && cs[i].style.visibility == 'hidden'
                    )) {
			        return str;
			    }
			    
				str += ts_getInnerText(cs[i]);
				break;
			case 3:	// It's a text node.
			    // Om noden innehåller en asterisk vill vi inte räkna med den.
			    // Vanligt är att siffror på Privattjänsten åtföljs av en sådan med en förklaring.
			    if (cs[i].nodeValue.indexOf('*') != 0) {
			        str += trim(cs[i].nodeValue);
			    }
				break;
		}
	}
	return str;
}

function ts_resortTable(lnk, clid) {
	var span;
	for (var ci=0;ci<lnk.childNodes.length;ci++) {
		if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') {
		    span = lnk.childNodes[ci];
        }
	}
	var spantext = ts_getInnerText(span);
	var td = lnk.parentNode;
	var column = clid || td.cellIndex;
	var t = getParent(td,'TABLE');
	
	// Remove all extra header rows. They should NOT be sorted.
	removeRepeatedHeaderRows(t);
	
	// Work out a type for the column
	if (t.rows.length <= 1) return;

    // Set sort function	
	sortfn = ts_sort_standard;
	
	currectSortColumnIndex = column;
	var firstRow = new Array();
	var newRows = new Array();
	for (k=0;k<t.tBodies.length;k++) {
		for (i=0;i<t.tBodies[k].rows[0].length;i++) { 
			firstRow[i] = t.tBodies[k].rows[0][i]; 
		}
	}
	for (k=0;k<t.tBodies.length;k++) {
		if (!thead) {
			// Skip the first row
			for (j=1;j<t.tBodies[k].rows.length;j++) { 
				newRows[j-1] = t.tBodies[k].rows[j];
			}
		} else {
			// Do NOT skip the first row
			for (j=0;j<t.tBodies[k].rows.length;j++) { 
				newRows[j] = t.tBodies[k].rows[j];
			}
		}
	}
	
	// The core. Let the Array sort itself using the comparer we have defined.
	newRows.sort(sortfn);

    // Make the correct arrow visible.
	if (span.getAttribute("sortdir") == 'down') {
			ARROW = '&nbsp;<img src="'+ IMAGE_PATH + IMAGE_ARROW_DOWN + '" alt="&darr;" border="0"/>';
			newRows.reverse(); // Reverse the array
			span.setAttribute('sortdir','up');
	} else {
			ARROW = '&nbsp;<img src="'+ IMAGE_PATH + IMAGE_ARROW_UP + '" alt="&uarr;" border="0"/>';
			span.setAttribute('sortdir','down');
	}
	
    // We append rows that already exist to the tbody, so it moves them rather than creating new ones.
    for (i=0; i<newRows.length; i++) { 
		if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf(CSS_PSEUDO_CLASS_INDICATING_SORTBOTTOM) == -1))) {
			t.tBodies[0].appendChild(newRows[i]);
		}
	}

    // Do sortbottom rows only.
    for (i=0; i<newRows.length; i++) {
		if (newRows[i].className && (newRows[i].className.indexOf(CSS_PSEUDO_CLASS_INDICATING_SORTBOTTOM) != -1)) 
			t.tBodies[0].appendChild(newRows[i]);
	}
	
	// Delete any other arrows there may be showing
	var allspans = document.getElementsByTagName("span");
	for (var ci=0;ci<allspans.length;ci++) {
		if (allspans[ci].className == 'sortarrow') {
			if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
				allspans[ci].innerHTML = '&nbsp;<img src="'+ IMAGE_PATH + IMAGE_ARROW_NONE + '" alt="&darr;" border="0"/>';
			}
		}
	}
	span.innerHTML = ARROW;
	alternate(t);
	repeatHeaderRows(t);
}

function getParent(el, pTagName) {
	if (el == null) {
		return null;
	} else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) {
		return el;
	} else {
		return getParent(el.parentNode, pTagName);
	}
}

function compare_numeric(a,b) {
	var a = parseFloat(a);
	a = (isNaN(a) ? 0 : a);
	var b = parseFloat(b);
	b = (isNaN(b) ? 0 : b);
	
	// If equal:
	if (a == b) {
        // Inverted version of the string return function.
        // Makes '1.000' sorts before '1.0'.
        return aa < bb ? 1 : aa > bb ? -1 : 0;
	}
	
	return a - b;
}

function ts_sort_standard(a,b) {
	aa = ts_getInnerText(a.cells[currectSortColumnIndex]).toLowerCase();
	bb = ts_getInnerText(b.cells[currectSortColumnIndex]).toLowerCase();

    // Check if is percent
    if (aa.indexOf('%') > 0 && bb.indexOf('%') > 0) {
        var p1 = aa.replace('%', '');
        var p2 = bb.replace('%', '');
	    if (isANumber(p1) && isANumber(p2)) {
            return compare_numeric(clean_num(p1), clean_num(p2));
        }
    }

    // Check if numbers. If so: sort them numeric!
	if (isANumber(aa) && isANumber(bb)) {
		//return ts_sort_numeric(a,b);
		return compare_numeric(clean_num(aa), clean_num(bb));
	}
	
	return aa < bb ? -1 : aa > bb ? 1 : 0;
}

// Alternates the rows CSS style.
function alternate(table) {
	// Take object table and get all it's tbodies.
	var tableBodies = table.getElementsByTagName("tbody");
	// Loop through these tbodies
	for (var i = 0; i < tableBodies.length; i++) {
		// Take the tbody, and get all it's rows
		var tableRows = tableBodies[i].getElementsByTagName("tr");

		// Loop through these rows.
		// If first table body: start at 1 to leave the heading row untouched.
		var hasAFooter = tableRows[tableRows.length-1].className.indexOf(CSS_PSEUDO_CLASS_INDICATING_SORTBOTTOM) > -1;
		var startIndex = 0; //i == 0 ? 1 : 0; <- To be used if we don't use <tbody> tags.
		var endIndex = tableRows.length-(hasAFooter ? 1 : 0);
		for (var j = startIndex; j < endIndex; j++) {
		    // Check if j is even, and apply classes for both possible results
	        if (j % 2 == 0) {
                // If odd-CSS: replace odd-CSS with even-CSS.
		        if (tableRows[j].className.indexOf(CSS_CLASS_ODD_ROW) > -1) {
			        tableRows[j].className = tableRows[j].className.replace(CSS_CLASS_ODD_ROW, CSS_CLASS_EVEN_ROW);
		        } 
		        // If NOT even-CSS, then no alternating CSS exists. Set even-CSS.
		        else if (SET_CSS_IF_NOT_SET && tableRows[j].className.indexOf(CSS_CLASS_EVEN_ROW) == -1) {
			        tableRows[j].className = tableRows[j].className + ' ' + CSS_CLASS_EVEN_ROW;
		        }
	        } else {
                // If even-CSS: replace even-CSS with odd-CSS.
		        if (tableRows[j].className.indexOf(CSS_CLASS_EVEN_ROW) > -1) {
			        tableRows[j].className = tableRows[j].className.replace(CSS_CLASS_EVEN_ROW, CSS_CLASS_ODD_ROW);
		        }
		        // If NOT odd-CSS, then no alternating CSS exists. Set odd-CSS.
		        else if (SET_CSS_IF_NOT_SET && tableRows[j].className.indexOf(CSS_CLASS_ODD_ROW) == -1) {
			        tableRows[j].className = tableRows[j].className + ' ' + CSS_CLASS_ODD_ROW;
		        }
	        }
		}
	}
}

// The replace in string function in javascript only makes one replace.
function realReplace(str, replaceThis, withThis) {
    // If the user is stupid enough to try to replace X with X, return!
    if (replaceThis == withThis) {
        return str;
    }

    // While the string contains replaceThis:
	while (str.indexOf(replaceThis) > -1) {
		str = str.replace(replaceThis, withThis);
	}
	
	// Return
	return str;
}

// Removes all spaces from a string.
function removeSpaces(str) {
	return realReplace(realReplace(str, String.fromCharCode(160), ''), ' ', '');
}

// Tries to parse the number as a float and then returns number != NaN.
function isANumber(nr) {
    nr = setCorrectDecimalSign(nr);
    return (new RegExp(/^[+-]?\d*[\.\,]?\d*$/)).test(removeSpaces(trim(nr)));
}

// Function for cleaning numbers from stuff that isn't... nubers.
function clean_num(str) {
    str = setCorrectDecimalSign(str);
	str = str.replace(new RegExp(/[^-?0-9.]/g),"");
	return str;
}

function setCorrectDecimalSign(str) {
    // If the string contains a ',' as decimal sign, we replace it with a '.'.
    return str.indexOf(',') > -1 && str.indexOf('.') == -1 ? str.replace(',', '.') : str;
}

// Trim function. Trims spaces, tabs and newlines.
function trim(s) {
	return s.replace(/^\s+|\s+$/g, "");
}

// Repeats the headerrow
function repeatHeaderRows(t) {
    if (t.className.indexOf(CSS_PSEUDO_CLASS_INDICATING_REPEAT_HEADER) > -1 && 
        t.className.indexOf(CSS_PSEUDO_CLASS_INDICATING_TABLE_GOT_REPEATED_HEADERROWS) == -1 &&
        t.rows && 
        t.rows.length) {
        var nr = t.className.substring(t.className.indexOf(CSS_PSEUDO_CLASS_INDICATING_REPEAT_HEADER));
        
        if (nr.length > CSS_PSEUDO_CLASS_INDICATING_REPEAT_HEADER.length) {
            nr = parseInt(nr.substring(CSS_PSEUDO_CLASS_INDICATING_REPEAT_HEADER.length));
            if (nr > 0) {
                t.className += ' ' + CSS_PSEUDO_CLASS_INDICATING_TABLE_GOT_REPEATED_HEADERROWS;
            
                // If the table isn't sortable, the headerRows array hasn't been set. Set it!
                if (typeof headerRows[t.id] == 'undefined' && t.rows.length > 1) {
                    /* START COPIED CODE FROM SORT_INIT FUNCTION */
                        // We create a standard header row for this table.
                        var repHeaderrow = document.createElement('TR');
                        repHeaderrow.className = CSS_CLASS_HEADER_ROW + ' ' + CSS_CLASS_REPEAT_HEADER_ROW;

                        // Try to get the first row.
	                    if (t.tHead && t.tHead.rows.length > 0) {
		                    var firstRow = t.tHead.rows[t.tHead.rows.length-1];
		                    thead = true;
	                    } else {
		                    var firstRow = t.rows[0];
	                    }
                    	
	                    // If we don't have a first row, we cannot make the table sortable. Sorry. We return.
	                    if (!firstRow) return;

                        // We have a first row: assume it's the header, and make its contents clickable links.
                        for (var i = 0; i < firstRow.cells.length; i++) {
	                        var cell = firstRow.cells[i];
	                        var txt = ts_getInnerText(cell);

	                        // Create a new cell and add it to the repeated headerrow.
	                        var repCell = document.createElement('TH');
	                        repCell.innerHTML = txt; 
	                        repHeaderrow.appendChild(repCell);
                        }

                        // Set the general header row for this table.
                        headerRows[t.id] = repHeaderrow;
                    /* END COPIED CODE FROM SORT_INIT FUNCTION */
                }
                
                // -5 to prevent a repeated header row to be appended less than five rows from the end.
                for (var i = nr + 1; i < t.rows.length - 3; i += nr + 1) {
                    t.rows[i].parentNode.insertBefore(headerRows[t.id].cloneNode(true), t.rows[i]);
                }
	        }
        }
    }
}

// Removes all repeated headerrows
function removeRepeatedHeaderRows(t) {
	if (t.rows && t.rows.length) {
	    for (i = 0; i < t.rows.length; i ++) {
	        if (t.rows[i].className.indexOf(CSS_CLASS_REPEAT_HEADER_ROW) != -1) {
	            t.deleteRow(i);
	        }
	    }
	    
	    t.className = t.className.replace(' ' + CSS_PSEUDO_CLASS_INDICATING_TABLE_GOT_REPEATED_HEADERROWS, '');
	}
}

// Can be used by any element to shift the edit marking of its row.
function ToggleRowMarking(targetElement) {
    // Get the targets row element.
    var targetRow = targetElement.parentNode;
    for (i=0; i<30 && targetRow.nodeName.toLowerCase() != 'tr'; i++) {
        targetRow = targetRow.parentNode;
        // If we reach the document root, return.
        if (targetRow == document) {
            return;
        }
    }
    
    // Shift the row color.
    if (targetElement.checked) {
        if (targetRow.className.indexOf(CSS_CLASS_ODD_ROW) > -1) {
            targetRow.className = targetRow.className.replace(CSS_CLASS_ODD_ROW, CSS_CLASS_EDIT_ROW);
        } else if (targetRow.className.indexOf(CSS_CLASS_EVEN_ROW) > -1) {
            targetRow.className = targetRow.className.replace(CSS_CLASS_EVEN_ROW, CSS_CLASS_EDIT_ROW);
        }
    } else {
        if (targetRow.rowIndex % 2 == 0) {
            targetRow.className = targetRow.className.replace(CSS_CLASS_EDIT_ROW, CSS_CLASS_ODD_ROW);
        } else {
            targetRow.className = targetRow.className.replace(CSS_CLASS_EDIT_ROW, CSS_CLASS_EVEN_ROW);
        }
    }
}

// Toggle a checkbox and change the row color when the row is clicked.
function ToggleRowMarkingAndCheckBoxValue(cbxId) {
    // Get the checkbox
    var cbx = document.getElementById(cbxId);
    
    // Toggle its checkmode.
    cbx.checked = !cbx.checked;
    
    // Toggle the row color.
    ToggleRowMarking(cbx);
}

// Cross browser safe function for getting the element who fired the given event.
function GetFiringElement(event) {
    var targetElement;
    if (!event) {
        var event = window.event;
    }
    
    if (event.target) {
        targetElement = event.target;
    } else if (event.srcElement) {
        targetElement = event.srcElement;
    } else if (typeof event == 'string') {
        targetElement = document.getElementById(event);
    }
    
    // Defeat Safari bug
    if (targetElement.nodeType == 3) {
        targetElement = targetElement.parentNode;
    }
	
    return targetElement;
}


// Expandable support
function ToggleExpandCollapse(link) {
    var div = document.getElementById(link.id + '_pnl');
    var td = div.parentNode;
    var tr = td.parentNode;
    var table = tr.parentNode;

    if (link.innerHTML == '\u2191') {
        // compress
        div.style.display = 'none';
        link.innerHTML = '\u2193'; // up arrow

        // move back and remove created tr
        link.parentNode.insertBefore(div, link);
        table.removeChild(tr);
    } else {
        //expand
        link.innerHTML = '\u2191'; // down arrow

        // calculate colspan
        var colspan = 0
        var node = tr.firstChild;
        while (node != null) {
            if (node.tagName == 'TD') {
                colspan++;
            }
            node = node.nextSibling;
        }
        
        // add a row after the current tr
        var newTr = document.createElement('TR');
        table.insertBefore(newTr, tr.nextSibling);
        
        // add a td
        var newTd = document.createElement('TD');
        var attrColspan = document.createAttribute('colspan');
        attrColspan.value = colspan;
        newTd.attributes.setNamedItem(attrColspan);
        newTd.appendChild(div);
        newTr.appendChild(newTd);

        div.style.display = 'block';
    }
    //alert(link.innerHTML);
}

/*================================================================   TreeGridView.js   =================================================================*/

/*
 Söderberg & Partners (http://www.soderbergpartners.se).
Copyright (c) 2009 Söderberg & Partners
*/
function TreeGridView() {
    this.pageIndex = null;
    this.createPropertyString = TreeGridView_createPropertyString;
    this.setStateField = TreeGridView_setStateValue;
    this.getHiddenFieldContents = GridView_getHiddenFieldContents;
    this.stateField = null;
    this.panelElement = null;
    this.callback = null;
}
function TreeGridView_createPropertyString() {
    return createPropertyStringFromValues_GridView(this.pageIndex);
}
function TreeGridView_setStateValue() {
    this.stateField.value = this.createPropertyString();
}
function TreeGridView_OnCallback(result, context) {
    var value = new String(result);
    var valsArray = value.split("|");
    var innerHtml = valsArray[1];
    for (var i = 5; i < valsArray.length; i++) {
        innerHtml += "|" + valsArray[i];
    }
    context.panelElement.innerHTML = innerHtml;
    context.stateField.value = createPropertyStringFromValues_GridView(valsArray[0]);
}
function GridView_getHiddenFieldContents(arg) {
    return arg + "|" + this.stateField.value;
}
function createPropertyStringFromValues_GridView(pageIndex) {
    var value = new Array(pageIndex);
    return value.join("|");
}


/*====================================================================   Menu.js   =====================================================================*/

function SwitchTab(liIdToShow, allLiIds, elementIdToShow, allElementIds) {
    allLiIds = allLiIds.split('|');
    for(var i=0; i<allLiIds.length; i++) {
        var li = document.getElementById(allLiIds[i]);
        li.className = li.id == liIdToShow ? 'active' : '';
    } 
    
    allElementIds = allElementIds.split('|');
    for(var i=0; i<allElementIds.length; i++) {
        var div = document.getElementById(allElementIds[i]);
        div.style.display = div.id == elementIdToShow ? 'block' : 'none';
    }
}



/*====================================================================   Panel.js   ====================================================================*/

function toggleExpandablePanel(aId, divId, expandText, collapseText) {
    var a = document.getElementById(aId);
    var div = document.getElementById(divId);

    var showDiv = div.style.display == 'none';
    div.style.display = showDiv ? 'block' : 'none';
    a.innerHTML = showDiv ? collapseText : expandText;
}

/*===================================================================   Textbox.js   ===================================================================*/

/** Används för att stänga av ENTER-knappen i exempelvis textfält.
  * Användning:
  * <input type="text" onKeyPress="JavaScript:return disableENTER(event);">
  * I fältet ovan händer det inget när användaren klickar på ENTER.
  */
function pressedKeyIsEnter(e) {
	return GetKeyCode(e) == 13;
}

function GetKeyCode(e) {
    var code;
	if (!e) var e = window.event;
	if (e.keyCode) code = e.keyCode;
	else if (e.which) code = e.which;
	return code;
}

function ValidateEmailOnBlur(control, language, requireInput) {
    if (!requireInput && control.value == '') {
        return;
    }

    var classNameWarning = 'Warning';
    var regExp = /^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i
    var valid = regExp.test(control.value);
    if (!valid) {
        var title = language == 1 ? 'Felaktig e-postadress' : 'Invalid e-mail address';
        var message = language == 1
            ? 'I textfältet du just skrev i är det tänkt att du ska skriva in en e-postadress. Du skrev "' + control.value + '", vilket inte är en giltig e-postadress. Vänligen prova igen.'
            : 'In this text field you should enter an e-mail address. You entered "' + control.value + '", which isn\'t an valid e-mail address. Please try again.'
        AlertPopupMessage(title, message);
        control.value = '';
        SafeClassNameAdd(control, classNameWarning);
    } else {
        SafeClassNameRemove(control, classNameWarning);
    }
}

function ValidateIntOnBlur(control, language) {
    control.value = FixNumericString(control.value, false)
    var classNameWarning = 'Warning';
    
    if (control.value.length > 0 && !IsAnInt(control.value)) {
        var title = language == 1 
            ? 'Ogiltigt värde' 
            : 'Invalid value';
        var message = language == 1 
            ? 'I textfältet du just skrev i är det tänkt att du ska skriva in ett heltal. Du skrev "' + control.value + '", vilket inte är ett heltal. Vänligen prova igen.' 
            : 'In this text field you should enter an integer. You entered "' + control.value + '", which isn\'t an integer. Please try again.' 
    
        control.value = '';
        AlertPopupMessage(title, message);
        SafeClassNameAdd(control, classNameWarning);
    } else {
        SafeClassNameRemove(control, classNameWarning);
    }
}

function IsAnInt(value) {
    return /^[-+]?[0-9]+$/.test(value);
}

function ValidateFloatOnBlur(control, language) {
    control.value = FixNumericString(control.value, true)
    var classNameWarning = 'Warning';

    if (control.value.length > 0 && !IsAFloat(control.value)) {
        var title = language == 1 
            ? 'Ogiltigt värde' 
            : 'Invalid value';
        var message = language == 1 
            ? 'I textfältet du just skrev i är det tänkt att du ska skriva in ett decimaltal. Du skrev "' + control.value + '", vilket inte är ett decimaltal. Vänligen prova igen.' 
            : 'In this text field you should enter an decimal value. You entered "' + control.value + '", which isn\'t an decimal value. Please try again.' 
    
        control.value = '';
        AlertPopupMessage(title, message);
        SafeClassNameAdd(control, classNameWarning);
    } else {
        SafeClassNameRemove(control, classNameWarning);
    }
}

function IsAFloat(value) {
    return /^[-+]?\d+(\.\d+)?$/.test(value.replace(',', '.'));
}

function FixNumericString(value, isAFloat) {
    return removeSpaces(value);
}

function ValidateSSNOrONOnBlur(event, currentValue, isSocialSecurityNumber, language) {
	var targetElement;
	if (!event) var event = window.event;
	if (event.target) targetElement = event.target;
	else if (event.srcElement) targetElement = event.srcElement;
	if (targetElement.nodeType == 3) targetElement = targetElement.parentNode; // defeat Safari bug
	
    // Om inget skrivits in: returnera.
    if (currentValue.length == 0) return true;

    // Om orgnr och angivet med 19 eller 20 i början
    if (!isSocialSecurityNumber && (currentValue.substr(0, 2) == '19' || currentValue.substr(0, 2) == '20')) {
        currentValue = currentValue.substr(2, currentValue.length - 2);
        targetElement.value = currentValue;
    }

    // Prova att autokomplettera om användaren skrivit in minst tio tecken och det är siffror och eventuellt ett bindestreck.
    if (currentValue.length >= 10 && (new RegExp(/^\d*\-?\d*$/)).test(currentValue)) {
	    // Lägg till bindestreck om det saknas och sätt det korrekt om det finns.
        if (targetElement.value.indexOf('-') == -1) {
            targetElement.value = targetElement.value.substring(0,targetElement.value.length-4) + '-' + targetElement.value.substring(targetElement.value.length-4)
        }

        // Lägg till 19 eller 20 i början om det saknas.
        if (isSocialSecurityNumber && targetElement.value.length < 13 && targetElement.value.substring(0,2) != '19' && targetElement.value.substring(0,2) != '20') {
            var y = parseInt(targetElement.value.substring(0,2)) < 10 ? '20' : '19';
            targetElement.value = y + targetElement.value;
        }
    }

    currentValue = targetElement.value;
	var isValid = false;
    var classNameWarning = 'Warning';
	var thisErrorDivId = "ERROR_BALLOONTIP_" + targetElement.id;
	if (currentValue.length > 0) {
		if (isSocialSecurityNumber) {
			isValid = currentValue.length == 13 && // Inmatningen ska vara 13 tecken lång.
				(currentValue.substring(0, 2) == "19" || currentValue.substring(0, 2) == "20") && // Rätt århundrade.
				currentValue.indexOf('-') == 8 && // Det åttonde tecknet ska vara ett bindestreck.
				(new personnummer(currentValue.substring(2))).valid; // Personnumret ska vara giltigt.
		} else {
			isValid = currentValue.length == 11 && // Inmatningen ska vara 13 tecken lång.
				currentValue.indexOf('-') == 6 && // Det sjätte tecknet ska vara ett bindestreck.
				(new organisationsnummer(currentValue)).valid; // Orgnumret ska vara giltigt.
		}
		
		if (!isValid) {
			if (isSocialSecurityNumber) {
			    var title = language == 1 
			        ? 'Felaktigt personnummer' 
			        : 'Incorrect social security number';
			    var message = language == 1 
			        ? 'Du har angivit ett felaktigt personnummer ("' + targetElement.value + '"). Textfältet har därför rensats.' 
			        : 'You have entered a non valid social security number ("' + targetElement.value + '"). The text field has been cleared.';
			
			    AlertPopupMessage(title, message);
			} else {
                var title = language == 1 
			        ? 'Felaktigt organisationsnumer' 
			        : 'Incorrect organization number';
			    var message = language == 1 
			        ? 'Du har angivit ett felaktigt organisationsnummer ("' + targetElement.value + '"). Textfältet har därför rensats.' 
			        : 'You have entered a non valid organization number ("' + targetElement.value + '"). The text field has been cleared.';
			
			    AlertPopupMessage(title, message);
			}
			
			targetElement.value = '';
            SafeClassNameAdd(targetElement, classNameWarning);
		} else {
            SafeClassNameRemove(targetElement, classNameWarning);
		}
	}
}

// Tagen från http://www.webforum.nu/showthread.php?t=42712 den 12 mars 2007. Skriven av Jojoxx.
function personnummer(nr){
	this.valid=false;
	if(!nr.match(/^(\d{2})(\d{2})(\d{2})\-(\d{4})$/)){ return false; }
	this.now=new Date(); this.nowFullYear=this.now.getFullYear()+""; this.nowCentury=this.nowFullYear.substring(0,2); this.nowShortYear=this.nowFullYear.substring(2,4);
	this.year=RegExp.$1; this.month=RegExp.$2; this.day=RegExp.$3; this.controldigits=RegExp.$4;
	this.fullYear=(this.year*1<=this.nowShortYear*1)?(this.nowCentury+this.year)*1:((this.nowCentury*1-1)+this.year)*1;
	var months = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	if(this.fullYear%400==0||this.fullYear%4==0&&this.fullYear%100!=0){ months[1]=29; }
	if(this.month*1<1||this.month*1>12||this.day*1<1||this.day*1>months[this.month*1-1]){ return false; }
	this.alldigits=this.year+this.month+this.day+this.controldigits;
	var nn="";
	for(var n=0;n<this.alldigits.length;n++){ nn+=((((n+1)%2)+1)*this.alldigits.substring(n,n+1)); }
	this.checksum=0;
	for(var n=0;n<nn.length;n++){ this.checksum+=nn.substring(n,n+1)*1; }
	this.valid=(this.checksum%10==0)?true:false;
	this.sex=parseInt(this.controldigits.substring(2,3))%2;
}

// Tagen från http://www.webforum.nu/showthread.php?t=42712 den 12 mars 2007. Skriven av Jojoxx.
function organisationsnummer(nr){
	this.valid=false;
	if(!nr.match(/^(\d{1})(\d{5})\-(\d{4})$/)){ return false; }
	this.group=RegExp.$1;
	this.controldigits=RegExp.$3;
	this.alldigits=this.group+RegExp.$2+this.controldigits;
	//if(this.alldigits.substring(2,3)<2){ return false } // Why was this added...? Seems totally wrong. Makes valid social security number fail.
	var nn="";
	for(var n=0;n<this.alldigits.length;n++){ nn+=((((n+1)%2)+1)*this.alldigits.substring(n,n+1)); }
	this.checksum=0;
	for(var n=0;n<nn.length;n++){ this.checksum+=nn.substring(n,n+1)*1; }
	this.valid=(this.checksum%10==0)?true:false;
}

/**
 * Simulerar ett klick på ett element. Fungerar på knappar och länkar.
 */
function simulateClickOnElement(e, elementIdToClick) {
	try {
		var keycode, elementToClick;
		if (!e) var e = window.event;
		keycode = e.keyCode ? e.keyCode : e.which ? e.which : null;
		if (keycode == 13) {
			// Hämta det element vi önskat klicka på och klicka på det!
			clickOnElement(elementIdToClick);
			
			// Viktigt! Annars postas sida om på traditionellt sätt.
			return false;
		}
		return true;
	} catch(err) {}
}

function clickOnElement(elementIdToClick) {
    var elementToClick = document.getElementById(elementIdToClick);

    // Om onclick är satt ska den köras först. Fungerar för alla element.
    try {
	    elementToClick.onclick();
    } catch(err) {}

    // Om det är en submit-knapp så postar vi formuläret och returnerar.
    if (elementToClick.type == 'submit') {
	    document.forms[0].submit();
	    return true;
    }

    // Om det är en a-tagg måste vi titta närmare på href-attributet.
    if (elementToClick.href) {
	    // Om den innehåller javascriptkod evaluerar vi den.
	    if (elementToClick.href.toLowerCase().indexOf('javascript') == 0) {
		    eval(elementToClick.href);
	    } else { // Annars går vi till den sidan.
		    document.location = elementToClick.href;
	    }
    }
}

function RequireInput(e) {
    var classNameWarning = 'Warning';
    var element = GetFiringElement(e);
    if (element.value.length == 0) {
        SafeClassNameAdd(element, classNameWarning);
    } else {
        SafeClassNameRemove(element, classNameWarning);
    }
}

function CheckTextLength(inputField, maxTextLength, language) {
    var classNameWarning = 'Warning';

    if (inputField.value.length > maxTextLength) {
         inputField.value = inputField.value.substring(0, maxTextLength);
         inputField.blur();
         
         var title = language == 1 
            ? 'För lång text' 
            : 'To long text';
        var message = language == 1 
            ? 'I textfältet du just skrev i är den maximala textlängden angiven till ' + maxTextLength + ' tecken.' 
            : 'Please enter a text shorter than ' + maxTextLength + ' chars.' 
    
        AlertPopupMessage(title, message);
        SafeClassNameAdd(inputField, classNameWarning);
    } else {
        SafeClassNameRemove(inputField, classNameWarning);
    }
}
