/**
 * global.js
 * 
 * $Rev: 11318 $
 * $Author: na_pelle $
 * $Date: 2010-01-15 09:50:55 +0100 (Fri, 15 Jan 2010) $
 * 
 * 0 INIT
 * 1 COMMONS
 *    1.1 Functions
 *    1.2 Objects
 * 2 SERVICES, sorted by service names
 * 3 DEPRECATED / OBSOLETE
 */

/**
 * Called on page load and ajax calls, put invoke methods here.
 * 
 * @param {Element}
 *            scope set scope for invoke methods. Default value is <body>.
 */

var hasRun = null;
var isIE = /*@cc_on!@*/false;
var lastClickElementId = null;

if (typeof MKT === 'undefined') {
	MKT = {};
}      
if (typeof MKT.requiredFeatures === 'undefined') {
	MKT.requiredFeatures = {};
}

function init(scope) {
	
	// init site settings
	Settings.init(scope || $(document.getElementsByTagName('body')[0]));

	hasRun = true;

	initTopUserToolbar();

	// Do this first in order to speed up modal links.
	initClickListener();
	
	// preparations
	prepareNewsLists();
	ArticleToolbar.init();
	SocialBookmarks.init();
	SortWidget.init();	
	prepareEventCalendar();
	prepareMyPhotos();
	prepareImageGallery();
	prepareFormValidation();
	prepareCharacterCounter();
	prepareExternalContent();
	prepareTogglers();
	BlogFeedParser.init();

	prepareLeftNav();
	DropDown.init();
	Blog.init();
	Poll.init();
	prepareForms();
	prepareUserForm();
	CrowdPictures.init();
	TVGuide.init();	
	TagCloud.init();

	PhotoAlbum.init();
	MyPage.init();
	Forum.init();

	FormEnhancedHelp.install();
	CommentCitation.init();
	prepareDateTimePickers();
	ScrollableMediagrid.init();
	ImageAlbumLinkChange.init();

	// preparations set, enable enhancements
	enableEnhancements();

	// init jsdependent services
	initTicker();
	initPrint();
	ArticleTagCloudLink.init();
	PaymentService.init();
	EventCalendarPaymentService.init();
	EventCalendarPaymentService.initChargeableFields();

	// this is always last!
	Chat.init();
}


/***************************** 1. COMMONS **********************************************/ 

/*
 * =========================== 1.1 Functions
 * =============================================
 */ 

/* *** Form and Link types handling *** */

/**
 * register a global click event to enable event delegation. Make sure to not
 * include any heavy tasks in here since it will execute every time a click
 * occour.
 */
function initClickListener(){
	var mp = $('mainPadding');
	if(!mp) return;
	mp.observe( 'click', function(e){
		var elm = Event.element(e);
		var evalLink = function(lnkelm) { // help function for links.
			if(typeof lnkelm.onclick == 'function') return;
			var v = lnkelm.getAttribute('rel');
			switch(v) {
				case "external":
					window.open(lnkelm.href);
					Event.stop(e);
					break;
				case "modal":
					var f = openAsModal(lnkelm);
						if(typeof f == 'function') {
							f();
							Event.stop(e);
						}
					break;
			}
		};
		
		// keep this up here or else some autosubmits might fail.
		var pForm = elm.up('form'); 
		if(pForm && pForm.className.match(/postAsModal/)){
			openAsModal(pForm);
		}
		
		// links can be opened as modal window or in a new window.
		if(elm.nodeName == 'A' && elm.getAttribute('rel')){
			evalLink(elm);
		}

		// elements inside of external or modal links
		var pA = elm.up('a');
		if(pA){
			evalLink(pA);
		}
		
		// which submits their parent form
		if(elm.nodeName == 'INPUT' && elm.className && elm.className.match(/submitWhenChecked/)){
			var pF = elm.up('form');
			// To prevent that the same click triggers several times
			if (lastClickElementId != elm.id) {
				if(pF.className.match(/postAsModal/)) {
					pF.onsubmit(); // asuming openAsModal(pF) has been called.
				}else{
					pF.submit();
				}
				lastClickElementId = elm.id;
			}
		}
	});
}

/* *** URL / Querystrings functions *** */

/**
 * Adds a querystring parameter to a String URL.
 * 
 * @param url
 *            The String URL
 * 
 * @param paramName
 *            The name of the parameter
 * 
 * @param paramValue
 *            The parameter value
 * 
 */
function addQueryStringParam(url, paramName, paramValue) {
	if(url == null || url == "")
		return null;

	var paramSuffix = "?";
	if(url.indexOf("?") > 0)
		paramSuffix = "&";

	if(url.indexOf(paramName + "=" + paramValue) > 0) {
		return url;
	}
	
	var newurl = (url.indexOf("#") < 0) ? (url + paramSuffix + paramName + "=" + paramValue) : (url.replace("#", (paramSuffix + paramName + "=" + paramValue + "#")) );
	return newurl;
}
	
/**
 * Fetches parameter from the url, empty string if it wasn't found.
 * 
 * @param {String} strParamName
 */
function getUrlParam(strParamName){
	var strReturn = "";
	var strHref = window.location.href;
	if ( strHref.indexOf("?") > -1 ){
		var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();
		var aQueryString = strQueryString.split("&");
		for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
			if (aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1 ){
				var aParam = aQueryString[iParam].split("=");
				strReturn = aParam[1];
				break;
			}
		}
	}
	return strReturn;
}

/*
 * This is the orginial function from Stuart Langridge at http://www.kryogenix.org/
 * This is the update function from Jeff Minard - http://www.jrm.cc/
 * Updated with nested lists support by madr - http://madr.se
 */
function superTextile(s) {
    var r = s;
    // quick tags first
    qtags = [['\\*', 'strong'],
             ['\\?\\?', 'cite'],
             ['\\+', 'ins'],  //fixed
             ['~', 'sub'],   
             ['\\^', 'sup'], // me
             ['@', 'code']];
    for (var i=0;i<qtags.length;i++) {
        ttag = qtags[i][0]; htag = qtags[i][1];
        re = new RegExp(ttag+'\\b(.+?)\\b'+ttag,'g');
        r = r.replace(re,'<'+htag+'>'+'$1'+'</'+htag+'>');
    }
    
	// underscores count as part of a word, so do them separately
    re = new RegExp('\\b_(.+?)_\\b','g');
    r = r.replace(re,'<em>$1</em>');
	
	// jeff: so do dashes
    re = new RegExp('[\s\n]-(.+?)-[\s\n]','g');
    r = r.replace(re,'<del>$1</del>');

    // links
    re = new RegExp('"\\b(.+?)\\(\\b(.+?)\\b\\)":([^\\s]+)','g');
    r = r.replace(re,'<a href="$3" title="$2">$1</a>');
    re = new RegExp('"\\b(.+?)\\b":([^\\s]+)','g');
    r = r.replace(re,'<a href="$2">$1</a>');

    // images
    // madr adds support for class attributes
	re = new RegExp('!\\(\\b(.+?)\\b\\)([^\\s\\(\\)]+)\\(\\b(.+?)\\b\\)!','g');
    r = r.replace(re,'<img class="$1" src="$2" alt="$3">');
	re = new RegExp('!\\(\\b(.+?)\\b\\)([^\\s\\(\\)]+)!','g');
    r = r.replace(re,'<img class="$1" src="$2" alt="">');
	// madr adds support for local images: ex "/img/loval.gif"
    re = new RegExp('!([^\\s\\(\\)]+)\\(\\b(.+?)\\b\\)!','g');
    r = r.replace(re,'<img src="$1" alt="$2">');
	// madr adds support for local images: ex "/img/loval.gif"
    re = new RegExp('!([^\\s\\(\\)]+)!','g');
    r = r.replace(re,'<img src="$1" alt="">');
    
    // block level formatting
	
		// Jeff's hack to show single line breaks as they should.
		// insert breaks - but you get some....stupid ones
	    re = new RegExp('(.*)\n([^#\*\n].*)','g');
	    r = r.replace(re,'$1<br />$2');
		// remove the stupid breaks.
	    re = new RegExp('\n<br />','g');
	    r = r.replace(re,'\n');
	
    lines = r.split('\n');
    nr = '';
    for (var i=0,max=lines.length;i<max;i++) {
        line = lines[i].replace(/\s*$/,'');
        changed = 0;
        if (line.search(/^\s*bq\.\s+/) != -1) { 
			line = line.replace(/^\s*bq\.\s+/,'\t<blockquote>')+'</blockquote>'; 
			changed = 1; 
		}
		
		// jeff adds h#.
        if (line.search(/^\s*h[1|2|3|4|5|6]\.\s+/) != -1) { 
	    	re = new RegExp('h([1|2|3|4|5|6])\.(.+)','g');
	    	line = line.replace(re,'<h$1>$2</h$1>');
			changed = 1; 
		}
		
		// madr adds ##, ###, ** and ***
		if (line.search(/^\s*\*\*\*\s+/) != -1) { 
			line = line.replace(/^\s*\*\*\*\s+/,'\t<ccliu>') + '</ccliu>'; 
			changed = 1; 
		}
        if (line.search(/^\s*\*\*\s+/) != -1) { 
			line = line.replace(/^\s*\*\*\s+/,'\t<cliu>') + '</cliu>'; 
			changed = 1; 
		} 
        if (line.search(/^\s*\*\s+/) != -1) { 
			line = line.replace(/^\s*\*\s+/,'\t<liu>') + '</liu>'; 
			changed = 1; 
		}
        if (line.search(/^\s*###\s+/) != -1) { line = line.replace(/^\s*###\s+/,'\t<cclio>') + '</cclio>'; changed = 1; } // ### for numeric list; make up an lio tag to be fixed later
        if (line.search(/^\s*##\s+/) != -1) { line = line.replace(/^\s*##\s+/,'\t<clio>') + '</clio>'; changed = 1; } // ## for numeric list; make up an lio tag to be fixed later
        if (line.search(/^\s*#\s+/) != -1) { line = line.replace(/^\s*#\s+/,'\t<lio>') + '</lio>'; changed = 1; } // # for numeric list; make up an lio tag to be fixed later
        
		if (!changed && (line.replace(/\s/g,'').length > 0)) line = '<p>'+line+'</p>';
        lines[i] = line + '\n';
    }
	
    // Second pass to do lists
    inlist = 0; 
	listtype = '';
	parentList = [];
    for (var i=0,max=lines.length;i<max;i++) {
        line = lines[i];
		// madr added : child lists, **
		if (inlist && listtype=='ul' && parentList.length==0 && !line.match(/^\t<liu/)  && !line.match(/^\t<c*liu/)) { 
			line = '</ul>\n' + line; inlist--; }
		if (inlist && parentList.length==1 && line.match(/^\t<liu/)) { 
			listtype = parentList[0]; parentList.pop(); line = '\n</ul></li' + listtype.charAt(0) + '>\n' + line; }
		if (inlist && line.match(/^\t<cliu/) && parentList.length==0) { 
			lines[i-1] = lines[i-1].replace("</liu>",""); parentList[0] = listtype; listtype = "ul"; line = '<ul>\n' + line; }
        if (inlist===0 && line.match(/^\t<liu/) && parentList.length==0) { 
			line = '<ul>' + line; inlist++; listtype = 'ul'; }
		//ol
		if (inlist && listtype=='ol' && parentList.length==0 && !line.match(/^\t<lio/)  && !line.match(/^\t<c*lio/)) { 
			line = '</ol>\n' + line; inlist--; }
		if (inlist && parentList.length==1 && line.match(/^\t<lio/)) { 
			listtype = parentList[0]; parentList.pop(); line = '\n</ol></li' + listtype.charAt(0) + '>\n' + line; }
		if (inlist && line.match(/^\t<clio/) && parentList.length==0) { 
			lines[i-1] = lines[i-1].replace("</lio>",""); parentList[0] = listtype; listtype = "ol"; line = '<ol>\n' + line; }
        if (inlist===0 && line.match(/^\t<lio/) && parentList.length==0) { 
			line = '<ol>' + line; inlist++; listtype = 'ol'; }
        lines[i] = line;
    }

    r = lines.join('\n');
	// madr added : will replace clio and cliu
	r = r.replace(/cli[o|u]>/g,'li>');
	// jeff added : will correctly replace <li(o|u)> AND </li(o|u)>
    r = r.replace(/li[o|u]>/g,'li>');

    return r;
}

/**
 * Checks for browser-enabled cookies and sets an arbitrary form field to true/false.
 *
 * @param id
 * 			Id of form field to populate
 */
function setFormCookie (id)
{
	var f = $(id);
	
	if (f)
	{
		f.value = (Cookie.accept()) ? "true" : "false";
	}
}

/* =========================== / 1.1 Functions ============================================ */ 

/*
 * =========================== 1.2 Objects
 * ================================================
 */ 

var CacheUtil = {
	
	/**
	 * Add unique number in URI to prevent cache.
	 */
	noCache : function(uri) {
		return uri.concat(/\?/.test(uri)?"&":"?","noCache=",new Date().getTime(),".",Math.random()*1234567);
	}
};

/* *** CharacterCounter *** */

/**
 * @author Pelle Andersson, Promedia, Nerikes Allehanda
 */
 
var CharacterCounter = {
	maxChars: 0,
	initsuccess: false,
	exists : function () {
		return Settings.scope.select("textarea").length;
	},
	/*
		Init #maxchar and .maxchar textareas

		NOTE: well known bug in IE if you use the
		word description or body as id of an element (it will return the meta tag???!!!).
		This is an IE fix
	*/
	init: function() {
		
		var elementCounter = Settings.scope.select("#maxchar");
		
		this.initElements(elementCounter);
		
		var elementCounter = Settings.scope.select(".maxchar");
		
		this.initElements(elementCounter);
	},
	/**
	 * Init textareas with charcount, i.e. #maxchar (for backward compability) and .maxchar
	 * 
	 * @param {Array} elements 
	 * @author na_fredrik
	 * @return void
	 */
	initElements: function (elementCounterNodes)
	{
		if(elementCounterNodes != null && elementCounterNodes.length > 0){
			
			for (var j=0; j<elementCounterNodes.length; j++)
			{
				var elementCounter = elementCounterNodes[j];
				var tree = elementCounter.up().ancestors();
				var textArea = false;
				
				for(var i=0; i<tree.length; i++) {
					if(tree[i].nodeName == 'FIELDSET' || tree[i].nodeName == 'DIV') {
						textArea = tree[i].select('textarea').last();
						break;
					}
				}

				if(textArea == false) return;
				
				CharacterCounter.initMaxCharValues(elementCounter);
				if(elementCounter.initsuccess == true){
					textArea.elementCounter = elementCounter;
					textArea.maxChars = elementCounter.maxChars;
					textArea.onkeyup = function () { CharacterCounter.countChars(this);};
					textArea.onkeydown = function () { CharacterCounter.countChars(this);};
					textArea.onfocus = function () { CharacterCounter.countChars(this);};
				} 
				else
					elementCounter.addClassName("JSDependent");
			}
		}
	},
	/**
		Method which count down number of charachter left.
			@param elementToCount
				The textarea element to count, gets called on keyup-, keydown- and focus-events. Each teaxtarea element contains a self reference to a corresponding counter element
	
	*/
	countChars: function(elementToCount){
	
		var elementCounter = elementToCount.elementCounter;
		
		if(elementToCount.value.length > elementCounter.maxChars){
			elementToCount.value = elementToCount.value.substring(0, elementCounter.maxChars);
		}
		else{
			elementCounter.value = elementCounter.maxChars - elementToCount.value.length;
		}
	},
	/**
	Attach a maxchars value to an counter element.
	
	@param elementToCount
	*/
	initMaxCharValues: function(obj) {
		if(obj.value != "" && parseInt(obj.value,10)){
			obj.maxChars = obj.value;
			obj.initsuccess = true;
		}
	}
};



/**
 * Init the character counter object.
 */
function prepareCharacterCounter(){
	if (CharacterCounter.exists()) {
		CharacterCounter.init();
	}
}

/**
 * Prototype extension to store and get cookies.
 */
var Cookie = {
  setC: function(name, value, daysToExpire) {
    return document.cookie = 
      escape(name) + '=' + escape(value || '') + this.expiration(daysToExpire);
  }, 

  getC: function(name) {
    var match = document.cookie.match(new RegExp('(^|;)\\s*' + escape(name) + '=([^;\\s]*)'));
    return match && unescape(match[2]) || null;
  },

  erase: function(name) {
    var cookie = Cookie.getC(name);
    Cookie.setC(name, '', -1);
    return cookie;
  },

  accept: function() {
    if (typeof navigator.cookieEnabled === 'boolean') {
      return navigator.cookieEnabled;
    }
    Cookie.setC('_test', '1');
    return Cookie.erase('_test') === '1';
  },
  
  expiration: function(daysToExpire) {
    if (daysToExpire === null) { return ''; }
    var d = new Date();
    d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));
    return '; expires=' + d.toGMTString();
  }
};


/**
 * ===DropDown====== Creates a navigation drop down (select with onchange event)
 * from a form.
 */
var DropDown = {
  init: function() {
    Settings.scope.select('select.submitOnChange').each(function(select) {
      var form = $(select.form), needlessButton = DropDown.findNeedlessButton(form);
      Event.observe(select, 'change', function() {
        if (needlessButton) {
          form.insert(new Element('input', { type: 'hidden', 
            name: needlessButton.name, value: needlessButton.value }));
        }
        form.submit();
      });
      needlessButton && needlessButton.remove();
    });
  },  
  findNeedlessButton: function(form) {
    var otherFields = form.select('input:not([type=submit]):not([type=hidden]), textarea, select:not(.submitOnChange)');
    if (otherFields.length == 0) {
      var buttons = form.select('input[type=submit]');
      if (buttons.length == 1) { return buttons[0]; }
    }
    return form.select('input.btnSelect')[0] || null;
  }
};
/** / ===DropDown====== */

/* ==== SortWidget ==== * */
/*
 * SortWidgets has autosubmit feature, so the submit button is removed by
 * script.
 */
var SortWidget = {
  init: function() {
	var elm = $('SortWidget');
	if(elm) {
	  var ts = elm.select('div.toolstrip');
	  if(ts.length==1) ts[0].remove();
	  ts = null;
	  elm = null;
	}
  }
};
/* ==== /SortWidget ==== */

/**
 * ====FORM==== various help functions for forms.
 * 
 * Object.extend √§r ett kortsiktigt hack f√∂r att Form inte skall krocka
 * med prototypes Form. Vid problem, kontakta Fleecelabs. 2008-12-10 (onsdag)
 */
 
function prepareForms() {
 	//Form.initModalForms();
 	Form.observeButtons();
 	Form.initSelectAll();
}

Object.extend(Form, {
	init : function(){
		//Form.initModalForms();
		Form.observeButtons();
		Form.initSelectAll();
	},
	cn : {
		firedBtn : "input.buttonPressed",
		clsFiredBtn : "buttonPressed",
		clsSelectAll : "input.chkSelectAll"
	},
	initSelectAll : function() {
		var sals = Settings.scope.select(this.cn.clsSelectAll);
		for(var i=0,max=sals.length; i<max; i++){
			Event.observe(sals[i],'click',function(evt){
				var elm = evt.element();
				var state = elm.checked;
				var elms = elm.up('form').select('input[type=checkbox].chkRemove');
				for(var j=0,max=elms.length; j<max; j++){
					elms[j].checked = state;
				}
			});
		}
	},
	/**
	 * init method. Prepare forms with more than one submit button with a hidden field. 
	 * The hidden field is updated with the value of the clicked button.
	 */
	observeButtons: function () {
		var forms = Settings.scope.select('form');
		for(var i=0, max=forms.length; i<max; i++){
			var form = forms[i];
			if (form.select('input[type=submit]').length > 1) {
				var hiddenField = new Element('input', { type: 'hidden' });
				hiddenField.addClassName(Form.cn.clsFiredBtn);
				form.insert(hiddenField);
				form.observe('click', function(event) {
					var element = event.element();
					if (element.nodeName == 'INPUT' && element.type == 'submit') {
						hiddenField.value = element.className;
					}
				});
			}
		}
	},
	
	initModalForms: function () {
		var forms = $('mainPadding').select(".postAsModal");
		for(var i=0, max=forms.length; i<max; i++){
			openAsModal(forms[i]);
		};	
	},
	
	getCaretPos : function  (ctrl) {
		var pos = 0;
		if (document.selection) {	// IE
			ctrl.focus();
			var sel = document.selection.createRange();
			sel.moveStart('character', -ctrl.value.length);
			
			pos = sel.text.replace(/^\s+\n/, '').length;
		} else if (ctrl.selectionStart || ctrl.selectionStart == '0') { // Firefox
			pos = ctrl.selectionStart;
		}
		return pos;
	},

	setCaretPos : function(ctrl, pos){
		if (ctrl.setSelectionRange) {
			ctrl.focus();
			ctrl.setSelectionRange(pos, pos);
		} else if (ctrl.createTextRange) {
			var range = ctrl.createTextRange();
			range.collapse(true);
			range.moveEnd('character', pos);
			range.moveStart('character', pos);
			range.select();
		}
	},
	
	updateTextArea: function(textarea, text) {
		if (textarea.nodeName == 'INPUT')
		{
			var textAreaId = textarea.id;
			var fckEditor = FCKeditorAPI.GetInstance(textAreaId);
			
			fckEditor.Focus();
			
			if (!isIE)
			{
				fckEditor.InsertHtml(text);
			}
			else
			{
				var timeOut = setTimeout("FCKeditorAPI.GetInstance('" + textAreaId + "').Focus();", 1000);
				var textInserted = false;
				
				fckEditor.Events.AttachEvent( 'OnFocus',
					function(fckEditor) {
						if (textInserted) {
							return;
						}
						fckEditor.InsertHtml(text);
						clearTimeout(timeOut);
						textInserted = true;
					}
				);
			}
		}
		else
		{
			var pos = Form.getCaretPos(textarea);
			var before = textarea.value.substr(0, pos);
			var after = textarea.value.substr(pos);
			textarea.value = [before, text, after].join('');
			Form.setCaretPos(textarea, pos + text.length);
		}
	},
	
  // getPasswordStrength: function (passwd) {
  //  var checks = [/[a-z]/, /[A-Z]/, /\d+/, /[$#%@&*(+){}+!,^?_~]/, /.{6,}/];
  // return checks.inject(0, function(percentage, check) {
  // return percentage + (passwd.match(check) ? 20 : 0);
  // });
  // },
	
	getPasswordStrength : function (passwd) {
		var requiredLength = 6;
		var percentage = 0;
		var increase = 20;
		
		var hasLowercase = false;
		var hasUppercase = false;
		var hasInteger = false;
		var hasSpecialchar = false;
		
		// At least one lower case letter
		if (passwd.match(/[a-z]/)) {
			percentage += increase;
			hasLowercase = true;
		}
		
		// At least one upper case letter
		if (passwd.match(/[A-Z]/)) {
			percentage += increase;
			hasUppercase = true;
		}
		
		// At least one number
		if (passwd.match(/\d+/)) {
			percentage += increase;
			 hasInteger = true;
		}
	
		// At least one special character
		if (passwd.match(/[$#%@&amp;*(+){}+!,^?_~]/)) {
			percentage += increase;
			hasSpecialchar = true;
		}
		
		// At least 6 characters
		if(passwd.length >= requiredLength)
			percentage += increase;
	
		return percentage;
	},
	
	
	iframe : {
		contid : 'userFormIframe',
		html : function() {
			return "<iframe style='visibility:hidden;width:0;height:0;border:0;z-index:-1' name='" +this.id+"' id='"+this.id+"'></iframe>";
		},
		onload : function() {
			var wrp = parent.frames[Form.iframe.id].document.getElementsByTagName('body')[0];
			var html = wrp.innerHTML;
			options = {
				beforeLaunch : null,
				params : {
					href: Form.iframe.id,
					type: null,
					reloadLinks : true,
					reloadOnClose : false,
					closeButton : true,
					scrollable : false,
					wrapperClass : null
				},
				onload : null,
				onsubmit : null,
				onunload : null,
				evalResponse : null
			};
			
			if (typeof options.beforeLaunch == "function") options.beforeLaunch();
			ModalWindow.onload = options.onload;
			ModalWindow.onunload = options.onunload;
			ModalWindow.evalResponse = options.evalResponse;		
			parent.frames[Form.iframe.id].location.href = '';
			ModalWindow.inner.innerHTML = '';
			ModalWindow.importFromIframe(options,html);
		},
		init : function(formElm,onloadFunc) {
			var ifrm = new Element('div',{'id':this.contid});
			this.id = this.contid+Math.random();
			ifrm.update(this.html());
			formElm.target = this.id;
			formElm.insert(ifrm);
			var c = this;
			Event.observe(formElm,'submit',function(e){
				if (FormValidation.checkForm(formElm) == true) {
					if (ModalWindow.overlay.getStyle('display') != 'none') {
						ModalWindow.initLoader();
						ModalWindow.resetWrapper();
						Event.observe($(Form.iframe.id), 'load', (typeof onloadFunc == "undefined") ? Form.iframe.onload : onloadFunc);
					}else{
						var wrp = parent.frames[Form.iframe.id].document.getElementsByTagName('body')[0];
						var html = wrp.innerHTML;
						return html;
					}
				}
				else {
					e.preventDefault();
				}
			});
		},
		exists : function() {
			return false;// $('modalWindowWrapper').select("#userFormIframe").length
							// > 0;
		}
	}
});/** ==== form === */


/*******************************************************************************
 * Form validation object. Performs dynamic validation of any form. For
 * requirements see http://mktmedia...
 * 
 * @author Pelle Andersson, Promedia, Nerikes Allehanda
 * 
 */

var FormValidation = {
	
	/*
		Different limitations used by the FormValidation object.
	*/

	DEFAULT_MAX_CHARS : 500,
	DEFAULT_MIN_CHARS : 10,
	MAX_FILE_SIZE : 4000000,
	DEFAULT_MAX_COUNT : 100,
	DEFAULT_MIN_COUNT : 2,
	MIN_PASSWORDLENGTH : 6,
	DEFAULT_SELECT_VALUE : "-- V\u00E4lj --",
	
	/*
		Current validation types used by the FormValidation object.
		Add more types when required
	*/
	
	currentForm : null,

	R : "requiredfield",
	MAX_CHARS_FIELD : "maxcharsfield",
	MIN_CHARS_FIELD : "mincharsfield",
	U : "urlfield",
	E : "emailfield",
	IS : "imagesizefield",
	CONTENT_TYPE_FIELD : "contenttypefield",
	ISE : "isequalfield",
	N : "numberfield",
	D : "datefield",
	
	/*
	** Deprecated - Anv√§nds inte vad vi kan se, men har nyligen modifierats
	** och f√•r d√§rf√∂r vara kvar. 2009-03-10 / FLEECELABS 
	*/
	MAX_COUNT_FIELD : "maxcountfield",
	MIN_COUNT_FIELD : "mincountfield",
  
	
	/*
		General error messages used by the FormValidation object.
		NOTE:Do not remove the word field since this is dynamically replaced by the header for the specific form element
	*/

	 ERROR_HEADER : "Fel intr\u00E4ffade i inmatningsf\u00E4lten:",
	 ERROR_EMPTY : "Var v\u00E4nlig fyll i f\u00E4ltet \"field\"",
	 ERROR_MAXCHARS : "F\u00E4ltet field \u00F6verstiger maximalt antal till\u00E5tna tecken",
	 ERROR_MINCHARS : "F\u00E4ltet field uppn\u00E5r ej minimalt antal inmatade tecken",
	 ERROR_URL : "F\u00E4ltet inneh\u00E5ller en eller flera ogiltiga l\u00E4nkar! (exempel: http://www.domain.com)",
	 ERROR_EMAIL : "Var v\u00E4nlig ange en giltig e-postadress (exempel: namn.efternamn@foretag.com)",
	 ERROR_CONTENT_TYPE : "Filen i field \u00E4r av ogiltigt format",
	 ERROR_FILE_SIZE : "Filen \u00E4r f\u00F6r stor, maxstorlek f\u00F6r bild \u00E4r 4MB",
	 ERROR_MAXCOUNT : "F\u00E4ltet field har f\u00F6r m\u00E5nga alternativ valda.",
	 ERROR_MINCOUNT : "F\u00E4ltet field har f\u00F6r f\u00E5 alternativ valda.",
	 ERROR_NOTEQUAL : "F\u00E4lten field och efield m\u00E5ste vara exakt lika",
	 ERROR_NOTCHECKED : "Var god kryssa i \"field\"",
	 ERROR_NOTNUMBER : "Var v\u00E4nlig ange ett numeriskt v\u00E4rde",
	 ERROR_DATE : "Var v\u00E4nlig ange ett giltigt datum i formatet \u00C5\u00C5\u00C5\u00C5-MM-DD",
	 ERROR_PNUMBER : "Var v\u00E4nlig ange ett giltigt personnummer i formatet \u00C5\u00C5MMDD-XXXX",
	 ERROR_ORGNUMBER : "Var v\u00E4nlig ange ett giltigt organisationsnummer",
	 ERROR_PASSWORD : "L\u00F6senordet m\u00E5ste inneh\u00E5lla minst 6 tecken",
	
	
	errorDiv : "div#error",
	
	errorDivIfrm: "div#errorIfrm",
	
	errorSummary: "Fel intr\u00E4ffade i inmatningsf\u00E4lten:\n",

	/**
		Base method for the form validation object. Iterates all the
		elements in the form and performs validation (if the requirements are 
		fullfilled). 
	*/
	
	checkForm : function(f){
		
		this.currentForm = f;
		
		var validators = new Array();
		var errorMessage = "";
		var globalErrorCount = 0;
		var origClassName = "";
		var fragmentErrorMessage = "Fel intr\u00E4ffade i inmatningsf\u00E4lten:\n";
		var notShown = 0;
		
		// Remove div shown in fallback mode e.g server validation if the
		// user has turned off javascript and then turn it back on again.
		this.hideAllErrorMessages("",true);
		
		// Iterate all elements in the form to validate (f parameter)
		for(var i = 0; i < f.elements.length; i++){
			var validate	=	f.elements[i].type == "text" || 
										 	f.elements[i].type == "textarea" || 
											f.elements[i].type == "select-multiple" || 
											f.elements[i].type == "file" || 
											f.elements[i].type == "checkbox" || 
											f.elements[i].type == "radio" || 
											f.elements[i].type == "password" || 
											f.elements[i].type == "select-one";
				
			var type = f.elements[i].type;
			if(validate){
				var node = f.elements[i];
				var nodeName = f.elements[i].id;
				var labelText = "";
				var fieldErrorCount = 0;
				
				// Get validators and field name for the current form element
				var validatorString = this.getValidators(nodeName);
				var header = this.getHeader(nodeName);
				
				
				if(validatorString != ""){
					//Select-multiple validation
					if(type == "select-multiple"){
						var message = this.validateDropDownList(node);
						if(message != ""){
							errorMessage += message;
							globalErrorCount++;	
							fieldErrorCount++;
							
							this.errorSummary += errorMessage + "\n";
						}
					}
					//Select-one validation
					else if(type == "select-one"){
						var message = "";
						if(validatorString.indexOf(this.D) > -1) {
							var yyyy = node.value;
							var mm = node.next().value;
							if(mm<10 && (mm+"").length==1) mm = "0"+mm;
							var dd = node.next(1).value;
							if(dd<10 && (dd+"").length==1) dd = "0"+dd;
							var datestr = yyyy+"-"+mm+"-"+dd;
							message = (this.isDate(datestr)) ? "" : this.ERROR_DATE;
						}
						message += this.validateSingleDropDownList(node);
						if(message != ""){
							errorMessage += message;
							globalErrorCount++;
							fieldErrorCount++;
							this.errorSummary += errorMessage + "\n";
						}
					
					}
					//Checkbox validation (only required)
					else if(type == "checkbox"){
						
						// is it group or single?
						
						var isGroup = node.up('.checkboxgroup');
						
						var tempArr = new Array();
						var tempVal = validatorString;
						tempArr = tempVal.split(" ");
						var go = false; // ta bort
						var checked = true;
						for(var k = 0; k < tempArr.length; k++){ // byt mot array.indexOf(this.R) != -1
							if(tempArr[k] == this.R){
								go = true;
								break;
							}
						}
						if (go == true) { // ta bort == true
							if (isGroup) {
								var res = "";
								isGroup.select("input[type=checkbox]").each(function(i){ // r√§kna inte upp, g√• ur loopen efter f√∂rsta ikryssade rutan
									var c = i.checked;
									res += c;
								});
								if(res.lastIndexOf('true') < 0) { // res skall bort, anv√§nds inte sedan.
									globalErrorCount++;
									fieldErrorCount++;
									if (header != "") {
										var str = this.ERROR_NOTCHECKED.replace("field", header.toLowerCase());
										errorMessage = (errorMessage.indexOf(str) < 0) ? str : "";
									}
									else {
										var str = this.ERROR_NOTCHECKED.replace("field", "");
										errorMessage = (errorMessage.indexOf(this.ERROR_NOTCHECKED) < 0) ? str : "";
									}
										
									this.errorSummary += errorMessage + "\n";
								}
							} else {
								checked = node.checked;
								if (checked == false) {
									globalErrorCount++;
									fieldErrorCount++;
									if (header != "") {
										errorMessage += this.ERROR_NOTCHECKED.replace("field", header.toLowerCase());
									}
									else {
										errorMessage += this.ERROR_NOTCHECKED.replace("field", "");
									}
									
									this.errorSummary += errorMessage + "\n";
								}
							}
						}
					}
					else if(type == "radio"){
						
						// is it group or single?
						var isGroup = node.up('.radiobuttongroup');
						
						var tempArr = new Array();
						var tempVal = validatorString;
						tempArr = tempVal.split(" ");
						var go = false;
						var checked = true;
						for(var k = 0; k < tempArr.length; k++){
							if(tempArr[k] == this.R){
								go = true;
								break;
							}
						}
							if (go == true) {
							if (isGroup) {
								var res = "";
								isGroup.select("input[type=radio]").each(function(i){
									var c = i.checked;
									res += c;
								});
								if(res.lastIndexOf('true') < 0) {
									globalErrorCount++;
									fieldErrorCount++;
									if (header != "") {
										var str = this.ERROR_NOTCHECKED.replace("field", header.toLowerCase());
										errorMessage = (errorMessage.indexOf(str) < 0) ? str : "";
									}
									else {
										var str = this.ERROR_NOTCHECKED.replace("field", "");
										errorMessage = (errorMessage.indexOf(this.ERROR_NOTCHECKED) < 0) ? str : "";
									}
									
										
									this.errorSummary += errorMessage + "\n";
								}
							}else{
								checked = node.checked;
								if (checked == false) {
									globalErrorCount++;
									fieldErrorCount++;
									if (header != "") {
										errorMessage += this.ERROR_NOTCHECKED.replace("field", header.toLowerCase());
									}
									else {
										errorMessage += this.ERROR_NOTCHECKED.replace("field", "");
									}
									
									this.errorSummary += errorMessage + "\n";
								}
							}
						}
					}
					else{
						validators = validatorString.split(" ");
						
						
						// Iterate and perform validation
						for(var j= 0; j < validators.length; j++){
							var validation = validators[j];
							// Validate required field
							if( validators[j] == this.R ){
								if(this.isEmpty(node.value)){
									globalErrorCount++;	
									fieldErrorCount++;
									// Construct html error message
									if(header != ""){
										errorMessage +=this.ERROR_EMPTY.replace("field", header.toLowerCase());
									}
									else
										errorMessage += this.ERROR_EMPTY.replace("field", "");
										
										this.errorSummary += errorMessage + "\n";										
								}
								else if (! this.isEmpty(node.value) && type == "password"){
									if(node.value.length < this.MIN_PASSWORDLENGTH){
										globalErrorCount++;	
										fieldErrorCount++;
								
										if(header != ""){
											errorMessage += this.ERROR_PASSWORD.replace("field", header.toLowerCase());
										}
										else
											errorMessage += this.ERROR_PASSWORD.replace("field","");
									
										this.errorSummary += errorMessage + "\n";
									}
								}
							}
							
							//Validate character count
							if (validation.match(this.MAX_CHARS_FIELD)){
								var length = /[0-9]+$/.exec(validation) || this.DEFAULT_MAX_CHARS;
								if (!this.isTooLong(node, length)) continue;
				
								globalErrorCount++;
								fieldErrorCount++;
								errorMessage += this.ERROR_MAXCHARS.replace("field", header.toLowerCase());
								this.errorSummary += errorMessage + "\n";
							}
														
							if (validation.match(this.MIN_CHARS_FIELD)){
								var length = /[0-9]+$/.exec(validation) || this.DEFAULT_MIN_CHARS;
								if (!this.isTooShort(node, length)) continue;
						
								globalErrorCount++;
								fieldErrorCount++;
								errorMessage += this.ERROR_MINCHARS.replace("field", header.toLowerCase());
								this.errorSummary += errorMessage + "\n";
							}
							//Validate url
							if ( validators[j] == this.U ){
								if (validators.join().indexOf(this.R)>=0 || node.value != "http://") {
									if(! this.isUrl(node.value)){
										globalErrorCount++;
										fieldErrorCount++;
										// Construct html error message
										if(header != ""){
											errorMessage += this.ERROR_URL.replace("field",  header.toLowerCase() );
										}
										else
											errorMessage += this.ERROR_URL.replace("field", "");	
											
										this.errorSummary += errorMessage + "\n";		
									}
								}
							}
							
							//Validate email
							if ( validators[j] == this.E ){
								if(node.value.length > 0){
									if(! this.isEmail(node.value)){
										globalErrorCount++;
										fieldErrorCount++;
										if(header != ""){
											errorMessage += this.ERROR_EMAIL.replace("field",  header.toLowerCase() );
										}
										else
											errorMessage += this.ERROR_EMAIL.replace("field", "");
											
										this.errorSummary += errorMessage + "\n";
									}
								}
							}
							
							//Validate content type
							if (validation.match(this.CONTENT_TYPE_FIELD)){
								if (node.value.length <= 0) continue;									
								if(this.isValidFileType(node.value, validation)) continue;
								globalErrorCount++;
								fieldErrorCount++;
								errorMessage += this.ERROR_CONTENT_TYPE.replace("field", header.toLowerCase());										
								this.errorSummary += errorMessage + "\n";										
							}
														
							//Validate equal to
							if( validators[j].indexOf(this.ISE) > -1 ){
								var arr = new Array();
								
								/*
								 * Html syntax for this special validator:
								 * 
								 * <label for="password" class="requiredfield"><span>*</span></label>
								 * <input type="password" id="password"
								 * name="password"/> <label for="passwordCopy"
								 * class="requiredfield isequalfield:password"><span>*</span></label>
								 * <input type="password" id="passwordCopy"
								 * name="passwordCopy"/>
								 * 
								 */
								
								// Get the field to compare with
								arr = validators[j].split(":"); // shold be
																// {'isequal',
																// 'password'}
																// from the
																// above example
								if(arr.length > 0){
									var key = arr[1];
									var compareElement = this.currentForm.select("input#" + key);
									if(compareElement != null && compareElement.length > 0){
										if( ! (node.value == compareElement[0].value) ){
											var compareElementHeader = this.getHeader(compareElement[0].id);
											globalErrorCount++;
											fieldErrorCount++;
											
											if(compareElementHeader != "" && header != "")
												errorMessage += this.ERROR_NOTEQUAL.replace("field", compareElementHeader).replace("efield", header); 
											else
												errorMessage += this.ERROR_NOTEQUAL.replace("field", "").replace("efield","");
												
											this.errorSummary += errorMessage + "\n";
										}//if
										
									}//if
								}//if
							}//if
							
							// Validate number
							if ( validators[j] == this.N ) {
								if (!!node.value && isNaN(parseInt(node.value,10))) {
								  globalErrorCount++;
									fieldErrorCount++;
									
									if(header != ""){
										errorMessage += this.ERROR_NOTNUMBER.replace("field", header.toLowerCase());
									} else {
										errorMessage += this.ERROR_NOTNUMBER.replace("field", "");
									}
										
									this.errorSummary += errorMessage;									
								}//if
							}//if
							
							// Validate date
							if( validators[j] == this.D ){
								
								var datestr = node.value;
								
								if(datestr.length > 0){
									if(this.isDate(datestr) == false){
										globalErrorCount++;
										fieldErrorCount++;
										
										if(header != ""){
											errorMessage += this.ERROR_DATE.replace("field", header.toLowerCase());
										}
										else
											errorMessage += this.ERROR_DATE.replace("field", "");
											
										this.errorSummary += errorMessage + "\n";
									
									}
								}
							}//if
							
							/*
							 * * Validate image size. * Deprecated. * Deprekerad
							 * d√• den endast fungerar i firefox med vissa
							 * plugins * installerade. √Ñr kvar f√∂r att
							 * den anv√§nds i Polopoly. * 2009-03-10
							 * /FLEECELABS
							 */
							if ( validators[j] == this.IS ){
								if(node.value.length > 0){
									var size = this.isFileToLarge(node.value);
									if(size != -1){
										if(size == true){
											globalErrorCount++;
											fieldErrorCount++;
											if(header != ""){
												errorMessage += this.ERROR_FILE_SIZE.replace("field", header.toLowerCase() );
											}
											else
												errorMessage += this.ERROR_FILE_SIZE.replace("field", "");
											
											this.errorSummary += errorMessage + "\n";
										}
									}
								}
							}//if							
														
						}//for
					}//else
					if(fieldErrorCount > 0){
						if(this.hasPageErrorElements()){
							if(this.errorElementExist(nodeName)){
								this.showErrorMessage(nodeName, errorMessage, false, f.id);
							}
							else{
								notShown++;
								fragmentErrorMessage += errorMessage + "\n";
							}
						}
						errorMessage = "";
					}
					else{
						if(this.hasPageErrorElements()){
							if(this.errorElementExist(nodeName)){
								this.hideErrorMessage(nodeName, false, f.id);
							}
						}
					}
				}//if
			}//if
		}//for
		
		if(globalErrorCount > 0){
			if(typeof( Settings.scope.select(this.errorDivIfrm)[0] )!= "undefined"){
				var errorDivIfrm = Settings.scope.select(this.errorDivIfrm)[0];
				// Special treatment for reporting an comment
				if(errorDivIfrm != null){
					this.ERROR_HEADER = this.ERROR_HEADER.replace("count", "");
					errorDivIfrm.className = "error";
					errorDivIfrm.innerHTML = this.ERROR_HEADER;
				}
			}
			else
			{
				this.ERROR_HEADER = this.ERROR_HEADER.replace("count", "");
				if(this.showErrorMessage(this.errorDiv, this.ERROR_HEADER, true, f.id) == false){
					alert(this.errorSummary);
				}
				else if(notShown > 0){
					alert(fragmentErrorMessage);
					fragmentErrorMessage = "";
				}
			}

			this.adjustModalWindow();
			// this.initForm(f);
			this.errorSummary = "";
			return false;
		}
		else{
			if(typeof( Settings.scope.select(this.errorDivIfrm)[0] )!= "undefined"){
				var errorDivIfrm = Settings.scope.select(this.errorDivIfrm)[0];
				// Special treatment for reporting an comment
				if(errorDivIfrm != null){
					errorDivIfrm.className = "errorHidden";
					errorDivIfrm.innerHTML = "";
				}
			}
			else
			{
				this.hideErrorMessage(this.errorDiv, true, f.id);
			}
		}
		
		//This is needed for a multiple select box
		this.selectAllOptions(f);
		return true;
		
	},
	
	/**
		Simple email validation
			@param formElementValue
				The value to validate.
	*/
	isEmail : function(formElementValue){
		var regexp = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
		return regexp.test(formElementValue);
	},
	/**
		Simple url validation
		TODO: Maybe add https and ftp?
		
		@param formElementValue
			The value to validate
			
	*/
	isUrl: function(formElementValue) {
		var regexp = /^((https?|ftp):\/\/)?([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
		return regexp.test(formElementValue.strip());
	},
	/**
		Checks if form element is empty.
			@param formElementValue
				The value to validate.
	*/
	isEmpty: function(formElementValue){
		return formElementValue.length == 0;
	},
	/**
		Simple max character validation.
			@param formElementValue
				The value to validate
			@param maxchars
				Character limit.
	*/
	isTooLong: function(formElement, maxchars){
		var max = formElement.maxChars;
		var m;
		
		m = (max != null) ? max : maxchars;
			
		return formElement.value.length > m;
	},
	/**
		Simple min character validation.
			@param formElementValue
				The value to validate
			@param minchars
				MInimum number of characters.
	*/
	isTooShort: function(formElement, minchars){
		return formElement.value.length < minchars;
	},
	countSelection: function(formElement) {
		var selectionCount = 0;
		for(var i = 0; i<formElement.length; i++) {
			if (formElement.options[i].selected) selectionCount++;
		}
		return selectionCount;
	},
	/**
		Simple file extension validation tha only works on jpg.
			@param formElementValue
				The value to validate.
	*/
	isJPG: function(formElementValue){
		return formElementValue.toLowerCase().indexOf(".jpg") > -1;
	},
	/**
		Simple file extension validation.
			@param value
				The value to validate.
			@param validation
				The name of the validation.
				
			Splits the name of the validation to extract allowed file types.
			The first value in the array is always CONTENT_TYPE_FIELD.
	*/
	isValidFileType: function(value, validation) {
		var contentTypes = validation.split(/(\-|\\\:)/);		
		if (contentTypes.length == 1) contentTypes.push('jpg');																		
		for(var i=1; i<contentTypes.length; i++) {
			if (/[^\.]+$/.exec(value.toLowerCase()) == contentTypes[i]) return true;
		}
		return false;
	},
	/*
	** Validate image size.
	** Deprecated.
	** Deprekerad d√• den endast fungerar i firefox med vissa plugins 
	** installerade. √Ñr kvar f√∂r att den anv√§nds i Polopoly.
	** 2009-03-10 /FLEECELABS
	*/
	isFileToLarge: function(formElementValue){
		var binary;
		var size = 0;
		
		
		if(this.isJPG(formElementValue)){
			var img = new Image();
			img.src = formElementValue;
			// alert(img.fileSize);
			
			if(typeof(img.fileSize) != "undefined"){
				if(img.fileSize != -1)
					return parseInt(img.fileSize,10) > this.MAX_FILE_SIZE;
			}
			
			if(typeof(img.fileSize) == "undefined"){
			
				// request local file read permission
				try {
					netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				} catch (e) {
					//alert("Permission to read file was denied.");
					return -1;
				}
				
				// open the local file
				var file = Components.classes["@mozilla.org/file/local;1"]
					.createInstance(Components.interfaces.nsILocalFile);
				file.initWithPath( formElementValue );		
				stream = Components.classes["@mozilla.org/network/file-input-stream;1"]
					.createInstance(Components.interfaces.nsIFileInputStream);
				stream.init(file,	0x01, 00004, null);
				var bstream =  Components.classes["@mozilla.org/network/buffered-input-stream;1"]
					.getService();
				bstream.QueryInterface(Components.interfaces.nsIBufferedInputStream);
				bstream.init(stream, 1000);
				bstream.QueryInterface(Components.interfaces.nsIInputStream);
				binary = Components.classes["@mozilla.org/binaryinputstream;1"]
					.createInstance(Components.interfaces.nsIBinaryInputStream);
				binary.setInputStream (stream);
	
					
				return parseInt(size,10) > this.MAX_FILE_SIZE;
			}
		}
		
		return -1;
		
	},

	/**
		Basic date validation
			@param formElementValue
				The value to validate
	
	*/
	isDate: function(formElementValue){
		var validformat = /^\d{4}\-\d{2}\-\d{2}$/; // Format validity
		var isValid = true;
	
		if (! validformat.test(formElementValue)){
			isValid = false;
		}
		else{ //Check date ranges
			var yearfield = formElementValue.split("-")[0];
			var monthfield = formElementValue.split("-")[1];
			var dayfield = formElementValue.split("-")[2];
			var dayobj = new Date(yearfield, monthfield-1, dayfield);
			
			if ( ( (dayobj.getMonth()+ 1) != monthfield )||( dayobj.getDate()!= dayfield )||( dayobj.getFullYear()!= yearfield )){  
				isValid = false;
			}
		}
		
		return isValid;
	},
	/**
	 * Seperate method for validating a mulitple select box, simply
	 * because the base method was too long :-D
	 *	
	 *	@param formElement
	 *		The select input element
	 */
	validateDropDownList: function(formElement){
		
		var errorMessage = "";
		this.deleteDefaultValue(formElement);
		var validators = new Array();
		
		var parent = formElement.parentNode;
		var validatorString = this.getValidators(formElement.id);
		var labelText = this.getHeader(formElement.id);
		
		if(validatorString != ""){
			validators = validatorString.split(" ");
			
			for(var i = 0; i < validators.length; i++){
				var validation = validators[i];
				
				if(validators[i] == this.R){
					if(formElement.selectedIndex == -1){
						if(labelText != ""){
							errorMessage += this.ERROR_EMPTY.replace("field", labelText.toLowerCase());
						}
						else
							errorMessage += this.ERROR_EMPTY.replace("field", "");
					}
				}
				if(validators[i] == this.MAX_CHARS_FIELD) continue;
				if(validators[i] == this.MIN_CHARS_FIELD) continue;
				if(validators[i] == this.E) continue;				
												
				if(validators[i] == this.U){
					if(formElement.length > 0){
						for(var j = 0; j < formElement.length; j++){
							if(! this.isUrl(formElement.options[j].value)){
								if(labelText != ""){
									errorMessage += this.ERROR_URL.replace("field", labelText.toLowerCase());
								}
								else
									errorMessage += this.ERROR_URL.replace("field",  "");
								break;
							}
						}
					}
				}
				
				/*
      	** Deprecated - Anv√§nds inte vad vi kan se, men har nyligen modifierats
      	** och f√•r d√§rf√∂r vara kvar. 2009-03-10 / FLEECELABS 
      	*/
      	
				if (validation.match(this.MAX_COUNT_FIELD)) {
					var length = /[0-9]+$/.exec(validation) || this.DEFAULT_MAX_COUNT;
					var sel_count = this.countSelection(formElement);
					if (sel_count <= length) continue;
					errorMessage += this.ERROR_MAXCOUNT.replace("field", labelText.toLowerCase());
				}
				
				if (validation.match(this.MIN_COUNT_FIELD)) {
					var length = /[0-9]+$/.exec(validation) || this.DEFAULT_MIN_COUNT;															
					if (this.countSelection(formElement) >= length) continue;
					errorMessage += this.ERROR_MINCOUNT.replace("field", labelText.toLowerCase());					
				}				
			}
		}
		
		return errorMessage;
	
	},
	
	/**
	 * Validates a single dropdown list. Only required.
	 * 
	 *	
	 *	@param formElement
	 *		The select input element
	 */
	 
	validateSingleDropDownList: function(formSelect){
		var validatorString = this.getValidators(formSelect.id);
		var labelText = this.getHeader(formSelect.id);
		var errorMessage = "";
		
		if(validatorString != ""){
			var validators = validatorString.split(" ");
			
			if(validators.length > 0){
				for(var i = 0; i < validators.length; i++){
					if(validators[i] == this.R){
						var selectedValue = formSelect.options[formSelect.selectedIndex].value;
						if(this.isEmpty(selectedValue) || selectedValue.length == 0 || selectedValue.length == this.DEFAULT_SELECT_VALUE){
							if(labelText != ""){
								errorMessage += this.ERROR_EMPTY.replace("field", labelText.toLowerCase());
							}
							else{
								errorMessage += this.ERROR_EMPTY.replace("field", "");
							}
						}	
					}
				}
			}
		}
		return errorMessage;
	},
	
	/**
	 *	This method selects all the validated options in
	 *	a multiple select box. This is required since no
	 *	values will be saved unless this is done. The 
	 *	method is called after that all elements in the
	 *	form passed its validation.
	 *	
	 *	@param f
	 *		The form
	 */
	selectAllOptions: function(f){
		for(var i= 0; i < f.elements.length; i++){
			if(f.elements[i].type == "select-multiple"){
				var selectbox = f.elements[i];
				if(selectbox.length > 0){
					for(var j = 0; j < selectbox.length; j++){
						if(selectbox.options[j].value == ""){
							selectbox.remove(j);
						}
						else
							selectbox.options[j].selected = true;
					}
				}
			}
		}
	},
	
	/**
	 *	Get the header from the label tag which is bound to 
	 *	the input form element. Is used to dynamically indicate
	 *	which field the error occured in.
	 *	
	 *	@param elementId
	 *		The form element id
	 */
	getHeader: function(elementId){
		var header = "";
		if (elementId != "") {
			var elm = $(elementId);
			if ( (typeof elm.up('fieldset.checkboxgroup') != 'undefined') || (typeof elm.up('fieldset.radiobuttongroup') != 'undefined')) {
				var h = $(elementId).up('fieldset').down('legend');
				if(h) return h.innerHTML;
				var ps = $(elementId).up('fieldset').select('p');
				h = (ps.length>1 && ps[0].up().hasClassName('error')) ? ps[1] : ps[0];
				if(h) {
					return h.innerHTML;
				}
			}
		}
		var allLabels = Settings.scope.select('label');
		var header = "";
		for(var i = 0; i < allLabels.length; i++){	
			if(allLabels[i].htmlFor == elementId){
				header = allLabels[i].innerHTML;
				if(header.toLowerCase().indexOf("<span") > -1)
					header = header.substring(0, header.toLowerCase().indexOf("<span"));
					
				break;
			}
		}
	
		return header;
	},
	/**
	 *  Returns validators for form element with specific id
	 *  
	 *  @param elementId
	 *	The id of the element to find validators for
	 *	
	 *	@returns
	 *	A string with one or more validators separated with whitespace
	 */
	getValidators: function(elementId){
		var validators = "";
		if (elementId != "") {
			var elm = $(elementId);
			if ((typeof elm.up('fieldset.checkboxgroup') != 'undefined') || (typeof elm.up('fieldset.radiobuttongroup') != 'undefined')) {
				return $(elementId).up('fieldset').className;
			}
		}
		var allLabels = Settings.scope.select('label');
		
		for(var i = 0; i < allLabels.length; i++){	
			if(allLabels[i].htmlFor == elementId){
				validators = allLabels[i].className;
				break;
			}
		}
	
		return validators;
	},
	/**
	 *	Shows an error message if an error ocurred
	 *	
	 *	@param elementId
	 *		The elementId of the formelement which will be used
	 *		as a part to form the div id to show.
	 *	
	 *	@param message
	 *		The error message to show
	 *	
	 *	@param isHeader
	 *		Indicate if we are showing a specific error
	 *		or the general error message.
	 *	
	 *	@param theFormId
	 *		The id on the form	
 	 */
	showErrorMessage: function(elementId, message, isHeader, theFormId){
		
		if(isHeader == false) {
			var div = this.getErrorElement(elementId);// $$(this.errorDiv +
														// elementId)[0];
		} else {
			var div = this.getErrorElement(theFormId);// $$(this.errorDiv)[0];
		}
		
		var span = Settings.scope.select("span#" + elementId + "Exclamationmark");
		
		if(span != null && span.length > 0){
			span[0].className = "exclamationmark_visible";
		}
			
		if(div != null){
			div.className = "error";
			div.innerHTML = "<p>" + message + "</p>";
			return true;
		}
		
		return false;
	
	},
	/**
	 * Hides an error message if an error ocurred
	 *	@param
	 *		The form element id.
	 *	@param isHeader
	 *		Indicate if we are hiding a specific error
	 *		or the general error message
	 *	@param theFormId
	 *		The id on the form.
	 */
	hideErrorMessage: function(elementId, isHeader, theFormId){
	
		if(isHeader == false)
			var div = this.getErrorElement(elementId);// $$(this.errorDiv +
														// elementId)[0];
		else
			var div = this.getErrorElement('error' + theFormId);// $$(this.errorDiv)[0];
			
		var span = Settings.scope.select("span#" + elementId + "Exclamationmark");
		
		if(span != null && span.length > 0){
			span[0].className = "exclamationmark_hidden";
		}
			
		if(div != null){
			div.innerHTML = "";
			div.className = "errorHidden";
			return true;
		}
		
		return false;
		
	},
	/**
	 *	Deletes a default value form a select-multiple box, usually an item with an empty value
	 *		@param formElement
	 *			The form element (select-multiple)
	 */
	deleteDefaultValue: function(formElement){
		//Delete the default value before submitting (if it is still there)
		for(i = formElement.length - 1; i >= 0; i--){
			if(formElement.options[i].value == "")
				formElement.remove(i);
		}
	},
	/**
	 *	Hides all previous error messages.
	 *		@param elementId
	 *			The form element id
	 *		@hideAll
	 *			Indicates if all errors will be hidden or if
	 *			all eccept one (@param elementId).
	 */
	hideAllErrorMessages: function(elementId, hideAll){
		var allDivs = Settings.scope.select('DIV');
		for(var i = 0; i < allDivs.length; i++){
			if(hideAll == true){
				if(allDivs[i].className == "error")
					allDivs[i].className = "errorHidden";
			}
			else{
				if(allDivs[i].className == "error" && allDivs[i].id != elementId)
					allDivs[i].className = "errorHidden";
					
			}
		}
	},
	/**
	 *	Makes sure that the ModalWindow appearance is ok.
	 */
	adjustModalWindow: function(){
		// removed since it has no function and created 
		// a unwanted blink effect.
		// See #1565
		// ModalWindow.finishLoad();
		
		// scroll to the top of the window.
		if(typeof($('modalWindowInner')) != "undefined" && $('modalWindowInner') != null){
			if(typeof($('modalWindowInner').childElements()[0]) != "undefined" && $('modalWindowInner').childElements()[0] != null){
				$('modalWindowClose').focus();
				ModalWindow.reposition();
			}else{
				var errs = $$('div.mainColumn div.error');
				if(errs.length>0) $$('div.mainColumn div.error')[0].scrollTo();
			}
		}
	},
	/**
	 *	Focus the first field in the form.
	 *		@param theForm
	 *			The form element
	 */
	initForm: function(theForm){
		for(var i = 0; i < theForm.elements.length; i++){
			var type = theForm.elements[i].type;
			var element = theForm.elements[i];
			
			if(type == "text" || type == "textarea"){
				element.focus();
				break;
			}
		}
	},
	
	/**
	 *	Check if the page has multiple login forms.
	 */
	hasDuplicateLogin: function(){
		var allForms = $$("form#formLoginStart");
		var allDivs = $$("div#login_container");
		return allForms.length > 1 && allDivs.length > 1;
	
	},
	
	/**
	 *	Get the error (div element) element to show the error message in.
	 *	@param elementId
	 *		The element.
	 */
	 
	getErrorElement: function(elementId) {
		var elm = $(elementId);
		if (elm != null) {
			if ((typeof elm.up('fieldset.checkboxgroup') != 'undefined') || (typeof elm.up('fieldset.radiobuttongroup') != 'undefined')) { 
				return elm.up('fieldset').select('div[class^=error]')[0];
			} else {
				var div = null;
				if (this.hasDuplicateLogin() && this.isModalVisible()) {
					var id = "error" + elementId;
					var divs = this.currentForm.getElementsByTagName("DIV");
					for (var i = 0; i < divs.length; i++) {
						if( (divs[i].className == "error" || divs[i].className == "errorHidden") && divs[i].id == id){
							div = divs[i];
							break;
						}
					}
				} else {
					div = this.currentForm.select('#error'+elementId)[0];
				}				
				return div;
			}
		}
	},
	/**
	 *	Check if the ModalWindow is visible or not.
	 */
	isModalVisible: function(){
		var modalDiv = $("modalWindowWrapper");
		return (modalDiv && modalDiv.style.display == "block");
	},
	/**
	  * Checks if there are error container elements on the page
	  *
	  */
	  
	hasPageErrorElements: function(){
		return $$('div[id*=error]').size() > 0;	
	},
	
	errorElementExist: function(elementId){
		if (Settings.scope.select( "div#error" + elementId).size() > 0) return true;
		var group = $(elementId).up('fieldset[class*=group]');
		return group && group.select('div[class^=error]').length > 0;
	}
};

/**
 * Init form validation on all existing forms on the page.
 */
function prepareFormValidation() {
	if(!Settings.isEnabled('FormValidation')) return;
	
	
	if ($$("form#articleUserGeneratedForm").length > 0) {
	
		// Special f√∂r Medlemsartikeln / na_fredrik
		Settings.scope.select("form#articleUserGeneratedForm").each( function(item){
			Event.observe(item,'submit',function(e) {
				var f = e.element();
				var firedButton = f.select(Form.cn.firedBtn);
				var noValidation = false;
				
				if(firedButton.length > 0) {
					var classNames = firedButton[0].value.toLowerCase();
					noValidation = (classNames.indexOf('btndefault') == -1);
				}
				
				if (noValidation == false) {
					if (!FormValidation.checkForm(f)) e.preventDefault();
				}
			});
		});
	}
	else
	{		
	    Settings.scope.select("form").each( function(item){
			Event.observe(item,'submit',function(e) {
				var f = e.element();
				var firedButton = f.select(Form.cn.firedBtn);
				var cancelButtonPressed = false;
				
				if(firedButton.length > 0) {
					cancelButtonPressed = firedButton[0].value.toLowerCase().indexOf('btncancel') >= 0 || firedButton[0].value.toLowerCase().indexOf('btnclose') >= 0;
				}
				
				if (cancelButtonPressed == false) {
					if (!FormValidation.checkForm(f)) e.preventDefault();
				}
			});
		});
	}
}


/* *** End FormValidation *** */

/* *** FormEnhancedHelp *** */

var FormEnhancedHelp = {
  install: function() {
    $$('input[type=text].enhancedHelp,textarea.enhancedHelp').each(function(textField) {
      if (textField.title == '') return;      
      FormEnhancedHelp.onTextFieldBlur(textField);
      $(textField).observe('focus', function(event) {				
        FormEnhancedHelp.onTextFieldFocus(event.element());
      });
      $(textField).observe('blur', function(event) {
        FormEnhancedHelp.onTextFieldBlur(event.element());
      });
      $(textField).observe('mkt:formfield:willinject', function(event) {
        FormEnhancedHelp.onTextFieldFocus(event.element());
      });		
    });
  },
  
  onTextFieldFocus: function(textField) {
    if (textField.value == textField.title) {
		textField.value = '';
		CharacterCounter.countChars(textField);
	}
  },
  
  onTextFieldBlur: function(textField) {
    if (textField.value == '') {
		textField.value = textField.title;
	}
  }
};
 
/* *** End FormEnhancedHelp *** */


/* *** Modal Window *** */

/**
 * Gets defined window options for the given element, or a default setting if no
 * custom options are set. This function is called every time a ModalWindow
 * instance is loaded or reloaded. See wiki for further explanations.
 * 
 * @param url
 *            String URL, in case element isn't a link
 * 
 * @param element
 *            The event element
 * 
 */
function getModalOptions(url, element) {
	// Default options
	var options = {
		beforeLaunch : null,
		params : {
			href: url,
			type: null,
			reloadLinks : true,
			reloadOnClose : false,
			closeButton : true,
			scrollable : false,
			wrapperClass : null
		},
		onload : null,
		onsubmit : null,
		onunload : null,
		evalResponse : null
	};
	
	if(element.className.length > 0) {
		var wcl = "";
		var cns = element.className.split(" ");
		for(var i=0,max=cns.length;i<max;i++){
			wcl += "mw_"+cns[i]+" ";
		}
		options.params.wrapperClass = wcl;
	}
	
	if(element.id.length > 0) {
		options.params.wrapperClass += "mw_"+element.id+" ";
	}
	
	// Customize options by element classnames
	
	if(element.hasClassName('tipAFriend')) {
		options.params.width = 300;
	}
	
	else if(element.hasClassName('reportForm')) {
	}
	
	else if(element.hasClassName('viewMyPhoto')) {
		options.params.width = 468;
		options.onload = function() {
			MyPhotos.initViewer();
		};
	}
	
	else if(element.id == "registerAndEditForm") {
		options.onload = function() {
			if ($$("#modalWindowWrapper p.back a").length > 0) {
				$$("#modalWindowWrapper p.back a")[0].onclick = function(){
					ModalWindow.reload(addQueryStringParam(this.href, "m", "modal"), this);
					return false;
				};
			}
		};
		options.evalResponse = function(response) {
			if($$("#modalWindowWrapper div.confirmation").length > 0) {
				ModalWindow.options.reloadOnClose = true;
			}
			else if($$("#modalWindowWrapper div.loggOffContainer").length > 0){
				ModalWindow.options.reloadOnClose = true;
			}
		};
		options.onsubmit = function() {
			setFormCookie('acceptsCookies');
			return true;
		};
	}
	
	else if(element.id == 'formLoginStart') {
		options.onsubmit = function() {
			setFormCookie('acceptsCookies');
			return true;
		};
		options.evalResponse = function(response){
			if($$("#modalWindowWrapper #registerAndEditForm").length > 0) {
				ModalWindow.time.delay = (10000*90);
				location.assign(location.href);
				/*
				 * for (var i=0; i < element.elements.length; i++) { var inpt =
				 * element.elements[i]; if(inpt.name == "redirectUrl") {
				 * location.assign(inpt.value.replace(/m=modal/,"")); break; } }
				 */
			}
		};
	}
	
	else if(element.id == 'confirmRemoval') {
		options.params.reloadOnClose = true;
	}
	
	else if(element.id == 'registerConfirmForm') {
		options.onload = function() {
			for (var i=0; i < element.elements.length; i++) {
				var inpt = element.elements[i];
				if(inpt.name == "redirectUrl") {
					inpt.value = addQueryStringParam(inpt.value,"m","modal");
					break;
				}
			}
		};
		options.params.reloadOnClose = true;
		options.onsubmit = function() {
			setFormCookie('acceptsCookies');
			return true;
		};
	}
	
	else if(element.id == 'recoverPasswordForm') {
		options.onload = function() {
			for (var i=0; i < element.elements.length; i++) {
				var inpt = element.elements[i];
				if(inpt.name == "redirectUrl") {
					inpt.value = addQueryStringParam(inpt.value,"m","modal");
					break;
				}
			}
		};
	}
	
	else if(element.id == 'reportContent') {

	}
	
	else if(url == 'blogFormExtras_link') {
		options.onload = function() {
			Blog.ManageEntry.prepareLinkDialog();
		};
		options.params.reloadLinks = false;
	}
	
	else if(url == 'blogFormExtras_image') {
		options.onload = function() {
			Blog.ManageEntry.prepareImageDialog();
		};
		options.params.reloadLinks = false;
	}
	
	else if(url.match(/blogFormExtras_m(?:ovie|kt{1,2}v)/)) {
		options.onload = function() {
			Blog.ManageEntry.prepareMovieDialog();
		};
		options.params.reloadLinks = false;
	}
	
	return options;
}

/**
 * The MKTWebb lightbox/thickbox copy. Needs Prototype 1.6 or higher to work properly.
 */
var ModalWindow = {
	progress:null,
	anchor:null,
	options : {
		iefixClassName : null,
		href : null,
		top : null,
		left : null,
		type :	null,
		height : null,
		width :	null,
		reloadLinks : true,
		reloadOnClose : false,
		scrollable : false,
		closeButton : true
	},
	loader : null,
	wrapper : null,
	inner : null,
	errors : null,
	overlay : null,
	onload : null,
	onunload : null,
	evalResponse : null,
	labels : {
		exception : "Ett fel intr\u00E4ffade. Var god st\u00E4ng f\u00F6nstret och f\u00F6rs\u00F6k igen om en stund.",
		notFound : "Sidan finns inte.",
		loading : "H\u00E4mta eller ",
		cancel : "avbryt",
		close : "St\u00E4ng"
	},
	elabel : null,
	buttons: {
		close: null,
		cancel:null
	},
	time : {
		delay : 800, // how long to show loader before quiting
		durationShrink : 0.0, // how long the window shrink time is
		// overlay fade in and out
		durationOverlay : 0.0, 
		fpsOverlay : 1,
		// loader fade in and out
		durationLoader : 0.0, 
		fpsLoader : 1
	},
	/**
	 * Open a modal window. This is how the "outside" can create a new ModalWindow.
	 * 
	 * @param {Object} options	created from getModalOptions(). required.
	 */
	open : function(options) {
		ModalWindow.progress = null;
		if(this.overlay.style.display == "block") return;
		this.options = Object.extend({
			iefixClassName : null,
			href : null,
			top : null,
			left : null,
			type : null,
			height : null,
			width : null,
			wrapperClass : null,
			reloadLinks : true,
			reloadOnClose : false,
			scrollable : false,
			closeButton : true
		}, options || {});
		this.iefix.ie6_selects("open");
		this.flashfix("open");
		this.wrapper.setStyle({width:'',height:'',display:''});
		this.inner.setStyle({width:'',height:'',display:''});
		this.initLoader(function(){
			ModalWindow.load(ModalWindow.options.href);
		});
		return false;
	},
	importInline : function(options) {
		ModalWindow.progress = null;
		this.options = Object.extend({
			iefixClassName : null,
			href : null,
			top : null,
			left : null,
			type : null,
			height : null,
			width : null,
			wrapperClass : null,
			reloadLinks : true,
			reloadOnClose : false,
			scrollable : false,
			closeButton : true
		}, options || {});
		this.iefix.ie6_selects("open");
		this.flashfix("open");
		var c = this;
		this.wrapper.setStyle({width:'',height:'',display:''});
		this.inner.setStyle({width:'',height:'',display:''});
		this.initLoader(function(){
			var htlm = $(c.options.href).cloneNode(true);
			htlm.id += "-eyecandy";
			if(htlm.select("input").length>0 && htlm.select("form").length==0) {
				var actile = $(c.options.href).up('form').action;
				c.options.href = actile;
				htlm = htlm.wrap('form',{action:actile,'method':'post','target':Form.iframe.id,'enctype':'multipart/form-data'});
				htlm = htlm.wrap('div',{'id':'userForm'});
			}
			htlm.select('input[id]').each(function(item){
				var l = item.id+"-eyecandy";
				var lbl = htlm.select("label[for="+item.id+"]");
				if(lbl.length>0) lbl[0].setAttribute('for',l);
				item.id = l;
			});
			c.inner.insert(htlm);
			if(typeof c.evalResponse == "function") c.evalResponse();
			setTimeout(function(){
				ModalWindow.finishLoad();
			}, ModalWindow.time.delay);
		});
		return false;
	},
	importFromIframe : function(options,htlm) {
		this.options = Object.extend({
			iefixClassName : null,
			href : null,
			top : null,
			left : null,
			type : null,
			height : null,
			width : null,
			wrapperClass : null,
			reloadLinks : true,
			reloadOnClose : false,
			scrollable : false,
			closeButton : true
		}, options || {});
		this.iefix.ie6_selects("open");
		this.flashfix("open");
		this.inner.insert(htlm);	
		var c = this;
		
 		if(typeof c.evalResponse == "function") c.evalResponse();
		setTimeout(function(){
			c.finishLoad();
		}, this.time.delay);

		return false;
	},
	/**
	 * refresh the options for the new modal window. Is called every time the window reloads with new content.
	 * 
	 * @param {Object} options	the result from a openAsModal call.
	 */
	loadOptions : function(options) {
		if (typeof options.beforeLaunch == "function") options.beforeLaunch();
		this.onload = options.onload;
		this.onunload = options.onunload;
		this.evalResponse = options.evalResponse;
		this.options = Object.extend({
			iefixClassName : null,
			href : null,
			top : null,
			left : null,
			type : null,
			height : null,
			width : null,
			wrapperClass : null,
			reloadLinks : true,
			reloadOnClose : false,
			scrollable : false,
			closeButton : true
		}, options.params || {});
	},
	/**
	 * Evaluates the content size, then expand and reposition window. Is called every time a form don't pass validation, but
	 * can also be called manually. 
	 */
	reposition : function() {
		if (this.wrapper != null && this.wrapper.style.display && this.wrapper.style.display == 'block') {
			this.inner.setStyle({
				height:''
			});
			this.wrapper.setStyle({
				height:''
			});
			var y = this.wrapper.getHeight();
			if (y != parseInt(this.height,10)) {
				var old = this.options.height;
				this.options.height = y;
				this.getDimensions();
				this.renderWindow();
				this.options.height = old;
			}
		}
	},
	cancel : function() {
			return this.close();
	},
	findReloader : function(){
		if(this.wrapper.select('.reloadOnClose').length > 0){
			this.options.reloadOnClose = true;
		};
	},
	/**
	 * Closes the Modal Window. Also quits any ajax calls quietly.
	 */
	close : function() {
		ModalWindow.progress = "close";
		if(this.currentAnimation) this.currentAnimation.cancel();
		this.currentAnimation = new Effect.Opacity(this.overlay,{
			from:0.7,
			to:0,
			duration:this.time.durationLoader,
			fps:this.time.fpsLoader
		});
		this.wrapper.setStyle({ display:'',width:'',height:'' });
		this.loader.setStyle({ display:'', width:'', height:'', marginTop:'', marginLeft:'' });
		this.errors.setStyle({ display:'' });
		this.inner.setStyle({ width:'',height:'' });
		this.inner.innerHTML = "";
		this.elabel.nodeValue = "";
		if(typeof this.onunload == "function") this.onunload();
		document.fire('mkt:modal:close');
		if(this.options.reloadOnClose == true) location.assign( location.href );
		this.iefix.ie6_selects("close");
		this.flashfix("close");
		var c = this;
		setTimeout(function(){c.overlay.setStyle({ display:'' });},(c.time.durationOverlay*1000)+5);
		return false;
	},
	/**
	 * Init variuos buttons. The classnames attach events to buttons, ex .close make the button close the Modal. 
	 */
	initButtons : function() {
		var c = this;
		$$("#modalWindowWrapper .close").each(function(item){
			item.onclick = function(){return c.close();};
		});
		$$("#modalWindowWrapper .btnOk").each(function(item){
			item.onclick = function(){return c.close();};
		});
	},
	/**
	 * Invoke method. Initiates and prepares the Modal Window markup.
	 */
	init : function() {
		if($$(Chat.App.cn.bclass).length > 0 
			|| $$('body.modalWindow').length > 0 
			|| $$('body.print').length > 0 
			|| $('modalWindowWrapper')) { return; }
		var c = this;
		var b = $$("body")[0];
		
		this.loader = document.createElement("div");
		this.loader.id = "modalWindowLoader";
		this.loader.innerHTML = '<p>'+this.labels.loading+' <a href="#" onclick="return ModalWindow.close();">'+this.labels.cancel+'</a></p>';
		this.loader.style.visibility = 'hidden';
		this.loader.style.display = 'block';
		
		this.errors = document.createElement("div");
		this.errors.id = "modalWindowErrors";
		this.errors.innerHTML = '<p></p><p><a class="close" href="#" onclick="ModalWindow.cancel(); return false;">'+this.labels.close+'</a></p>';
		
		this.wrapper = document.createElement("div");
		this.wrapper.id = 'modalWindowWrapper';
		this.wrapper.innerHTML = '<a name="focusModalWindow" id="focusModalWindow" href="">.</a>' + 
								 '<div id="modalWindowInner"></div>' +
								 '<a id="modalWindowClose" href="#" class="close">'+this.labels.close+'</a>';
		
		this.overlay = document.createElement("div");
		this.overlay.id = "modalWindowOverlay";
		this.overlay.onclick = function(){return c.close();};
		
		var ihv = document.createDocumentFragment();
		
		this.elabel 	= document.createTextNode('');
		
		ihv.appendChild(this.loader);
		ihv.appendChild(this.errors);
		ihv.appendChild(this.wrapper);
		ihv.appendChild(this.overlay);
		Settings.scope.appendChild(ihv);
		
		this.loader 	= $(this.loader);
		this.errors 	= $(this.errors);
		this.wrapper 	= $(this.wrapper);
		this.overlay 	= $(this.overlay);
		this.inner 		= $('modalWindowInner');
		this.anchor 	= $('focusModalWindow');
		this.mainclose 	= $('modalWindowClose');
		
		this.errors.select('p')[0].appendChild( this.elabel );
		
		
		var lolcuttr = $((function(){
			var a = document.createElement('div');
			a.id 				= 'modalWindowLoader';
			a.style.width 		= '0px';
			a.style.height 		= '0px';
			a.style.display 	= 'block';
			a.style.visibility 	= 'hidden';
			return a;
		})());// new
				// Element('div',{id:"modalWindowLoader",style:"width:0;height:0;display:block;visibility:hidden;"});
		b.insert(lolcuttr);
		this.loader.myOffset = {width:this.loader.offsetWidth, height:this.loader.offsetHeight};// lolcuttr.getDimensions();
		lolcuttr.id = "modalWindowWrapper";
		this.wrapper.myOffset = {width:this.wrapper.offsetWidth, height:this.wrapper.offsetHeight};// lolcuttr.getDimensions();
		lolcuttr.remove();
		var loaderxy = {width:this.loader.offsetWidth, height:this.loader.offsetHeight};
		this.loader.defaultSizeX = (loaderxy.width-this.loader.myOffset.width);
		this.loader.defaultSizeY = (loaderxy.height-this.loader.myOffset.height);
		this.loader.style.display = "none";
		this.loader.style.visibility = "visible";
	},
	/**
	 * displays the loader dialog while fetching the content of the Modal.
	 */
	initLoader : function(afterFinishFunc) {
		var os = document.viewport.getScrollOffsets();
		var c = this;
		// this.overlay.getStyle('display') == 'none' ||
		// this.overlay.getStyle('display') == null
		if(!this.overlay.style.display || this.overlay.style.display != "block") {
			var hA = document.viewport.getHeight();
			var hB = $$('body')[0].getHeight();
			this.overlay.setStyle({ display:"block",opacity:0,height:((hB > hA) ? hB : hA)+"px" });
			this.currentAnimation = new Effect.Opacity(this.overlay,{
				from:0,
				to:0.7,
				duration:this.time.durationOverlay,
				fps:this.time.fpsOverlay
			});
		}
		this.loader.setStyle({ 
				display:"block",
				marginTop:((c.loader.getHeight()/2) - os.top)*(-1)+"px",
				marginLeft:((c.loader.getWidth()/2) - os.left)*(-1)+"px"
			});
		if (typeof afterFinishFunc == "function") {
			new Effect.Opacity(c.wrapper,{
				from:1.0,
				to:0,
				duration:c.time.durationOverlay,
				fps:c.time.fpsOverlay,
				afterFinish : afterFinishFunc
			});
		}
		this.wrapper.className = "";
	},
	/**
	 * Shows error messages when ajax errors occur. The error message dialog is similar to the
	 * loader, but have a error sign instead of ajax loader animation.
	 * 
	 * @param {Object} value	the error code, which determines what error message to show.
	 */
	showErrors : function(value) {
		this.loader.setStyle({display:"none"});
		var os = document.viewport.getScrollOffsets();
	switch (value) {
		case 1:
		this.elabel.nodeValue = this.labels.exception;
		break;
		case 2:
		this.elabel.nodeValue = this.labels.notFound;
		break;
	}
	this.errors.setStyle({ 
		display:"block",
			marginTop:((this.loader.getHeight()/2) - os.top)*(-1)+"px",
			marginLeft:((this.loader.getWidth()/2) - os.left)*(-1)+"px"
		});
		this.initButtons();
	},
	/**
	 * Reload the Modal with other content. This method is called frm inside the modal.
	 * 
 	* @param {string} url	url to the new content.
 	*/
	reload : function(url,el) {
		if (typeof el != "undefined") {
			var options = getModalOptions(url, el);
			this.loadOptions( options );
		}
		var c = this;
		this.initLoader(function(){
			c.wrapper.setStyle({ display:'',width:'',height:'' });
			c.inner.setStyle({ width:'',height:'' });
			c.inner.innerHTML = "";
			c.load(url);
		});
		return false;
	},
	resetWrapper : function() {
		this.wrapper.setStyle({ display:'',width:'',height:'' });
		this.inner.setStyle({ width:'',height:'' });
	},
	/**
	 * Load the content and append it to Modal. This is done by an ajax request.
	 * 
	 * @param {string} url
	 */
	load : function(url) {
		this.iefix.ie6_width(this);
		var funcObj = {
			OnSuccess : function(response){
				if (typeof ModalWindow.evalResponse == "function") {
					ModalWindow.evalResponse(response);
				}
				setTimeout(function(){
					ModalWindow.finishLoad();
				}, ModalWindow.time.delay);
			},
			OnException : function(response){
				ModalWindow.showErrors(1);
			}, 
			OnFailure : function(response){
				ModalWindow.showErrors(2);
			}
		};
		mktAjax.load( url, this.inner, funcObj);
	},
	/**
	 * Makes some general link fixes. Similar to initLinkExtensions(), but for Modal purposes.
	 */
 	hreffix : function() {
 		if (!this.options.reloadLinks) return;

		this.wrapper.select("* a").each(function(el) {
  	  if (/^e(xternal|nhanced)$/.test(el.getAttribute('rel'))) return;
  		if (el.href.indexOf("javascript:") >= 0) return;
  		if (el.hasClassName('toggleContent') || el.hasClassName('toggleTerms')) return;
  	  
  		el.href = addQueryStringParam(el.href, "m", "modal");
  		el.onclick = function() {
  			return ModalWindow.reload(this.href,this);
  		};
		});
 	},
	/**
	 * Init form instances and prepare onsubmit events. Custom onsubmit events is stored by openAsModal() utilities based on the form's ID.
	 */
	initForms : function() {
		var c = this;
		var forms = $$("#modalWindowWrapper form");
		if (forms.length > 0) {
			var userFormExists = false;// UserForm.exists() ||
										// Form.iframe.exists();
			forms.each(function(f){
				if ((f.action.indexOf && f.action.indexOf("#") > 0) || f.action == "#"  || f.action == null || f.action == "") {
					f.action = c.options.href;
				}
				if (!userFormExists) {
					openAsModal(f);
				}else{
					f.action = addQueryStringParam(f.action,'m','modal');
				}
				for(var i = 0; i < f.elements.length; i++){
					if(f.elements[i].type == "text" || f.elements[i].type == "textarea"){
                    	f.elements[i].focus();
                        break;
                    }
                }
			});
		}
	},
	/**
	 * Send form event inside a Window, works much like reload(). This method is called from th openAsModal function.
	 * @param {String} url		the action url
	 * @param {String} pbody	the POST body. Is set by openAsModal().
	 */
	sendForm : function (url,form,options) {
		ModalWindow.progress = null;
		this.options = Object.extend({
			iefixClassName : null,
			href : null,
			top : null,
			left : null,
			type : null,
			height : null,
			width : null,
			wrapperClass : null,
			reloadLinks : true,
			reloadOnClose : false,
			scrollable : false,
			closeButton : true
		}, options || {});
		var c = this;
		this.initLoader(function(){
			c.wrapper.setStyle({ display:'',width:'',height:'' });
			c.inner.setStyle({ width:'',height:'' });
			c.iefix.ie6_width(c);
			var funcObj = {
				OnSuccess : function(response){
						if (response.responseText != "") {
							if (typeof ModalWindow.evalResponse == "function") {
								ModalWindow.evalResponse(response);
							}
							setTimeout(function(){
								ModalWindow.finishLoad();
							}, ModalWindow.time.delay);
						}else{
							ModalWindow.close();
						}
				},
				OnException : function(response){
					ModalWindow.showErrors(1);
				}, 
				OnFailure : function(response){
					ModalWindow.showErrors(2);
				}
			};
			mktAjax.send(url, c.inner, form, funcObj);
		});
		return false;
	},
	/**
	 * Finish the (successfull) ajax load by appending the content and hide the loader.
	 */
	finishLoad : function() {
		// this.overlay.getStyle("display") == "none" || this.overlay.getStyle("display") == null
		if (ModalWindow.progress == 'close') {
			this.wrapper.setStyle({display:''});
			this.loader.setStyle({display:''});
			ModalWindow.progress = null;
		}else {
			this.wrapper.setStyle({
				width:"auto",
				height:"auto",
				marginTop:"0",
				marginLeft:"0"
			});
			this.wrapper.addClassName("factory");
			if (this.options.reloadLinks) {
				this.hreffix();
			}
			this.initButtons();
			if(!this.options.closeButton) {
				this.mainclose.setStyle({display:"none"});
			}else{
				this.mainclose.setStyle({display:"block"});
			}
			this.findReloader();
			this.getDimensions();
			var c = this;
			this.renderWindow(function(){
				c.anchor.focus();
				c.initForms();
				if (typeof c.onload == "function") c.onload();
				c.wrapper.className = c.options.wrapperClass;
				c.wrapper.className += c.getChildWrapperClass();
			});
		}
	},
	getChildWrapperClass : function() {
		if(this.inner.innerHTML) {
			var cw = this.inner.select("div");
			
			if(cw.length > 0) {
				var cls = " ";
				var element = (cw[0].className=='modalWindow') ? cw[1] : cw[0];
				if(element.className.length > 0) {
					var wcl = "";
					var cns = element.className.split(" ");
					for(var i=0,max=cns.length;i<max;i++){
						if(!this.wrapper.hasClassName("mw_"+cns[i])) {
							wcl += "mw_"+cns[i]+" ";
						}
					}
					cls += wcl;
				}
				
				if(element.id.length > 0) {
					cls += "mw_"+element.id+" ";
				}
				return cls;
			}
		}
		return "";
	},
	/**
	 * Render the window: remove the loader, set sizes and positions and make the loaded content visible.
	 */
	renderWindow : function(renderCallFunc) {
		//this.loader.setStyle({display:"none"});
		
		// this.loader.getStyle('display')=='block'
		if(typeof renderCallFunc == "function"){
			this.shrinkWindow(renderCallFunc);
		}else{
			this.wrapper.setStyle({
				width : this.width,
				height : this.height,
				marginTop : this.top,
				marginLeft : this.left,
				display : "block"
			});
			this.inner.setStyle({
				width : this.width,
				height : this.height
			});
			if(this.options.scrollable) {
				this.inner.addClassName("scrollable");
			}
		}
	},
	/**
	 * calculates the dimensions of the Modal. If the modal is to big to fit viewport, size is reduced.
	 * Size can be set manually by either getModalOptions() or by using CSS on the fetched content block.
	 */
	getDimensions : function() {
		var x,y,max,os;
		max = document.viewport.getDimensions();
		os = document.viewport.getScrollOffsets();
		x = (this.options.width != null) ? this.options.width : this.wrapper.getWidth();
		y = (this.options.height != null) ? this.options.height : this.wrapper.getHeight();
		this.wrapper.removeClassName("factory");
		if (this.inner.hasClassName("scrollable")) {
			this.inner.removeClassName("scrollable");
		}
		
		if (max.width <= x+this.wrapper.myOffset.width) {
			x = (max.width - 20);
			this.inner.addClassName("scrollable");
			this.iefix.ie67_overflowx(this,x);
		}
		if (max.height <= y+this.wrapper.myOffset.height) {
			y = (max.height - 20);
			this.inner.addClassName("scrollable");
			this.iefix.ie67_overflowy(this,y);
		}
		this.width = parseInt(x-this.wrapper.myOffset.width,10) + "px";
		this.height = parseInt(y-this.wrapper.myOffset.height,10) + "px";
		this.top = parseInt((((y)/2)-os.top)*(-1),10) + "px";
		this.left = parseInt((((x)/2)-os.left)*(-1),10) + "px";
	},
	/**
	 * iefixes object. This fixes some lack of standards support for ie without using browser sniffing. all methods in the object
	 * has a prefix which tells of the targeted ie version. Methods can therefore be removed when no longer needed.
	 */
	iefix : {
		ie6_selects : function(e) {
			var selfix = (e=="close") ? "visible" : "hidden";
			$$("#mainPadding select").each(function(s){
				s.setStyle({
					visibility: selfix
				});
			});
		},
		ie6_width : function(c){
			if (c.options.iefixClassName != null) {
				c.inner.addClassName(c.options.iefixClassName);
			}
		},
		ie67_overflowx : function (c,x) {
			var ft = $$("."+c.options.iefixClassName);
			if(ft.length==0) return;
			ft[0].setStyle({width:x+"px",overflow:"auto",position:"relative"});
		},
		ie67_overflowy : function (c,y) {
			var ft = $$("."+c.options.iefixClassName);
			if(ft.length==0) return;
			ft[0].setStyle({height:y+"px",overflow:"auto",position:"relative"});
		}
	},
	/**
	 * Cross browser flash fixes. Called initially to hide flash movies below the overlay, 
	 * and called again onclose to restore visibility.
	 */
	flashfix : function(e) {
		var fix = (e=="close") ? "visible" : "hidden";
		$$('#mainPadding .flashContent','#mainPadding object','#mainPadding embed','#mainPadding iframe').each(function(b){
			b.setStyle({visibility:fix});
		});
	},
	shrinkWindow : function(renderCallFunc){
		// what should we do?
		// shrink loader to the correct size, fade out and fade in content.
		var c = this;
		var newX, newY, oY, oX;
		newY = parseInt((parseInt(c.height,10) - c.loader.myOffset.height + c.wrapper.myOffset.height),10) + "px";
		newX = parseInt((parseInt(c.width,10) - c.loader.myOffset.width + c.wrapper.myOffset.width),10) + "px";
			this.currentAnimation = new Effect.Morph(this.loader, {
				style: {
					width: newX,
					height:  newY,
					marginTop: c.top,
					marginLeft: c.left
				},
				duration: this.time.durationShrink,
				afterFinish: function(){
					if (!c.loader.style.display=='') {
						c.wrapper.setStyle({
							width: c.width,
							height: c.height,
							marginTop: c.top,
							marginLeft: c.left,
							display: "block",
							opacity: 0
						});
						c.inner.setStyle({
							width: c.width,
							height: c.height
						});
						new Effect.Opacity(c.wrapper, {
							from: 0,
							to: 1,
							fps: c.time.fpsOverlay,
							duration: c.time.durationOverlay,
							afterFinish: function(){
								c.loader.setStyle({
									display:''
								});
								renderCallFunc();
							}
						});
					}
				}
			});
	}
};

/**
 * Make links with rel="modal" open in ModalWindow instead of default action.
 * This is made by adding querystring M and appending the modal configuation
 * needed.
 * 
 * @param {HTMLElement}
 *            el the link element
 */
function openAsModal(el,href) {
	if(!ModalWindow.overlay) {
		ModalWindow.init();
	}
	var eType = null;
	var targetURL = null;
	if (typeof href == 'undefined') {
		var eType = (el.nodeName == "A") ? "href" : "action";
		targetURL = el.getAttribute(eType);
	}
	else {
		targetURL = href;
		eType = (!$(href)) ? 'href' : 'inline';
	}

	if (targetURL != null) {

		var evtFunc;

		if(eType=="action") {
			if(typeof el.onsubmit == 'function') return el.onsubmit;
			evtFunc = function() {
				targetURL = addQueryStringParam(targetURL, "m", "modal");
				var options = getModalOptions(targetURL, el);
				if (typeof options.beforeLaunch == "function") options.beforeLaunch();
				ModalWindow.onload = options.onload;
				ModalWindow.onunload = options.onunload;
				ModalWindow.evalResponse = options.evalResponse;
				var valid = FormValidation.checkForm(el);
				var ok = (typeof options.onsubmit == "function") ? options.onsubmit() : true;
				var lol = "";
				if(!valid) {
					ModalWindow.reposition();
				}
				if (ok && valid) {
					ModalWindow.sendForm(targetURL, el, options.params);
				}
				return false;
			};
			el.onsubmit = evtFunc;
		}else if(eType=='href'){
			if(typeof el.onclick == 'function') return el.onclick;
			evtFunc = function() {
				targetURL = addQueryStringParam(targetURL, "m", "modal");
				var options = getModalOptions(targetURL, el);
				if (typeof options.beforeLaunch == "function") options.beforeLaunch();
				ModalWindow.onload = options.onload;
				ModalWindow.onunload = options.onunload;
				ModalWindow.evalResponse = options.evalResponse;
				ModalWindow.open(options.params);
				return false;
			};
			el.onclick = evtFunc;

		}else if(eType=='inline'){
			if(typeof el.onclick == 'function') return el.onclick;
			evtFunc = function(){
				var options = getModalOptions(targetURL, el);
				if (typeof options.beforeLaunch == "function") options.beforeLaunch();
				ModalWindow.onload = options.onload;
				ModalWindow.onunload = options.onunload;
				ModalWindow.evalResponse = options.evalResponse;

				ModalWindow.inner.innerHTML = "";
				ModalWindow.importInline(options.params);
			};
			el.onclick = evtFunc;
		}
		return evtFunc;
	}
}


/* *** News lists functions *** */

/**
 * NewsList object, shared by "Senaste Nytt" and "Mest l√§sta" services.
 * Enhance news lists by toggle functionality.
 */
var NewsList = {
	NEWSLIST_CONTAINER_CLASS : "newsListContainer",
	NEWSLIST_NAVIGATION_TAGNAME : "li",
	NEWSLIST_NAVIGATION_SELECTED_CLASSNAME : "selected",
	NEWSLIST_NAVIGATION_DESELECTED_CLASSNAME : "",	
	/**
	 * Search the page for instances of NewsLists and return boolean as answer.
	 */
	exists : function() {
	  this.lns = Settings.scope.select("div.latestNewsContainer", "div.readerListContainer"); 		
		return this.lns.length > 0;
	},
	/**
	 * Init method. 
	 * Prepares newslists interaction schemes for readersList and LatestNews.
	 * LatestNews also gets handmade toggle functionality.
	 * 
	 */
 	init : function() {
 		for(var x=0; x<this.lns.length; x++) {
 			var wrap = this.lns[x];
 			var titles = wrap.select("div.contentContainer ul.newsNavigation li a");
 			var cnts = wrap.select("div.contentContainer div.newsListContainer");

 			for(var i=0; i<titles.length; i++) {
 				if(cnts[i]) {
 					cnts[i].style.display = (i>0) ? "none" : "block";
 					cnts[i].id = "newList_"+(Math.round( Math.random()*1000 ));
 					this.registerShowNewsList(titles[i], wrap, cnts[i], i);
 				}
 			}
 			if (wrap.hasClassName("latestNewsContainer")) {
 				var tl = wrap.select("div.contentContainer div.newsListContainer a.entire_list");
 				for (var i = 0; i < tl.length; i++) {
           this.registertoggleLongList(tl[i],wrap);
 				}
 			}
 		}
 	},
	/**
	 * registers to help newslists to keep scope. 
	 * 
	 * @param {HTMLElement} elem	the element to toggle visible
	 * @param {HTMLElement} wrap	the wrapper reference
	 */
	registertoggleLongList : function(elem,wrap) {
		var c = this;
		elem.onclick = function(){ return c.toggleLongList(this, wrap); };
	},
	/**
	 * registers to help newslists to keep scope. 
	 * 
	 * @param {HTMLElement} elem	the element to toggle visible
	 * @param {String} containerId	
	 * @param {String} newsListId
	 * @param {Integer} navPosition
	 */
	registerShowNewsList : function(elem, containerId, newsListId, navPosition) {
		var c = this;
		elem.onclick = function(){ return c.showNewsList(elem, containerId, newsListId, navPosition); };
	},
	/**
	 *  Shows the selected newslist.
	 * This method does two things:
	 * 1. Iterates the newslist containers and shows 
	 *    the one asked for, and hides the others.
	 * 2. Iterates the navigation elements and 
	 *    changes their classes. This is to mark the
	 *    button selected.
	 *  
	 */
	showNewsList : function(elem, containerDiv, selectedNewsList, navPosition) {
		// Get list of containers and show the one asked for, hide the rest
		var lists = containerDiv.getElementsByTagName("div");
		for (var i = 0; i < lists.length; i++) {
			var tempDiv = lists[i];
			if(tempDiv.style) {
				// Only affect elements with the required classname
				if(tempDiv.className == this.NEWSLIST_CONTAINER_CLASS) {
					if(tempDiv.id == selectedNewsList.id) {
						tempDiv.style.display = "block";
					}else{
						tempDiv.style.display = "none";
					}
				}
			}
		}
		// Iterate all nav-elements and set their classNames
		var liList = containerDiv.getElementsByTagName(this.NEWSLIST_NAVIGATION_TAGNAME);
		for (var i = 0; i < liList.length; i++) {
			var li = liList[i];
			if(i == navPosition) {
				li.className = this.NEWSLIST_NAVIGATION_SELECTED_CLASSNAME;
			}else{
				li.className = this.NEWSLIST_NAVIGATION_DESELECTED_CLASSNAME;
			}
		}
		return false;
	},
	/**
	 * Toggles the newslist between short or long list.
	 * 
	 * @param {HTMLElement} elem	the element to toggle children in
	 * @param {HTMLElement} wrap	the wrapper
	 */ 
	toggleLongList : function(elem,wrap) {
		var cats = wrap.getElementsByTagName('dl');
		for(var j=0; j<cats.length ; j++ ) {
			var news = cats[j].getElementsByTagName('dt');
			for(var i=0; i<news.length ;i++) {
				if(news[i].className == 'visibleAfterToggle') {
					news[i].className = 'hiddenAfterToggle';
					var next = news[i].nextSibling;
					if(next.nodeName!='DD') next = next.nextSibling;
					next.className = 'hiddenAfterToggle';
				} else if(news[i].className == 'hiddenAfterToggle') {
					news[i].className = 'visibleAfterToggle';
					var next = news[i].nextSibling;
					if(next.nodeName!='DD') next = next.nextSibling;
					next.className = 'visibleAfterToggle';
				}
			}
		}
		var tl = wrap.select('a.entire_list');
		for(var i=0;i<tl.length;i++) {
			var elem = tl[i];
			if(elem.className == 'entire_list visibleAfterToggle') {
					elem.className = 'entire_list hiddenAfterToggle';
				} else {
					elem.className = 'entire_list visibleAfterToggle';
				}
		}
		return false;
	}
};

/**
 * Invoke method. Search the page for NewsList instances and activate the JS
 * enhancement if found.
 */
function prepareNewsLists() {
	if(NewsList.exists()) {
		NewsList.init();
	}
}





/* *** Site Settings *** */

/**
 * Tool to allocate disabled features by site-specific JS.
 * 
 * @type Object
 */
var Settings = {
	/**
	 * Contains List of disabled features for current page.
	 * 
	 * @type {Array} Arry set by sitejs
	 * @fieldOf Settings
	 */
	disabled : [],
	scope : null,
	/**
	 * invoke method: fetches the disabledFeatures array from site-specific JS 
	 * 
	 * @type void
	 * @returns void
	 * @methodOf Settings
	 */
	init : function(scope) {
		this.scope = scope;
		this.disabled = (typeof disabledFeatures == "undefined") ? [] : disabledFeatures;
	},
	/**
	 * Checks if a functionality is enabled or disabled. Returns bool.
	 * 
	 * @returns {Boolean} is the quested feature enabled?
	 * @param {String} name	The keyword to the service
	 * @type Boolean
	 */
	isEnabled : function(name) {
		return this.disabled.toString().indexOf(name) < 0;
	}
};

/* *** Toggler *** */

var Toggler = {
	classnames : {
		hidden : 'visibleAfterToggle',
		visible : 'hiddenAfterToggle',
		expanded : 'expanded',
		toggable : 'fieldset.toggable',
		dnt : 'open'
	},
	defaults : {
		extendedSearch : false
	},
	labels : {
		show : "Visa",
		hide : "G√∂m"
	},
	toggler : null,
	hide : function(element) {
		element.addClassName( this.classnames.hidden );
		element.removeClassName( this.classnames.visible );
		ModalWindow.reposition();
	},
	show : function(element) {
		element.addClassName( this.classnames.visible );
		element.removeClassName( this.classnames.hidden );
		ModalWindow.reposition();
	},
	toggle : function(element) {
		var elements = element instanceof Array ? element : [element];
		var isHidden = elements.any(function(element) {
			return $(element).hasClassName(this.classnames.hidden);
		}.bind(this));
		elements.each(function(element) {
			element = $(element);
			if (isHidden) {
				element.removeClassName(this.classnames.hidden);
				element.addClassName(this.classnames.visible);
			} else {
				element.removeClassName(this.classnames.visible);
				element.addClassName(this.classnames.hidden);
			}
		}.bind(this));
		ModalWindow.reposition();
	},
	children : function(parent) {
		var c = this;
		var x = parent.select("."+this.classnames.hidden);
		var y = parent.select("."+this.classnames.visible);
		x.each(function(elm){
			c.show(elm);
		});
		y.each(function(elm){
			c.hide(elm);
		});
		ModalWindow.reposition();
	},
	restore : function(elem) {
		elem.removeClassName(this.classnames.hidden);
		elem.removeClassName(this.classnames.visible);
		ModalWindow.reposition();
	},
	ToggableContent : {
		instance : null,
		instance2 : null,
		labels :  {
			toggler : [".toggleTerms",".toggleContent"],
			content : [".toggableTerms",".toggableContent"],
			hide : "a.hide"
		},
		exists : function() {
			this.instance = Settings.scope.select(this.labels.toggler[0] + ',' + this.labels.toggler[1]);
			return this.instance.length > 0;
		},
		init : function() {
			for (var i = 0, max = this.instance.length; i < max; i++) {
				var toggler = this.instance[i];
				var cls = (toggler.hasClassName(this.labels.toggler[0].substr(1))) ? 0 : 1; 
				var taa = toggler.up(2).select(this.labels.content[cls])[0];
				
				if (taa != null) {
					this.registerToggle(toggler,taa);
					var c = this;
					taa.select(this.labels.hide).each(function(item){
						c.registerToggle(item,taa);
					});
				}
			}
		},
		registerToggle : function(toggler, toggled) {
			var a = toggled instanceof Array ? toggled : [toggled];
			a.each(function(e) { e.addClassName(Toggler.classnames.hidden); });
			Event.observe(toggler, 'click', function(e) {
				Toggler.toggle(toggled);
				e.preventDefault();
			});
		}
	},
	ToggableFieldset : {
		instance : null,
		labels : {
			toggable : 'fieldset.toggable',
			dnt : 'open'
		},
		exists : function() {
			return Settings.scope.select(this.labels.toggable).length > 0;
		},
		fieldset : function(fldset) {
			if( fldset.hasClassName(Toggler.classnames.expanded) ) return;
			var l = fldset.select('legend');
			if( l.length == 0 ) return;
			var c = this;
			fldset.select("*").each(function(item){
				Toggler.hide(item);
			});
			var item = l[0];
			item.cleanWhitespace();
			var text = /*c.labels.show + " " + */item.firstChild.nodeValue;
			var nl = new Element('a',{href:"#"}).update(text);
			Toggler.restore(item);
			
			nl.onclick = function() {
				var nlt = c.fold(this,fldset);
				return false;
			};
			Element.remove(item.firstChild);
			item.appendChild(nl);
			item.appendChild( new Element('span',{'class':'togglerIcon'}) );
		},
		fold : function(toggler,wrapper) {
			var c = this;
			if(wrapper.hasClassName( Toggler.classnames.expanded )) {
				wrapper.removeClassName(Toggler.classnames.expanded);
				Toggler.children(wrapper);
				return Toggler.labels.show;
			}else{
				wrapper.addClassName(Toggler.classnames.expanded);
				Toggler.children(wrapper);
				return Toggler.labels.hide;
			}
			ModalWindow.reposition();
		},
		init : function() {
			var c = this;
			Settings.scope.select(this.labels.toggable).each(function(item){
				if(!item.hasClassName(c.labels.dnt)) {
					c.fieldset(item);
				}
			});
		}
	}
};

function prepareTogglers() {
	if(Toggler.ToggableFieldset.exists()) {
		Toggler.ToggableFieldset.init();
	}
	if(Toggler.ToggableContent.exists()) {
		Toggler.ToggableContent.init();
	}
}

/** =====================The mktAjax object ===================================
 * extends the prototype ajax obejct with necessary mktwebb enhancements.
 */

var mktAjax = {
	load: function(url, wrapper, funcObj) {
	  this.doReply(url, wrapper, { method: 'get' }, funcObj);
	},
	
	send: function(url, wrapper, form, funcObj) {
	  this.doReply(url, wrapper, { method: 'post', postBody: Form.serialize(form) }, funcObj);
	},

  doReply: function(url, wrapper, options, funcObj) {
		new Ajax.Request(CacheUtil.noCache(url), Object.extend(options, {
			onSuccess: function(transport) {
				wrapper.innerHTML = transport.responseText;

				if (typeof funcObj.OnSuccess === 'function') {
				  funcObj.OnSuccess(transport); 
				}
				init(wrapper);

				transport.responseText.evalScripts();
			},

			onFailure: (funcObj.OnFailure || Prototype.emptyFunction),
			onException: (funcObj.OnException || Prototype.emptyFunction)
		}));
  }
};

/** ===/ mktAjax ===* */

/*
 * =========================== / 1.2 Objects
 * ================================================
 */
 
/**
 * *************************** 2. SERVICES
 * ********************************************
 */ 
 
/**
 * ========= T01.03 ========= LeftNav @ mktwebb 1.1 Left column navigation, some
 * eyecandy effects added!
 * 
 * HTML hooks: #leftNav main slide appear. #leftNav #currentSection submain
 * slide appear, main locked.
 * 
 */
function prepareLeftNav() {
	if(LeftNav.exists() && Settings.isEnabled('LeftNav')) {
		LeftNav.init();
	}
}

var LeftNav = {
	currentAnimation : null,
	animation : {
		from : 0,
		to : 0.7,
		duration : 0.5,
		currentWait : 1000,
		curtainDuration : {
			main: 1,
			current : 1.5
		}
	},
	labels : {
		selected : 'selected',
		id : 'leftNavWrapper',
		section : {
			main : 'leftNav',
			current : 'currentSection',
			subcurrent : '.deployment li ul'
		},
		jsgen : 'eyecandy',
		item : 'li.item a'
	},
	refs : {
		main : null,
		current : null
	},
	exists : function() {
		return ($(this.labels.id));
	},
	init : function() {
		enableJSStyles([$(this.labels.id)]);
		this.refs.main = $(this.labels.section.main);
		this.refs.current = $(this.labels.section.current) || null;
		if (this.refs.current != null) {
			this.prepareCurrentSection();
		}
		this.prepareMainHovers();
	},
	prepareCurrentSection : function () {
		var c = this;
		var subcur = this.refs.current.select(this.labels.section.subcurrent);
		if (subcur.length > 0) {
			var cur = subcur[0].wrap('div');
			cur.hide();
			setTimeout(function(){
				new Effect.SlideDown(cur, {
					duration:c.animation.curtainDuration.current
				});
			}, this.animation.currentWait);
		}
		else {
			var cur = this.refs.current.wrap('div');
			cur.hide();
			setTimeout(function(){
				new Effect.SlideDown(cur, {
					duration:c.animation.curtainDuration.main
				}); 
			}, this.animation.currentWait);
		}
	},
	prepareMainHovers : function () {
		var c = this;
		var mainItems = this.refs.main.select(this.labels.item);
		for(var i=0,max=mainItems.length; i<max; i++) {
			var item = mainItems[i];
			if (this.isSelected(item) == false) {
				var l = item.childElements()[0];
				var ecl = new Element('span').update(l.innerHTML);
				var ec = ecl.wrap(new Element('div').addClassName(this.labels.jsgen).setStyle({
					opacity:0,visibility:'hidden'
				}));
				item.insert({
					'top': ec
				});
				var eyec = item.childElements()[0];
				
				Event.observe(l, 'mouseover', function(e){
					var ec = this.previous();
					if (ec != null && ec.className == 'eyecandy') {
						c.hilightMain(ec);
					}
				});
				
				Event.observe(eyec, 'mouseout', function(e){
					//var ec = this;
					if (ec.className == 'eyecandy') {
						c.restoreMain(this);
					}
				});
			}
		}
	},
	isSelected : function(elm) {
		return elm.up().hasClassName(this.labels.selected);
	},
	hilightMain : function (elm) {
		if (this.isSelected(elm.up(1)) == false) {
			var c = this;
			elm.setStyle( {visibility:'visible',opacity:0});
			new Effect.Opacity(elm, {
				from: c.animation.from,
				to: c.animation.to,
				duration: c.animation.duration
			});
		}
	},
	restoreMain: function(elm){
		if (this.isSelected(elm.up(1)) == false) {
			var c = this;
			new Effect.Opacity(elm, {
				from: c.animation.to,
				to: c.animation.from,
				duration: c.animation.duration,
				afterFinish: function(){
					elm.setStyle({
						visibility: 'hidden'
					});
				}
			});
		}
	}
};
/** ===/End LeftNav=== * */

/**
 * ========= T02.01 ========= ArticleToolbar @ mktwebb 1.0
 */
var ArticleToolbar = {
	articleZoomLevel : [100,120,130,140,150],
	exists : function() {
		this.instance = Settings.scope.select(".textSizerContainer");
		return this.instance.length > 0;
	},
	init : function() {
	  if (!MKT.requiredFeatures.articleToolbar) return;
		if(!this.exists()) return;
		this.restoreArticleZoom();
		var wr = this.instance;
		for (var j = 0, max = wr.length; j < max; j++) {
			var l = wr[j].select("a");
			for (var i = 0; i < l.length; i++) {
				this.registerSetArticleZoom(l[i], i);
			}
			var parentElm = wr[j].up();
			Event.observe(parentElm.select('span.print a')[0],'click',function(e){
				var src = e.element().href;
				if (src.match(/javascript:/)) {
					window.print();
				}else {
					var x = (screen.availWidth - 640) / 2;
					window.open(src, 'printArticle', "address=no,resizable=yes,scrollbars=yes,height=640,location=no,left=" + x + ",top=50,width=640");
				}
				e.preventDefault();
			});
		}
	},
	/**
	 * register function to help keep scope and closure.
	 * @param {HTMLElement} elem	the setter link element
	 * @param {Integer} lev	the level index.
	 */
	registerSetArticleZoom : function(link,level) {
		var that = this;
		Event.observe(link, 'click', function(event) {
			that.setArticleZoom(level);		
			that.selectButton(link);	
			Event.stop(event);
		});
	},
	/**
	 * Sets the new Article Zoom level.
	 * @param {Integer} level	the new zoom level
	 */
	setArticleZoom : function(level) {	
		var container = $('articleContent');
		if (!container) { 
			var contentList = $$('.familyAdItem-content');
			container = contentList && contentList[0];
		}
		if (!container) { return; }
		new Element.setContentZoom(container, this.articleZoomLevel[level]);
	  
		Cookie.erase('zoomLevel');
		Cookie.setC('zoomLevel', level);
	},
	
	selectButton: function(button) {
		var className = button.className;
		if (/selected/.test(className)) { return; }
		button.siblings().each(function(link) {
			link.removeClassName('selected');
		});
		button.addClassName('selected');		
	}, 
	
	/**
	 * Init method. Fetch stored Article Zoom from Cookie.
	 */
	restoreArticleZoom : function(){
		var myLevel = parseInt(Cookie.getC('zoomLevel'),10);
		
		if (myLevel > -1)
			this.setArticleZoom (myLevel);
	}
};/** ===/end ArticleToolbar === * */

/* *** Social bookmarks *** */

var SocialBookmarks = {
  init: function() {
    var linkList = $('socialBookmarkLinks');
    if (!linkList) return;
    Event.observe(linkList, 'mousedown', this.pingStatisticsServer);
  },

  pingStatisticsServer: function(event) {
    var eventElement = event.element();
    if (eventElement.tagName.toLowerCase() != 'a') eventElement = eventElement.up('a');
    var urlElement = eventElement && eventElement.select('.data-logUrl')[0];
    if (urlElement) {
      new Ajax.Request(urlElement.innerHTML.unescapeHTML(), {});
    }
  }
};

/** ===/end Social bookmarks === * */

/* *** External contents *** */

/**
 * Shared object to handle and progressively enhance external contents within
 * IFrames.
 * 
 */
var ExternalContent = {
	slcts : ".externalContent > iframe",
	wrappers : null,
	/**
	 * init method to trig and hook on JS enhancements.
	 */
	init : function() {
		this.resize();
		Event.observe(window,'resize',function(){
			ExternalContent.resize();
		});
	},
	/**
	 * resize all chosed IFrames to the height of the viewport. Is called by init() and on RESIZE event.
	 */
	resize : function() {
		for(var i=0, max=this.wrappers.length; i<max; i++) {
			var ifrm = this.wrappers[i];
			var isFixed = (ifrm.up('.externalContent').hasClassName('fixed') || ifrm.height!=null);
			if (!isFixed) {
				this.setSize(ifrm);
			}
		}
	},
	/**
	 * Updates the height of an iFrame if the iFrames's height is lower than the available viewport height.
	 * @param {Element} ifrm	the iframe Element ref.
	 */
	setSize : function(ifrm) {
		var y; // the height to be calculated in pixels.
		var max = 0; // max value if SOP.

		// is there any (min-)HEIGHT set on iframe?
		var heightSet = !(isNaN(parseInt(ifrm.height,10))) || !(isNaN(parseInt(ifrm.getStyle('height'),10)));

		// is part of the iframe visible? NOT USED RIGHT NOW
		// isPartlyVisible = (posTop-vscroll) < vp && (posTop-vscroll) >= 0;

		// has the page scrolled down?
		var vscroll = document.viewport.getScrollOffsets().top;

		// where is the iframe positioned?
		var posTop = ifrm.cumulativeOffset().top;

		// how much viewport does we have?
		var vp = document.viewport.getHeight();

		// if the iframe follows SOP, calculate a max-height.
		try{
			var doc = (ifrm.contentWindow.document) ? ifrm.contentWindow.document : ifrm.contentDocument;
			max = doc.getElementsByTagName('body').offsetHeight;
		}catch(e){
		}

		// return if the iframe is in the extra column.
		if( ifrm.up('.extraColumn') ) return;

		// default value: the same height as the viewpot
		y = vp;

		// if HEIGHT is set and the calculated height is less than HEIGHT,
		// let the HEIGHT become min-height!
		if(heightSet && y <= ifrm.height) {
			y = !(isNaN(parseInt(ifrm.height,10))) ? ifrm.height : parseInt(ifrm.getStyle('height'),10);
		}

		// if max is set, reduce height if to high.
		if(max > 0 && y > max) {
			y = max;
		}

		ifrm.setStyle({height:y+'px'});
	},
	/**
	 * Called by the invoke method to see if there are any external contents on the page.
	 */
	exists : function() {
		this.wrappers = Settings.scope.select(this.slcts);
		return this.wrappers.length > 0;
	}
};

/**
 * invoke method to check for external contents instances. If there are any, the
 * JS enhancements are activated.
 */
function prepareExternalContent(){
	if(ExternalContent.exists()) {
		ExternalContent.init();
	}
}

/** ======= T02.12 | T06.12 =======
 * Blog @ mktwebb 1.2
 * 
 */
var Blog = {
	instance : null,
	cn : {
		wrap : 'blog'
	},
	exists : function() {
		this.instance = $(Blog.cn.wrap);
		return this.instance;
	},
	init : function(){
		if (this.exists()) {
			if (this.ManageEntry.exists()) {
				this.ManageEntry.init();
			}
		}else{
			return;
		}
	},
	ManageEntry : {
		cn : {
			tagsep : ", ",
			wrap : 'manageBlogEntry',
			tagcloud : 'tagCloud',
			tagfld : 'taTags',
			tag : 'span',
			me : '#extraForm > fieldset > legend',
			txtbody : 'taBlogBody',
			ewi : "div#extraForm input",
			preview : "#blog blockquote.preview"
		},
		exists : function() {
			return Blog.instance.hasClassName(this.cn.wrap);
		},
		init : function () {
			this.modalExtras();
			// this.preview();
		},
		movie : function(url,size){
			// url: 	http://www.youtube.com/watch?v=96Aa7r066Dw
			// modurl: http://www.youtube.com/v/96Aa7r066Dw&hl=en&fs=1
			var modurl = url.replace("watch?v=","v/");
			if (/http:\/\/[^\/]*\byoutube.com\/\b/.test(url)) { 
			  modurl += "&hl=en&fs=1";
			}
			return '('+ size +')@@'+ modurl +'@@';
		},
		img : function(imgSize,imgJustify,imgUrl) {
			return "\n\n!(" + imgSize + " " + imgJustify + ")" + imgUrl + "!\n\n";
		},
		preview : function() {
			var wrp = Settings.scope.select(this.cn.preview);
			var bq,bqp,bqpb,bqtsA;
			var ta = Settings.scope.select('textarea.' + this.cn.txtbody)[0];
			bqpb = Settings.scope.select("#blog input.btnPreview");
			bqtsA = Settings.scope.select("#blog input.btnClose");
			var bqpbpos = bqpb[0].next();
			var bqpbv = bqpb[0].value;
			bqpb[0].remove();
			bqpb = new Element("input", {
				'class': 'btnPreview',
				'type': 'button'
			});
			bqpbpos.insert({before:bqpb});
			bqpb.value = bqpbv;
			if(bqtsA.length>0){
				var bqtsApos = bqtsA[0].up();
				var bqtsAv = bqtsA[0].value;
				bqtsA[0].remove();
				bqtsA = new Element("input", {
					'class': 'btnClose',
					'type': 'button'
				});
				bqtsApos.insert(bqtsA);
				bqtsA.value = bqtsAv;
			}
			if (wrp.length == 0) {
				bq = new Element("blockquote", {
					'class': 'preview inactive'
				}).update("");
				bqp = new Element("div", {
					'class': 'preview richText formattedText clearfix'
				}).update("");
				var bqts = new Element("div", {
					'class': 'toolstrip'
				}).update("");
				
				bqtsA = Settings.scope.select("#blog input.btnClose");
				bqtsA = new Element("input", {
					'class': 'btnClose',
					type: "button"
				});
				bqtsA.value = "St√§ng";
				bqts.insert({
					bottom: bqtsA
				});
				bq.insert({
					bottom: bqts
				});
				bq.insert({
					bottom: bqp
				});
				ta.insert({
					after: bq
				});
			}else{
				bq = Settings.scope.select("blockquote.preview")[0];
				bqp = Settings.scope.select("div.preview")[0];
			}
			var c = this;
				Event.observe(bqpb,'click',function(e){
					bqp.innerHTML = superTextile(ta.value);
					bq.removeClassName('inactive');
					bqpb.addClassName("inactive");
				});
				Event.observe(bqtsA,'click',function(e){
					bq.addClassName('inactive');
					bqpb.removeClassName("inactive");
				});
				Event.observe(ta,'keyup',function(e){
					if(!bq.hasClassName('inactive')) {
						bqp.innerHTML = superTextile(ta.value);
					}
				});
		},
		modalExtras : function () {
			var txtbody = $(this.cn.txtbody);
			if(!txtbody) return;
			Settings.scope.select(this.cn.me).each(function(item){
			 if (!txtbody.previous('button.'+item.up().id) && item.up().id!="blogFormExtras_image") {
				 var btn = new Element('button', {
						type: 'button'
					}).addClassName(item.up().id).update(item.innerHTML);
				   openAsModal(btn, btn.className);
			   txtbody.insert({
			     before: btn
			   });
			 }
			});
			// temporary fix
			$('blogEntryForm').insert($('blogFormExtras_image'));
			// end temporary fix
		},
		prepareLinkDialog : function() {
			var wrp = $('modalWindowWrapper');
			var btn = wrp.select('form')[0];
			var c = this;
			btn.onsubmit = null;
			Event.observe(btn,'submit',function(e){
					var ta = $(c.cn.txtbody);
					var inpt = wrp.select('input[type=text]');
					var insrt = "\n" + '"' + inpt[1].value + '":' + inpt[0].value + "\n";
					Form.updateTextArea(ta, insrt);
					ModalWindow.close();
					ta.focus();
				Event.stop(e);
			});
		},
		prepareMovieDialog : function() {
			var wrp = $('modalWindowWrapper');
			var btn = wrp.select('form')[0];
			var c = this;
			btn.onsubmit = null;
			Event.observe(btn,'submit',function(e){
					var ta = $(c.cn.txtbody);
					var inpt = wrp.select('input[type=text]')[0];
					
					// adding size to the mix.
					var sizes = wrp.select('input[type=radio]');
					var size = null;
					for(var i=0,max=sizes.length; i<max; i++){
						var isChecked = sizes[i].checked;
						if(isChecked){
							size = sizes[i];
							break;
						}
					}
					var url = c.movie(inpt.value,size.value);
					Form.updateTextArea(ta, url);
					ModalWindow.close();
					if (ta.nodeName == 'INPUT')
					{
						var fckEditor = FCKeditorAPI.GetInstance(ta.id);
						fckEditor.Focus();
						fckEditor.Selection.Collapse(false);
					}
					else
					{
						ta.focus();
					}
				Event.stop(e);
			});
		},
		prepareImageDialog : function() {
			var wrp = $('modalWindowWrapper');
			var btn = wrp.select('form')[0];
			var c = this;
			var elms = $('blogEntryForm').elements;
			for(var i=0,max=elms.length; i<max; i++) {
				var elm = elms[i];
				if (!elm.up('fieldset') || elm.up('fieldset').id != 'blogFormExtras_image') {
					if(typeof elm.name !="undefined" || elm.name == null || elm.name=="") {
					btn.insert(new Element('input', {
						'name': elm.name,
						'value': elm.value,
						'type': 'hidden'
					}));
					}
				}
			}
			Form.iframe.init(btn, c.getUploadedPicture);
		},
		getUploadedPicture : function() {
			if (parent.frames[Form.iframe.id]) {
				var tat = $(Blog.ManageEntry.cn.txtbody);
				var p = parent.frames[Form.iframe.id].document;
				var taz = p.getElementsByTagName('textarea');
				var newValue = "";
				for (var i = 0, max = taz.length; i < max; i++) {
					var ta = taz[i];
					if (ta.className == 'taBlogBody') {
						newValue = ta.value;
						break;
					}
				}
				tat.value = newValue;
				parent.frames[Form.iframe.id].location.href = '';
				ModalWindow.onload = null;
				ModalWindow.inner.innerHTML = '';
				ModalWindow.close();
				tat.focus();
			}
		}
	}
};
/** ===/Blog=== * */

/* *** Day in pictures *** */

/**
 * t04.04 Day in pictures, a modified version of the general image gallery
 * service.
 */
var ImageGallery = {
	selectors : {
		dipExists : ".dip_container .dip_nrOfRows",
		wrapper : ".dip_container",
		pictures : ".dip_nrOfRows a",
		placeholder : ".dip_placeholder",
		collapseLink : ".dip_placeholder a.collapse",
		orderLink : ".dip_placeholder a.orderPhoto"
	},
	labels : {
		dayId : "bigPic_"
	},
	wrapper : null,
	pictures : [],
	placeholder : [],
	current : [],

	/**
	 * Check if any Days in Pictures services is on the current page. Called by the invoke method.
	 */
	exists : function() {
		return Settings.scope.select(this.selectors.dipExists).length > 0;
	},
	/**
	 * Starts the Days in pictures service by adding some event listeners and toggles.
	 */
	init : function() {
		var c = this;
		var id = 0;
		this.wrapper = Settings.scope.select(this.selectors.wrapper);
		this.wrapper.each(function(wrap) {
			c.pictures.push(wrap.select(c.selectors.pictures));
		
			var phw = wrap.select(c.selectors.placeholder)[0];
			var ph = phw.select("img")[0];
			
			if (!ph) {
					phi = new Element('img', {
						src: '',
						alt: ''
					});
					phw.insert(phi);
				}
			
			for(var i=0,max=c.pictures[id].length; i<max; i++){
				var item = c.pictures[id][i];
				item.onclick = function() {
					return c.show(this,wrap);
				};
			}
			var clps = wrap.select(c.selectors.collapseLink);
			if (clps.length == 0) {
				return;
			}
			else {
				clps[0].onclick = function(){
					return c.hide(wrap);
				};
			}
			/* T04.14
			 * Hack to enable the orderPhoto link from within the placeholder.
			 * More specific selectors and classes on the show image links 
			 * would probably be more ideal. - Svante Adermark, Fleecelabs. 
			 */
			
			var orderLink = wrap.select(c.selectors.orderLink)[0];
			if (orderLink) orderLink.onclick = null;			
			
			id++;
		});
	},
	/**
	 * reload placeholder with image.
	 * @param {Element} elem	the image wrapper to show.
	 */
	show : function(elem,wrap) {
		var phw = wrap.select(this.selectors.placeholder)[0];
		var ph = phw.select("img")[0];
		ph.src = elem.href;
		
		if (phw.hasClassName("collapsed")) {
			phw.toggleClassName("collapsed");	
		}
		if(Settings.scope.id == 'modalWindowWrapper') {
			ModalWindow.reposition();
		}
		return false;
	},
	/**
	 * reset placeholder by removing the current image.
	 * @param {Element} elem	the image to remove.
	 */
	hide : function(wrap) {
		wrap.select(this.selectors.placeholder)[0].addClassName("collapsed");
		
		return false;
	},
	
	navsExists: function(){
		return Settings.scope.select('.dip_navigation').length > 1;
	},
	
	getNav: function(){
		return Settings.scope.select('.dip_navigation')[1];
	}	
};

/**
 * Invoke method: check if any Image Gallery instances is on the page, and
 * initiate if true.
 */
function prepareImageGallery() {
	if(!Settings.isEnabled('ImageGallery')) { return; }
	
	if(ImageGallery.exists()) {
		ImageGallery.init();
	}
}

function initPrint() {
	if($$('body.print').length > 0) {
		window.print();
	}
}

/* *** T04.10 - Ticker *** */

/**
 * Initiates and starts the ticker. interval parameters sets the update time in
 * milliseconds.
 * 
 * Letters : the time between printing of a single line's characters. Lines :
 * how long a printed line will be saved before switching.
 */
var Ticker = {
	MAX: 6,
	// update interval
	interval : { letters:50, lines:3000 },
	// pointers
	pos : 0,
	current : 0,
	// overflow handler (scrolls the line to the left if line is too long -> wider than maxwidth)
	maxwidth : 0,
	// containers
	elems : [],
	chars : [],
	max : [],
	/**
	 * Initiates and prepare the ticker to get started.To start ticker, call this.start.
	 * 
	 * @param {Array} elems	an array of elements, like $$('#ticker dd a')
	 */ 
	init : function(elems) {
		var c = this;
		var max = (elems.length < this.MAX) ? elems.length : this.MAX;
		for(var i=0; i<max; i++) {
			this.max[i] = (function(){ return c.chars[i] = elems[i].innerHTML.strip().toArray(); })().length;
			elems[i].innerHTML = '';
			this.elems[i] = elems[i];
		}
		this.elems[0].up().addClassName("active");
		
		// TODO: the below line takes about 170ms (!) in FF3.5. what to to? (ay,
		// 2009.11.26)
		this.maxwidth = this.elems[0].up(1).getWidth() - this.elems[0].up().previous().getWidth();
	},
	/**
	 * print characters in line (i.e. the headline). Also triggers the next line when done. interval.letters defines the speed.
	 * 
	 */ 
	printChars : function() {
		if(this.max[this.current] > this.pos) {
			if (this.elems[this.current].movement) {
				clearTimeout(this.elems[this.current].movement);
			}
			this.elems[this.current].update( this.elems[this.current].innerHTML + this.chars[this.current][this.pos] );
			this.pos++;
			var overflow = this.maxwidth - (this.elems[this.current].getWidth()+10);
			if( overflow < 0 ) this.elems[this.current].style.marginLeft = (overflow-5)+"px";
			var closure = this;
			this.elems[this.current].movement = setTimeout( function(){ closure.printChars(); }, closure.interval.letters );
		}else {
			var closure = this;
			this.pos = 0;
			this.movement = setTimeout( function(){closure.nextLine();}, closure.interval.lines );
			return true;
		}
	},
	/**
	 * restore printed line to default values. Called before the next line starts.
	 * 
	 * @param {HTMLElement} elem	the element which should be restored.
	 */
	cleanup : function (elem) {
		elem.up().removeClassName("active");
		elem.style.marginLeft = "0";
		elem.update("");
	},
	/**
	 * switch lines. When the last line is printed, the whole set is rewinded to first line. 
	 */
	nextLine : function() {
		if (this.current >= this.elems.length) {
			return true;
		}
		this.cleanup(this.elems[this.current]);
		var next;
		if(this.current < (this.elems.length-1)) {
			next = this.current+1;
			this.current++;
		}else{
			next = this.current = 0;
		}
		this.elems[next].up().addClassName("active");
		this.printChars();
	},
	/**
	 * starts the ticker by printing the first line.
	 */
	start : function() {
		this.pos = 0;
		setTimeout(function() { Ticker.printChars();});
	}
};

/**
 * Init method. Search the page for ticker instance.If ticker is found, init and
 * start it. Aborts and return if otherwise. JSDependent service.
 */
function initTicker() {
	var elem = Settings.scope.select("#ticker a");
	if(elem.length == 0) return false;
	Ticker.init( elem );
	Ticker.start();
}


/************************************************************
 * PhotoAlbum, by andersy & Fleecelabs @ T04.15
 */

if (typeof PhotoAlbum === 'undefined') {
  var PhotoAlbum = {};
}

Object.extend(PhotoAlbum, {
  instance : null,
  sels : {
    wrp : 'div.photoWrapper',
    fb : 'li.facebook a'
  },
  exists: function() {
    this.instance = Settings.scope.select(this.sels.wrp);
    return this.instance.length > 0; 
  },
  // init method
  init: function() {
    if (!this.exists()) { return; }
    this.shareLinks();
    this.ModalSlideShow.init();
  },
  // give facebook sharelinks a popup target
  shareLinks: function() {
    Settings.scope.select(this.sels.fb).each(function(elm){
      Event.observe(elm,'click',function(e){
        window.open(e.element().href,'shareFacebook',"location=no,resizable=yes,scrollbars=yes,height=500,location=no,left=50,top=50,width=800");
        e.preventDefault();
      });
    });
  }
});

if (typeof PhotoAlbum.ModalSlideShow === 'undefined') {
  PhotoAlbum.ModalSlideShow = {};
}
Object.extend(PhotoAlbum.ModalSlideShow, {
  timer: null,
  imageInitializerTimer: null,
  delay: 5,
  imageIndex: 0,
	
  init: function() {    
    if (!this.select('.photoWrapper').length) return;
    var nextLink = this.select('.simplePager .next a').first();
    var previousLink = this.select('.simplePager .previous a').first();
    var autoplayLink = this.autoplayLink();
    var photoLink = this.select('a.photoLink').first();
    
    nextLink && nextLink.observe('click', this.stepAhead.bindAsEventListener(this));
    previousLink && previousLink.observe('click', this.stepBack.bindAsEventListener(this));
    
    if (photoLink) {
      photoLink.observe('click', this.stepAhead.bindAsEventListener(this));
      this.imageElement().wrap('div');
      photoLink.setStyle({ 'width': (this.maxWidth || 650) + 'px', 'height': (this.maxHeight || 460) + 'px' });
    }
    
    if (autoplayLink) {
      autoplayLink.observe('click', this.toggleAutoplay.bindAsEventListener(this));
      autoplayLink.insert(new Element('span'));
    }
    
    [nextLink, previousLink, autoplayLink, photoLink].each(function(link) {
      link && link.setAttribute('rel', 'enhanced');
    });
    
    document.observe('mkt:modal:close', this.close);
    this.initializeImages();  
  },
  
  initializeImages: function() {
    if (!this.images) {
      this.imageInitializerTimer = setTimeout(function() { 
        this.initializeImages();
      }.bind(this), 1000);
      return;
    }
    clearTimeout(this.imageInitializerTimer);    
    
    if (Settings.scope.id === 'modalWindowInner') {
      var photoLink = this.select('a.photoLink').first();
      if (photoLink && this.maxWidth && this.maxHeight) {
        photoLink.setStyle({'width':this.maxWidth + 'px','height': this.maxHeight + 'px'});
        // ModalWindow.reposition();
      }
    }
    
    this.images.each(function(imageData, index) {
      var eachImage = new Image();
      eachImage.src = imageData.url;
      imageData.image = eachImage;
    }.bind(this));
    
    if (this.images.length > 1) {
      var autoplayLink = this.autoplayLink();
      document.observe('keydown', this.navigateWithArrowKeys);
      if (!autoplayLink) return;
      this.startAutoplay();
    }        
  },
  
  close: function() {
    //with (PhotoAlbum.ModalSlideShow) {
      clearTimeout(PhotoAlbum.ModalSlideShow.timer);
      PhotoAlbum.ModalSlideShow.timer = null;
      document.stopObserving('mkt:modal:close', arguments.callee);
      document.stopObserving('keydown', PhotoAlbum.ModalSlideShow.navigateWithArrowKeys);
    // }
  },

  startAutoplay: function() {
    this.autoplayLink().addClassName('autoplayON').removeClassName('autoplayOFF');
    this.timer = setTimeout(function() { 
      this.stepAhead(); 
      this.startAutoplay(); 
    }.bind(this), PhotoAlbum.ModalSlideShow.delay * 1000);
  },
  
  stopAutoplay: function() {
    clearTimeout(this.timer);
    this.timer = null;
    this.autoplayLink().addClassName('autoplayOFF').removeClassName('autoplayON');
  },
  
  toggleAutoplay: function(event) {
    if (event) { Event.stop(event); }
    if (!this.timer) {
      this.startAutoplay();
    } else {
      this.stopAutoplay();
    }
  },

  stepAhead: function(event) {
    if (event) { Event.stop(event); this.stopAutoplay();}
    this.step(this.nextSlide());
    this.imageIndex = this.nextIndex();
  },

  stepBack: function(event) {
    if (event) { Event.stop(event); this.stopAutoplay();}
    this.step(this.previousSlide());
    this.imageIndex = this.previousIndex();
  },
  
  step: function(slide) {
    this.repopulate(slide);
    this.crossfade(slide);
  },
  
  crossfade: function(slide) {       
    var ref = this.select('.photoWrapper a.photoLink').first();
    var imgUrl = slide['url'];
	var imgQuerystring = imgUrl.substring(imgUrl.indexOf('?'));
	var maxPixels = imgQuerystring.match(/\d\d*/g);
	var maxHeight = maxPixels[0];
	var maxWidth = maxPixels[1];
		
	ref.insert({
		top: new Element('img', { src: imgUrl, width: maxWidth, height: maxHeight } ).wrap('div') });
    this.imageElement().parentNode.fade({
      afterFinish: function(effect) { effect.element.remove(); }
    });
  },

  repopulate: function(slide) {
    var that = this;
    $H(slide).each(function(pair) {
	  var element = that.select('.metaWrapper .'+pair.key).first();
      if (!element) { return; }
      if (pair.key == 'albums' || pair.key == 'tags') {
        element.update(element.childElements().first());
        pair.value.each(function(object, index) {
          if (index > 0) { element.insert(', '); }
          var link = new Element('a', { href: object['url'] }).update(object['name']);
          element.insert(link); 
        });
      } else if (pair.key != 'url' && pair.key != 'photoHeight' && pair.key != 'photoWidth') {
        element.update(pair.value);
      }
    });
  },

  nextSlide: function() {
    return this.images[this.nextIndex()];
  },

  previousSlide: function() {
    return this.images[this.previousIndex()];
  },
  
  nextIndex: function() {
    if (this.images.length - this.imageIndex ===  1) { return 0; }
    return this.imageIndex + 1;    
  },
  
  previousIndex: function() {
    if (!this.imageIndex) return this.images.length - 1;
    return this.imageIndex - 1;    
  },

  imageElement: function() {
    var images = this.select('.photoWrapper img');
    return images[1] || images.last();
  },
  
  autoplayLink: function() {
    return this.select('.simplePager .autoplay a').first();
  },

  navigateWithArrowKeys: function(event) {
    //with (PhotoAlbum.ModalSlideShow) {
      if (!([37, 39].indexOf(event.keyCode) > -1)) return;
      PhotoAlbum.ModalSlideShow.stopAutoplay();
      event.keyCode == 39 ? PhotoAlbum.ModalSlideShow.stepAhead() : PhotoAlbum.ModalSlideShow.stepBack();
      Event.stop(event);
    // }
  },
  
  select: function(selector) {
    return $$('#modalWindowWrapper ' + selector + ', #articleContainer ' + selector);
  }
  
});

/** ===/PhotoAlbum=== * */



/**
 * ========T06.01============ My Page functions @ mktwebb 1.3
 * 
 * Interactive form widget which calculate and tell strength on password inputs.
 * 
 * @param {HTMLElement}
 *            formField
 * @param {String}
 *            passwordMeterElementId
 */
function measurePasswordStrength(formField, passwordMeterElementId) {
	var meter = document.getElementById(passwordMeterElementId);
	if(formField && meter) {
		var strength = Form.getPasswordStrength(formField.value);
		meter.className = "percentage" + strength;
	}
}

var MyPage = {
	init : function() {	  
	  if (!MKT.requiredFeatures.myPage) return;
		MyPage.Edit.init();
		MyPage.Profile.init();
	},
	Edit : {
		sels : {
			wrp : "div[class=pluginWrapper editMyPage]"
		},
		mess : "Du har osparade \u00E4ndringar. Vill du spara?",
		instance : null,
		checksum : null,
		isSubmit : null,
		exists : function() {
			this.instance = Settings.scope.select(this.sels.wrp);
			return this.instance.length > 0;
		},
		init : function() {
			if(!this.exists()) return;
			this.formElm = this.instance[0].select('form')[0];
			this.formElm.observe('submit',this.noValidation);
			var c = this;
			Event.observe(window,'load',function(evt){
				c.checksum = c.createChecksum();
			});
			window.onunload = this.validate;
		},
		validate : function(evt){
			if(MyPage.Edit.createChecksum() !== MyPage.Edit.checksum && MyPage.Edit.isSubmit!==true) {
				if (confirm(MyPage.Edit.mess) === true) {
					MyPage.Edit.formElm.submit();
				}
			}
		},
		noValidation : function(evt){
			MyPage.Edit.isSubmit = true;
		},
		createChecksum : function(){
			var cs = "";
			for(var i=0, max=this.formElm.elements.length; i<max; i++){
				if (this.formElm.elements[i].type == 'checkbox' || this.formElm.elements[i].type == 'radio') {
					cs += this.formElm.elements[i].checked;
				}else if(this.formElm.elements[i].type == 'select-multiple'){
					for(var j=0, maxJ=this.formElm.elements[i].length; j<maxJ; j++ ){
						cs += this.formElm.elements[i].options[j].value;
					}
				}else {
					cs += this.formElm.elements[i].value;
				}
			}
			return cs;
		}
	},
	Profile : {
		lnk : null,
		exists :function() {
			if(!Settings.isEnabled("MyPageProfileToggler")) return false;
			this.lnk = Settings.scope.select('.showMoreMyPage a');
			return this.lnk.length > 0;
		},
		init : function() {
			if(!this.exists()) return;
			var t = this.lnk;
			var c = Settings.scope.select('.contact_information')[0];
			if (!c.hasClassName(Toggler.classnames.hidden)) {
				c.addClassName(Toggler.classnames.hidden);
			}
			var a = Settings.scope.select('.additional_information')[0];
			if (!a.hasClassName(Toggler.classnames.hidden)) {
				a.addClassName(Toggler.classnames.hidden);
			}
			t.each(function(item){
				Event.observe(item, 'click', function(e){
					Toggler.toggle(c);
					Toggler.toggle(a);
					Toggler.toggle(item);
					var siblings = item.up().childElements();
					if (siblings[0] == this) {
						Toggler.toggle(siblings[1]);
					}
					else {
					Toggler.toggle(siblings[0]);
					}
					ModalWindow.reposition();
					Event.stop(e);
				});
			});
		}
	}
};/** ======== /mypage ============* */

/*
 * =========T06.02============= * Event Calendar @ mktwebb 1.1 * * Initiates and
 * prepares the Event Calendar with toggle functions. The description of each
 * event is * toggled. One can toggle all descriptions at the same time, or each
 * one manually.
 */
var EventCalendar = {
	selregion : "select.eventCity",
	createButton : ".btnAdd",
	eventCalendarCreateForm : "#eventCalendarCreateForm",
	eventCalendarSearchForm : "#eventCalendarSearch-form",
	sortRadioButtons : '#eventCalendarSearch-sorting input[type="radio"]',
	exists : function() {
		return (Settings.scope.select('#eventCalendar').length > 0 || Settings.scope.select('#eventCalendarTeaserlist').length > 0);
	},
	init : function() {
		this.initEventToggler();
		this.initRegionChanger();
		this.initCreateEventDirectly();
		this.initSearchOnClick();
		this.showFCK();
		this.setFallback();
	},
	initEventToggler : function() {
		var toggledRows = [], pt = $('parentToggle');
		$$('#eventCalendarList-hits tr.vevent').each(function(eventRow) {
			var heading = eventRow.select('h4')[0];
			var link = new Element('a', {'class': 'toggle'}).update(heading.innerHTML);
			heading.update(link);
			var toggledRow = eventRow.next();
			toggledRow && Toggler.ToggableContent.registerToggle(link, toggledRow);
			toggledRow && toggledRows.push(toggledRow);
		});
		pt && Toggler.ToggableContent.registerToggle(pt, toggledRows);
		toggledRows.length && Toggler.show(toggledRows[0]);
	},
	initRegionChanger: function() {
		var selectRegion = Settings.scope.select(this.selregion);
		
		if (selectRegion) {
			var c = this;
			// Add event change event
			selectRegion.each(function(eachRegion) {
				// Check if there is a value selected
				var selectedParent = eachRegion.value;
				if (selectedParent != "undefined") {
					c.changeRegion(eachRegion);
				}
				
				eachRegion.onchange = function(){
					c.changeRegion(this);
				};
			});	
		}
	},
	initCreateEventDirectly: function() {
		var createButton = Settings.scope.select(this.createButton)[0];
		if (createButton) {
			var c = this;
			createButton.onclick = function(){
				c.changePostAction();
			};
		}
	},
	initSearchOnClick : function() {
		var sortButtons = Settings.scope.select(this.sortRadioButtons);
		if (sortButtons) {
			var submitForms = Settings.scope.select(this.eventCalendarSearchForm);
			submitForms.each(function(submitForm) {
				sortButtons.each(function(sortButton) {
					// Change all existing radiobuttons on page when user clicks a sort radiobutton,
					// otherwise there will be different post-values from each form
					sortButton.onclick = function() {
						var chosenValue = sortButton.value;
						submitForms.each(function(submitForm) {
							sortButtons.each(function(sortButton) {
								if (sortButton.value == chosenValue) {
									sortButton.checked = true;
								}
							});
						});
						submitForm.submit();
					};
				});
			});
		}
	},
	showFCK : function(){
		var fckWrapper = $('eventCalendarCreate-eventDescription');
		if(fckWrapper){
			fckWrapper.show();
		}
	},
	setFallback: function(){
		var theForm = Settings.scope.select(this.eventCalendarCreateForm)[0];
		if(theForm){
			var fallback = theForm.select("input#fallback");
			if(fallback){
				fallback[0].value = "false";
			}
		}
	},
	changeRegion : function (selectElement){
		var selectCity = selectElement.up(3).down("select.eventNeighbourhood");
			
		selectCity.disabled = false;
		selectCity.length = 0;
		var a = new Array();
		var b = new Array();
		var selectedValue = selectElement.options[selectElement.selectedIndex].value;
		
		if(selectedValue != ""){
			selectCity.enable();
			if(cityArray.length > 0){
				for(var i = 0; i < cityArray.length; i++){
					a = cityArray[i].split(",");
					if(a.length > 0){
						b = a[0].split(":");
						
						if(b.length > 0 && selectedValue == b[0]){
							var index = selectCity.length;
							// If first, add empty option
							if(index == 0) {
								selectCity.options[index++] = new Option("--V\u00E4lj ort--", "");
							}
							
							// Add new option, select if value is identical
							selectCity.options[index] = new Option(a[1], b[1]);
							if(selectedCityId != "" && selectedCityId == b[1]){
								selectCity.selectedIndex = index;
							}
						}
					}
				}
			}
		}
		
		if(selectCity.length <= 1) {
			selectCity.disable();
		}
	},
	changePostAction : function () {
		var formElement;
		if (formElement = Settings.scope.select(this.eventCalendarCreateForm)[0]) {
			formElement.setAttribute("action", formElement.getAttribute("action").replace("Preview", "Confirm"));
		}
	}
}; /** ====== Event calendar =====* */

/**
 * Init method. Search the page for a EventCalendar instance, and initiates the
 * calendar if instance exists. Return if null.
 */
function prepareEventCalendar() {
	if(!Settings.isEnabled('EventCalendar')) return;
	
	if (EventCalendar.exists()) {
		EventCalendar.init();
	}
}

/**
 *  T06.04
 * 
 *	@author Fredrik Herlitz, Promedia, Nerikes Allehanda
 *	
 *	Handle polls. They have to have a <form>-element inside an element with class ".pollContainer"
 */

var Poll = {
	AUTO_SUBMIT: 'submitWhenChecked',
	labels :  {
		pollForms : '.pollContainer form',
		submitOnSelect : 'input[type="hidden"][name="submitOnSelect"]',
		noOptionSelectedText : 'input[type="hidden"][name="noOptionSelectedText"]',
		submitLinkID : 'input[type="hidden"][name="submitLinkID"]',
		radios : 'input[type="radio"]'
	},
	init : function () {
    if (!MKT.requiredFeatures.poll) return;
		// no need anymore. if (!this.exists()) return;
		var c = this;
		var forms = Settings.scope.select(this.labels.pollForms);
		for(var i=0, max=forms.length; i<max; i++){
			(function(theForm) {	
				var submitOnSelect;
				var noOptionSelectedText;
				c.replaceBtnWithLink(theForm);
				try {
					submitOnSelect = theForm.select(Poll.labels.submitOnSelect)[0].value;
					noOptionSelectedText = theForm.select(Poll.labels.noOptionSelectedText)[0].value;
				}catch(e){}
				if (submitOnSelect == 'true') {
					try{
						var arrRadios = theForm.select(Poll.labels.radios);
						arrRadios.each(function(item) {
							item.addClassName(Poll.AUTO_SUBMIT);
						});
					}catch(e){}
				}else{
					try{
						var submitLinkID = theForm.select(Poll.labels.submitLinkID)[0].value;
						$(submitLinkID).onclick = function(evt) { 
							if (Poll.checkChecked(theForm, noOptionSelectedText)){ 
								theForm.onsubmit();
								return false;
							}else{
								return false;
							}
						};
					}catch(e){}
				}
			})(forms[i]);
		}
	},
	checkChecked : function (theForm, noOptionSelectedText) {
		var optionSelected = false;
		var arrRadios = theForm.select(this.labels.radios);
		
		for (i = 0; i < arrRadios.length; i++) {
	        if (arrRadios[i].checked) {
				optionSelected = true;
				break;
	        }
	     }
		 
	     if (!optionSelected) {
	         alert(noOptionSelectedText);
	         return false;
	     }
		 return true;
	},
	exists : function() {
		return Settings.scope.select(this.labels.pollForms).length > 0;
	},
	replaceBtnWithLink : function(frmElm){
		var btn = frmElm.select("input.btnDefault");
		if (btn.length > 0) {
			var lnk = new Element('a', {
				'id': ((frmElm.id.replace("pollForm_", "")) + "_submit"),
				'href': ""
			}).update(btn[0].value);
			btn[0].insert({
				after: lnk
			});
			btn[0].remove();
		}
	}
};


/**
 * ============T06.11====================== MyPhotos @ mtwebb 1.4
 * 
 * MyPhotos, "L√§sarnas bilder". Enhance forms and search results listing.
 */
var MyPhotos = {
	wrapId : { 
		search:"myPhotoSearch", 
		upload1:"newMyPhotoContainer", 
		upload1Form:"newMyPhoto", 
		confirm:"newMyPhotoConfirmation"
	},
	agreement : "#newMyPhotoContainer .agreement",
	/**
	 * Init the view Image service. Is called when the ModalWindow instance is loaded.
	 */
	initViewer : function() {
		enableEnhancements();
		if (typeof prepareImageCaptions === 'function') prepareImageCaptions();
	},
	/**
	 * Makes the whole resultrow clickable instead of just the image thumbnail.
	 */
	initSearch : function() {
		Settings.scope.select("#" + this.wrapId.search + " ol.images > li").each( function(item){
			item.addClassName("clickable");
			Event.observe( item, 'click', function(){item.select("a")[0].onclick();},false);
		});
	},
	/**
	 * Disables the submit button and don't enable it until the user has agreed to the terms and conditions (checking a checkbox).
	 */
	initUploadForm : function() {
		var sbmt = Settings.scope.select("#" +MyPhotos.wrapId.upload1 + " input[type=submit]")[0];
		sbmt.disabled = true;
		closure = this;
		var agreed = Settings.scope.select("#" +MyPhotos.wrapId.upload1 + " .chkAgreement")[0];
		this.checkDisabled(agreed,sbmt);
		agreed.onchange = function() {
			closure.checkDisabled(agreed,sbmt);
		};
	},
	/**
	 * function to enable or disable the terms and conditions checkbox
	 * @param {Element} agreed	the terms and conditions checkbox reference
	 * @param {Element} sbmt	the submit button reference
	 */
	checkDisabled : function(agreed,sbmt) {
		if(agreed.checked) {
			sbmt.disabled = false;
		}else{
			sbmt.disabled = true;
		}
	}
};

/**
 * Invoke method. Prepare various JS to myPhoto service.
 */
function prepareMyPhotos(){
	if (!Settings.isEnabled('MyPhotos')) return;

	if ( Settings.scope.select('#'+MyPhotos.wrapId.search).length > 0 ) {
		MyPhotos.initSearch();
	}
	if (Settings.scope.select('#'+MyPhotos.wrapId.upload1).length > 0 ) {
		MyPhotos.initUploadForm();
	}
}


/* =======T06.09==========
** Citering av kommentarer @ mktwebb 1.4
*/


var CommentCitation = {

	exists: function() {
	  return $('commentForm');
	},

	init: function() {
	  if (!CommentCitation.exists()) {
      $$('div.posting_reply').each(function(each) { 
        each.hide();
        each.style.overflow = 'hidden';
        each.style.height = '0px';
      });
	    return;
	  }

    var x;
  	if (x = $('bodyQuote')) { x.hide(); }
  	if (x = $('bodyQuoteLabel')) { x.hide(); }

		$$('div.posting_reply a').each(function(link) {
			link.observe('click', function(event) {
				CommentCitation.citeComment(link);
				Event.stop(event);
			});
		});
		
		if (document.location.hash == '#commentForm') {
			this.focusBody();
		}
	},

	citeComment: function(link) {
	  var x;
		if (x = $('bodyQuoteLabel')) { x.show(); }
		
		var bodyQuotePart = null, textAreaContent, textarea = $('bodyQuote');
		textarea.show();
		textarea.fire('mkt:formfield:willinject');		
		textarea.value = "";

		// Prototype does not seem to like dots in id-names
		// var comment =
		// link.up('div.commentContainer').select('div.comment')[0];
		var comment = link.up(".toolstrip").previous();
		var citee = comment.select('.vcard .fn')[0].innerHTML.stripTags().strip();
		citee = citee.replace(/\n/gi, ' ');
		
		if (comment.select('p.bodyQuotePart').size() > 0) {
			bodyQuotePart = comment.select('p.bodyQuotePart')[0].innerHTML.replace(/<br>/gi,"\n");
		}
		
		var commentText = comment.select('p.bodyCommentPart')[0].innerHTML.replace(/<br>/gi, "\n");
		
		if (bodyQuotePart != null) {
			textAreaContent = [bodyQuotePart + '\n\n' + citee + ' skrev: ' + commentText, ''];
		} else {
			textAreaContent = [[citee, 'skrev:', commentText].join(' '), ''];
		}
		
		if ($F('bodyQuote')) {
		  textAreaContent.unshift($F('bodyQuote'));
		}
		
		textAreaContent = textAreaContent.join("\n\n");
		textAreaContent = textAreaContent.strip();
		textAreaContent = textAreaContent.replace(/\t/gi, '');
		textarea.value = textAreaContent;
		Form.setCaretPos(textarea, textarea.value.length);
		$$('div.newComment')[0].scrollTo();
		
		this.focusBody();
	},
	
	focusBody: function(){
		var x;
		if (x = $('body')) {
			x.value = "";
			var timeout = Prototype.Browser.IE ? 750 : 1;
			setTimeout(function() { x.focus(); }, timeout);
		}
	}
};


/** ===/end T06.09 - Citering === * */

/**
 * =======T06.15========== Chat @ mktwebb 1.3
 * 
 */
var Chat = {
	cn : {
		wrap : '.chatWrapper'
	},
	frms : {
		q : "listQuestions",
		a : "chatEditor"
	},
	init : function(){
    if (!MKT.requiredFeatures.chat) return;
		Chat.App.init();
		Chat.JoinChat.init();
		Chat.Questions.init();
		Chat.ManageChat.init();
		Chat.Moderator.init();
		Chat.LatestAnswers.init();
		Chat.LoginRequired.init();
	},
	exists : function () {
		return Settings.scope.select(this.cn.wrap).length > 0;
	},
	LoginRequired : {
		instance : null,
		sels : {
			wrp : "loginRequired",
			lnk : "a[rel=modal]"
		},
		exists: function(){
			this.instance = $(this.sels.wrp);
			return this.instance;
		},
		init: function(){
			if(!this.exists()) return;
			var lnk = this.instance.select(this.sels.lnk);
			$$('a.toggleTerms').each(function(elm){elm.hide();});
			if(lnk.length>0){
				$('loginRequired').hide();
				var url = addQueryStringParam(lnk[0].href, "m", "modal");
				ModalWindow.open({href:url});
			}
		}
	},
	// moderator window. add cancel actions to the answer <textarea>.
	Moderator : {
		cn : {
			lnk : 'chatSubmitEntryEditorForm',
			frm : 'chatSubmitAnswerEditorForm',
			bck : 'hiddenURLforBackwardNavigation'
		},
		exists : function(){
			var frm = $(this.cn.frm);
			return frm;
		},
		init : function(){
			if(!this.exists()) return;
			var frm = $(this.cn.frm);
			// var lnk = $(this.cn.lnk);
			if (frm && !frm.up('#chatEditorModerator')) {
				var tac = frm.select("textarea").length;
				var hasMultiTA = tac > 1 && tac < 3; // &&
														// frm.select('textarea#txtChatHeading').length
														// == 0;
				var isExpert = $('txtChatQuestionHeading') && !$('chatEntryModerator');
				if (hasMultiTA && !isExpert) {
					frm.insert({
						after: new Element('div', {
							'id': 'hiddenStuff'
						}).setStyle({
							display: "none"
						}).insert($('taChatAnswer').up('.box'))
					});
				}
				frm.hide();
				var bck = getUrlParam(this.cn.bck);
				var cnl = Settings.scope.select("input.btnCancel");
				if (cnl.length > 0) {
					Event.observe(cnl[0], 'click', function(){
						frm.hide();
						if($('isRejected')) $('isRejected').remove();
						if($('alreadyApproved')) $('alreadyApproved').remove();
						if (hasMultiTA) {
							var ta = frm.select("textarea")[0];
							if (ta.id != 'taChatAnswerHeading') {
								// not visible, make it visible
								var cea = ta.up('.chatEditAnswer').down('.toolStrip');
								var hs = frm.next('#hiddenStuff');
								hs.insert(ta.up('.box'));
								cea.insert({
									before: hs.select('.box')[0]
								});
							}
						}
						Settings.scope.select('textarea').each(function(ta){
							ta.value="";
						});
						Settings.scope.select('input[type=text]').each(function(ta){
							ta.value="";
						});
						// var qstn = $('txtChatHeading');
						// if(qstn) qstn.value = "";
						// frm.select('h3')[0].innerHTML = "";
					});
				}
			}
			frm.observe('submit',this.reloadInboxAmpQuestions);
			Event.observe(parent.frames[self.name],'load',function(evt){
				setTimeout(function(){
					parent.frames['listQuestionsOther'].location.assign(parent.frames['listQuestionsOther'].location.href);
					parent.frames['listQuestions'].location.assign(parent.frames['listQuestions'].location.href);
				},1*100);
			});
		},
		reloadInboxAmpQuestions : function(evt){
			if (FormValidation.checkForm(this)) {
				if($('alreadyApproved') === null && !$('chatEditorModerator')) {
					Chat.Questions.refresh(0);
				}
				if($('isRejected')) {
					Chat.Questions.decrease(1);
				}
			}
		}
	},
	/** 
	 * chat manager: focus the answer <textarea> field and 
	 * add close functionality to the app window's close buttons.
	 * 
	 * Also switches the label of the undo-button. 
	 */
	ManageChat : {
		cn : {
			wrp : 'chatSubmitQuestionForm',
			cls : 'a.btnClose'
		},
		exists : function() {
			return $(this.cn.wrp); 
		},
		init : function() {
			if(!this.exists()) return;
			var c = this;
			Settings.scope.select('textarea')[0].focus();
			Event.observe(window, 'load', function(){
				if (window.opener) {
					window.opener.location.reload();
				}
			});	
			if (window.opener) {
				Settings.scope.select(this.cn.cls).each(function(i){
					var lbl = $('whenJS_btnClose');
					if (lbl) {
						i.innerHTML = lbl.value;
					}
					Event.observe(i, 'click', function(e){
						window.opener.location.reload();
						window.close();
						Event.stop(e);
					});		
				});
			}
		}
	},
	// app window. toggles the class names in the nav tabs.
	// also appends a periodical updater for the incomig questions
	App : {
		settings : {
			constr : "resizable=yes,height=400,left=50,top=50,width=500"
		},
		cn : {
			wrp : "chatAppWrapper",
			bclass : 'body.webapp',
			nav : 'level1',
			wapp : '#panelB #level1',
			sel : 'selected',
			qs : 'listQuestions',
			qso : 'listQuestionsOther'
		},
		intervals : {
			questions : 30,
			answers: {
				p: 10,
				d: 2
			},
			wait : 3
		},
		exists : function(){
			return Settings.scope.select(this.cn.wapp).length > 0;
		},
		init : function(){
			if(!this.exists()) return;
			var c = this;
			Event.observe(Settings.scope.select(this.cn.wapp)[0],'click',function(e){
				var i = e.element();
				if(i.nodeName=='A' && !(i.up().hasClassName(c.cn.sel))) {
					this.select('li').each(function(item){
						item.toggleClassName(c.cn.sel);
					});
				}
			});
		}
	},
	// opens the app window.
	JoinChat : {
		cn : {
			wrap : 'chatJoinForm'
		},
		exists : function() {
			return $(this.cn.wrap);
		},
		init : function() {
			if(!this.exists()) return;
			var c = this;
			Event.observe($(this.cn.wrap),'submit',function(e){
				var elm = e.element();
				if(typeof elm.onclick == "function") elm.onsubmit=null;
				if (FormValidation.checkForm(elm)) {
					c.open(e.element());
				}
				e.preventDefault();
			});
		},
		open : function(formElm) {
			var c = this;
			var p = location;
			Chat.ManageChat.inPopup = true;
			// adding ?alias=foo
			var url = addQueryStringParam(formElm.action,'alias',formElm.select('#txtAlias')[0].value);
			var win = window.open(url,'chatapp',Chat.App.settings.constr);
		}
	},
	Questions : {
		cn : {
			q : 'chatViewAnswersForm',
			a : 'chatSubmitAnswerEditorForm',
			aq : "listQuestionsOther",
			btn : 'btnDefault',
			confirm : "Var god avsluta ditt p\u00E5b\u00F6rjade svar eller avbryt f\u00F6rst.",
			confirmE : "Var god avsluta eller avbryt p\u00E5b\u00F6rjad redigering f\u00F6rst.",
			confirmM : "Var god avsluta eller avbryt p\u00E5b\u00F6rjat inl\u00E4gg fr\u00E5n moderator.",
			ta : "textarea"
		},
		q : null,
		aq : null,
		exists : function() {
			this.q = $(this.cn.q);
			return this.q;
		},
		init : function() {
			if(!this.exists()) return;
			var c = this;
			Event.observe(this.q, 'click', function(e){
				var btn = e.element();
				Chat.pressedButton = btn;
				if (btn.value && btn.name == 'answer') {
					c.answer(btn);
				}
				if (btn.value && btn.name == 'edit') {
					c.edit(btn);
				}
				if (btn.value && btn.name == 'editAnswer') {
					c.editAnswer(btn);
				}
			});
			Event.observe(window, 'load', function(e){
				var names = ["listQuestions","listQuestionsOther"];
				var theFrame = (window.name == names[0]) ? names[1] : names[0];
				while (parent.hasLoaded === false && parent.childSubmitted===true) {
					parent.frames[theFrame].location.assign(parent.frames[theFrame].location.href);
					parent.hasReloaded = true;
					parent.childSubmitted = null;
				}
			});
			Event.observe(this.q, 'submit', function(e){
				btn = Chat.pressedButton;
				if (btn.value && btn.name.indexOf("Reject")>-1) {
					c.drop(btn);
				}else{
					c.approve(btn);
				}
				parent.hasLoaded = false;
				parent.childSubmitted = true;
			});
			setTimeout(function(){
				location.assign(location.href);
			},(Chat.App.intervals.questions*1000));
		},
		answer : function(btnPressed) {
			var answer = this.getFromFrame(Chat.frms.a,this.cn.a);
			if(answer.up('#chatEditorModerator')){
				alert(this.cn.confirmM);
				return;
			}
			
			if(window.name == "listQuestionsOther" && !btnPressed.up('form.rejected')){
			 	answer.insert("<div id='alreadyApproved'></div>");
			}
			
			 if(btnPressed.up('form.rejected')){
			 	answer.insert("<div id='isRejected'></div>");
			 }
			
			// is it an expert?
			var isExpert = answer.select('#txtChatQuestionHeading').length>0 && answer.select('#chatEntryModerator').length==0;
			
			answer.show();
			var ta = answer.select( this.cn.ta );
			// title only available in expert mode.
			var t = btnPressed.up().previous('h2');
			var q = btnPressed.up().previous('h3').innerHTML;
			var aid = btnPressed.up(".message").id.replace("message_","");
			var hasInput = answer.select("input[type=text]")[0];
			if (ta[0].value.length > 0) {
				alert(this.cn.confirm);
				if(hasInput){
					hasInput.focus();
				}else{
					ta.focus();
				}
			}else {
				
				if (ta.length == 0) {
					// not visible, make it visible
					ta = answer.next().select( this.cn.ta )[0];
					var cea = answer.select('.toolStrip')[0];
					var hs = answer.next('#hiddenStuff');
					hs.insert(ta.up('.box'));
					cea.insert({
						before: hs.select('.box')[0]
					});
				}else{
					ta = ta[0];
				}
				
				// if there is a title, insert it as well
				if(t){
					var titl = answer.select("input#txtChatQuestionHeading");
					if(titl.length>0){
						titl[0].value = t.innerHTML;
					}
				}
				
				// if it is an expert, let him edit the question.
				if(isExpert){
					answer.select('#taChatAnswerHeading')[0].value = btnPressed.up().previous('h3').lastChild.nodeValue.strip();
				}
				
				answer.select("input#inReplyTo")[0].value = aid;
				answer.select("h3")[0].innerHTML = q;
				
				if(hasInput){
					hasInput.focus();
				}else{
					ta.focus();
				}
				
				answer.select("div.error").each(function(er){
					er.className = "errorHidden";
				});
				
				var c = this;
			}
		},
		edit : function(btnPressed) {
			var answer = this.getFromFrame(Chat.frms.a,this.cn.a);
			if(answer.up('#chatEditorModerator')){
				alert(this.cn.confirmM);
				return;
			}
			
			if(window.name == "listQuestionsOther" && !btnPressed.up('form.rejected')){
			 	answer.insert("<div id='alreadyApproved'></div>");
			}
			
			if(btnPressed.up('form.rejected')){
			 	answer.insert("<div id='isRejected'></div>");
			 }
			
			answer.show();
			// title only available in expert mode.
			var t = btnPressed.up().previous('h2');
			var ta = answer.select( this.cn.ta )[0];
			var q = btnPressed.up().previous('h3').innerHTML;
			var aid = btnPressed.up(".message").id.replace("message_","");
			var hasInput = answer.select("input[type=text]")[0];
			if (ta.value.length > 0) {
				alert(this.cn.confirmE);
				if(hasInput){
					hasInput.focus();
				}else{
					ta.focus();
				}
			}else {
				
				if (ta.id != 'taChatAnswerHeading') {
					// not visible, make it visible
					var cea = ta.up('.chatEditAnswer').down('.toolStrip');
					var hs = answer.next('#hiddenStuff');
					hs.insert(ta.up('.box'));
					cea.insert({
						before: hs.select('.box')[0]
					});
				}
				
				// if there is a title, insert it as well
				if(t){
					var titl = answer.select("input#txtChatQuestionHeading");
					if(titl.length>0){
						titl[0].value = t.innerHTML;
					}
				}
				
				answer.select("input#inReplyTo")[0].value = aid;
				answer.select("textarea#taChatAnswerHeading")[0].value = q;
				answer.select("h3")[0].innerHTML = q;
				ta.value = btnPressed.up().previous('h3').lastChild.nodeValue.strip();
				var ta2 = answer.select(this.cn.ta)[1];
				if (ta2) {
					var bq = btnPressed.up().previous('blockquote');
					if (bq) {
						ta2.value = bq.getElementsByTagName('*')[0].lastChild.nodeValue.strip();
						ta2.focus();
						answer.select("div.error").each(function(er){
							er.className = "errorHidden";
						});
					}
					else {
						if(hasInput){
							hasInput.focus();
						}else{
							ta.focus();
						}
					}
				}
				else {
					if(hasInput){
						hasInput.focus();
					}else{
						ta.focus();
					}
				}
				var c = this;
			}
		},
		editAnswer : function(btnPressed) {
			var answer = this.getFromFrame(Chat.frms.a,this.cn.a);
			if(answer.up('#chatEditorModerator')){
				alert(this.cn.confirmM);
				return;
			}
			
			if(window.name == "listQuestionsOther" && !btnPressed.up('form.rejected')){
			 	answer.insert("<div id='alreadyApproved'></div>");
			}
			
			if(btnPressed.up('form.rejected')){
			 	answer.insert("<div id='isRejected'></div>");
			 }
			
			if(btnPressed.up('form.rejected')){
			 	alert('a canceled question!');
				new Element('div',{id:'isRejected'}).insert({bottom:answer});
			 }
			
			answer.show();
			var hasInput = answer.select("input[type=text]")[0];
			// title only available in expert mode.
			var t = btnPressed.up().previous('h2');
			var ta = answer.select( this.cn.ta )[0];
			var qid = btnPressed.up("dd").id.replace("answer_","");
			if (ta.value.length > 0) {
				alert(this.cn.confirmE);
			}
			else {
				
				// if there is a title, insert it as well
				if(t){
					var titl = answer.select("input#txtChatQuestionHeading");
					if(titl.length>0){
						titl[0].value = t.innerHTML;
					}
				}
				
				var q = btnPressed.up('dl').previous('h3').innerHTML;
				answer.select("h3")[0].innerHTML = q;
				answer.select("input#inReplyTo")[0].value = qid;
				if (ta.id != 'taChatAnswer') {
					// not visible, make it visible
					var cea = ta.up('.chatEditAnswer').down('.toolStrip');
					var hs = answer.next('#hiddenStuff');
					hs.insert(ta.up('.box'));
					cea.insert({
						before: hs.select('.box')[0]
					});
					ta = answer.select(this.cn.ta)[0];
					ta.value = btnPressed.up('dd').firstChild.nodeValue.strip();
				}
			}
			
			if(hasInput){
				hasInput.focus();
			}else{
				ta.focus();
			}
			
		},
		drop : function(btnPressed) {
			//var q = btnPressed.up('div.message');
			
			this.refresh(1);
			// q.remove();
		},
		approve : function(btnPressed) {
			var q = btnPressed.up('div.message');
			
			this.refresh(0);
			// q.remove();
			
			if (window.location.href.indexOf("Rejected") > -1)
			{
				this.decrease(1);
			}
		},
		refresh : function(item) {
			var prnt = this.getFromParent(Chat.App.cn.nav);
			var cnt = prnt.select("span")[item];
			cnt.innerHTML = "(" + (parseInt(cnt.innerHTML.substr(1),10) + 1) + ")";		
			var cntp = cnt.up('li');
			var c = this;
		},
		decrease : function(item) {
			var prnt = this.getFromParent(Chat.App.cn.nav);
			var cnt = prnt.select("span")[item];
			cnt.innerHTML = "(" + (parseInt(cnt.innerHTML.substr(1),10) - 1) + ")";		
			var cntp = cnt.up('li');
			var c = this;
		},
		// return document from <iframe>.
		getFromFrame : function(frame,wrapperElmId) {
			var awrap = parent.frames[frame].document;
			return Element.extend(awrap.getElementById(wrapperElmId));
		},
		// return parent to <iframe>.
		getFromParent : function(wrapperElmId) {
			var awrap = parent.document;
			return Element.extend(awrap.getElementById(wrapperElmId));
		}
	},
	LatestAnswers : {
		cn : {
			wrp : 'chatRead',
			lst : '.chatList'
		},
		exists : function() {
			var wrp = $(this.cn.wrp);
			if(!wrp) return false;
			return wrp.select(this.cn.lst).length > 0;
		},
		init: function(){
			if(!this.exists()) return;
			var c = this;
			this.elm = new Element('div');
			$$('body')[0].insert(this.elm);
			this.elm.setStyle({
				display: 'none'
			});
			new PeriodicalExecuter(function(){
				var elm = $$(c.cn.lst)[0];
				elm.addClassName('loading');
				new Ajax.Request( CacheUtil.noCache(location.href), {
					method: 'get',
					onSuccess:function(request){
						c.elm.innerHTML = request.responseText;
						elm.innerHTML = c.elm.select(c.cn.lst)[0].innerHTML;
						elm.removeClassName('loading');
					}
				});
			},30);
		}
	}
};/** ===/end T06.15 - Chat=== * */


/**
 * ======= T06.19 ========= Forum @ mktwebb 1.0
 */
var Forum = {

	links: "select#links",
	url: "input#url",
	error: "div#error",
	defaultValue: "http://www",
	errorMax: "Max antal l\u00E4nkar har uppn\u00E5tts (" + FormValidation.MAX_COUNT + ")",
	errorUrl: "Var v\u00E4nlig ange en giltig url (ex. http://www.doman.se)!",
	errorEmpty: "Det finns inga l\u00E4nkar att ta bort f\u00F6r tillf\u00E4llet!",
	errorSelect: "Var god markera vilken/vilka l\u00E4nkar som skall tas bort!",
	defaultLinkText: "Inga l\u00E4nkar",
	init : function() {
		if ( !Settings.isEnabled('MyPageUtil') ) return;
		this.prepareBtnARemoveSelectedLink();
		this.prepareBtnRemoveAllLinks();
		this.prepareBtnAddLink();
		this.prepareEmEntry();
	},
	prepareEmEntry : function(){
		var wrp = $('forum_comments');
		var hasHash = location.hash.length > 0;
		if(!wrp || !hasHash) return;
		var elm = wrp.select("li"+location.hash);
		if(elm.length>0){
			elm[0].addClassName('hilight');
		}
	},
	/**
	 *	Adds a link written in a input element to
	 *	a select multiple box. 
	 */
	addLink: function() {
		var linksElement = Settings.scope.select(this.links)[0];
		var formUrlElement = Settings.scope.select(this.url)[0];
		if(!FormValidation.currentForm) FormValidation.currentForm = linksElement.up('form');
		FormValidation.hideAllErrorMessages("", true);
		if(linksElement.length >= FormValidation.MAX_COUNT){
			FormValidation.showErrorMessage(formUrlElement.id, this.errorMax, false);
			FormValidation.showErrorMessage(FormValidation.errorDiv, FormValidation.ERROR_HEADER.replace("count", "1"), true);
			formUrlElement.value = this.defaultValue;
			formUrlElement.focus();
			return;
		}
		else if (!FormValidation.isUrl(formUrlElement.value)){
			FormValidation.showErrorMessage(formUrlElement.id, this.errorUrl, false);
			FormValidation.showErrorMessage(FormValidation.errorDiv, FormValidation.ERROR_HEADER.replace("count", "1"), true);
			formUrlElement.value = this.defaultValue;
			formUrlElement.focus();
			return;
			
		}
		else{
			this.addOption(formUrlElement.value, formUrlElement.value);
		}
	},
	/**
	 *	Adds a new option to the select multiple box.
	 *		@param optionText
	 *			The option text
	 *		@param optionValue
	 *			The option value
	 */
	addOption: function(optionText, optionValue){
		var linksElement = Settings.scope.select(this.links)[0];
		var linksElement = Settings.scope.select(this.links)[0];
		var index = linksElement.length;
		var formUrlElement = Settings.scope.select(this.url)[0];
		FormValidation.hideErrorMessage(formUrlElement.id, false);
		FormValidation.hideErrorMessage(FormValidation.errorDiv, true);
		var oOption = new Option(optionText,optionValue);
		linksElement.options[index] = oOption;
		formUrlElement.value = this.defaultValue;
		formUrlElement.focus();
		if(linksElement.length > 1)
			FormValidation.deleteDefaultValue(linksElement);
	},	
	/**
	 *	Removes all options form the select multiple box.
	 *
	 */
	removeAllLinks: function(){
		var linksElement = Settings.scope.select(this.links)[0];
		FormValidation.hideAllErrorMessages(linksElement.id, false);
		
		if(linksElement.length == 0){
			FormValidation.showErrorMessage(linksElement.id, this.errorEmpty, false);
			FormValidation.showErrorMessage(FormValidation.errorDiv, FormValidation.ERROR_HEADER.replace("count", "1"), true);
			return;
			
		}
		else{
			linksElement.length = 0;
			FormValidation.hideErrorMessage(linksElement.id, false);
			FormValidation.hideErrorMessage(FormValidation.errorDiv, true);
			this.addOption(this.defaultLinkText , "");
		}
	},
	/**
	 *	Removes the selected options in the multiple select box.
	 */
	removeSelectedLinks: function(){
		var linksElement = Settings.scope.select(this.links)[0];
		FormValidation.hideAllErrorMessages(linksElement.id, false);
		var selCount = 0;
		
		for (i = linksElement.length - 1; i>=0; i--) {
	    	if (linksElement.options[i].selected) {
	    		selCount++;
	      		linksElement.remove(i);
	   	 	}
  		}
  	
  		if(selCount == 0){
			FormValidation.showErrorMessage(linksElement.id, this.errorSelect, false);
			FormValidation.showErrorMessage(FormValidation.errorDiv, FormValidation.ERROR_HEADER.replace("count", "1"), true);
			return;
			
		}
		else{
			FormValidation.hideErrorMessage(linksElement.id, false);
			FormValidation.hideErrorMessage(FormValidation.errorDiv, true);
		}
		
		if(linksElement.length == 0)
			this.addOption(this.defaultLinkText, "");
	
	},
	prepareBtnARemoveSelectedLink : function(){
		Settings.scope.select("input#btnRemove").each(function(item){
			item.onclick = function(){
				Forum.removeSelectedLinks(this);
			};
		});
	},
	prepareBtnRemoveAllLinks : function(){
		Settings.scope.select("input#btnRemoveAll").each(function(item){
			item.onclick = function(){
				Forum.removeAllLinks();
			};
		});
	},
	prepareBtnAddLink : function(){
		Settings.scope.select("input#btnAdd").each(function(item){
			item.onclick = function(){
				Forum.addLink();
			};
		});
	}
};/** =======/forum=========== */

/* *** Top User Toolbar *** */

function initTopUserToolbar() {
	if (typeof topUserToolbarContentURL != 'undefined' && (!Settings.scope || Settings.scope.id != "modalWindowInner")) {
		//mktAjax.load(topUserToolbarContentURL, $('topUserToolbar'),{});
		new Ajax.Updater('topUserToolbar', CacheUtil.noCache(topUserToolbarContentURL), {
			method: 'get',
			asynchronous:true,
			onComplete: function(){
				//initLinkExtensions( $('topUserToolbar') );
			}
		});
	}
}

/* *** Eniro Sponsored Links *** */

function doEniroRequest(){
	
	var eniro_container;
	if(colMode == '0'){
		eniro_container = $$('div.mainColumn div#eniro_SponsoredLinksContainer')[0];
	}
	else if(colMode == '1'){
		eniro_container = $$('div.adColumn div#eniro_SponsoredLinksContainer')[0];
	}
	if( eniro_container && typeof sponsoredLinkUrl != "undefined"){
		new Ajax.Updater(eniro_container, CacheUtil.noCache(sponsoredLinkUrl),{
			method: 'get',
			asynchronous:true,
			onCreate: function(){
				var span = new Element("span").update("H\u00E4mtar sponsrade l\u00E4nkar...");
				$(eniro_container).update(span);
			},
			onComplete:function(){
				initLinkExtensions( $(eniro_container));
			}
		});
	}

}

/**===========T09.04=============
 * UserForm @ mktwebb 1.2
 */

var UserForm = {
	scope : null,
	cn : {
		wrp : 'form.formComposed'
	},
	wrapper : null,
	exists : function() {
		this.wrapper = Settings.scope.select(this.cn.wrp);
		return this.wrapper.length > 0;
	},
	init : function() {
		if(Settings.scope.id == 'modalWindowInner') {
			Form.iframe.init(this.wrapper[0]);
		}
	}
};

function prepareUserForm() {
	if(UserForm.exists()){
		UserForm.init();
		return true;
	}
	return false;
}

/************************************************************
 * TVGuide, by Fleecelabs @ T10.11
 * 
 */

var TVGuide = {
  init: function() {
	  if (!MKT.requiredFeatures.tvGuide) return;
    if (this.exists()) this.install();
		new TVGuideTooltips().install();			
  },
  exists: function() {
    return this.findForm() != null;
  },
  install: function() {
    var that = this;    
    this.findForm().observe('submit', function(ev) {
      Event.stop(ev);
      var checkboxes = ev.target.select('input[type=checkbox]');
      if (!checkboxes.any(function(cb) { return cb.checked; })) {
        $('errorTvGuideSettings')
          .update('<p>V\u00E4nligen v\u00E4lj minst en kanal!</p>')
          .addClassName('error')
          .removeClassName('errorHidden')
          .scrollTo();
      } else {
        that.storeAsCookie();
        that.gotoURL($('tvGuideBackLink').href);
      }
    });
    $('ResetSetting').observe('click', function(ev) {
      Cookie.erase('tvGuideChannels');
      that.reloadPage();
    });
  },
  findForm: function() {
    var a = Settings.scope.select('.tvGuideSettings form');
    return a.length > 0 ? a.first() : null;
  },
  cookieValue: function() {
    return $H(Form.serializeElements($('TvGuideSettings').select('input[type=checkbox]'), true)).values().join(',');
  },
  storeAsCookie: function() {
    Cookie.setC('tvGuideChannels', this.cookieValue(), 365 * 3);
  },
  gotoURL: function(url) {
    window.location.assign(url);
  },
  reloadPage: function() {
    window.location.reload();
  }
};

var Tooltip = Class.create({
  hoveree: null,
  tooltip: null,

  initialize: function(hoveree, tooltip) {
    this.hoveree = hoveree;
    this.tooltip = tooltip;
    Event.observe(this.hoveree, 'mouseover', this.show.bindAsEventListener(this));
    Event.observe(this.hoveree, 'mousemove', this.reposition.bindAsEventListener(this));
    Event.observe(this.hoveree, 'mouseout', this.hide.bindAsEventListener(this));
  },
  show: function(event) {
    Event.stop(event);
		this.tooltip.setStyle({
			position: 'absolute',
			visibility: 'visible'
		});
		this.reposition(event);
  },
  reposition: function(event) {
    Event.stop(event);
    var x = Event.pointerX(event), y = Event.pointerY(event);
    var offset = {x: 5, y: 5};

    var dimensions = Element.getDimensions(this.tooltip);
    var element_width = dimensions.width;
    var element_height = dimensions.height;

    var viewport_dimensions = document.viewport.getDimensions();
    var viewport_width = viewport_dimensions.width;
    var viewport_height = viewport_dimensions.height;

    var scroll_offset = document.viewport.getScrollOffsets();

    if ((element_width + x) >= (viewport_width + scroll_offset.left - offset.x)) {
      x = x - element_width - offset.x;
    } else {
      x = x + offset.x;
    }     
    if ((element_height + y) >= (viewport_height + scroll_offset.top - offset.y)) {
      y = y - element_height - offset.y;
    } else {
      y = y + offset.y;
    } 

	  this.tooltip.setStyle({left: x + 'px', top: y + 'px'});
  },
  hide: function(event) {
    Event.stop(event);
		this.tooltip.setStyle({
			visibility: 'hidden'
		});	
  }
});

var TooltipFactory = Class.create({
  tooltips: null,
  hoveree_selector: null,

  initialize: function() {
  },
  install: function() {
    this.tooltips = $$(this.hoveree_selector).findAll(function(hoveree) {
      var tooltip = this.getTooltipElement(hoveree);
      if (tooltip) return new Tooltip(hoveree, tooltip);
    }.bind(this));
  },
  getTooltipElement: function(hoveree) {
    return null; // override
  }
});

var TVGuideTooltips = Class.create(TooltipFactory, {
  hoveree_selector: '.program .summary',

  initialize: function($super) {
    $super();
  },
  getTooltipElement: function(hoveree) {
    return hoveree.up().select('.description')[0];
  }
});

/** ===/TVGuide=== * */

/**
 * ===== Tag cloud ==== by andersy @ t20.01
 */
var TagCloud = {
	widgets:null, 
	cn:{
		widget : "div.chooseTag",
		tagsep : ", ",
		tagcloud : '.widget',
		tagfld : '.taTags',
		tag : 'span'
	},
	exists:function(){
		this.widgets = Settings.scope.select(this.cn.widget);
		return this.widgets.length > 0;
	},
	init:function(){
		if(!this.exists()) return;
		for (var i = 0, max = this.widgets.length; i < max; i++) {
			var w = this.widgets[i];
			var tc = w.select(this.cn.tagcloud)[0];
			
			tc.select(this.cn.tag).each(function(item){
				var ne = new Element('a', {
					'class': item.className,
					'href': '#'
				}).update(item.innerHTML);
				tc.insert(ne);
				tc.insert(' ');
				item.remove();
			});
			var c = this;
			
			Event.observe(tc, 'click', function(e){
				var ne = e.element();
				if (ne.nodeName != 'A') 
					return;
				var fld = ne.up(c.cn.widget).select(c.cn.tagfld)[0];
				var tag = ne.innerHTML;
				var exists = fld.value.indexOf(tag);
				if (exists >= 0) {
					var str = tag + c.cn.tagsep;
					fld.value = fld.value.replace(str, "");
					fld.value = fld.value.replace(tag, "");
				}
				else {
					var str = (fld.value.length == 0) ? tag : c.cn.tagsep + tag;
					fld.value += str;
				}
				if (fld.value.substr((fld.value.length - 2), 2) == c.cn.tagsep) {
					fld.value = fld.value.substr(0, (fld.value.length - 2));
				}
				e.preventDefault();
			});
		}
	}
};
/** ===== /Tag cloud ==== * */

/* ==== Blog Feed Parser (Sidhuvudpuff) ==== */
var BlogFeedParser = function(){ // created by singleton.
	// status monitors.
	var hasRun = false;
	var ajaxRunning = false;
	var entries = [];
	
	// private vars.
	var template,newestFeed,newestItem,newestFile,newestAuthor,wrapper,checksum,feedsParsed=0;

	var sels = { // css sels.
		wrapper : "div.LocalNewsWrapper",
		blogWrapper : '.BlogWrapper',
		blogLoading : 'loading'
	};

	var blogEntry = new Template( // blog entry template.
		'<dl>'+
			'<dt><span class="#{author}"></span> #{blogTitle}:</dt>'+
			'<dd><a href="#{link}"> #{itemTitle}</a></dd>'+
		'</dl>'
	);
	
	var getLocalSite = function() {
		return false; // not used in this build.
	};
	
	var parseBlogFeeds = function(){
		var localSite = getLocalSite();
		for(var i=0, max=blogUrlItems.length; i<max; i++){
			if((localSite!=null && (blogUrlItems[i].indexOf('/'+localSite) > -1)) || !localSite){
				ajaxRunning = true;
				new Ajax.Request(blogUrlItems[i],{
					method : 'get',
					onSuccess: function(request){
						var item = request.responseXML.getElementsByTagName('item');
						if(item.length > 0){
							var obj = {};
							obj.item = item[0];
							obj.channel = request;
							obj.file = request.request.url.substring(request.request.url.length-7,request.request.url.length-4);
							entries.push(obj);
						}
						ajaxRunning = false;
					}
				});
			}
			feedsParsed++;
		}
	};

	var getInnerHTML = function(parentElm,elm){ // move this to global?
		return parentElm.getElementsByTagName(elm)[0].lastChild.nodeValue;
	};

	return { // public interface.
		exists: function(){
			var testItems, testPageHead;
			testItems = (typeof blogUrlItems == 'object' && blogUrlItems.length>0);
			wrapper = $('mainTop');
			if(!wrapper) return;
			wrapper = wrapper.select(sels.wrapper);
			return testItems && wrapper.length>0;
		},

		init: function(){
			if(this.exists() && hasRun == false){
				this.install();
				// should only run once per pageLoad.
				hasRun = true;
			}
		},

		install : function(){
			var data = {};
			checksum = blogUrlItems.length;
			var current;
			
			var blogs = wrapper[0].select(sels.blogWrapper)[0];
			blogs.addClassName(sels.blogLoading);
			
			parseBlogFeeds();
			
			var whileFeedsParsed = setInterval(function(){
				if(feedsParsed==checksum && !ajaxRunning){
					for(var i=0,max=entries.length;i<max;i++){
						var test = Date.parse(getInnerHTML(entries[i].item,'pubDate'));
						if((!current && !newestItem) || (test > current)){ /* no item stored OR test item newer than current item */
							newestFeed = entries[i].channel.responseXML.getElementsByTagName('channel')[0];
							newestItem = entries[i].item;
							newestFile = entries[i].file;
							newestAuthor = entries[i].file;
							current = test;
						}	
					}
					
					blogs.removeClassName(sels.blogLoading);
					
					data['itemTitle'] = getInnerHTML(newestItem,'title');
					data['blogTitle'] = getInnerHTML(newestFeed,'title');
					data['link'] = getInnerHTML(newestItem,'link');
					data['author'] = newestAuthor;
					blogs.insert(blogEntry.evaluate(data));
					clearInterval(whileFeedsParsed);
				}
			},1000);
		}
	};
}();
/* *** /Blog Feed Parser *** */

/* *** DateTimePicker *** */

function prepareDateTimePickers() {
	DateTimePicker.init();
}
 
var DateTimePicker = {
  picker: null,
  
	init: function() {
    $$('input[type=hidden].date_time_picker_field').each(function(field) {
  		var link = $(field).next('a.calendar_date_select_link');
  		if (link) { 
    		link.onclick = function() {
    			DateTimePicker.showDateTimePicker(field, this);
    			return false;
    		};
        field.onchange = function() {
    			DateTimePicker.updateSelectBoxesFromHiddenField(field);
    		};
  		}
  	}.bind(this));
	},
	
	hasTime: function(field) {
	  return !!$(field.id + "Hour") && !!$(field.id + "Minute");
	},
	
	showDateTimePicker: function(field, link){
		this.updateHiddenFieldFromSelectBoxes(field);
    this.picker = new CalendarDateSelect(field, { popup_by: link, 
      year_range: this.customYearRange(field), time: this.hasTime(field) });
	},
	
	updateHiddenFieldFromSelectBoxes: function(element) {
	  var s = [$F(element.id + "Year"), Date.padded2($F(element.id + "Month")), 
	    Date.padded2($F(element.id + "Day"))].join('-'), hasTime = this.hasTime(element);
		if (hasTime) { 
		  s += ' ' + $F(element.id + "Hour") + ':' + $F(element.id + "Minute");
		}
    element.value = !!this.parseDate(s) ? s : new Date().toFormattedString(hasTime);
	},
	
	updateSelectBoxesFromHiddenField: function(field) {
	  if (!$F(field)) { return; }
    this.updateSelect($(field.id + 'Year'), field, 1);
    this.updateSelect($(field.id + 'Month'), field, 2);
    this.updateSelect($(field.id + 'Day'), field, 3);
		if (this.hasTime(field)) {
      this.updateSelect($(field.id + 'Hour'), field, 4);
  	  this.updateSelect($(field.id + 'Minute'), field, 5);
		}
	},
	
	updateSelect: function(select, element, index) {
    var value = (this.parseDate(element.value) || [])[index];
		if (value) {
		  value = parseInt(value, 10);
			$A(select.options).each(function(option){
				option.selected = parseInt(option.value, 10) == value;
			});
		}
	},
	
	parseDate: function(dateString) {
	  return dateString.match(/(\d{4})-(\d{2})-(\d{2})(?: (\d{2}):(\d{2}))?/);
	},
	
	customYearRange: function(element) {
		var options = $A($(element.id + "Year").options);
		return [parseInt(options[0].value, 10) || parseInt(options[1].value, 10),
		  parseInt(options.last().value, 10)];
	}
};

Date.weekdays = $w('M\u00E5 Ti On To Fr L\u00F6 S\u00F6');
Date.months = $w('Januari Februari Mars April Maj Juni Juli Augusti September Oktober November December');
Date.first_day_of_week = 1;

_translations = {
  "OK": "OK",
	"Now": "Nu",
	"Today": "Idag",
	"Clear": "Rensa"
};

Date.prototype.getAMPMHour = function() { return Date.padded2(this.getHours()); };
Date.prototype.getAMPM = function() { return ''; };

Date.prototype.toFormattedString = function(include_time) {
  var str = [this.getFullYear(), Date.padded2(this.getMonth() + 1), Date.padded2(this.getDate())].join('-');
  if (include_time) {
    str += ' ' + this.getAMPMHour() + ':' + this.getPaddedMinutes();
  }
  return str;
};

Date.parseFormattedString = function(string) {
  var dateArray = DateTimePicker.parseDate(string);
  var date = new Date(dateArray[1], dateArray[2]-1, dateArray[3]); 
  if (dateArray[4] && dateArray[4]) {
    date.setHours(dateArray[4]);
    date.setMinutes(dateArray[5]);
  } 
  return date; 
};

/* *** End DateTimePicker *** */

/*
 * ArticleTagCloudLink by Pelle Andersson, Adeprimo
 * 
 * Post tag cloud link value to search article.
 */

var ArticleTagCloudLink = {
		wrapper: null,
		exists: function(){
			this.wrapper = Settings.scope.select('div.articleTagCloudTeaserWrapper');
			return this.wrapper.length > 0;
		},

		init: function(){
			if(!this.exists()) return;
			if(this.wrapper && this.wrapper.length > 0){
				var tagContainer = this.wrapper[0].select('div.tagCloudContainer p.tagCloud');
				if(tagContainer && tagContainer.length > 0){
					var aElements = tagContainer[0].childElements();
					if(aElements && aElements.length > 0){
						aElements.each(function(item){
							item.onclick = function(){
								return false;
							};
							var span = item.down(0);
							if(span){
								span.onclick = function(){
									ArticleTagCloudLink.postTag(span);
								};
							}
						});
					}
				}
			}
		},
		
		postTag: function (item){
			var aElement = item;
			if(aElement && aElement.tagName.toUpperCase() == 'SPAN'){
				var valueToPost = aElement.innerHTML;
				var form = $('articleTagCloudTeaserForm');
				form.action += "?tag=" + valueToPost;
				form.submit();
			}
		}
		
};

/** ===/ArticleTagCloudLink=== * */

/* *** ScrollableMediagrid *** */

var ScrollableMediagrid = {
  DEFAULT_CAROUSEL_OPTIONS: {
    duration: 0.5,
    frequency: 2.5,
    controlClassName: 'scroller'
  },
  SETTABLE_OPTIONS: ['transition', 'duration', 'auto', 'frequency', 'circular', 'wheel', 'effect'],
  
  init: function() {
    if (!MKT.requiredFeatures.scrollableMediagrid) return;
    Settings.scope.select('div.scrollableMediagrid').each(function(wrapper) {
      this.installCarousel(wrapper);
    }.bind(this));
  },
  
  installCarousel: function(wrapper) {
    var scroller = wrapper.down('div.mediagrid'), slides = scroller.select('ul.mediagrid li');
    var options = Object.extend(this.DEFAULT_CAROUSEL_OPTIONS, 
      this.extractOptions(wrapper.className));
    options.visibleSlides = this.visibleSlides(scroller, slides);
    new Carousel(scroller, slides, wrapper.select('a.scroller'), options);
  },
  
  visibleSlides: function(scroller, slides) {
    if (slides.length == 0) return 0;
    var width = scroller.getWidth(), initial = Position.cumulativeOffset(slides[0])[0];
    for (var i = 1; i < slides.length; i++) {
      if (width < Position.cumulativeOffset(slides[i])[0] - initial) return Math.max(i - 1, 1);
    }
    return slides.length;
  },
  
  extractOptions: function(classnames) {
    var re = /\b([^: ]+):(\S+)\b/g, matches, options = {};
    while (matches = re.exec(classnames)) {
      if (this.SETTABLE_OPTIONS.indexOf(matches[1]) >= 0) {
        options[matches[1]] = matches[2];
      }
    }
    return options;
  }
};


/** ===/ ImageAlbumLinksChange === * */

var ImageAlbumLinkChange = {
	init: function() {

		var url = document.location.pathname;
		var hostName = document.location.hostname;
		var contentIdPattern = /1\..*/;
		var linkHref = null;
		var newPath = "";
		var baseUrl = url.replace(contentIdPattern, "");
		var myPageNode = $$(".myPagesNav .selected a")[0];
		var myPageImageNode = $$(".pictureSummary li.goto a")[0];
		
		if (myPageImageNode) {
			var myPageImage = myPageImageNode.getAttribute("href");
			myPageImage = myPageImage.substring(myPageImage.indexOf("/1.") + 1);
			baseUrl = baseUrl + myPageImage;
		}
		else if (myPageNode) {
			baseUrl = myPageNode.getAttribute("href");
		}
		
		$$("div.photoWrapper a", ".myPagePictures .mediagrid a", ".pictureSummary .slideshow").each(function(link) {
			linkHref = link.getAttribute("href");
			if (linkHref != null) {
				linkExtractedContentId = linkHref.substring(linkHref.indexOf("/1.") + 1);
				newPath = baseUrl + "/" + linkExtractedContentId;
				
				if (linkHref.match("facebook")) {
					newPath = linkHref.match(/[^\?]*/)[0] + '?u=http://' + document.location.hostname + newPath;
				}
				
				newPath = newPath.split('/').uniq().join('/'); // Remove
																// duplicate
																// content-id:s
				
				// Remove possible errors
				newPath = newPath.replace("?u=http:/", "?u=http://");
				newPath = newPath.replace("http:/" + hostName, "");
				newPath = newPath.replace("/?", "?");
				
				link.setAttribute("href", newPath);
			}
		});
	}
};

/** ===/ end ImageAlbumLinksChange === * */

/** ===/ PaymentService === * */

/**
 * @author Pelle Andersson, Adeprimo
 * 
 * Below code is checked in JS Lint online at
 * http://www.javascriptlint.com/online_lint.php
 */

var PaymentService = {
		response : {
			error: 'ERROR',
			valid : 'OK'
		},
		alertErrorClass : 'alertErrorIcon',
		alertConfirmationClass: 'alertConfirmationIcon',
		isError : false,
		exist : function (){
			var mktMobileWrapper = Settings.scope.select("div[class=mobileServiceWrapper clearfix]");
			return mktMobileWrapper.length > 0;
		},
		init: function(){
			if(!this.exist()){
				return;
			}
			
			var mktMobileWrapper = Settings.scope.select('div.mobileServiceWrapper');
			
			mktMobileWrapper.each(function(item){
				var theForm = item.select('form')[0];
				var guid = theForm.id.substring(theForm.id.indexOf("-") + 1);
				var byAjax = $('byAjax-' + guid);
				if(byAjax){
					byAjax.value = "true";
				}
				setFormCookie("acceptCookie-" + guid);
				var paymentBtn = theForm.select('input[type=button]')[0];
				PaymentService.hideError(theForm);
				PaymentService.hideLoader(theForm);
				document.observe('click', function (e){
						PaymentService.hideError(theForm);
					});
				
				if(paymentBtn){
					paymentBtn.show();
					paymentBtn.onclick = function(e){
						PaymentService.validate(theForm);
						if(PaymentService.isError === false){
							PaymentService.verifyPayment(true, theForm);
						}
						Event.stop(e);
					};
				}
			});
		},
		validate : function (f){
			var guid = f.id.substring(f.id.indexOf("-") + 1);
			var code = $('mobileCode-' + guid);
			var password = $('password-' + guid);
			var acceptCookies = $('acceptCookie-' + guid);
			if(!code){
				this.showError("Var god ange koden du fick returnerat till din mobiltelefon!",f);
				this.isError = true;
			}
			else if (code.value.length === 0 || code.value === ''){
				this.showError("Var god ange koden du fick returnerat till din mobiltelefon!",f);
				this.isError = true;
			}
			else if(!acceptCookies){
				this.showError("Kakor m\u00E5ste vara till\u00E5tna f\u00F6r att tj\u00E4nsten skall fungera korrekt!",f);
				this.isError = true;	
			}
			else if(acceptCookies === "false"){
				this.showError("Kakor m\u00E5ste vara till\u00E5tna f\u00F6r att tj\u00E4nsten skall fungera korrekt!",f);
				this.isError = true;
			}
			
		},
		verifyPayment : function(redirect, f, formElementToSet, valueToSet,elmToHide){
			this.hideError(f);
			this.showLoader(f);
			var actionUrl = f.getAttribute('action');
			new Ajax.Request(actionUrl,{
				method : 'post',
				parameters: f.serialize(true),
				onSuccess: function(request){
					PaymentService.hideLoader(f);
					var result = request.responseText;
					PaymentService.hideLoader(f);
					if(result.split(",")[0] === PaymentService.response.valid){
						if(redirect === true){
							location.href = result.split(",")[1];
						}
						else{
							PaymentService.setFormElement(formElementToSet, valueToSet);
							PaymentService.showConfirmation('Verifiering slutf\u00F6rd med lyckat resultat! Spara eller editera evenemanget!',f);
							PaymentService.hideElement(elmToHide);
						}
						
					}
					else if(result.split(",")[0] ===  PaymentService.response.error){
						PaymentService.showError(result.split(",")[1],f);
						
					}
				},
				onFailure : function(){
					PaymentService.showError("Ett fel uppstod vid verifieringen!",f);
				}
			});
		},
		
		setFormElement : function (formElementName, value){
			var allForms = Settings.scope.select('form');
			allForms.each(function(item){
				var hiddenItems = item.select('input[type=hidden]');
				hiddenItems.each(function(hiddenField){
					if(hiddenField.getAttribute("name") === formElementName){
						hiddenField.value = value;
					}
				});		
			});
					
		},
		hideElement: function(elm){
			if(elm){
				elm.hide();
			}
		},
		showError: function(message,f){
			var guid = f.id.substring(f.id.indexOf("-") + 1);
			var errorWrapper = $('mobileServiceErrorWrapper-' + guid);
			if(errorWrapper){
				errorWrapper.removeClassName("alert alertConfirmation clearfix");
				errorWrapper.addClassName("alert alertError clearfix");
				errorWrapper.show();
				var span = new Element("span");
				span.addClassName(this.alertErrorClass);
				errorWrapper.insert(span);
				var p = new Element("p");
				p.update(message);
				errorWrapper.insert(p);
			}
			
		},
		showConfirmation: function (message, f){
			var guid = f.id.substring(f.id.indexOf("-") + 1);
			var errorWrapper = $('mobileServiceErrorWrapper-' + guid);
			if(errorWrapper){
				errorWrapper.removeClassName("alert alertError clearfix");
				errorWrapper.addClassName("alert alertConfirmation clearfix");
				errorWrapper.show();
				var span = new Element("span");
				span.addClassName(this.alertConfirmationClass);
				errorWrapper.insert(span);
				var p = new Element("p");
				p.update(message);
				errorWrapper.insert(p);
			}
		},
		hideError: function(f){
			this.isError = false;
			var guid = f.id.substring(f.id.indexOf("-") + 1);
			var errorWrapper = $('mobileServiceErrorWrapper-' + guid);
			if(errorWrapper){
				errorWrapper.update("");
				errorWrapper.hide();
			}
		},
		showLoader: function(f){
			var guid = f.id.substring(f.id.indexOf("-") + 1);
			var loader = $('loaderWrapper-' + guid);
			if(loader){
				loader.addClassName("ajaxLoader");
				loader.show();
			}
		},
		hideLoader: function(f){
			var guid = f.id.substring(f.id.indexOf("-") + 1);
			var loader = $('loaderWrapper-' + guid);
			if(loader){
				loader.hide();
			}	
		}
};

/** ===/ end PaymentService === * */

/** ===/ PaymentService EventCalendar === * */


var EventCalendarPaymentService = {
		serviceWrappers : [],
		chargeable: '.mktmobil-payment',
		chargeablePreview: '.mktmobil-payment preview',
		chargeableFields: [],
		exist : function(){
			this.serviceWrappers = Settings.scope.select('div[class=mobileServiceWrapper clearfix eventCalendar]');
			if(this.serviceWrappers === null){
				return false;
			}
			else{
				return this.serviceWrappers.length > 0;
			}
		},
		init : function(){
			if(!this.exist()){
				return;
			}
			
			this.initCancelLink();
			
			this.serviceWrappers.each(function(item){
				var calendar =	$('eventCalendarCreate');
				var payed = $('paymentOk');
				if(!payed || payed.value.length === 0 || payed.value !== "true"){
					var theForm = item.select('form')[0];
					theForm.setAttribute("action","/serviceServlet");
					var guid = theForm.id.substring(theForm.id.indexOf("-") + 1);
					var byAjax = $('byAjax-' + guid);
					if(byAjax){
						byAjax.value = "true";
					}
					document.observe('click', function (e){
						PaymentService.hideError(theForm);
					});
					setFormCookie("acceptCookie-" + guid);
					var paymentBtn = theForm.select('input[type=button]')[0];
					PaymentService.hideError(theForm);
					PaymentService.hideLoader(theForm);
					if(paymentBtn){
						paymentBtn.show();
						paymentBtn.onclick = function(e){
							PaymentService.validate(theForm);
							
							if(PaymentService.isError === false){
								PaymentService.verifyPayment(false, theForm,'paymentOk','true', EventCalendarPaymentService.getCancelLink());
							}
							Event.stop(e);
						};
					}
				}
				else{
					item.hide();
				}
			});
					
					
		},
		initChargeableFields : function (){
			var counter = 0;
			var calendar =	$('eventCalendarCreate');
			var payed = $('paymentOk');
			if(!payed || payed.value.length === 0 || payed.value !== "true"){
				if(calendar){
					var chargeableWrappers = calendar.select(this.chargeable);
					if(chargeableWrappers){
						chargeableWrappers.each(function(item){
							counter++;
							var inputElement = item.down(0).next(0);
							if(inputElement &&
									(inputElement.type === "text" || 
									  inputElement.type === "file" || 
									  inputElement.type === "textarea")){
								EventCalendarPaymentService.chargeableFields.push(inputElement);
								inputElement.onkeyup = function(e){
									EventCalendarPaymentService.checkInput(e);
								};
								
								inputElement.onkeydown = function(e){
									EventCalendarPaymentService.checkInput(e);
								};
								
								inputElement.onfocus = function(e){
									EventCalendarPaymentService.checkInput(e);
								};
								
								if(inputElement.type === "file"){
									inputElement.onchange = function(e){
										EventCalendarPaymentService.checkInput(e);
									};
								}
							}
						});	
					}
				}
				EventCalendarPaymentService.initSubmitBtn(calendar);
			}
			
		},
		checkInput: function(e){
			var elm = Event.element(e);
			if(elm && elm.value.length > 0){
				this.disableSubmitButton(true)
			}
			else{
				this.disableSubmitButton(false);
			}
		},
		disableSubmitButton: function (disable){
			var toolStrip = Settings.scope.select('.toolstrip')[0];
			if(toolStrip){
				var btn = toolStrip.select('input[type=submit]')[0];
				if(btn && disable){
					btn.hide();
				}
				else if(btn){
					btn.show();
				}
			}
		},
		initSubmitBtn : function(calendar){
			var counter = 0;
			var hide = false;
			
			this.chargeableFields.each(function(item){
				if(item.value.length > 0){
					counter++;
				}
			});
			
			var t = Settings.scope.select('#eventCalendarCreate-eventPicture');
			var cClass = 'txtFileUpload clearfix  mktmobil-payment preview';
			if(t.length > 0 && t[0] && t[0].hasClassName(cClass)){
				var pic = t[0].select('#eventCalendarCreate-eventPicturePreview');
				if(pic.length > 0 && pic[0]){
					 var div = pic[0];
					 var img = div.down(1);
					 //alert("Next: " + img.tagName);
					 if(img && img.tagName === 'IMG'){
						 hide = true;
					 }
				}
			}
			
			
			if(counter > 0){
				var tools = Settings.scope.select('.toolstrip')[0];
				if(tools){
					tools.select('input[type=submit]')[0].hide();
				}
			}
			else if (hide === true){
				var tools = Settings.scope.select('.toolstrip')[0];
				if(tools){
					tools.select('input[type=submit]')[0].hide();
				}
			}
		},
		initCancelLink: function (){
			var span = Settings.scope.select('span[class=btnCancel]')[0];
			var elm = $('paymentOk');
			var payed = (elm !== null && elm !== 'undefined' && elm.value === 'true');
			if(payed && span){
				span.down(0).hide();
			}
		},
		getCancelLink : function(){
			var span = Settings.scope.select('span[class=btnCancel]')[0];
			if(span){
				return span.down(0);
			}
		}
};

/** ===/ end PaymentService EventCalendar === * */



/**
 * *************************** 3. DEPRECATED / OBSOLETE
 * ******************************
 */ 
 
/**
 * !!! These functions and objects is not recommended for production use any
 * more. !!!
 */

/*******************************************************************************
 * CrowdPictures, by andersy @ T04.15
 * 
 * Light-version: only opens facebook in popup.
 */
var CrowdPictures = {
	instance : null,
	sels : {
		wrp : 'div.crowdPictures',
		fb : 'li.facebook a'
	},
	exists : function(){
		this.instance = Settings.scope.select(this.sels.wrp);
		return this.instance.length > 0; 
	},
	// init method
	init : function(){
		if(!this.exists()) return;
		this.shareLinks();
	},
	// give facebook sharelinks a popup target
	shareLinks : function(){
		Settings.scope.select(this.sels.fb).each(function(elm){
			Event.observe(elm,'click',function(e){
				window.open(e.element().href,'shareFacebook',"location=no,resizable=yes,scrollbars=yes,height=500,location=no,left=50,top=50,width=800");
				e.preventDefault();
			});
		});
	}
};/** ===/CrowdPictures=== * */


/* *** Javascript enhancements *** */

/**
 * Init method. Makes JS-dependent blocks visible (they are hidden by CSS in
 * case Javascript is not available). Varning! this does not apply on
 * JS-generated markup like Modal Windows.
 * 
 * THIS SHOULD BE REMOVED WITH REFACTORING
 */
function enableEnhancements() {
	Settings.scope.select(".hiddenByJS").each(function(item) {
		item.setStyle({position:'absolute',visibility:'hidden'});
	});
}

/**
 * Switch CSS on partly JSDependent blocks (these have fallback styles by default).
 * This function must be called manually, typically from init methods.
 * 
 * @param {Array} elements	the result array from a $$() call, ex. $$(".imageCaption div")
 * @author andersy
 * @return void
 *
 * THIS SHOULD BE REMOVED WITH REFACTORING
 */
function enableJSStyles( elements ) {
	elements.each(function(item) {
		item.wrap('div', {'class':'JSEnabled'});
	});
}

/**
 * Force external links to opens in new window. This is applied to all links with rel="external".
 * 
 * @param {HTMLElement} e	the link element
 */
function openExternalLink(e) {
	var el = Event.element(e);
	var valid = false;
	var href = "";

	if(el.tagName != 'A'){
		//Fix for teaser images
		if(el.up(0) && el.up(0).tagName == 'A'){
			valid = true;
			href = el.up(0).href;
		}
	}
	else{
		valid = true;
		href = el.href;
	}
	
	//if no teaser image or link exit quietly
	if(! valid){
		return false;
	}
	
	// open the window		
	window.open(href, '_blank');
	Event.stop(e);
	return false;
}

/**
 * Locates all links with customized rel-attributes
 * and makes them open up as modal windows or in new windows.
 */
function initLinkExtensions(customScope) {
	// Get all links with a rel attribute
	var relLinks = (typeof customScope == 'undefined') ? Settings.scope.select('a[rel]') : customScope.select('a[rel]');
	// Iterate found links and set behaviour
	relLinks.each(function(link) {
		var relValue = link.getAttribute('rel');
		// Set different behaviour depending on value
		switch(relValue) {

			case "external":
				link.observe('click', openExternalLink, false);
				break;
			
			case "modal":
				if (Settings.isEnabled('ModalWindow') && Settings.scope.id != 'modalWindowWrapper') {
					openAsModal(link);
				}
				break;
		}
	});
}
