var debug = '';
var reservationExpire = '';
var numPerPageLoans = 10;
var confirmPinPopUp = '';
var reservedMaterialPopup = '';
var borrowedMaterialPopup = '';
var lastFmResponsed = true;
var extRecourcesResponsed = true;
var sendToFriendPopup = '';

EoContextCfg = {
	userLogin : {
		priority : 50
	},
	backButton : {
		priority : 1
	},
	appovePublicProfileTerms : {},
	uploadAvatar : {},
	searchResult : {
		priority : 30,
		reloadOnStateChange : true
	},
	reservation : {
		priority : 15,
		reloadOnStateChange : true
	},
	searchResultWikipedia : {
		priority : 500
	},
	didYouMean : {
		priority : 10
	},
	sidebarSearch : {
		priority : 5
	},
	searchDefaultText : {},
	article : {},
	summaList : {},
	showRecord : {
		reloadOnStateChange : true
	},
	profile : {
		reloadOnStateChange : true
	},
	profileEdit : {
		reloadOnStateChange : true
	},
	dcAutoList : {},
	showRecordAdhl : {},
	showRecordSimilarTitles : {},
	showRecordSocialServices : {},
	extctlShowRecord : {},
	payment : {},
	assignPrintOnShowArticle : {},
	opacListImage : {},
	myLists : {
		reloadOnStateChange : true
	},
 	myStatusPage : {}, 
	sendToFriend : {},
	searchResultSocialServices : {}
}

HeartBeat = {
	timer : null,
	beat : 50000,
	payload : null,
	init: function(params){
		jQuery.extend(this,params);
		HeartBeat.timer = setTimeout(HeartBeat.run,HeartBeat.beat);
	},
	start : function() {
		HeartBeat.stop();
		HeartBeat.timer = setTimeout(HeartBeat.run,HeartBeat.beat);
	},
	run : function() {
		HeartBeat.stop();
		HeartBeat.payload();
		HeartBeat.timer = setTimeout(HeartBeat.run,HeartBeat.beat);
	},
	stop : function() {
		if(HeartBeat.timer) clearTimeout(HeartBeat.timer);
	}	
}

jQuery.extend(EasyOpac, {
	cropAvatarPopup: null,
	termsPopup: null,
	debug : false,
	needReloadOnStateChange : false,
	contexts : [],
	ssEnabled : true,
	ssOutOfOrderMsg : 'Vi beklager, funktionen er midlertidigt ude af drift.',

	addContext : function(context) {
		// alert('trying to add context: '+context);
		if(-1 == jQuery.inArray( context,this.contexts  ) ) {
			if('object' == typeof(EoContextCfg[context]) ) {
				this.contexts.push(context);
			} 
		} 
	},
	statusPageLoansUpdate : function() {
		$('.sp_loans_ajax').show();
		$.inleadAjax('reservationctl', {func : 'fetchLoans'}, function(resp) {
			$('.sp_loans_ajax').hide();
			if (resp.status == false) {
				EasyOpac.alert(resp.msg);
				return false;
			}
			if (resp.data == false) {
				EasyOpac.alert('Kunne ikke hente l&aring;neoversigten.');
			} else {
				if (resp.data) {
					$('#myLoansContainerBody').items('replace', resp.data).chain({
						'.opacContentType'       : '{material}',
						'.opacContentTitle a' : {
							'href'    : '{url}',
							'alt'     : '{titleAndAuthorTotalData}',
							'title'   : '{titleAndAuthorTotalData}',
							'content' : '{titleAndAuthor}'
						},
						'.opacContentTitle'      : {'id' : 'sp_loan_{copyno}'},
						'.opacContentTitle span.copyno' : '{copyno}',
						'.opacStatusCenter .copyno' : '{copyno}',
						'.opacContentTitle span.type' : '{material}',
						'.opacLoginPopupContentCheckout'     : '{checkout}',
						'.opacLoginPopupContentDeliver span' : {
							'title'   : '{daysLeft+ " " + daysLeftToDeliver}',
							'content' : '{duedate}'
						},
						'.opacLoginPopupContentDeliver' : {
							'class' : '{"opacLoginPopupContentDeliver " + dateColor'
						},
						'.opacLoginPopupContentExtra' : '{renew}'
					});
					/* make sure we zebra stribe the rows correctly */
					/* FIXME might not be the most elegant way to do it ;) */
					$('#myLoansContainerBody tr:odd').removeClass('r2').addClass('r1');
					$('#myLoansContainerBody tr:even').removeClass('r1').addClass('r2');

				}
			}
		});
 	},
	runContexts : function() {
		if(this.debug) console.log('Starting to run contexts');

		// avoid running contexts in ES BE
		if(EasyOpac.backendActive) return true;

		// Sort this.contexts before run
		var c = EoContextCfg;
		this.contexts.sort(function(a, b) {
			return (c[a].priority ? c[a].priority : 1000) > (c[b].priority ? c[b].priority : 1000);
		});
		jQuery.each(this.contexts,this.runContext);
	},
	runContext : function(index,name) {
		if(EasyOpac.debug) {
			console.log('Running init for context #'+index+" "+name);
		}
		var funcRef = EasyOpacContexts[name];
		if ('function' == typeof funcRef){
			funcRef();
		}
		if(EasyOpac.debug) {
			console.log('Done running context #'+index+" "+name);
		}
	},
	assignPrintOnShowRecord : function () {
		$('#printButtonShowRecord').bind('keypress click',
			function(e) {
				var evt = window.event || e;
				if (evt.keyCode && (evt.keyCode == 9 || evt.keyCode == 32))
					return true;
				window.print();
				return false;
			}
		);
	},
	alert : function(msg, fn)  {
		Boxy.ask('<div>'+msg+'</div>', ['Ok'], function(answer) {
			if(typeof fn == 'function') fn(answer);
		}, {title: "System meddelse"});
	},
	toggleExtResources : function (obj) {
		if ($(obj).hasClass('selected')) {
			$(obj).removeClass("selected");
			$(obj).parent().parent().parent().find('div.tab').filter(obj.hash).hide();
		} else {
			$(obj).parent().parent().parent().find('div.tab').hide();
			$(obj).parent().parent().parent().find('div.tab').filter(obj.hash).show();
			$(obj).parent().parent().find('a').removeClass('selected');
			$(obj).addClass('selected');
			$(obj).parent().parent().find('a:not(.selected) img').fadeTo("slow", 0.33);
			$(obj).parent().parent().find('a.selected img').fadeTo("slow", 1);
		}
	},
	getAnchorFromUrl : function () {
		var hash = location.hash;
		return hash.substring(1);
	},
	popBox : function(title, contentDom, placementId ) {

		/* some plaement code is still here.. not in use anymore */

		/* default position */
		var posX = false;
		var posY = false;

		if(placementId) {
			pos =  $(placementId).offset();
			posX = pos.left-50;
			posY = pos.top;
		}
		return  new Boxy(contentDom, {title: title});
		return  new Boxy(contentDom, {title: title, x : posX , y : posY});
	}, 
	popConfirm : function(q, fn) {
		Boxy.ask(q, ["Ok", "Annuller"], function(val) {
			if('Ok' == val )
				fn();
		} , {title: "Er du sikker p&aring;.."});
	},
	popMakeSticky : function(id) {
	},
	popShowStikies : function() {
	},
	
	loadContent : function(recordId) {
		// $('.record').html('Opdaterer...');
		$.inleadAjax('externalsctl', {t : 'entireRecord', recordId : recordId}, function(resp) {
			if(null != resp.data.entireRecord) {
				
				$('.showRecord').replaceWith(resp.data.entireRecord);
				// EasyOpac.runSpecificContexts(['showRecord','showRecordSocialServices','reservation','extctlShowRecord','backButton']);
				EasyOpac.runSpecificContexts(['showRecordSocialServices','reservation', 'extctlShowRecord', 'backButton']);
			}
		});
	},
	
	addSpecificContexts : function (contexts){
		for (context in contexts) {
			EasyOpac.addContext(contexts[context]);		
		}
	},
	
	runSpecificContexts : function(contexts) {
		if(this.debug) console.log('Starting to run specific contexts');

		// Sort this.contexts before run
		/*
		var c = EoContextCfg;
		this.contexts.sort(function(a, b) {
			return (c[a].priority ? c[a].priority : 1000) > (c[b].priority ? c[b].priority : 1000);
		});
		*/
		jQuery.each(contexts,this.runContext);
	},
	
	updateSearchHistory : function(offset, order) {
		$('.searchHistoryPopupContent .opacLoginPopupTableMargin').hide();
		$('.searchHistoryPaging .pagingString').empty();
		$('.searchHistoryPopupContent .ajaxImage').show();
		$.inleadAjax('SearchHistory', {method : 'get', offset : offset, order : order}, function(resp) {
			$('.searchHistoryPopupContent .opacLoginPopupTableMargin').show();
			$('.searchHistoryPopupContent .ajaxImage').hide();
			if(!resp.status) {
				easyopac.alert('Der opstod en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
				popup.remove();
				return false;
			}
			if (resp.data) {
				$('#searchList').items('replace', resp.data.records ).chain({
					'.searchHistoryDelete' : {rel :'{id}'},
					'.query': {href:'{searchUrl}', content:'{query}'},
					'.hits': '{hits}',
					'.lastUpdate': '{lastUpdate}'
				}).find('.searchHistoryDelete').click(function() {
					var elm = $(this)
					var entryId = elm.attr('rel');
					$.inleadAjax('SearchHistory', {method : 'delete', entryId : entryId}, function(resp) {
						if(!resp.status) {
							easyopac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
							popup.remove();
							return false;
						} else {
							EasyOpac.updateSearchHistory(offset, order);
						}
					});
				});
			} else {
				return;
			}

			if(resp.data.offset != 0) {
				$('.searchHistoryPaging .searchHistoryPrev').show();
			} else {
				$('.searchHistoryPaging .searchHistoryPrev').hide();
			}
			// why 10?
			var perPage = 10;
			var returned = parseInt(resp.data.returned);
			var offset = parseInt(resp.data.offset);
			var total = parseInt(resp.data.total);
			var page = 1 + parseInt(offset);
			var totalPages = Math.ceil(total / perPage);
			if (page < 1)
				page = 1;
			if (page > totalPages)
				page = totalPages;
			var startItem = (offset * perPage) + 1;
			var endItem = startItem + returned - 1;
			
			var pagingString = '';
			
			// less than 6 pages
			if (totalPages < 6) {
				$.each(Array(totalPages), function(index) {
					if (index < (page - 1)) {
						pagingString += '<span style="color:#a70000;font-weight:bold;">[' + (index + 1) + ']</span>&nbsp;';
					} else if (index > (page - 1)) {
						pagingString += '&nbsp;<span style="color:#a70000;font-weight:bold;">[' + (index + 1) + ']</span>';
					} else {
						pagingString += '<span>' + (index + 1) + '</span>';
					}
				});
			} else {
				pagingString = '<span>' + page + '</span>';
				// prev pages
				if (page > 1) {
					pagingString = '<span style="color:#a70000;font-weight:bold;">[' + (page - 1) + ']</span>&nbsp;' + pagingString;
				}
				if (page > 2) {
					pagingString = '<span style="color:#a70000;font-weight:bold;">[' + (page - 2) + ']</span>&nbsp;' + pagingString;
				}
				if (page > 10) {
					pagingString = '<span style="color:#a70000;font-weight:bold;">[' + (page - 10) + ']</span>&nbsp;' + pagingString;
				}
				if (page > 20) {
					pagingString = '<span style="color:#a70000;font-weight:bold;">[' + (page - 20) + ']</span>&nbsp;' + pagingString;
				}
				// next pages
				if (totalPages > 1 && page < (totalPages)) {
					pagingString = pagingString + '&nbsp;<span style="color:#a70000;font-weight:bold;">[' + (page + 1) + ']</span>';
				}
				if (totalPages > 2 && page < (totalPages - 1)) {
					pagingString = pagingString + '&nbsp;<span style="color:#a70000;font-weight:bold;">[' + (page + 2) + ']</span>';
				}
				if (totalPages > 10 && page < (totalPages - 9)) {
					pagingString = pagingString + '&nbsp;<span style="color:#a70000;font-weight:bold;">[' + (page + 10) + ']</span>';
				}
				if (totalPages > 20 && page < (totalPages - 19)) {
					pagingString = pagingString + '&nbsp;<span style="color:#a70000;font-weight:bold;">[' + (page + 20) + ']</span>';
				}
			}
			$('.searchHistoryPaging .pagingString').empty();
			$('.searchHistoryPaging .pagingString').html('Side ' + pagingString + ' (' + startItem + '-' + endItem + ' af ' + total + ' resultater, ' + totalPages + ' sider)');
			
			// bind inClick to each page
			$('.searchHistoryPaging .pagingString span').unbind('click').click(function() {
				var tmp = $(this).text();
				// current page clicked
				if (!/^\[/i.test(tmp))
					return;
				page = /(\d+)/i.exec(tmp);
				if (!parseInt(page[1]))
					return;
				EasyOpac.updateSearchHistory(parseInt(page[1])-1,$('.searchHistoryPaging .orderBy'));
			});
			
			if((parseInt(resp.data.offset) +1) < Math.ceil(resp.data.total/10)) {
				$('.searchHistoryPaging .searchHistoryNext').show();
			} else {
				$('.searchHistoryPaging .searchHistoryNext').hide();
			}
			//$('.opacPagingContent .totaltSearches').text(resp.data.total);
			$('.searchHistoryPaging .offset').text(resp.data.offset);
			$('.searchHistoryPaging .orderBy').text(resp.data.orderBy);

			//$('.opacPagingContent .opacResultPaging').empty();

			// dynamicly create paging
			/*$.each(Array(Math.ceil(resp.data.total/10)), function(index) {
				if(index == offset ) {
					$('.opacPagingContent .opacResultPaging').append('<span style="color:#79797B;font-weight:bold;">'+(index+1)+'</span>&nbsp;');
				} else {
					$('.opacPagingContent .opacResultPaging').append('<span>'+(index+1)+'</span>&nbsp;');
				}
			});
			// bind inClick to each page
			$('.opacPagingContent .opacResultPaging span').click(function() {
				EasyOpac.updateSearchHistory(parseInt($(this).text())-1,$('.searchHistoryPaging .orderBy'));
			});*/
		});

	}, 
	updateReservationsContent : function(type) {
		$.inleadAjax('reservationctl', {func : 'fetchReservations'}, function(resp) {
			if (resp.expired)
				return false;
			if(resp.status == false) {
				EasyOpac.alert(resp.msg);
				return false;
			}
			if(resp.data == false) {
				if(resp.data.length == 0)
					EasyOpac.alert('Du har ikke nogen reserveringer.');
				else
					EasyOpac.alert('Kunne ikke hente reserveringsoversigten.');
				if ($('span.reservationCount'))
					$('span.reservationCount').text('0');
				if (reservedMaterialPopup) {
					reservedMaterialPopup.hide();
					reservedMaterialPopup = null;
				}
			} else {
                if (type == 'static') {
					EasyOpac.updateReservationsContentDoLayoutStatic(resp);
				} else {
					EasyOpac.updateReservationsContentDoLayoutPopup(resp);
				}
			}
		});
	},
	
	updateReservationsContentDoLayoutStatic: function(resp) {
		if (resp.data)
			$('span.reservationCount').text(resp.data.length);

		$('#reservationList').items('replace', resp.data ).chain({
			'.reservationNumber': '{resno}',
			'.opacLoginPopupContentTitle a': {'href' : '{url}', 'alt' : '{titleAndAuthorTotalData}', 'title' : '{titleAndAuthorTotalData}', 'content' : '{titleAndAuthor}'},
			'.opacLoginPopupContentTitle span.type' : '{material}',
			'.opacStatusCenter' : '{resdate}',
			'.opacLoginPopupContentDeliver span' : {'content' : '{expdate}'},
			'.opacLoginPopupContentKonr' : '{qno}',
			'.opacContentFilial' : '{branch}',
			'.opacLoginPopupRight input' : {'value': '{resno}'}
		});
	},
	updateReservationsContentDoLayoutPopup: function(resp) {
				if (resp.data)
					$('span.reservationCount').text(resp.data.length);

				$('#reservationList').items('replace', resp.data ).chain({
					'.reservationNumber': '{resno}',
					'.interurban' : '{interurban}',
					'.opacLoginPopupContentTitle a': {'href' : '{url}', 'alt' : '{titleAndAuthorTotalData}', 'title' : '{titleAndAuthorTotalData}', 'content' : '{titleAndAuthor}'},
					'.opacLoginPopupContentType' : '{material}',
					'.opacLoginPopupContentKonr' : '{qno}',
					'.opacLoginPopupContentBranch' : '{branch}',
					'.opacLoginPopupContentDeliver span' : {'content' : '{expdate}'},
					'.opacLoginPopupContentDeliver' : {'class' : '{"opacLoginPopupContentDeliver opacLoginPopupRight"+dateColor'},
					'.opacLoginPopupContentInterurban' : '{interurban}'
				});
                $('#reservationList tr').each(
                function (index, domEle) {
                    var check = $('.opacLoginPopupContentKonr', domEle).text();
                    if (check == 'FL'){
                        $('.opacLoginPopupRight', domEle).html('');
                    }
                });
                $('.deleteReservation').unbind('click').click(function(e) {
				EasyOpac.popConfirm('Er du sikker p&aring; du vil slette reserveringen?', function() {
						e = e || window.event;
						targ = e.target || e.srcElement;
						resno = $(targ).parent().find('span.reservationNumber').text();
						var interurban = $(targ).parent().find('span.interurban').text();
						$.inleadAjax('reservationctl', { 
								func : 'delete', 
								resno : resno,
								interurban: interurban}, 
							function(resp) {
								if (resp.status == false) {
									EasyOpac.alert(resp.msg);
									return false;
								}
								if (resp.data.status == true && !resp.expired) {
									$(targ).parent().parent().hide();
									EasyOpac.alert('Reservationen blev slettet.');
									EasyOpac.updateReservationsContent();
								} else {
									if (!resp.expired) {
										if (resp.data.msg && resp.data.msg != "") {
											EasyOpac.alert(resp.data.msg);
										} else {
											EasyOpac.alert('Reservationen kunne ikke slettes.');
										}
									}
								}
						});
					});
				});

				$('.reservationEdit img').click(function(e) {
					if(!EasyOpac.isLoggedIn) {
						EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne &aelig;ndre din reservering.');
						return true;
					}
					updateItemReservationPopUp = EasyOpac.popBox('Opdater reservering', $('.opacUpdateItemReservation'));
					resno = $(e.target).parent().parent().find('span.reservationNumber').html();
					$('div.opacUpdateItemReservation div.opacReserveItemResno').text(resno);
				});
	},
	
	updateLoanContent : function() {
		$.inleadAjax('reservationctl', {func : 'fetchLoans'}, function(resp) {
			if(resp.status == false) {
				EasyOpac.alert(resp.msg);
				return false;
			}
			if(resp.data == false) {
				EasyOpac.alert('Kunne ikke hente l&aring;neoversigten.');
				if (borrowedMaterialPopup)
					borrowedMaterialPopup.hide();
			} else {
				if (resp.data)
					$('.borrowedMaterial').next('span.count').text(resp.data.length);
				$('#loanList').items('replace', resp.data ).chain({
					'.opacLoginPopupContentTitle a': { 
						'href' : '{url}', 
						'alt' : '{titleAndAuthorTotalData}', 
						'title' : '{titleAndAuthorTotalData}', 
						'content' : '{titleAndAuthor}'
					},
					'.opacLoginPopupContentTitle': {'id' : 'loan_{copyno}'},
					'.opacLoginPopupContentTitle span': '{copyno}',
					'.opacLoginPopupContentType' : '{material}',
					'.opacLoginPopupContentCheckout' : '{checkout}',
					'.opacLoginPopupContentDeliver span' : {
						'title' : '{daysLeft+" "+daysLeftToDeliver}', 
						'content' : '{duedate}'
					},
					'.opacLoginPopupContentDeliver' : {
						'class' : '{"opacLoginPopupContentDeliver opacLoginPopupRight"+dateColor'
					},
					'.opacLoginPopupContentExtra' : '{renew}'
				});

				$('.opacLoginPopupRenew').click(function() { 
					var target = $(this);
					EasyOpac.popConfirm('Er du sikker p&aring; at du vil forny l&aring;net?', function() {
						// The class '.opacLoginPopupRenew' is on a span-element that comes from the arpPlugin.
						copyno = target.parents('tr:first').find('.opacLoginPopupContentTitle span.copyno').text();

						$('#loanList tr:not(:first)').remove();
						$('#loanList .opacLoginPopupContentType').html('<img src="images/ajax.gif" />');
						$('#loanList .opacLoginPopupContentTitle a').empty();
						$('#loanList .opacLoginPopupContentDeliver span').empty();
						$('#loanList .opacLoginPopupContentExtra').empty();

						$.inleadAjax('reservationctl', {func : 'renewLoan', copyno : copyno}, function(resp) {
							if(resp.data) {
								var failedRenews = 0;
								var y = $('<div></div>');
								y.addClass('renewErrors');
								var i,j;
								for (i in resp.data.failed) {
									var errorTitle = $("#loanNotRenewedTpl .red").clone();
									var error = resp.data.translate[i];
									errorTitle.html(error);
									y.append(errorTitle);
									for (j = 0; j < resp.data.failed[i].length; j++) {
										var title = $("#loanNotRenewedTpl .title").clone();
										title.html($("td#loan_" + resp.data.failed[i][j] + " a").html());
										y.append(title);
										failedRenews++;
									}
								}
								if (failedRenews > 0) {
									EasyOpac.alert(y.html());
								}
								EasyOpac.updateLoanContent();
							} else {
								EasyOpac.updateLoanContent();
								EasyOpac.alert('Fornyelsen kunne ikke gennemf&oslash;res.');
							}						
						});
					});
				});
				$(".borrowedMaterialContent #renewAll .selectAll").unbind("click").click(function() {
					if ($(".borrowedMaterialContent input:checkbox:visible").length == $(".borrowedMaterialContent input:checkbox:visible:checked").length) {
						$(".borrowedMaterialContent input:checkbox:visible:checked").attr("checked", "");
					} else {
						$(".borrowedMaterialContent input:checkbox:visible").attr("checked", "checked");
					}
				});
				$(".borrowedMaterialContent #renewAll .renewSelected").unbind("click").click(function() {
					var loader = $(".borrowedMaterialContent #renewAll .renewSelectedLoader");	
					var btn = $(this);
					var a = new Array();
					$(".borrowedMaterialContent input:checkbox:visible:checked").each(function(){
						a.push($(this).attr("value"));
					});
					if (a.length > 0) {
						btn.hide();
						loader.show();
						$.inleadAjax('reservationctl', {func : 'renewLoans', copyno : a.join(",")}, function (resp) {

							loader.hide();
							btn.show();
							if (resp.status == false) {
								EasyOpac.alert(resp.msg);
								return false;
							}
							var failedRenews = 0;
							var y = $('<div></div>');
							y.addClass('renewErrors');
							var i,j;

							for (i in resp.data.failed) {
								var errorTitle = $("#loanNotRenewedTpl .red").clone();
								var error = resp.data.translate[i];
								errorTitle.html(error);
								y.append(errorTitle);
								for (j = 0; j < resp.data.failed[i].length; j++) {
									var title = $("#loanNotRenewedTpl .title").clone();
									title.html($("td#loan_" + resp.data.failed[i][j] + " a").html());
									y.append(title);
									failedRenews++;
								}
							}
							
							if (failedRenews > 0) {
								EasyOpac.alert(y.html());
							}

							EasyOpac.updateLoanContent();
						});
					} 
				});
					$('.borrowedMaterialContent .paginated').each(function() {
						var currentPage = 0;
						var numPerPage = numPerPageLoans;

						var $table = $(this);

						$table.bind('repaginate', function() {
							$table.find('tbody tr').show()
								.filter(':lt(' + currentPage * numPerPage + ')')
								.hide()
								.end()
								.filter(':gt(' + ((currentPage + 1) * numPerPage - 1) + ')')
								.hide()
								.end();
						});

						var numRows = $table.find('tbody tr').length;
						var numPages = Math.ceil(numRows / numPerPage);

						if (numPages > 1) {
							var $pager = $('#borrowedMaterialPager');
							$pager.find('.pager-pages').empty();
							$pager.find('.pager-message').empty();
							for (var page = 0; page < numPages; page++) {
								$('<span class="page-number">' + (page + 1) + '</span>').bind('click', {'newPage': page},
									function(event) {
										currentPage = event.data['newPage'];
										var fromItem = (currentPage) * numPerPage + 1;
										var toItem;
										toItem = fromItem + numPerPage - 1;
										if (currentPage == (numPages - 1)) {
											toItem = numRows;
										}
										$table.trigger('repaginate');
										$(this).addClass('active').siblings().removeClass('active');
										$(this).parent().parent().find('.pager-message').empty().text(' (' + fromItem + ' - ' + toItem + ' af ' + numRows + ' resultater, ' + numPages + ' sider)');
									}).appendTo($pager.find('.pager-pages')).addClass('clickable');
							}
							$pager.find('span.page-number:first').addClass('active');
							$pager.insertAfter($('.borrowedMaterialContent .paginated #renewAll'));
							$table.trigger('repaginate');
						}
						if ($pager)
							$pager.find('span.page-number:first').click();
					}); 
			}
		});
	},
	addToMyList : function(param) {

		if(!EasyOpac.isLoggedIn) {
			EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne benytte lister.');
			return true;
		}
		var foreignKey = param.data.foreignKey;
		var popupPosition = param.data.positionAfterElement;
		var itemType = param.data.itemType;
//alert(foreignKey+popupPosition+itemType);

		if (popup && popup.isVisible()) {
			return true;
		}

		$('.personalTagsListDropDown').empty();

		if (popup && EasyOpac.ssEnabled) {
			popup.show();
		} else {
			if (EasyOpac.ssEnabled) {
				popup = EasyOpac.popBox($('.addToListTitle').html(), $('.addToListContent'), popupPosition); // FIXME - put loading gif here;
			}
			else {
				EasyOpac.alert(EasyOpac.ssOutOfOrderMsg);
			}
		}

		// should be converted to Bosy.ask 
		$('.closeAddToMyList').unbind('click'); //Prevent several calls;

		$('.closeAddToMyList').click(function(){
			$('.newListInputText').val('');
			popup.hide();
		});
		
		$('.addToListContent .spinner').show();
		
		$.inleadAjax('SocialServicesCurrentUserPersonalTags', {}, function(resp) {
			$('.addToListContent .spinner').hide();
			if(!resp.status) {
				easyopac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
				popup.hide();
				return false;
			} else {
				var tagsDropDown = "";

				if (resp.expired && resp.expired == 1) {
					popup.hide();
					return;
				}

				if (!resp.data) {
					$('.addToListContent .addToList').attr('disabled','disabled');
					return false;
				} else {
				    $('.addToListContent .addToList').removeAttr('disabled');
				}

				for (var i=0; i < resp.data.length; i++) {
					var tagName = resp.data[i].tagName;
					var tagType = "Shared";

					if (resp.data[i].type == "personal_private")
						tagType = "Private";

					var option = "<option title='" + tagType + "' class='personalTagOption' id='" + resp.data[i].id + "'>" + tagName + "</option>";
					$('.personalTagsListDropDown').append(option);
				}
				$('.addToListContent').find('.spacer').click();
				$('.addToListContent').find('.spacer').html("&nbsp;");
				return true;
			}

		});

		//Add to My List - add to existing list
		$('.addToList').unbind('click'); //Prevent several calls;
		$('.addToList').click(function() {
			// if there is no list return
			if (!$('.personalTagsListDropDown option:selected').length)
			    return false;
			$('.addToListContent .spinner').show();
			var tagType = 'personal_private';

			if ($('.personalTagsListDropDown option:selected').attr('title') == "Shared")
				tagType = "personal_shared";
	
			if ($('.personalTagsListDropDown option:selected').attr('title') == "Private")
				tagType = "personal_private";

			$.inleadAjax('SocialServicesTagItem', {
				foreignKey : foreignKey,
				tagId : $('.personalTagsListDropDown option:selected').attr('id'),
				type : itemType,
				tagType: tagType
			}, function(resp) {
				$('.addToListContent .spinner').hide();
				if (!resp.status) {
					EasyOpac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
					popup.remove();
					return false;
				} else {
					if(!resp.data) {
						EasyOpac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
						return false;
					} else {
						EasyOpac.alert('Tilf&oslash;jet til din liste.');
                        if (popup){
							try {
								popup.remove();
							} catch(e) {
							
							} 
						}
						$('.closeAddToMyList').click();
						return true;
					}
				}
			});
		});

		// Add to My List - Create new list
		$('.createList').unbind('click'); //Prevent several calls;
		$('.createList').click(function(){
			var tag = jQuery.trim($('.newListInputText').val());
			var tagType = $('.tagType:checked').attr('value');
			$('.addToListContent .spinner').show();
			if(tag)
			$.inleadAjax('SocialServicesAddTag', {
				foreignKey : foreignKey,
				tagName : tag,
				type : itemType,
				tagType: tagType
			}, function(resp) {
				$('.addToListContent .spinner').hide();
				if(!resp.status) {
					EasyOpac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
					if (popup)
						popup.remove();
					return false;
				} else {
					if (!resp.data) {
						EasyOpac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
						return false;
					} else  {
						var option = "<option title='" + ( tagType == "personal_private" ? "Private" : "Shared")  + "' class='personalTagOption' id='" + resp.data.id + "'>" + resp.data.name + "</option>";
						// append and mark as selected
						$('.personalTagsListDropDown').append(option).find('option[id='+resp.data.id+']').attr('selected',true);
						// empty input field
						$('.newListInputText').val('');
						return true;
					}
				}
			});
		});

		$('.newListInputText').keypress(function (e) {
			if (e.which == 13) //If "Enter"
			{
				$(".newListInputText").blur();
				$('.createList').click();
			}
		});

		$('.personalTagsListDropDown').keypress(function (e) {
			if (e.which == 13) //If "Enter"
			{
				$(".personalTagsListDropDown").blur();
				$('.addToList').click();
			}
		});

	}
});

// namespace for all SocialService-related stuff, like functionality present  
// in several contexts 
var SS = { 
        // high level template/container holders
	hc: function() {return $('#ssMessages .headersContainer')},
	mc: function() {return $('#ssMessages .messageContainer')},
	tc: function() {return $('#ssMessages .template')}, // tc == template container

	// at the moment there's no way in 'inleadAjax' to send a 'post' request, 
	// adding seventh argument is kinda cumbersome, like specifying all other 
	// default arguments. so here's a small wrapper around jQuery.post, calling
	// specified arp with provided action.
	ajax: {
		post: function(action, data, callback) { 
			$.post('/ajaxResponder.php?action=' + action, data, callback, "json");
		}
	},

	// everything related to SS messages should reside in this object
	message: {
		// if we fire second ajax function before we have a return from the first
		// one - both callback will trigger as soon as they are received, in no
		// specific order. we really only need to take action on the last callback, 
		// so we're storing the last called function in this variable, and then each
		// function will check it, before executing
		lastCallback: "",

		trc: function() {return $('#ssMessages .template .trans')}, // trc == translation container

		// translations for messaging system, call with class name as argument
		// and it'll return text string from template in html
		trans: function(holder) {return SS.message.trc().find('.' + holder).text();},

		// limit height of displayed message body, so it won't get too big and
		// run off bottom of the screen
		limitBodyHeight: function(bodyElement) {
			var maxBodyHeight = 200; // 300 won't fit on 1400x900 Andrew's screen :-P

			if (bodyElement.height() > maxBodyHeight) {
				bodyElement.height(maxBodyHeight);
			}
		},

		// show amount of unread messages in inbox
		getUnreadMessages: function() {
			// set last action, so we would know if other callbacks should process their data
			SS.message.lastCallback = 'getUnread';
			$.inleadAjax('SocialServicesMessage', {method : 'getHeaders', folder: 'inbox'}, SS.message.showUnreadMessages); 
		},
		
		// check amount of messages in 'getHeaders' response and display amount
		// of unread messages to the right of the 'messages' popup link
		showUnreadMessages: function(resp) {
			// do not run it if the last action was different
			if (SS.message.lastCallback != 'getUnread') {return false;}

			if (!resp.status) { return false; }

			var unreadMessages = 0;

			if (!resp.data || !resp.data.messages) { return false; }

			// messages could be an array of messages, or the message object
			var messages = resp.data.messages.message;
			if (messages.id) {messages = Array(messages);}

			jQuery.each(messages, function() {
				if ((this).isRead == 0) {unreadMessages += 1;}
			});

			// do not show them if there are no new messages
			if (unreadMessages != 0) {
				$('.opacLogin .unreadMessagesAmount').text(unreadMessages);
				$('.opacLogin .unreadMessages').removeClass("template");
			}
		},

		// sort messages headers by clicked subject
		sortHeaders: function(header) {
			// get the column name to sort by
			var sortBy = header.attr('class');

			if (sortBy == 'check') {return false;} // no need to sort it

			var sort = header.find('.sortOrder');
			var sortClone = header.find('.sortOrder').clone();

			var direction = 'down';
			var sortClass = 'sortDown';

			SS.hc().find('.columnHeaders th.isRead .sortOrder').addClass('unread');

			if (sortBy == 'isRead') { 
				SS.hc().find('.columnHeaders th.isRead .sortOrder').removeClass('unread');
			}

			// remove all sorting arrows initially, later show only for the
			// clicked subject
			SS.hc().find('.columnHeaders th .sortOrder').removeClass('sortUp').removeClass('sortDown');
				
			// change arrow direction by changing class
			if (sortClone.hasClass('sortDown')) {
				direction = 'up';
				sortClass = 'sortUp';
			}

			sort.addClass(sortClass);

			// get list of messages
			var messages = SS.hc().find(".messages .message");

			// sort by text, case insensitive
			var iSortText = function(a, b) {
								var text1 = $(a).find("td." + sortBy).text().toLowerCase();
								var text2 = $(b).find("td." + sortBy).text().toLowerCase();

								if (text1 == text2) {return 0;}

								if (direction == 'down') { 
									return ((text1 > text2) ? -1 : 1); 
								}

								return ((text1 < text2) ? -1 : 1); 
						    };

			// replace tbody with messages, sorted by clicked column
			SS.hc().find(".messages tbody").empty().append(messages.sort(iSortText));
		},

		// success callback action for message.send
		sendSuccess: function() {
			// remove any spinners left after sending/replying
			// and hide any messageContainer leftovers
			SS.hc().find('.loading').remove();
			SS.mc().empty().hide();

			SS.message.getInbox();
			EasyOpac.alert(SS.message.trans('messageSent'));
		},

		// falure callback action for message.send
		sendFailure: function(error) {
			// if there's a server side error - show it to user, remove spinner
			// and show the message they were editing for possible retries
			if (error.error) {
				EasyOpac.alert(error.error);
			} else {
				EasyOpac.alert(SS.message.trans('messageNotSent'));
			}

			// show filled new message form on server error
			SS.hc().find('.loading').remove();
			SS.hc().find('.newMessage').show();

			// show body of the message user's replying to, if it's there
			SS.mc().find('.replyToText').show();
			SS.mc().find('.loading').remove();
		},

		// callback dispatcher for sending message
		sendCallback: function(resp) {
			if (resp.data === "1") {SS.message.sendSuccess();} 
			else {SS.message.sendFailure(resp.data);}
		 },

		// reply to message, after variables were checked
		reply: function(newMessage) {
			// set last action, so we would know if other callbacks should process their data
			SS.message.lastCallback = 'reply';

			var subject = newMessage.find('.subject').val();
			var body = newMessage.find('.body').val();
			var toUserId = newMessage.attr('toUserId');
			var toMessageId = newMessage.attr('toMessageId');

			SS.ajax.post('SocialServicesMessage', 
				{method : 'send', 
				  subject: subject, 
				  body: body, 
				  toUserId: toUserId,
				  toMessageId: toMessageId 
				}, 
				SS.message.sendCallback
			); 

			// provide visual feedback of processing the reply
			var loading = SS.tc().find(".loading").clone();
			SS.hc().find('.newMessage').hide();
			SS.mc().find('.replyToText').hide();
			SS.mc().append(loading).show();
		},

		// send new message, after variables were checked
		send: function(newMessage) {
			var subject = newMessage.find('.subject').val();
			var body = newMessage.find('.body').val();
			var toUserScreenname = newMessage.find('.to').val();

			SS.ajax.post(
				'SocialServicesMessage', 
				{method : 'send', 
				  subject: subject, 
				  body: body, 
				  toUserScreenname: toUserScreenname 
				}, 
				SS.message.sendCallback
			);

			// hide new message, but keep it there if we'll have server-side
			// error, so user could change something and retry
			var loading = SS.tc().find(".loading").clone();
			SS.hc().find('.newMessage').hide();
			SS.hc().append(loading);
		},

		// check every variable for arp to be valid, type should be 'send' or
		// 'reply', to check for 'toMessageId' and 'toUserId'
		// for 'new message' we only need to check 'to' field to be non-empty,
		// getting SS user id by screenname will happen in arp
		isValid: function(newMessage, type) {
			var subject = newMessage.find('.subject').val();
			var body = newMessage.find('.body').val();
			var toUserId = newMessage.attr('toUserId');
			var toMessageId = newMessage.attr('toMessageId');
			var toUserScreenname = newMessage.find('.to').val();

			if (!subject || subject == SS.message.trans('defaultSubject')) {
				EasyOpac.alert(SS.message.trans('noSubject'));
				return false;
			}

			if (!body) {
				EasyOpac.alert(SS.message.trans('noBody'));
				return false;
			}

			if (type == 'send' && (toUserScreenname == '')) {
				EasyOpac.alert(SS.message.trans('noScreenname'));
				return false;
			}

			if (type == 'reply' && (toUserId == '' || toMessageId == '')) {
				EasyOpac.alert(SS.message.trans('wrongReplyInfo'));
				return false;
			}

			return true;
		},

		// show reply form
		showReply: function() {
			// get message id, user id, message body and subject
			var message = SS.mc().find('.msg');
			var toUserId = message.attr('fromUserId');
			var toUserName = message.attr('fromUserName');
			var toMessageId = message.attr('messageId');
			var replySubject = 'Re: ' + message.find('.subject .text').html();

			var replyBody = message.find('.body').html();

			SS.hc().empty();
			SS.mc().empty();

			var replyMessageTemplate = SS.tc().find('.newMessage').clone().addClass('replyMessage');

			replyMessageTemplate.find('.subject').val(replySubject);
			replyMessageTemplate.attr('toUserId', toUserId);
			replyMessageTemplate.attr('toUserName', toUserName);
			replyMessageTemplate.attr('toMessageId', toMessageId);
			replyMessageTemplate.find('.to').val(toUserName);
			replyMessageTemplate.find('.to').attr('disabled', 1);

			// replace 'send' class with 'reply' to differentiate user actions later
			replyMessageTemplate.find('.send').addClass('reply').removeClass('send');

			SS.hc().append(replyMessageTemplate).show();

			var replyTemplate = SS.tc().find('.replyToText').clone();

			replyTemplate.find('.replyBody').html(replyBody);

			SS.mc().append(replyTemplate).show();

			// limit displayed body, scroll will appear with 'overflow: auto'
			SS.message.limitBodyHeight(replyTemplate.find('.replyBody'));

			// focus on body
			replyMessageTemplate.find("textarea.body").focus();
		},

		// show new message form
		showNew: function() {
			// reset, so no other callbacks would run
			SS.message.lastCallback = '';

			SS.hc().empty();
			SS.mc().hide();

			var newMessageTemplate = SS.tc().find('.newMessage').clone();

			// append default text to subject, need to check it later before sending
			newMessageTemplate.find('.subject').val(SS.message.trans("defaultSubject")).addClass('helper');

			SS.hc().append(newMessageTemplate);

			newMessageTemplate.find(".name input.to").autocomplete("/ajaxResponder.php?action=SocialServicesMessage&method=recieverSuggestion&resulttype=simple", {selectFirst : false});

			// focus on receiver
			newMessageTemplate.find("input.to").focus();
		 },

		// get body of clicked subject and callback it with displaying
		get: function(subjectElement) {
			var mid = $(subjectElement).attr('messageid');

			// set last action, with specific message id, so we won't show
			// several message callbacks when user rapidly clicks on headers
			SS.message.lastCallback = 'get_' + mid;

			// remove 'unread' dot for this message
			var messageTemplate = subjectElement.find('.isRead').empty();

			// add 'loading' div with a spinner as background
			var loading = SS.tc().find(".loading").clone();
			SS.mc().empty().append(loading).show();

			$.inleadAjax('SocialServicesMessage', {method : 'get', messageId: mid}, SS.message.show); 
		},

		// write to html and display selected message body
		show: function(resp) {
			var message = resp.data.message;

			// do not run it if the last action was a specific message 'get'
			if (SS.message.lastCallback != 'get_'+message.id) {return false;}

			var messageTemplate = SS.tc().find('.msg').clone();

			var from = message.fromUserName;

			// if we're showing 'sent' message - display 'from' as 'to'
			if ($('#ssMessages .highlight').hasClass('sent')) {
				from = message.toUserName;
			}

			messageTemplate.attr('fromUserId', message.fromUserId);
			messageTemplate.attr('fromUserName', message.fromUserName);
			messageTemplate.attr('messageId', message.id);
			messageTemplate.find('.subject .text').html(message.subject);
			messageTemplate.find('.from').html(from + ', '+ message.date);
			messageTemplate.find('.body').html(message.body);

			SS.mc().empty().append(messageTemplate).show();

			// set max body height with javascript, because not all browsers
			// support max-height
			SS.message.limitBodyHeight(messageTemplate.find('.body'));
		},

		// return int array of messaged ids, checked by user
		getCheckedIds: function() {
			var mids = [];

			jQuery.each(SS.hc().find('.message input:checked'), function() {
				mids.push(parseInt($(this).parents('.message').attr('messageId')));
			});

			return mids;
		},

		// tell showList to show inbox or sent messages
		getInbox: function() { 
			// set last action, so we would know if other callbacks should process their data
			SS.message.lastCallback = 'inbox';

			// some clicks are not directly on tabs, like 'cancel', so we still
			// need to highlight the tabs before callback
			$('#ssMessages .tab').removeClass('highlight');
			$('#ssMessages .inbox').addClass('highlight');

			// add 'loading' div with a spinner as background
			var loading = SS.tc().find(".loading").clone();
			SS.hc().empty().append(loading);

			$.inleadAjax('SocialServicesMessage', {method : 'getHeaders', folder: 'inbox'}, SS.message.showInbox); 
		},

		// highlight inbox tab and call showList to display received messages data
		showInbox: function(resp) { 
			// do not run it if the last action was different
			if (SS.message.lastCallback != 'inbox') {return false;}

			return SS.message.showList(resp, 'inbox'); 
		},

		// show spinner and set highlight when asked for 'sent' folder
		getSent: function(resp) {
			// set last action, so we would know if other callbacks should process their data
			SS.message.lastCallback = 'sent';

			// some clicks are not directly on tabs, like 'cancel', so we still
			// need to highlight the tabs before callback
			$('#ssMessages .tab').removeClass('highlight');
			$('#ssMessages .sent').addClass('highlight');

			// add 'loading' div with a spinner as background
			var loading = SS.tc().find(".loading").clone();
			SS.hc().empty().append(loading);

			$.inleadAjax('SocialServicesMessage', {method : 'getHeaders', folder: 'sent'}, SS.message.showSent); 
		},

		// show sent messages on ajax callback
		showSent: function(resp) { 
			// do not run it if the last action was different
			if (SS.message.lastCallback != 'sent') {return false;}

			return SS.message.showList(resp, 'sent'); 
		},

		// display message listing content, inbox or sent
		showList: function(resp, folder) {
			if (!resp.status) return false;

			var headersContainer = SS.hc();

			// message if folder is empty
			if (resp.data == "") {
				headersContainer.html(SS.message.trans('emptyFolder'));
				return false;
			};

			var headersTpl = SS.hc().find('.messagesHeaders');

			// messages could be an array of messages, or the message object
			var messages = resp.data.messages.message;

			if (messages.id) {messages = Array(messages);}

			headersContainer.empty();

			SS.tc().find('.folder .massSelect').clone().appendTo(headersContainer);
			SS.tc().find('.folder .messagesHeaders').clone().appendTo(headersContainer);

			var scroll = SS.tc().find('.folder .scroll').clone();
			var messagesTable = scroll.find('.messages tbody');
			var messageTr = scroll.find('.message').clone();

			// fill each message and append them to folder table
			SS.message.addMessages(messages, messageTr, messagesTable, folder);

			scroll.appendTo(headersContainer);
			var ma = SS.tc().find('.folder .massAction').clone();

			// do not show 'read'/'unread' for 'sent' folder
			if (folder == 'sent') {
				ma.find('.markRead').remove();
				ma.find('.markUnread').remove();
			}

			ma.appendTo(headersContainer);

			// limit scroll height to defined amount of pixels
			var maxScrollHeight = 180;

			if (scroll.height() > maxScrollHeight) {
				scroll.height(maxScrollHeight);

				// now that we have less width for subject line because of scrollbar
				// - increase width of 'check' column to compensate headers 
				// adjustment and reduce other columns acoordingly
				var check = SS.hc().find('.columnHeaders th.check');
				var subj = SS.hc().find('.columnHeaders th.subject');
				var date = SS.hc().find('.columnHeaders th.date');
				var arrow = SS.hc().find('.massActionArrow');
				var tableMessages = SS.hc().find('table.messages');

				check.width(check.width() + 15);
				subj.width(subj.width() - 15);
				date.width(date.width() - 10);

				// this is MSIE workaround, setting width in percentage works
				// different in FF and IE. this should resize messages headers
				// window, so horisontal scrollbar won't appear.
				// 31 pixel is enough for IE, need extra pixel for safari
				tableMessages.width($('#ssMessages').width() - 32);

				// also - move massActionArrow to the left with right margin
				arrow.css('margin-right', parseInt(arrow.css('margin-right')) + 15);
			}
		},

		// populate messages to table cells
		addMessages: function(messages, messageTr, messagesTable, folder) {
			messagesTable.empty();

			// truncate subject and name to defined amount of chars to fit on one line
			// end with ellipses and add full subject as 'title'
			var maxSubjectLength = 35;
			var maxNameLength = 7;

			jQuery.each(messages, function(i, message) {
				var newRow = messageTr.clone();

				// display addressee for 'sent' folder
				var name = (folder == 'sent') ? message.toUserName : message.fromUserName;

				var shortName = name;
				var shortSubject = message.subject;

				if (shortSubject.length > maxSubjectLength) {
					shortSubject = shortSubject.substr(0, maxSubjectLength) + "...";
				}

				if (shortName.length > maxNameLength) {
					shortName = shortName.substr(0, maxNameLength) + "...";
				}

				// if we're in 'sent' - show receiver, not sender
				if (folder == 'sent') {name = message.toUserName;}

				newRow.find('.subject').html(shortSubject);
				newRow.attr('title', message.subject);
				newRow.find('.date').html(message.date);
				newRow.find('.name .profileLink').html(shortName);
				newRow.find('.name .profileLink').attr('href', message.fromProfileLink);
				newRow.find('.name').attr('title', name);
				newRow.attr('messageId', message.id);
				newRow.attr('isRead', message.isRead);
				newRow.attr('isReply', message.isReply);

				if (message.isRead == "1" || folder == 'sent') {
					newRow.find('.isRead').empty();
				}

				newRow.appendTo(messagesTable);
			});
		 },

		// mass actions binding and manipulation
		massActions: {
			bind: function() { 
				SS.hc().find('.massAction .markRead').live("click", function() {SS.message.massActions.run('change', 'read');});
				SS.hc().find('.massAction .markUnread').live("click", function() {SS.message.massActions.run('change', 'unread');});
				SS.hc().find('.massAction .delete').live("click", SS.message.massActions.deleteConfirm);
			},

			// call arp with appropriate method and action
			run: function(method, action) {
				var mids = SS.message.getCheckedIds();

				SS.message.massActions.showLoading();

				$.inleadAjax(
					'SocialServicesMessage', 
					{method : method, statusAction: action, messagesIds: mids.join(',')}, 
					SS.message.getInbox
				); 
			},

			// mass deletion requires modal confirmation from user
			deleteConfirm: function() {
				EasyOpac.popConfirm(SS.message.trans('confirmDeletion'), function() {SS.message.massActions.run('delete');});
			},

			// tell user we're actually doing something on every action, then
			// call action itself
			showLoading: function(action) {
				var loading = SS.tc().find(".loading").clone();
				SS.mc().empty().hide();
				SS.hc().empty().append(loading);
			}
		},

		// selectors binding and manipulation
		selectors: {
			bind: function() {
				var ms = SS.hc().find('.massSelect');

				ms.find('.selectAll').live("click", SS.message.selectors.all);
				ms.find('.selectNone').live("click", SS.message.selectors.none);
				ms.find('.selectRead').live("click", SS.message.selectors.read);
				ms.find('.selectUnread').live("click", SS.message.selectors.unread);
			},

			all: function() {
				SS.hc().find('.message input:checkbox').attr('checked', true);
			},
			none: function() {
				SS.hc().find('.message input:checkbox').attr('checked', false);
			},
			read: function() {
				SS.message.selectors.none();
				SS.hc().find(".message[isread=1] input:checkbox").attr('checked', true);
			},
			unread: function() {
				SS.message.selectors.none();
				SS.hc().find(".message[isread=0] input:checkbox").attr('checked', true);
			}

		}
	},
	
        showItemTags: function (tags, tpl, tagsContainer, searchUrl, isSearchResult) { 
                var searchUrl = searchUrl || '/forside/opac/soegeresultat?tagname=%tagName%'; 
 
                // set searchUrl to template, so showAddedTag could find it later 
                var tag = $(tpl).find('.recordTagHighlight').find('a').attr('href', searchUrl); 
 
                var tagsNames = []; 
 
                // tags may be array of objects, or array of tag names 
                jQuery.each(tags, function() {  
                        tagsNames.push(this.name || this.toString()); 
                }); 
 
                // need to display tags sorted by name 
                function sortTagsByNameCaseInsensitive(a, b) { 
                        return (a.toLowerCase() >= b.toLowerCase()) ? 1 : -1; 
                }  
 
                var tagsSortedByName = tagsNames.sort(sortTagsByNameCaseInsensitive); 

                jQuery.each(tagsSortedByName, function() { 
                        // get rid of object context 
                        var name = this.toString(); 
 
                        // strip tags to fit on one line 
                        // if (name.length > 18) {name = name.substring(0, 17);} 
 
                        var tagUrl = searchUrl.replace('%tagName%', name); 
 
                        var tag = $(tpl).find('.recordTagHighlight').clone(); 
 
                        tag.find('a').attr('href', tagUrl).html(name);
 
                        // exit .each loop if this SearchResult page and length of tags plus  
                        // separators won't fit on two lines 
                        if (isSearchResult && (tagsContainer.text().length + name.length > 35)) {return false;} 
 
                        tagsContainer.append(tag); 
                }); 
        }, 
 
        showItemRating: function (rating, votes, template, ratingContainer) { 
                // empty rating container, in case we're updating rating 
                ratingContainer.empty(); 
 
                showItemStars(rating, ratingContainer); 
 
                showItemVotes(votes, ratingContainer); 
 
                // only show votes if there are any 
                function showItemVotes(voteNum, ratingContainer) { 
                        if (voteNum == 0) {return;} 
 
                        var votesTpl = template.find('.ratingCountSpan').clone(); 
                        votesTpl.find('.ratingVotesNumber').html(voteNum); 
 
                        $(ratingContainer).append(votesTpl); 
                } 
 
                // 5-star rating 
                function showItemStars(rating, ratingContainer) { 
                        for (var i=1; i<=5; i++) { 
                                var status = (i <= rating) ? 'Active' : 'Inactive'; 
 
                                var star = $('.tpl .opacStar' + status).clone(); 
 
                                $(ratingContainer).append(star); 
                        } 
                } 
        }, 
         
        // add tag to tags container, preserving sorting, and blink it 2 times 
        showAddedTag: function (name, tpl, tagsContainer) { 
                var tag = tpl.find('.recordTagHighlight').clone().hide(); 
 
                var searchUrl = tag.find('a').attr('href'); 
                var tagUrl = searchUrl.replace('%tagName%', name); 
 
                tag.find('a').html(name).attr('href', tagUrl); 
 
                var added = false; 
 
                // insert new tag before what element 
                jQuery.each(tagsContainer.find('.recordTagHighlight'), function() { 
                        if ($(this).find('a').html().toLowerCase() > name.toLowerCase()) { 
                                tag.insertBefore($(this)); 
 
                                pulse(tag); // what, pulse? :] 
 
                                added = true; 
 
                                // quit 'each' loop 
                                return false; 
                        } 
                }); 
 
                // if element was added 
                if (added == true) {return true;} 
 
                // if there were no elements, or 
                // all elements were less, than new one 
                tagsContainer.append(tag); 
 
                pulse(tag); 
 
                function pulse(tag) {tag.fadeIn().fadeOut().fadeIn();} 
        } 
} 

var Lapi = {
	// shows item availability status for preferred and other libs on SearchResult page
	// according to case 1462: https://docs.google.com/a/inleadmedia.com/Doc?docid=0ASnxCmhfHdEZZGdtNnNweDVfMTdnZDJmNWRjZw&hl=en
	// this is a callback function for ajax 'lapistatus' call, so we have lapi
	// response as the argument
	showItemsAvailability: function (resp) {
		var respStatus = resp.status;
		var prefLib = resp.data.homeFilial;
		var prefLibCode = resp.data.homeFilialCode;
		var records = resp.data.records;
		var loggedStatus = EasyOpac.isLoggedIn ? 'logged' : 'notLogged';

		// templates for statuses
		var tpl= $('.template');
		var tplBranch = $('.template .branch');
		var tplStatus = $('.template .' + loggedStatus);

		if (!respStatus) {return false;}

		// iterate over all records on the page and add
		jQuery.each($('.searchRecord'), function() {
			var sr = $(this);
			var primaryStatus = sr.find('.lapiStatusContainer .primary .statusComment');
			var secondaryStatus = sr.find('.lapiStatusContainer .secondary .statusComment');
			var secondary = sr.find('.lapiStatusContainer .secondary');

			// get faustNum for this record
			var fnum = sr.find('.recordInfo .faustNum').text();

			// get record type
			var recordType = sr.find('.recordInfo .recordType').text();


			// remove initial grey 'Status' status when we have data
			sr.find('.lapiStatusContainer .initial').remove();

			// backend may _not_ return a record, not even empty, for the given
			// faustNum, so we need to check it and unset known flag
			if (records[fnum]) { 
				var record = records[fnum];
				var item = itemStatus(record);
			} else if('netdokument' == recordType) {
				var on = tpl.find('.itemOnline').clone();
				primaryStatus.html(on);
				return true;
			} else {
				var item = {known: false}; 
			}
			
			// logged in item statuses
			if (EasyOpac.isLoggedIn) {
				// set the preferred library name to template
				tplStatus.find('.prefBranch').html(prefLib);

				// available in the preferred lib
				if (item.availablePref) {
					var ap = tplStatus.find('.itemAvailable').clone();
					ap.find('.availableCopies').html(item.copiesPref);
					primaryStatus.html(ap);
				}

				// not available at preferred, but registered there
				if (!item.availablePref && item.registeredPref) {
					var uarp = tplStatus.find('.itemUnavailable').clone();
					uarp.find('.waitingTime').html(item.waitPref);
					primaryStatus.html(uarp);
				}

				// not registered at preferred lib
				if (!item.registeredPref && item.known) {
					var nr = tplStatus.find('.itemNotRegistered').clone();
					primaryStatus.html(nr);
				}

				/////// here goes second row item status - for other libraries

				// not available at pref, but immediately available in any branch
				if (!item.availablePref && item.available) {
					var brav = tplBranch.find('.itemAvailable').clone();
					secondaryStatus.html(brav);
					secondary.show();
				}

				// not available at pref, and not available in any branch
				if (!item.availablePref && !item.available && item.registered) {
					var brua = tplBranch.find('.itemUnavailable').clone();
					brua.find('.waitingTime').html(item.waitAll);
					secondaryStatus.html(brua);
					secondary.show();
				}

				// not registered in any of the branches
				if (item.onlyAtPref) {
					var pro = tplBranch.find('.itemNotRegistered').clone();
					secondaryStatus.html(pro);
					secondary.show();
				}
			}

			// not logged in item statuses
			if (!EasyOpac.isLoggedIn) {
				// if available in any library
				if (item.available) {
					tplStatus.find('.itemAvailable').clone().appendTo(primaryStatus);
				}

				// if it's not available in any library, but registered and can be picked later
				if (!item.available && item.registered) {
					var ua = tplStatus.find('.itemUnavailable').clone();
					ua.find('.waitingTime').html(item.waitAll);
					primaryStatus.html(ua);
				}
			}
			// common for logged and non-logged
			if( -1 != jQuery.inArray(fnum, EasyOpacContexts.faustNumsPeriodica) ) {
				var un = tpl.find('.itemPeriodica').clone();
				primaryStatus.html(un);
			} else if (!item.registered && item.known) {
				var nr = tplStatus.find('.itemNotRegistered').clone();
				primaryStatus.html(nr);
			} else if (!item.registered && !item.known) {
				var un = tpl.find('.itemUnknown').clone();
				primaryStatus.html(un);
			}
		});

		// helper - return item with all the statuses in preferred and other
		// libs, along with availability, waiting time etc
		function itemStatus(record) {
			var isLogged = EasyOpac.isLoggedIn;

			var item = { 
				available: false, 
				registered: false, 
				availablePref: false, 
				registeredPref: false, 
				copiesPref: 0,
				known: true, 
				onlyAtpref: false,
				waitAll: "",
				waitPref: ""
			};

			// need to check significantly less for non-logged statuses
			if (!isLogged) {
				item.available = available(record);
				item.registered = registered(record);
				item.waitAll = record.date;
			} else {
				item.availablePref = availableAt(prefLibCode, record);
				item.copiesPref = copiesAt(prefLibCode, record);
				item.registered= registered(record);
				item.registeredPref = registeredAt(prefLibCode, record);
				item.available = available(record);
				item.waitPref = record.date;
				item.waitAll = record.date;
				item.onlyAtPref = registeredOnlyAt(prefLibCode, record);
			}

			return item;
		}

		// check if item registered at any library
		function registered(record) {
			if (!record.filial || record.filial.length == 0) {return false;}

			return true;
		}

		// check if item is available at any library
		function available(record) {
			if (!record.filial) {return false;}

			var found = false;

			jQuery.each(record.filial, function() {
				if (this.available) {
					found = true;

					return false;
				}
			});

			return found;
		}

		// do not rely on 'atHomeFilial' and 'existsAtHomeFilial' 'cause they're
		// repeating existing data and error-prone to caching
		function availableAt(lib, record) {
			if (!record.filial || !record.filial[lib]) {return false;}

			return record.filial[lib].available;
		}

		// is given lib exists with this item
		function registeredAt(lib, record) {
			if (!record.filial || !record.filial[lib]) {return false;}

			return true;
		}

		// check if item is registered only in preferred library
		function registeredOnlyAt(lib, record) {
			if (!record.filial) {return false;}

			if (record.filial.length == 1 && registeredAt(lib, record)) {return true;}

			return false;
		}

		// how many copies do we have at the library available
		function waitAt(lib, record) {
			if (!record.filial[lib]) {return false;}

			return record.filial[lib].date;
		}

		// how many copies do we have at the library available
		function copiesAt(lib, record) {
			if (!record.filial || !record.filial[lib]) {return false;}

			return record.filial[lib].availableCopies;
		}
	},
	showItemExtendedAvailability : function(faustNum, resp) {
		if(resp.status == false) {
			EasyOpac.alert(resp.msg);
			return false;
		}
		var data = resp.data;
		var homeFilial = data.homeFilial;
		var homeFilialCode = data.homeFilialCode;

		// clean up our target container
		$('#lapiExtendedStatus').empty();

		// set status to undefined and exit on empty data
		if (!data.records || data.records[faustNum].filial.length == 0) { 
			$('#lapiExtendedStatus').append('<span class="unknown">Ukendt&nbsp;</span><span class="statusComment">Kunne ikke hente status</span>');
			return false; 
		}

		// we should have a record at this point
		var availabilityPeriod = data.records[faustNum].date;

		// if we do have home filial set, but item doesn't exist there
		if(homeFilial && data.records[faustNum].existsAtHomeFilial == false) {
			$('#lapiExtendedStatus').append("<div><span class='unavailable'>"+homeFilial+"</span><br /><span>Materialet findes ikke i denne afdeling</span></div>");
		}

		// case 1845 - preferred library should be shown first.
		// put preferred library first, if item is there, in records array, 
		// so it would be displayed first. 'records' object, that we receive in
		// response cannot be ordered, so we have to convert it to array and
		// then put home branch info as first element
		var recordsArray = [];

		// only if we have home filial code and there is a records for this filial
		if(homeFilialCode && data.records[faustNum].filial[homeFilialCode]) {
			// save it
			var homeAvailability = data.records[faustNum].filial[homeFilialCode];

			// remove from object
			delete data.records[faustNum].filial[homeFilialCode];

			// push as a first element of array, so it's displayed first
			recordsArray.push(homeAvailability);
		}

		// put all the rest of filials to array
		jQuery.each(data.records[faustNum].filial, function(libCode, libStatus) {
			recordsArray.push(libStatus);
		});

		// for each branches/filialer in sorted array
		jQuery.each(recordsArray, function() {
			var lib = this;

			var name = lib.name;
			var opstilling = lib.opstilling;
			var availableCopies = lib.availableCopies;
			var isAvailable = lib.available;
			var onTheWay = lib.ontheway || false; // not delivered to lib yet
			var stylesheet = isAvailable && !onTheWay? "available" : "unavailable";

				var author = $('.recordInfo .author').html();

				author = jQuery.trim(author);

				if (author) {opstilling += ' - ' + author;}

			// css background for availability with library name
			var statusHtml = "<div><span class='"+stylesheet+"'>"+name+"&nbsp;</span>";

			// case 2028: if item is requested by library, but still on the way to it
			if (onTheWay) {statusHtml += ' <span>Ikke modtaget</span></div>';}

			// if it's not on the way and we have copies. or time, when item
			// will be available
			if (!onTheWay) {
				if (isAvailable) {
					statusHtml += " (" + availableCopies + " stk. hjemme)";
				}

				if (!isAvailable) {
					statusHtml += " <span>Ventetid: " + availabilityPeriod + "</span>";
				}

				// breadcrumb category in the library
				statusHtml += "<br /><span>"+opstilling+"</span></div>";
			}

			// add lib status and clear float, so they won't stick in
			// one line, but each lib would be on separate row
			$('#lapiExtendedStatus').append(statusHtml);
			$('#lapiExtendedStatus').append("<div class='clearFloat'>&nbsp;</div>");

			// If it's possible to reserve the book, show the reservelink
			if (isAvailable) {$('.recordReserveBookLink').show();}

		}); // end each recordsArray

	}
}

var EasyOpacContexts = {
	payment : function() {
		if(!EasyOpac.isLoggedIn) {
			return true;
		}

		$('#dibsPopUp').submit(function(submitEvent) {

			var acctNumbers = $('.materialPaymentContent .acctNumbers').html();

			if(0 ==  acctNumbers.length ) {
				EasyOpac.alert('Der opstod en fejl!<br />pr&oslash;v evt. igen eller kontakt webmasteren.');
				submitEvent.preventDefault();
				return false;
			}

			$.inleadAjaxSync('PaymentCtl', {method : 'prepare', acctno : acctNumbers}, function(resp) {

				if(!resp.status) {
					EasyOpac.alert('Der opstod en fejl!<br />'+resp.msg);
					submitEvent.preventDefault();
					return false;
				}

				var transnum = resp.data.transno;
				var sum = resp.data.sum; // Not sure what this should be used for

				/* Prep the form for dibs with transaction number from ILS */
				$('#dibsPopUp input[name=orderid]').val(transnum);

				return true; // this submits the form to dibs
			});

		});
	}, 
	article : function() {
		//		var type = $('#recordData .recordSimpleData img:first').attr('src').split('/').pop().split('.')[0];
		var type = 'cd'; // FIXME MAjor Hack. Remove me when im working!
		//		var recordId = $('.recordInfo div.recordId').html();
		var recordId = 'gentofte_0 931 872 0';
		$.inleadAjax('externalsctl', {teaserType : type , recordId : recordId}, function(resp) {
			if(resp.status && resp.data[0]) {
				var first = $('.similarContent .similarItem:first');

				first.find('span.simTiAuthor').text(resp.data[0].author);
				link = first.find('span.simTiLink a').attr('href');
				first.find('span.simTiLink a').attr('href', link+'?recordId='+resp.data[0].id).text(resp.data[0].title);

				var img = Image();
				img.onload = function() {
					ratio = img.width / 100;
					img.width = 100;
					img.height = Math.round(img.height / ratio);
					first.find('.similarPicture').append(img);
				}
				img.src = resp.data[0].data.thumbnail;

				img.onclick = function() {
					window.location = link+'?recordId='+resp.data[0].id;
				}

				if(resp.data[1]) {
					var second = $('.similarContent .similarItem:last');

					second.find('span.simTiAuthor').text(resp.data[1].author);
					link = second.find('span.simTiLink a').attr('href');
					second.find('span.simTiLink a').attr('href', link+'?recordId='+resp.data[1].id).text(resp.data[1].title);

					var img2 = Image();
					img2.onload = function() {
						ratio = img2.width / 100;
						img2.width = 100;
						img2.height = Math.round(img2.height / ratio);
						second.find('.similarPicture').append(img2);
					}
					img2.src = resp.data[1].data.thumbnail;

					img2.onclick = function() {
						window.location = link+'?recordId='+resp.data[1].id;
					}

					second.show();
				}
				$('.similarTeaserHider').slideDown();

			}
		});
	},
	sendToFriend : function() {
		$('.sendToFriendPopupContent .sendToFriendSendMessage').click(function(evnt) {
			// Stop the submit
			evnt.preventDefault();
			
			if(!$('.toEmail').val()) {
				alert('Indtast venligst en modtager emailadresse');
				$('.toEmail').focus();
				return;
			} else if(!$('.sendToFriendPopupTextareaContent').val()) {
				alert('Indtast venligst en besked til modtageren');
				$('.sendToFriendPopupTextareaContent').focus();
				return;
			}
			
			// Retrieve the info and end mail via AJAX
			$.inleadAjax('sendMail', { 
				subject : $('.sendToFriendPopupSubject').val(),
				body : $('.sendToFriendPopupTextareaContent').val(),
				fromName : $('.fromName').val(),
				fromEmail : $('.fromEmail').val(),
				toEmail : $('.toEmail').val()},
			function(resp) {
				sendToFriendPopup.hide();
			});
		});
		
		$('.sendToFriend').click(function(e) {
			if(sendToFriendPopup) {
				sendToFriendPopup.show();
			} else {
				sendToFriendPopup = EasyOpac.popBox($('.sendToFriendPopupTitle').html(), $('.sendToFriendPopupContent'), ".sendToFriendPopup");
			} 
		});
	},

	summaList : function() {
		listContainer = $('.opacList.listSumma');
		
		$.inleadAjax('SimpleSummaSearch', {query : EasyOpac.articleQuery}, function(resp) {
			if(resp.status && resp.data != false) {
				
				$(listContainer).each(function() {
					var thisContainer = this;
					elm = $(this).find('.summaListRow').removeClass('hidden').hide();
					seperator = $(this).find('.opacListSeperator');

					$(resp.data).each(function() {
						elmClone = elm.clone();
						
						// Update the data
						elmClone.find('a .title').html(this['title']);
						if(this['creator'])
							elmClone.find('a .creator').html(this['creator']).removeClass('hidden');

						// Set the image, if we have any. Else keep the default one
						if(this['thumbnail']) {
							elmClone.find('.opacListItemImage img').attr('src', this['thumbnail']).attr('alt', this['title']+' af '+this['creator']);
						
						}

						// Correct the link
						link = $(elmClone).find('a').attr('href');
						elmClone.find('a').attr('href', link+this['faustNum']);

						elmClone.show();

						$(thisContainer).append(elmClone).append(seperator.clone().removeClass('first'));
					});
				});

			} else {
				$(listContainer).html('<span>Tom liste</span>');
			}
		});
	},
	showRecord : function() {
		// show more link
		$('#recordShowExtraData').click(function() {
			$('#recordDataExtended').slideToggle();
			$(this).toggleClass('arrowDown').toggleClass('arrowRight');
		});

		// show marc
		$('#recordShowMarc').click(function() {
			$('#recordDataMarc').slideToggle();
			$(this).toggleClass('arrowDown').toggleClass('arrowRight');
		});

		$('#recordWikiShowAll').click(function() {
			$(this).hide();
			$('#recordWikiCutText').fadeIn();
		});

		var faustNum = $('.recordInfo div.faustNum').html();

		// bind "Add to my list" 
		$('.opacAddToListLink').bind('click', {
			foreignKey : $('.faustNum').html(),
			positionAfterElement: ".opacAddToListLink",
			itemType: $(".ssRecordType").html()
		}, EasyOpac.addToMyList);

		// Update the document title
		$.addToDocumentTitle($('.recordInfo .trimedtitle').html());

		// Try getting frontpage image
		author = $('.record .recordInfo .author').text();
		title = $('.record .recordInfo .title').text();

		var type = $('#recordData .recordImageContainer .recordImageLarge img:first').attr('src').split('/').pop().split('.')[0];

		var recordId = $('.recordInfo div.recordId').html();

		if('cd' != type && 'node' != type) {
			$.inleadAjax('addi', {faust : faustNum}, function(resp) {
				if(resp.data[faustNum]) {
					imgSpec = resp.data[faustNum];
				} else {
					if(EasyOpac.debug)
						console.log('Failed getting image for showRecord.');
					return true;
				}

				if(imgSpec['thumbnail']) {
					$('.recordImage').attr('src', imgSpec['thumbnail']);
				}

				if(imgSpec['detail']) {
					$('.recordImageLarge').attr('href', imgSpec['detail']);
					$('a.recordImageLarge').lightBox();
				}
				return true;
			});
		}
	

		var isCollectionMasterItem =  $('.record .recordInfo .isCollectionMasterItem').text();
		var isPeriodica =  $('.record .recordInfo .isPeriodica').text();

		// Get library catalog holding information
		if (isCollectionMasterItem) {

			// clear out masterItem faustnumber beacause we can't make reservation against it
			$('.recordInfo .faustNum:first').empty();

		
			$('#collectionItemSelector').change(function() {
				// we have a funny formated faustnumber
				faustNum = $('#collectionItemSelector option:selected').val().replace(/ /g,'');

				// empty out any existing status
				$('#lapiExtendedStatus').empty();

				// show the ajax spinner
				$('#lapiExtendedStatusActivity').show();

				// swap our current faust active fasutnumber so reserve works
				$('.recordInfo .faustNum:first').text(faustNum);

				$.inleadAjax('lapistatus', {faust : faustNum, homeBranch :    EasyOpac.homeBranch}, function( resp) {
					Lapi.showItemExtendedAvailability(faustNum,resp);
				}, '', '', $('#lapiExtendedStatusActivity'));

				// hide any subItem descriptions that might be visible
				$('#collectionItemDescrptions div').hide();

				// show desctiption for subItem
				$('#subItem_'+faustNum).show();

			});
		} else if (isPeriodica) {

			// clear out masterItem faustnumber beacause we can't make reservation against it
			$('.recordInfo .faustNum:first').empty();


			$.inleadAjax('lapistatus', {faust : faustNum, homeBranch : EasyOpac.homeBranch}, function(resp) {
				if( resp.status && 'periodica' == resp.data.statusType ) {
					$('.periodica').show();
					jQuery.each(resp.data.records, function() {
						$('#periodicaSelect').append('<option value="'+faustNum+'ZX'+this+'">'+this+'</option>');
					});

					$('#periodicaSelect').change(function() {

						 // clear out masterItem faustnumber beacause we can't make reservation against it
			                        $('.recordInfo .faustNum:first').empty();

						// clear out our selector
						$('#periodicaVolumeSelect').empty();

						faustNum = $('#periodicaSelect option:selected').val().replace(/ /g,'');
						$.inleadAjax('lapistatus', {faust : faustNum, homeBranch : EasyOpac.homeBranch}, function(resp) {
							if(resp.status && 'periodica' == resp.data.statusType ) {
								$('.periodicaVolumes').show();
								$('#periodicaVolumeSelect').empty();
								jQuery.each(resp.data.profiles, function() {

									// FIXME have no idea if this works all the time, but did for the testcases we got
									var volumenTitle = '';
									if(this.V) 
										volumenTitle += 'Volumen: '+this.V+' ';
									if(this.N) 
										volumenTitle += 'Nummer: '+this.N+' ';
					
									$('#periodicaVolumeSelect').append('<option value="'+this.orderLink+'">'+volumenTitle+'</option>');
								});
								$('#periodicaVolumeSelect').change(function() {
									faustNum = $('#periodicaVolumeSelect option:selected').val().replace(/ /g,'');
									// swap our current faust active fasutnumber so reserve works
									$('.recordInfo .faustNum:first').text(faustNum);
								});
							}
						});
					});

				} else {
					EasyOpac.alert("Returned status object didn't match record type.");
				}
			}, '', '', $('#lapiExtendedStatusActivity'));

		} else if ($('#lapiExtendedStatusActivity').length != 0) { 
			$.inleadAjax('lapistatus', {faust : faustNum, homeBranch : EasyOpac.homeBranch}, function(resp) {
				Lapi.showItemExtendedAvailability(faustNum,resp);
			}, '', '', $('#lapiExtendedStatusActivity'));
		}
	},
	
	backButton : function() {
		if (EasyOpac.isReferer == true) {
			$('#backButton').show();
			$('#openPrintSelectionSeperator').show(); 
		}
	},
	
	appovePublicProfileTerms : function() {
		
		var checkboxSetup = null;
		
		$("#radioProfilePulic").click(function() {
			checkboxSetup = $("#approve").attr("checked");
			if (EasyOpac.termsPopup) {
				EasyOpac.termsPopup.show();
			} else {
				EasyOpac.termsPopup = EasyOpac.popBox($('.publicProfileTermsTitle').html(), $('.publicProfileTermsContent'));
				EasyOpac.termsPopup.show();
			}
			return false;
		});
		
		$('.publicProfileTermsContent .termsOK').unbind('click').bind('click',function(){
			if ($("#approve").attr("checked") == true) {
				$("#radioProfilePulic").attr("checked", "true");
			} else {
				$("#radioProfilePrivate").attr("checked", "true");
			}
			EasyOpac.termsPopup.hide();
		});

		$('.publicProfileTermsContent .termsCANCEL').unbind('click').bind('click',function(){
			document.getElementById("approve").checked = checkboxSetup;
			EasyOpac.termsPopup.hide();
		});
	},
	
	uploadAvatar : function() {
		var avatarFile = '';
		
		var hideCropavatarPopup = function () {
			$("#avatarCropPopup").hide();
			$('.imgareaselect-outer').hide();
			$(".cropBox").hide();
		}
		var preview = function (img, selection) {
			$("#x1").val(selection.x1);
			$("#y1").val(selection.y1);
			$("#x2").val(selection.x2);
			$("#y2").val(selection.y2);
			$("#w").val(selection.width);
			$("#h").val(selection.height);
		}
		
		$("#avatarCropPopup a.close").unbind("click").click(function(e) {
			e.preventDefault();
			hideCropavatarPopup();
			return false;
		});
		
		$("#avatarCropPopup input.cancel").unbind("click").click(function(e) {
			e.preventDefault();
			hideCropavatarPopup();
			return false;
		});
		
		$("#avatarCropPopup input.save").unbind("click").click(function(e) {
			e.preventDefault();
			var x1 = $("#x1").val();
			var y1 = $("#y1").val();
			var x2 = $("#x2").val();
			var y2 = $("#y2").val();
			var w = $("#w").val();
			var h = $("#h").val();
			if(x1=="" || y1=="" || x2=="" || y2=="" || w=="" || h==""){
				EasyOpac.alert("You must make a selection first");
				return false;
			}else{
				$("#avatarCropPopup input.save").hide();
				$("#saveCroppedAvatarSpinner").show();
				$.inleadAjax('UploadAvatar', { 
					x1 : x1,
					y1 : y1,
					x2 : x2,
					y2 : y2,
					w : w,
					h : h,
					file : avatarFile,
					'actionType' : 'crop'
					}, function(resp) {
						if ($("#userAvatarContainer img").length == 0) {
							var i = new Image();
							$("#userAvatarContainer").append(i);
						}
						$("#userAvatarContainer img").attr("src", "/" + resp.data + "?hash="+Math.random());
						$("#userAvatarContainer img").show();
						hideCropavatarPopup();
						$("#saveCroppedAvatarSpinner").hide();
						$("#avatarCropPopup input.save").show();
						$("#removeAvatarContainer").show();
						$("#removeAvatarLink").show();
					}
				);
			}
			return false;
		});
		
		var clientCoords = function(){
			if(window.innerHeight || window.innerWidth){
				return {w:window.innerWidth, h:window.innerHeight}
			}
			return {
				w:document.documentElement.clientWidth,
				h:document.documentElement.clientHeight
			}
		}

		new AjaxUpload('uploadAvatar', {
			action: '../../ajaxResponder.php',
			name: 'avatar',
			data: {action: 'UploadAvatar'},
			autoSubmit: true,
			responseType: false,
			onSubmit : function(file , ext){
                if (! (ext && /^(jpg|png|jpeg|gif)$/.test(ext))){
                        EasyOpac.alert('Error: invalid file extension');
                        return false;
                }
				$("#uploadAvatar").hide();
				$("#uploadAvatarSpinner").show();
			},
			onComplete: function(file, response) {
				eval("var data="+response);
				if (data.status == true) {
					$("#avatarCropPopup img#imageToCrop").attr("src", "/"+data.data.file);
					$("#avatarCropPopup img#imageToCrop").attr("width", data.data.width);
					$("#avatarCropPopup img#imageToCrop").attr("height", data.data.height);
					avatarFile = data.data.file;
					var size = clientCoords();
					$("#avatarCropPopup").show();
					$("#avatarCropPopup").css({'left' : ((size.w - $("#avatarCropPopup").width()) / 2) + "px", 'top' : ((size.h - $("#avatarCropPopup").height()) / 2) + "px"});
					$('#imageToCrop').imgAreaSelect({aspectRatio: '1:1', onSelectChange: preview}); 
				}
				$("#uploadAvatarSpinner").hide();
				$("#uploadAvatar").show();
			}
		});
		
		$("#removeAvatarLink").click(function() {
			EasyOpac.popConfirm("Er du sikker p&aring; du vil fjerne dit profilbillede?", function() {
				$("#userAvatarContainer img").hide();
				$("#removeAvatarInput").attr("value", 1);
				$("#clearAvatarNotice").show();
				$("#removeAvatarLink").hide();
			});
			return false;
		});
	},
	
	opacListImage : function() {
		faustNumbers = '';
		$('.opacListFaustNumbers').each(function(i) {
			faustNumbers += $(this).html();
		});
		
		$.inleadAjax('addi', {faust : faustNumbers}, function(resp) {
			$.each(resp.data, function(i, val){
				$('.opacListItem.faustnum_'+i+' .opacListItemImage img').attr('src', val['thumbnail']);
			});
		});
	},
	
	profile : function() {

		if(0) { // OLD profile code
			// showProfile
			$.opacToggle($('.profileDataGroup'));

			// show more link
			$('#profileShowExtraData').click(function() {
				$('#profileDataExtended').slideToggle();
				$(this).toggleClass('arrowDown').toggleClass('arrowRight');
			});
		}
	},
	
	profileEdit : function() {
		// 05.08.2009 bty Dragan
		// This peace of code should be deleted as a part of opac.js refactoring case.		
		if(0) { // OLD profile code
			//change picture on profile stuff
			$(".addNewImageClone").click(function(){
				$(".addNewProfileImageContent input").clone(true).prependTo("#userprofileedit").hide();
			});

			// change profile picture popup
			$('.changeProfilePicture').click(function(e) {
				$('.changeProfilePictureMargin').hide();
				$('.changeProfilePictureSlidedown').slideDown();
			});
			
			//instantiate all fileuploads to look OPAC nice
			var aUploadFileBtns = $('.frontendInputFile');
			for(var i=0;dBtn = aUploadFileBtns[i];i++){
			    new FileUploadUI(dBtn);
			};
		}
		// new profile code
		$('.date-pick').datePicker();	
		$('#start-date').bind(
			'dpClosed',
			function(e, selectedDates)
			{
				var d = selectedDates[0];
				if (d) {
					d = new Date(d);
					$('#end-date').dpSetStartDate(d.addDays(1).asString());
				}
			}
		);
		$('#end-date').bind(
			'dpClosed',
			function(e, selectedDates)
			{
				var d = selectedDates[0];
				if (d) {
					d = new Date(d);
					$('#start-date').dpSetEndDate(d.addDays(-1).asString());
				}
			}
		);
		$("#clearVacatioLink").click(function() {
			$("#vacationEndDate").attr("value", "");
			$("#vacationStartDate").attr("value", "");
			$("#resetVacationNotice").show();
			return false;
		});
		$("#clearVacationLink").click(function() {
			$("#vacationStartDate").attr("value", "");
			$("#vacationEndDate").attr("value", "");
			$("#resetVacationNotice").show();
			return false;
		});
	},
	
	didYouMean : function() {

	//	var searchWord = EasyOpac.currentQuery;
//		var searchWord = $('#searchWord').text().substring;
		var searchString =  $('#searchWord').text();
		var searchWord = searchString.substring(1,searchString.length-1)

		// http://www.google.com/complete/search?hl=en&client=suggest&json=t&jsonp=CALLBACK_FUNCTION&q=QUERY
		$.ajax({
			url : 'http://www.google.com/complete/search',
			dataType: 'jsonp',
			data : {
				hl : 'en',
				client : 'suggest',
				json : 't',
				q : searchWord
			},
			success : function(resp) {
				var word = resp[1][0];	

				if(jQuery.trim(word) == '' ) return false;

				$('.summaDidYouMeanGoogle span a').text(word);
				href = $('.summaDidYouMeanGoogle span a').attr('href');
				$('.summaDidYouMeanGoogle span a').attr('href', href+word);
				$('.summaDidYouMeanGoogle').show();
			}
		});
		if(0){ /* disabled by request from customer */
		$.inleadAjax('didyoumean', {query : searchWord}, function(resp) {
			if(resp.status && resp.data != false) {
				$('.summaDidYouMean span a').text(resp.data);
				href = $('.summaDidYouMean span a').attr('href');
				$('.summaDidYouMean span a').attr('href', href+resp.data);
				$('.summaDidYouMean').show();
			} 
		});
		}
		$.inleadAjax('miniArticle', {query : searchWord}, function(resp) {
			if(resp.status && resp.data != false) {
				$('#searchTeaserHeadline').html(resp.data.title);
				$('#siteTeaserRightText').html(resp.data.teaser);
				$('#siteTeaserRightReadmore a').attr('href', resp.data.url);
				if(resp.data.imgUrl && resp.data.imgAlt ) {
					$('#searchTeaserLeft img').attr('src', resp.data.imgUrl);
					$('#searchTeaserLeft img').attr('alt', resp.data.imgAlt);
					$('#searchTeaserLeft').show();
				}
				$('#searchTeaser').show();
			} 
		});

	},
	dcAutoList : function() {
		listContainer = $('.opacList.listDcAuto');
		
		$.inleadAjax('DcAutoList', {query : EasyOpac.dcMetaKey}, function(resp) {
			if(resp.status && resp.data != false) {
				
				$(listContainer).each(function() {
					elm = $(this).find('.dcAutoRow').removeClass('hidden').hide();
					seperator = $(this).find('.opacListSeperator');

					$(resp.data).each(function() {
						
						elmClone = elm.clone();
						
						// Update the data
						elmClone.find('a .title').html(this['title']);
						if(this['creator'])
							elmClone.find('a .creator').html(this['creator']).removeClass('hidden');
							
						// Set the image, if we have any. Else keep the default one
						if(this['thumbnail']) {
							elmClone.find('.opacListItemImage img').attr('src', this['thumbnail']).attr('alt', this['title']+' af '+this['creator']);
							
						}
						
						// Correct the link
						link = $(elmClone).find('a').attr('href');
						elmClone.find('a').attr('href', link+this['faustNum']);

						elmClone.show();
						
						listContainer.append(elmClone).append(seperator.clone().removeClass('first'));
					});
				});
				
			} 
		});
		
	},
	showRecordAdhl : function() {
		// Find all ContenTypes of this type and remove them
		$('.adhlContainer').each(function() {
			container = $(this);
			elm = $(this).find('.adhlElement');
			$(elm).each(function() {
				if ($(this).find('.adhlAuthor').html() != '&nbsp;') {
				  $(this).remove();
				}
			});
		});
	
		var faustNum = $('.recordInfo div.faustNum').html();

		$.opacToggle($('.adhlContainer'));
		if(faustNum)
		$.inleadAjax('adhl', {faust : faustNum}, function(resp) {
			if(resp.status == false) {
				EasyOpac.alert(resp.msg);
				return false;
			}

			if('' == resp.data)  {
				$('.adhlContainer .recordGroupTitle').html('');
				$('.adhlContainer .recordGroupTitle').unbind('click');
				return true;

			}

			// Find all adhl contentTypes and fill them with info 
			$('.adhlContainer').each(function() {
				container = $(this);
				elm = $(this).find('.adhlElement');
				$(resp.data).each(function() {
					elmClone = elm.clone();
					$(elmClone).find('.adhlAuthor').html(this['creator']);
					$(elmClone).find('.adhlLink a').html(this['title']);
					link = $(elmClone).find('.adhlLink a').attr('href');
					$(elmClone).find('.adhlLink a').attr('href', link+this['faust']+'&name='+this['title']);
					$(elmClone).find('.adhlLink a').attr('title', this['desc']);
					elmClone.appendTo($('.recordExtendedData',container)).show();
				});
				$('.recordGroupTitle',container).removeClass('arrowRight').addClass('arrowDown');
				$(this).find('.recordExtendedData').show();
				$('.adhlContainer').show();
			});
		});
	},
	reservation : function() {
		// Reserve Item popup
		var reserveItemPopUp;
		$('.opacReserveItemLink').click(function(e) {
			e = e || window.event;
			target = e.target || e.srcElement;
			if(!EasyOpac.isLoggedIn) {
				EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne reservere.');
				return true;
			}

			// check to see if we are on a collection and if the user have choosen a subItem
			// if not bail out because we can't make a reservation against a masterItem
			var isCollectionMasterItem =  $('.record .recordInfo .isCollectionMasterItem').text();

			if(isCollectionMasterItem  && '' == $('.recordInfo .faustNum:first').text()) {
				EasyOpac.alert('Du skal f&oslash;rst v&aelig;lge et bind for at kunne reservere.');
				return true;
			}
			
			// ditto for periodica
			var isPeriodica =  $('.record .recordInfo .isPeriodica').text();

			if(isPeriodica && '' == $('.recordInfo .faustNum:first').text()) {
				EasyOpac.alert('Du skal f&oslash;rst v&aelig;lge en &aring;rgang og et nummer for at kunne reservere.');
				return true;
			}

			if(reserveItemPopUp) {
				reserveItemPopUp.show();
			} else {
				reserveItemPopUp = EasyOpac.popBox('Reserver her', $('.opacReserveItem'));
				reservationExpire = $('.reservationExpire').val();
			}
			faust = $(target).parent().parent().parent().find('.recordInfo .faustNum:first').text();
			$('.opacReserveItemFaust').text(faust);
		});

		$(".opacReserveItemButton").click(function() {
			var elm = $(this).parent().parent();

			var days = elm.find('.reservationExpire').val();
			var branch = elm.find('select').val(); 
			var faust = elm.find('.opacReserveItemFaust').text();
			
			var re = /^\d+$/;
			if (!(re.test(days)) || (days < 1 || days > 365)) {
				elm.find('.opacReserveItemError').html('Ugyldig indtastning. Indtast et tal mellem 1 og 365.');
				return false;
			} else {
				elm.find('.opacReserveItemError').html('');
				
			}
			
			//reserveItemPopUp.hide();
			$(".opacReserveItemButton").hide();
			$(".opacReserveItemButton").parent().find('.spinner').show();
			
			elm.find('.reservationExpire').val(reservationExpire);
			
			$.inleadAjax('reservationctl', {func : 'reserve', faust : faust, branch : branch, days : days}, function(resp) {
				$(".opacReserveItemButton").show();
				$(".opacReserveItemButton").parent().find('.spinner').hide();
				reserveItemPopUp.hide();
				if(resp.status == false) {
					EasyOpac.alert(resp.msg);
					return false;
				}

				if(resp.data) {
					var failedRenews = 0;
					var y = $('<div></div>');
					y.addClass('renewErrors');
					var i,j;
					for (i in resp.data.failed) {
						var errorTitle = $("#loanNotRenewedTpl .red").clone();
						var error = resp.data.translate[i];
						errorTitle.html(error);
						y.append(errorTitle);
						for (j = 0; j < resp.data.failed[i].length; j++) {
							var title = $("#loanNotRenewedTpl .title").clone();
							title.html($("td#loan_" + resp.data.failed[i][j] + " a").html());
							y.append(title);
							failedRenews++;
						}
					}
					if (failedRenews > 0) {
					    EasyOpac.alert(y.html());
					} else {
					    EasyOpac.alert('Reservationen blev gennemf&oslash;rt.');
					}
					EasyOpac.updateReservationsContent();
				}
			});
		});

		$(".opacUpdateItemReservationButton").click(function() {
			updateItemReservationPopUp.hide();

			var elm = $(this).parent().parent();
			var resno = elm.find('.opacReserveItemResno').text();
			var days = elm.find('.reservationExpire').val();
			var branch = elm.find('select').val(); 

			$.inleadAjax('reservationctl', {func : 'update', resno : resno, branch : branch, days : days}, function(resp) {
				if(resp.status == false) {
					EasyOpac.alert(resp.msg);
					return false;
				}

				if(resp.data == true) {
					EasyOpac.alert('Reservationen blev &aelig;ndret.');
					EasyOpac.updateReservationsContent();
				} else {
					EasyOpac.alert('Reservationen kunne ikke &aelig;ndres.');
				}
			});

		});
	},
	showRecordSimilarTitles : function() {
		// empty the container before filling it
		// Find all ContenTypes of this type and fill them with nothing
		
			// Find all ContenTypes of this type and remove them
		$('.simTiContainer').each(function() {
			container = $(this);
			elm = $(this).find('.simTiElement');
			$(elm).each(function() {
				if ($(this).find('.simTiAuthor').html() != '&nbsp;') {
					// alert($(this).find('.simTiAuthor').html());
					$(this).remove();
				}
						
			});
		});

		
		var recordId = $('.recordInfo div.recordId').html();
		if(recordId)
		$.inleadAjax('simti', {recordId : recordId}, function(resp) {
			if(false == resp.status || false ==  resp.data) {
				$('.simTiContainer .recordGroupTitle').html('');
				$('.simTiContainer .recordGroupTitle').unbind('click');
				return;
			}

			// Find all ContenTypes of this type and fill them with info
			$('.simTiContainer').each(function() {
				container = $(this);
				elm = $(this).find('.simTiElement');
				$(resp.data).each(function() {
					elmClone = elm.clone();
					$(elmClone).find('.simTiAuthor').html(this['author']);
					$(elmClone).find('.simTiLink a').html(this['title']);
					link = $(elmClone).find('.simTiLink a').attr('href');
					$(elmClone).find('.simTiLink a').attr('href', link+this['recordId']);
					elmClone.appendTo($('.recordExtendedData',container)).show();
				});
				$('.recordGroupTitle',container).click();
			});
			$('.simTiContainer').show();
		});
		
	},
	 // ran from searchResult.tpl
	searchResultSocialServices : function() {
		 // gather faust numbers for all items on page and load SS content via 
		 // ajax calls for each(tags, comments, rating)
		 var records = $('.searchRecord');
		 var faustNums = [];

		 // get list of faustnumbers with their records types from current page
		 jQuery.each(records, function() { 
			 var fnum = $(this).find('.recordInfo .faustNum').html();

			 faustNums.push(fnum); 
		 });

		 // ask SS for aggregated data on them
		 getItemsData(faustNums.join(','));

		 // ask and ye shall receive!
		 function getItemsData(faustNums) {
			 var data = {method: 'getAll', foreignKey : faustNums};

			 $.inleadAjax('SocialServicesItem', data, showItemsData);
		 }

		 function showItemsData(resp) {
			 var totalAmount = resp.data.totalAmount;
			 var items = resp.data;
			 var template = $('.tpl');

			 // iterate over html items, inserting SS content for each item
			 jQuery.each(records, function() {
				 var fnum = $(this).find('.recordInfo .faustNum').html();
				 var ratingContainer = $(this).find('.opacStars');
				 var tagsContainer = $(this).find('.showRecordTagsContainer');

				 // now get this item data from data we received, if we have it
				 var item = items[fnum] || {rating: 0, ratingCount: 0, tags: [], commentsCount: 0, tagSearchUrl: ''};

				 // add content for record with this fk
				 SS.showItemRating(item.rating, item.ratingCount, template, ratingContainer);

				 // 'true' says we want to limit tags to two lines for each item
				 SS.showItemTags(item.tags, template, tagsContainer, item.tagSearchUrl, true);

				 $(this).find('.amountOfComments').html(item.commentsCount);
			 });
		 }
	 },
	// ran by showRecord.tpl
	showRecordSocialServices : function() {
        // define them here, so we could track their state through the whole 
        // function space. no need to store them in html 
        var commentsPerPage = 5; 
        var totalAmountOfComments = false; // initialisation 
        var faustNum = $('.faustNum').html(); 
        var type = $(".ssRecordType").html(); 

        $(".commentsPerPage").html(commentsPerPage); 

        // moved displaying first page of comments from php/templates 
        // onload - fill in comments paging for this item 
        changeCommentsPage(1); 


        // get item rating and tags 
        var data = {method: 'getAll', foreignKey : faustNum}; 

        $.inleadAjax('SocialServicesItem', data, showTagsRating); 

        function showTagsRating(resp) { 
                 var totalAmount = resp.data.totalAmount; 
                 var items = resp.data; 
                 var template = $('.tpl'); 

                 var fnum = $('.record .recordInfo .faustNum').html(); 

                 var ratingContainer = $('.opacStars'); 
                 var tagsContainer = $('.showRecordTagsContainer'); 

                 // now get this item data from data we received, if we have it 
                 var item = items[fnum] || {rating: 0, ratingCount: 0, tags: [], commentsCount: 0, tagSearchUrl: ''}; 

                 // add content for record with this fk 
                 SS.showItemRating(item.rating, item.ratingCount, template, ratingContainer); 

                 SS.showItemTags(item.tags, template, tagsContainer, item.tagSearchUrl); 
        } 

		//We need to move these functions somewhere ...
		function str_replace(search, replace, subject) {
			var f = search, r = replace, s = subject;
			var ra = is_array(r), sa = is_array(s), f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;

			while (j = 0, i--) {
				while (s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f){};
			};
			return sa ? s : s[0];
		}

		function is_array( mixed_var) {
			return ( mixed_var instanceof Array );
		}

		// Enable autocomplete for Social Services tags
		$("#socialServicesAddTags").autocomplete("/ajaxResponder.php?action=SocialServicesTags&resulttype=simple", {selectFirst : false});

		// Enable autocomplete for Social Services tags (Create new list)
		$(".createNewListInputText").autocomplete("/ajaxResponder.php?action=SocialServicesTags&resulttype=simple", {selectFirst : false});

		// Add tag
		$('.recordTagAddSubmit').click(function(record) {
			var tag = jQuery.trim($('.recordTagAddInput').val());

			if(!EasyOpac.isLoggedIn) {
				EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne tif&oslash;je tags.');
				return true;
			}

			if(tag)
			$.inleadAjax('SocialServicesAddTag', {foreignKey : $('.faustNum').html(), tagName : tag, type : $(".ssRecordType").html()}, function(resp) {
				if(resp.status == false) {
					EasyOpac.alert(resp.msg);
					return false;
				}
				if (resp.expired) return false;
				if(0 == resp.data) {
					$('.recordTagAddInput').val('');
					$(".showRecordTagsContainer .recordTagHighlight").each(function() {
						if ($(this).children(':first').text().toLowerCase() == tag.toLowerCase())
							$(this).effect("shake", {times: 3, distance: 3, direction: "left"}, 30);
					});
					if (EasyOpac.ssEnabled) {
						EasyOpac.alert('Kunne ikke tilf&oslash;je dit tag.<br />Pr&oslash;v igen eller kontakt webmasteren.');
					} else {
						EasyOpac.alert(EasyOpac.ssOutOfOrderMsg);
					}
					return false;
				}

				// add tag to tags container, preserving sort order, and blink it 2 times 
				SS.showAddedTag(resp.data.name, $('.tpl'), $('.showRecordTagsContainer')); 
				
				// clear tag input field 
				$('.recordTagAddInput').val(''); 
			});
		});

		// Add tag by enter

		$('.recordTagAddInput').keypress(function (e) {
			if (e.which == 13) //If "Enter"
			{
				$("#socialServicesAddTags").blur();
				$('.recordTagAddSubmit').click();
			}
		});


		// Add comment
		$('.recordFeedbackCommentSubmit').click(function(record) {
			var comment = jQuery.trim($('.recordFeeedbackComment').val());

            if (!EasyOpac.isLoggedIn) {
                    EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne tilf&oslash;je kommentarer.');
                    return true;
            }

			if (comment)
			$.inleadAjax('SocialServicesCreateComment', {
				foreignKey : $('.faustNum').html(),
				body : comment,
				type : $(".ssRecordType").html(),
				parentId : 0
			}, function(resp) {
				if(resp.status == false) {
					EasyOpac.alert(resp.msg);
					return false;
				}
				if (resp.expired == 1)
					return false;
				if(0 == resp.data ) {
					if (EasyOpac.ssEnabled) {
						EasyOpac.alert('Kunne ikke tilf&oslash;je din kommentar.<br />Pr&oslash;v igen eller kontakt webmasteren.');
					}
					else {
						EasyOpac.alert(EasyOpac.ssOutOfOrderMsg);
					}
					return false;
				}

				var commentsPerPage = $('.commentsPerPage:first').html();

				if (totalAmountOfComments % commentsPerPage == 0)
				{
					// if pages are full already
					createCommentsPaggingButton();

				}

 	            totalAmountOfComments = parseInt(totalAmountOfComments) + 1; // increase amount of comments 
 	            if (totalAmountOfComments > commentsPerPage) { 
 	    			$('.paging').fadeIn(); 
 				} 
				// show updated amount of comment
				$(".totalAmountOfComments").html(totalAmountOfComments); 

				if (Math.ceil(totalAmountOfComments / commentsPerPage) == $('.currentCommentsPage').attr('id')
				&& totalAmountOfComments % commentsPerPage != 0)
				{
					// if you're on the last page and if you have the place to put the comment - do not reload the whole page


					var commentNum = parseInt(totalAmountOfComments) + 1;
					
					if (resp.data) {
						var newComment = $('.comment:first').find("li:first").clone(true).hide().insertAfter($('.comment:first').find("li:last"));
						newComment.attr({id: resp.data.id});
						newComment.find(".commentTopContentRight").text(resp.data.dateCreated);
						newComment.find(".commentTopContentLeft").find("a").text(data.authorScreenName);
						newComment.find("#recordOtherDataContent").find(".commentContent").html(resp.data.body);
						newComment.find(".commentNumber").text("# "+commentNum);
						newComment.find(".markAsPositive").bind("click", {comment: newComment, subaction: "markAsPositive"}, moderationConfirm);
						newComment.find(".markAsNegative").bind("click", {comment: newComment, subaction: "markAsNegative"}, moderationConfirm);
						newComment.find(".reportButton").bind("click", {comment: newComment, subaction: "markAsUnsuitable"}, moderationConfirm);
						newComment.find(".commentAuthor").attr({href: resp.data.authorProfile});
	
						if (comment.score == "")
							comment.score = 0;
	
						newComment.find(".commentBottomContentMiddle").text(comment.score);
						newComment.fadeIn('slow');
						newComment.blur();
					}
				}
				else
				{
					changeCommentsPage('last');
				}


				$('.recordFeeedbackComment').val('');

			});
		});

		// Rate item
		$('.star_group_recordFeedbackRating').children().click(function(record) {
			rating = $(this).html();
			
			if (!EasyOpac.isLoggedIn) {
				EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne rate.');
				return true;
			}
      
			if (rating) {
				$.inleadAjax('SocialServicesRateItem', {
					foreignKey : $('.faustNum').html(),
					type : $(".ssRecordType").html(),
					rating : rating
				}, function(resp) {
					if (resp && resp.expired && resp.expired == 1)
						return false;
					// The new rating on the item
					var rating = resp.data.rating; 
					var votes = resp.data.votes; 
					var starsContainer = $('.opacStars'); 
					
					starsContainer.fadeOut(); 
					
					SS.showItemRating(rating, votes, $('.tpl'), starsContainer); 
					
					starsContainer.fadeIn(); 
				});
			}
		});

		// Universal confirm and login check wrapper function for moderation
		function moderationConfirm(paramObject) {
			/*
				Passthroug function used to validate the user action and promt for confirms on some of them..
			*/

			var subaction = paramObject.data.subaction;
			var comment = paramObject.data.comment;

			/* object used to store various settings for each subaction */
			var actions = {
				markAsPositive : {
					requireLogin : true,
					requireConfirm : false,
					description : 'Modere'
				},
				markAsNegative :  {
                                        requireLogin : true,
                                        requireConfirm : false,
					description : 'Modere'
                                }, 
				markAsUnsuitable : {
                                        requireLogin : true,
                                        requireConfirm : true,
					description : 'Anmelde'
                                }
			};

			/*
				keep a pointer for the current action.
				TODO error checking for missing actions
			*/
			var curAction = actions[subaction];

                        if(curAction.requireLogin && !EasyOpac.isLoggedIn) {
                                EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne '+curAction.description);
                                return true;
                        }

			/*
				if confirm is required	
					pop the box and arm the callback on the ok button for the right action
				else
					just call the right callback
			*/
			if( curAction.requireConfirm) {
				EasyOpac.popConfirm('Er du sikker p&aring; at du vil '+curAction.description+' denne kommentar?',function() {moderation(paramObject)});
			} else {
				moderation(paramObject);
			}
		}

		var moderationPopup = null;

		// Universal function for moderation
		function moderation(paramObject)
		{
			var subaction = paramObject.data.subaction;
			var comment = paramObject.data.comment;
			
                        if(!EasyOpac.isLoggedIn) {
                                EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne moderere.');
                                return true;
                        }

			if (moderationPopup && moderationPopup.isVisible())
			{
				moderationPopup.moveTo(comment.clientX-50, comment.clientY);
				return true;
			}

			$.inleadAjax('SocialServicesModeration', {subaction : subaction,
			commentId : comment.attr("id")},
			function(data) { // FIXME: Correct indentation and change 'data' to 'resp'
				if (data && data.expired && data.expired == 1)
					return false;
				if (subaction == "markAsPositive" || subaction == "markAsNegative")
				if (data.data != "null" && data.data != "error" && data.data != "No such subaction") // Sorry about that ... seems like it needs isInteger validation here
				comment.find(".commentBottomContentMiddle").hide().html(data.data).fadeIn();
				else
					if(!EasyOpac.isLoggedIn) {
						EasyOpac.alert('Du skal v&aelig;re logget ind for at kunne rate en kommentar');
						return true;
					}
					else {
						comment.find(".commentBottomContentMiddle").effect("shake", {times: 3, distance: 2, direction: "up"}, 50);
					}
				else
				if (subaction == "markAsUnsuitable")
				{
					if(!EasyOpac.isLoggedIn) {
						EasyOpac.alert('Du  skal v&aelig;re logget ind for at kunne anmelde en kommentar.');
						return true;
					}
					else {
						if (data == 1) {
							moderationPopup = EasyOpac.popBox($('.moderationPopupTitle').html(), $('.moderationPopupTextAccepted'));
						}
						else {
							moderationPopup = EasyOpac.popBox($('.moderationPopupTitle').html(), $('.moderationPopupTextBad'));
						}
					}

				}
				else
				return data;
			});
		};

		$('.closeModerationPopup').click(function(){moderationPopup.hide();moderationPopup = null});

		//Binding of the actions to buttons

		function bindCommentButtonsActions ()
		{
			$('.oneComment').each(function() {
				if ($(this).css("display") != "none")
				{
					$(this).find(".markAsPositive").bind("click", {comment: $(this), subaction: "markAsPositive"}, moderationConfirm);
					$(this).find(".markAsNegative").bind("click", {comment: $(this), subaction: "markAsNegative"}, moderationConfirm);
					$(this).find(".reportButton").bind("click", {comment: $(this), subaction: "markAsUnsuitable"}, moderationConfirm);
				}
			});
		};

		bindCommentButtonsActions();

		function createCommentsPaggingButton()
		{
			var pageNum = $('.commentsPagingButton').size();
			var newPageButton = $('.commentsPagingButton:first').clone();
			// (pageNum - 1) - because of teh first empty paging container
			newPageButton.find('span').html(" " + (pageNum - 1) + " ").attr('id', pageNum - 1);
			$('.commentPagesContent:first').append(newPageButton.fadeIn());
		}


		// changing of the comments Page Page function

		function changeCommentsPage(page)
		{
			// FIXME - put a switch here...
			if (page == "last")
			{
				page = Math.ceil(totalAmountOfComments / commentsPerPage);
				$('.pagingNextButton').fadeOut();
				$('.pagingPrevButton').fadeIn();
			}
			if (page == "next")
			{
				page = parseInt($('.currentCommentsPage').attr('id'))+1;
			}

			if (page == "previous")
			{
				page = parseInt($('.currentCommentsPage').attr('id'))-1;
			}

			$('.currentCommentsPage').addClass("commentsPagingLink").addClass("handcursor").removeClass("currentCommentsPage"); //back to all unpresed
			$('.commentsPagingLink').filter("#"+page).removeClass("commentsPagingLink").removeClass("handcursor").addClass("currentCommentsPage"); //press on the page
			bindPaggingButtonsActions();


			$('.comment:first').fadeOut();
			var newPage = $('.comment:first').clone().empty();
			newPage.append($('.comment:first').find("li:first").clone(true));

			$.inleadAjax('SocialServicesComments', {foreignKey : $('.faustNum').html(),
			type : $(".ssRecordType").html(),
			commentsPerPage : commentsPerPage,
			page : page
			}, function(resp) {
				if(!resp.status)
				{
					$('.comment:first').fadeIn();
					return false; // FIXME need error reporting
				}
				
				if (!resp.data)
					return;


                var comments = resp.data.comments; 
                totalAmountOfComments = resp.data.totalAmount; 
 
                // set for html, so other functions could find it. 
                $(".totalAmountOfComments").html(totalAmountOfComments); 
 
                // apparently, arp returns one malformed 'comment', when there 
                // are no comments. arpSocialServicesComment.php 
                if (totalAmountOfComments == 0) {return;} 
 
                for (var i=0; i < comments.length; i++) { 
                    var comment = comments[i]; 

					if (comment.score == "")
					comment.score = 0;

					var commentNum = (commentsPerPage * (page-1))+i+1;

					var newComment = $('.comment:first').find("li:first").clone(true).show();
					newComment.attr("id", comment.id);

					var hAgoText = "";
					if (comment.amountOfHours != null)
					{
						if (comment.amountOfHours > 1)
						hAgoText = str_replace('%hoursAgo%', comment.amountOfHours, $('.hoursAgoText').html());
						else
						hAgoText = str_replace('%hourAgo%', comment.amountOfHours, $('.hourAgoText').html());
					}
					newComment.find(".commentTopContentRight").text(hAgoText + " " + comment.dateCreated);
					// comment.amountOfHours

					newComment.find(".commentTopContentLeft").find("a").text(comment.authorScreenName);
					newComment.find("#recordOtherDataContent").find(".commentContent").html(comment.body);
					newComment.find(".commentNumber").text("# "+commentNum);
					newComment.find(".commentBottomContentMiddle").text(comment.score);
					newComment.find(".commentAuthor").attr({href: comment.authorProfile});
					newPage.append(newComment);

				}

				$('.comment:first').replaceWith(newPage).fadeIn();
				bindCommentButtonsActions();

                // display 'none' is right after the initial html loading, 
                // 'block' is when we shown it with fadeIn 
                var display = $(".paging").css("display"); 

                // display pagination, if amount of comments doesn't fit on one page 
                // do not redisplay if we already shown it to user 
                if (totalAmountOfComments > commentsPerPage && display == 'none') { 

                        // populate pagination links with content, based on comments 
                        generatePaginationLinks(totalAmountOfComments, page); 

                        // show generated pagination 
                        $('.paging').fadeIn(); 

                        // also we need to (re)bind clicks on those pagination buttons 
                        bindPaggingButtonsActions(); 
			     } 

			});
		};

		// generate number of page-links, according to total number of comments 
		// and comments-on-page 
		function generatePaginationLinks(totalComments, viewedPage) { 
		    var amountOfPages = Math.ceil(totalComments / commentsPerPage); 
		
		    for (var cPage=1; cPage <= amountOfPages; cPage++) { 
		        var pbutton = $(".commentsPagingButtonTemplate .commentsPagingButton").clone(); 
		        pbutton.find(".commentsPagingButtonId").attr('id', cPage).html(cPage); 
		
		        if (viewedPage == cPage) { 
		            pbutton.find(".commentsPagingButtonId").addClass("currentCommentsPage"); 
		        } 
		
		        if (viewedPage != cPage) { 
		            pbutton.find(".commentsPagingButtonId").addClass("commentsPagingLink").addClass("handcursor"); 
		        } 
		
		        $(".commentPagesContent").append(pbutton); 
		    } 
		} 

		//Paging of the comments
		function bindPaggingButtonsActions()
		{
			$('.currentCommentsPage').unbind('click');
			$('.commentsPagingLink').unbind('click');
			$('.commentsPagingLink').click(function() {
				var page = $(this).attr('id');
				//var page = 'last';
				changeCommentsPage(page);

				$('.pagingNextButton').show();
				$('.pagingPrevButton').show();

				var commentsPerPage = $('.commentsPerPage:first').html();

				if (page == Math.ceil(totalAmountOfComments / commentsPerPage))
				$('.pagingNextButton').fadeOut();

				if (page == 1)
				$('.pagingPrevButton').fadeOut();


			});
		};

		$('.pagingNextButton').click(function(){
			changeCommentsPage('next');

			if ($('.currentCommentsPage').attr('id') == Math.ceil(totalAmountOfComments / commentsPerPage))
			$(this).fadeOut();

			$('.pagingPrevButton').fadeIn();
		});

		$('.pagingPrevButton').click(function(){
			changeCommentsPage('previous');

			if ($('.currentCommentsPage').attr('id') == 1)
			$(this).fadeOut();

			$('.pagingNextButton').fadeIn();
		});
	}, // end of showRecordSocialServices 
	sidebarSearch : function() {

		// Enable autocomplete
		//$("#opacSearchInput").autocomplete("/ajaxResponder.php?action=Summasuggest&resulttype=simple", {selectFirst : false});

		$("#opacSearchInput").autocomplete("/ajaxResponder.php?action=Summasuggest&resulttype=simple", {
			minChars:2,
			selectOnly:1,
			formatItem: function(row) {
				return row[0] + ' <span style="float:right;">' + row[1] + "<\/span>";
			}
		});
		
		$(".searchCriteriaDropdown").change(function() {
			document.location = $(this).val();
		});

		// Cluster search
		// to avoid declare clusterResultCount for all templates
		try {
			var count = clusterResultCount; // items to show
		} catch (e) {
			return false;
		}
		$(".clusterSearchResult .firstLevel").toggle(
			function(){
				$(this).addClass('show');
				$(this).parent().find('.secondLevel').each(function(n){
					if (n < count)
						$(this).addClass('show');
					else
						$(this).removeClass('show');
				});
				$(this).parent().find('.show_more').addClass("show");
			},
			function(){
				$(this).removeClass('show');
				$(this).parent().find('.secondLevel').removeClass('show');
				$(this).parent().find('.show_more').removeClass("show");
			}
		);
		
		$('.show_more').toggle(
			function(){
				$(this).parent().find('.secondLevel').removeClass('show');
				$(this).parent().find('.secondLevel').each(function(){
					$(this).addClass('show');
				});
				$(this).html("Vis f&aelig;rre...");
				return false;
			},
			function(){
				$(this).parent().find('.secondLevel').removeClass('show');
				$(this).parent().find('.secondLevel').each(function(n){
					if (n < count)
						$(this).addClass('show');
				});
				$(this).html("Vis flere...").addClass('show');
				return false;
			}
		);
		$('.show_more a').unbind('click').bind('click',function(e){
			var evt = e || window.event;
			evt.preventDefault();
			return false;
		});

	},
	userLoginPopulate : function(resp) {
		if(resp) {
			profileInfo = resp.data.profileInfo;
			$('.opacUserLoginInformationBoks span.realName').text(profileInfo.realName);
			$('.opacUserLoginInformationBoks span.totalActivitys').text(profileInfo.totalActivitys);
			$('.opacUserLoginInformationBoks span.loanCount').text(profileInfo.numLoan);
			$('.opacUserLoginInformationBoks span.reservationCount').text(profileInfo.numRes);
			$('.opacUserLoginInformationBoks span.readyCount').text(profileInfo.numReady);
			$('.opacUserLoginInformationBoks span.fineCount').text(profileInfo.numFines);
			$('.opacUserLoginInformationBoks span.msgCount').text(profileInfo.numMsg);

			// The link hash
			link = $('.opacUserLoginInformationBoks a.profileRef').attr('href');
			$('.opacUserLoginInformationBoks a.profileRef').attr('href', link+'?opacId='+profileInfo.userHash);

			$('.opacUserLoginInformationBoks').slideDown();
		} else {
			$.inleadAjax('Loginctl', {method : 'login', username : '', password : ''}, function(resp) {
				if(resp.status && null != resp.data.profileInfo) {

					profileInfo = resp.data.profileInfo;
					$('.opacUserLoginInformationBoks span.realName').text(profileInfo.realName);
					$('.opacUserLoginInformationBoks span.totalActivitys').text(profileInfo.totalActivitys);
					$('.opacUserLoginInformationBoks span.loanCount').text(profileInfo.numLoan);
					$('.opacUserLoginInformationBoks span.reservationCount').text(profileInfo.numRes);
					$('.opacUserLoginInformationBoks span.readyCount').text(profileInfo.numReady);
					$('.opacUserLoginInformationBoks span.fineCount').text(profileInfo.numFines);
					$('.opacUserLoginInformationBoks span.msgCount').text(profileInfo.numMsg);
	
					// The link hash
					link = $('.opacUserLoginInformationBoks a.profileRef').attr('href');
					$('.opacUserLoginInformationBoks a.profileRef').attr('href', link+'?opacId='+profileInfo.userHash);

					$('.opacUserLoginInformationBoks').slideDown();
				}
			});
		}
	},
	userLogin : function() {
		if(EasyOpac.isLoggedIn) {
			////////////////  begin bindings for messaging system 

			// remove helpers text on focus
			// currently jQuery doesn't support 'focus' for live, so i went with 'click'
			$('#ssMessages .newMessage input.subject').live("click", function() {
				var defaultSubject = SS.message.trans('defaultSubject');
				var subject = SS.hc().find('.newMessage input.subject');

				if (subject.val() == defaultSubject) {
					subject.val('').removeClass('helper');
				}
			});
			$('#ssMessages .newMessage input.to').live("click", function() {
				var defaultTo = SS.message.trans('defaultTo');
				var to = SS.hc().find('.newMessage input.to');

				if (to.val() == defaultTo) {
					to.val('').removeClass('helper');
				}
			});

			// make inputs display helper text if it's empty and it doesn't have focus
			$('#ssMessages .newMessage input.to, .newMessage textarea.body').live("click", function() {
				var defaultSubject = SS.message.trans('defaultSubject');
				var subject = SS.hc().find('.newMessage input.subject');

				if (subject.val() == "") {
					subject.val(defaultSubject).addClass('helper');
				}
			});
			$('#ssMessages .newMessage input.subject, .newMessage textarea.body').live("click", function() {
				var defaultTo = SS.message.trans('defaultTo');
				var to = SS.hc().find('.newMessage input.to');

				if (to.val() == "") {
					to.val(defaultTo).addClass('helper');
				}
			});

			// get messages headers on load, count amount of unread messages and
			// show them to user next to link to messages popup
			SS.message.getUnreadMessages();

			// close message preview 
			SS.mc().find('.close').live("click", function() {SS.mc().hide();});

			// bind sorting
			SS.hc().find('.columnHeaders th').live("click", function() {
				SS.message.sortHeaders($(this));
			});

			// bind SS messages checkboxes selectors functions
			SS.message.selectors.bind();
			SS.message.massActions.bind();

			// reply to message 
			$('#ssMessages .newMessage .reply').live("click", function() {
				if (!SS.message.isValid($('.headersContainer .newMessage'), 'reply')) {return false;}

				SS.message.reply($('.headersContainer .newMessage'));
			});

			// send message
			$('#ssMessages .newMessage .send').live("click", function() {
				if (!SS.message.isValid($('.headersContainer .newMessage'), 'send')) {return false;}

				SS.message.send($('.headersContainer .newMessage'));
			});

			// change 'write' tab to 'reply' and highight it, when replying 
			$('#ssMessages .msg .reply').live("click", function() {
				$('#ssMessages .tab').removeClass('highlight');
				$('#ssMessages .write').text('Svar').addClass('highlight').removeClass('createNew');

				SS.message.showReply();
			});

			// bind tab switching and background color
			$('#ssMessages .tab').live("click", function() {
				$('#ssMessages .write').text('Skriv besked').addClass('createNew');
				$('#ssMessages .write').text('Skriv besked');
				$('#ssMessages .tab').removeClass('highlight');
				$(this).addClass('highlight');
			});

			// bind get and show message body with click on subject line
			$('#ssMessages .message .subject, #ssMessages .message .date').live("click", function() {
				var message = $(this).parent('tr');

				SS.message.get(message);
				SS.hc().find('.messages tr').removeClass('highlightSubject');
				$(message).addClass('highlightSubject');
			});

			// show new message box 
			$('#ssMessages .createNew').live("click", function() {SS.message.showNew();});

			// show popup box with SS messages and get inbox content
			$('#ssMessagesPopupInbox').click(function() {
				var ssMessagesPopup = EasyOpac.popBox($('#ssMessages').attr('title'), $('#ssMessages'));
				SS.message.getInbox();
			});

			// get list of messages headers of SS inbox for logged users
			$('#ssMessages').find('.inbox,.cancel').live("click", function() {
				SS.mc().hide();
				SS.tc().find('.msg .reply').show();
				SS.message.getInbox();
			});

			// get list of messages headers of sent SS messages for logged users
			$('#ssMessages .sent').click(function() {
				SS.mc().hide();

				// can't reply to yourself :)
				SS.tc().find('.msg .reply').hide();

				SS.message.getSent();
			});

			////////////////  end bindings for messaging system 

			// Startup the HeartBeat controller
			HeartBeat.init({payload : function(){
				$.inleadAjax('Heartbeat', {type : 'ping'}, function(resp) {
					if(resp.status) {
					} else {
						if(EasyOpac.isLoggedIn) {
							EasyOpac.isLoggedIn = false;
							$('.opacUserLoginInformationBoks').slideUp();
							$('.opacUserLoginLoginBoks').slideDown();
						}
						HeartBeat.stop();
					}
				});
			}});
			EasyOpacContexts.userLoginPopulate();
		} else {
			$('.opacUserLoginLoginBoks').fadeIn();
		}

		var remoteLogin = function() {
			var username = $('.opacUserLoginLoginBoks input.pno').val();
			var password = $('.opacUserLoginLoginBoks input.pin').val();

			// if it's set - means on first login we received reply with a 
			// screenname suggestion from SS
			var screenname = $('#firstTimeLogin input.screenname').val() || '';

			// if we have firstTimeLogin popup present, and ok is pressed there
			// - hide any errors and show spinner for "ok" action.
			$('#firstTimeLogin').find('.loader').show();
			$('#firstTimeLogin').find('.error span').hide();

			$('#opacLoginLoader').show();

			$.inleadAjax('Loginctl', {method: 'login', username: username, password: password, screenname: screenname}, function(resp) {
				// we got data - remove loading spinner for firstTimeLogin window and login form
				// also re-enable 'ok' button for FTL popup if it's there
				$('#firstTimeLogin').find('.loader').hide();
				$('#opacLoginLoader').hide();
				$('#firstTimeLogin .ok').removeAttr("disabled");

				var screennameSuggestion = ''; // default state

				if (resp.status && null != resp.data.profileInfo) {
					$('.opacUserLoginLoginBoks').slideUp();

					/* FIXME had to disable this because the frontpage didn't enable popups correctly after a login */
					jQuery.each(EasyOpac.contexts, function(index, name) {
						if(EoContextCfg[name].reloadOnStateChange) {
						}
					});                    

					EasyOpacContexts.userLoginPopulate(resp);
                    
                    $('body').fadeOut();

					EasyOpac.isLoggedIn = true;
					HeartBeat.start();
                    
					var url = window.location.href;
					url = url.replace(/\#.+/ig,"&refresh");
					window.location.href = url;
                    
				// to differentiate on errors - first time login uses error code 101 
				} else if(resp.status == false && !resp.code) {
					$('#opacLoginLoader').hide();
					EasyOpac.alert(resp.msg);
				}

				// error code 101 indicates first time login with suggestion
				// ajax-get popup template and show it
				if (resp.status == false && resp.code == 101) {
					screennameSuggestion = resp.msg;
					$.inleadAjax('Template', {path : 'fm/opac/popups/firstTimeLogin.tpl'}, showFirstTime);

					return false;
				}

				// 102 is user creation error with duplicate screenname
				// show screenname suggestion error
				if (resp.status == false && resp.code == 102) {
					$('#firstTimeLogin').find('.screenname').val(resp.msg);
					$('#firstTimeLogin').find('.suggestion .error .tryAnother').show();
				}

				// any other unexpected SS reponses
				if (resp.status == false && resp.code == 103) {
					EasyOpac.alert(resp.data.msg);
				}

				// callback from Loginctl arp, showing first time login when
				// needed, with suggested screenname
				function showFirstTime(resp) {
					$('#firstTimeLogin').replaceWith($(resp.data));

					// save container, so it could be accessed later
					var ftl = EasyOpac.popBox($('#firstTimeLogin').attr('title'), $('#firstTimeLogin'));

					$('#firstTimeLogin').show();

					// add screenname suggestion to input box
					$('#firstTimeLogin').find('input.screenname').val(screennameSuggestion);

					_bindFtlCallbacks($('#firstTimeLogin'));
				}

				// bind actions for freshly created popup
				function _bindFtlCallbacks(ftl) {
					ftl.find('.cancel').click(function() {Boxy.get(this).hide();});
					ftl.find('.ok').click(function() {_resubmit(ftl);});
				}

				// ask user to check 'agreement' checkbox or submit form
				function _resubmit(ftl) {
					// no empty name please
					if (ftl.find('input.screenname').val() == '') {
						ftl.find('.suggestion .error .emptyName').show();
						return false;
					}

					// agreement not checked
					if (!ftl.find("input.agreed").attr("checked")) {
						ftl.find('.agreement .error .agree').show();
						return false;
					}

					// disable button, preventing several submissions
					$('#firstTimeLogin .ok').attr("disabled", true);
					remoteLogin();
				}
			});

			return false;
		};

		// custom event to sumbit form, triggered by 'login' button click and
		// hitting 'enter' in password field
		$('.opacUserLoginLoginBoks').bind("loginSubmit", function() {
			$('#firstTimeLogin input.screenname').val('');
			remoteLogin();
		});

		// need to reset 'screenname' suggestion on plain 'login' click
		$('.opacUserLoginLoginBoks input.opacUserLoginLoginButton').click(function() {
			$('.opacUserLoginLoginBoks').trigger('loginSubmit');
			return false;
		});

		// trigger submitting event on login for submit 
		$('.opacUserLoginLoginBoks form').submit(function() {
			$('.opacUserLoginLoginBoks').trigger('loginSubmit');
			return false;
		});

		$('.opacUserLoginInformationBoks input.opacUserLoginLogoutButton').click(function() {
			$.inleadAjax('Loginctl', {method : 'logout'}, function(resp) {
				if(resp.status) {
					jQuery.each(EasyOpac.contexts, function(index, name) {
						if(EoContextCfg[name].reloadOnStateChange) {
							$('body').fadeOut();
							var url = window.location.href;
							url = url.replace(/\#.+/ig,"&refresh");
							window.location.href = url;
						}
					});
					$('.opacUserLoginInformationBoks').slideUp();
					$('.opacUserLoginLoginBoks').slideDown();
					EasyOpac.isLoggedIn = false;
					HeartBeat.stop();
				}
			});
		});

		$.opacToggle($('.recordDataGroup'));	

		$('#CommunityMessageInbox').toggle(function() {
			$.inleadAjax('Messagectl', {method : 'fetchInbox'}, function(resp) {
				$(resp.data).each(function(key, value) {
					clone = $('#messagesPopupInbox .message:first').clone(true);
					$(clone).find('.myMessagesPopupAuthor span.name').html(value['userScreenname']);
					$(clone).find('div.leftFloat span.myMessagesPopupMargin').html(value['subject']);
					$(clone).find('div.leftFloat input.messageId').val(value['messageId']);
					$(clone).find('#recordOtherDataContent .myMessagesPopupOverflow').html(value['message']);
					$(clone).find('.hiddenReplyUserId').val(value['userHash']);
					$(clone).find('.hiddenReplyUsername').val(value['userScreenname']);

					$(clone).insertAfter($('#messagesPopupInbox .message:last')).slideDown();
				});
			});
		},
		function() {
			$('#messagesPopupInbox .message:not(:first)').remove();
		});

		$('#CommunityMessageOutbox').toggle(function() {
			$.inleadAjax('Messagectl', {method : 'fetchOutbox'}, function(resp) {
				$(resp.data).each(function(key, value) {
					clone = $('#messagesPopupOutbox .message:first').clone(true);
					$(clone).find('.myMessagesPopupAuthor span.name').html(value['userScreenname']);
					$(clone).find('div.leftFloat span.myMessagesPopupMargin').html(value['subject']);
					$(clone).find('div.leftFloat input.messageId').val(value['messageId']);
					$(clone).find('#recordOtherDataContent .myMessagesPopupOverflow').html(value['message']);

					$(clone).insertAfter($('#messagesPopupOutbox .message:last')).slideDown();
				});
			});
		},
		function() {
			$('#messagesPopupOutbox .message:not(:first)').remove();
		});

		$('.showProfileInfoHeader').click(function() {
			$('.showProfileInfoHeader').toggleClass('show');
			$('.showProfileInfoContent').slideToggle();

		});

		/*
			Bind autocomlete and catch userId from the json return if user selects a user
		*/
		$(".writeMessagePopupContent input.reciever").autocomplete("/ajaxResponder.php?action=messagectl&method=recieverSuggestion&resulttype=simple", {selectFirst : false}).result(function (e, data, formatted) {
			$(e.target).parents().find('input.messageHiddenReciever').val(String(data).split(',').pop());
		});
		
		$('input.opacLoginSendMessage').click(function(e) {
			to = $(e.target).parent().find('input.messageHiddenReciever').val();
			toName = $(e.target).parent().find('input.reciever');
			subject = $(e.target).parent().find('input.writeMessagePopupHeadline');
			message = $(e.target).parent().find('textarea.writeMessagePopupTextareaContent');

			if (to < 1 || toName.hasClass('formError')) {
				toName
				.val('Modtager mangler')
				.addClass('formError')
				.focus(function() {
					$(this).val('').unbind('focus').removeClass('formError');
				});	
				return;
			}

			if (subject.val().length < 1 || subject.hasClass('formError')) {
				subject
				.val('Emne mangler')
				.addClass('formError')
				.focus(function() {
					$(this).val('').unbind('focus').removeClass('formError');
				});	
				return;
			}
			if (message.val().length < 1 || message.hasClass('formError')) {
				message
				.val('Skriv din besked her..')
				.addClass('formError')
				.focus(function() {
					$(this).val('').unbind('focus').removeClass('formError');
				});	
				return;
			} else {message = message.val();}

			$.inleadAjax('Messagectl', {
					method : 'sendMessage',
					toName : toName.val(),
					to : to,
					subject : subject.val(),
					message : message
				},
				function(resp) {
					if (resp.data.status)
						writeMessagePopup.hide();
					EasyOpac.alert(resp.data.msg);
			});
		});

		$('.message span.deleteMessage').click(function(e) {

			if (!e) var e = window.event;
			e.cancelBubble = true;
			if (e.stopPropagation) e.stopPropagation();
			messageId = $(e.target).parents().find('input.messageId:first').val();

			if(EasyOpac.popConfirm('Er du sikker p&aring; at du vil slette beskeden?', function() {
				$.inleadAjax('Messagectl', {method : 'deleteMessage', messageId : messageId}, function(resp) {
					if (resp.data && resp.data.status) {
						$(e.target).parent().parent().parent().parent().slideUp();
					} else {
						EasyOpac.alert(resp.data.msg);
					}
				});
			}));
		});
		

		if(EasyOpac.isLoggedIn) {
			/*
				Hook all our functionPopups up
			*/

			// Borrowed material popup
			$('.borrowedMaterial').click(function(e) {
				if (borrowedMaterialPopup) {
					borrowedMaterialPopup.show();
				} else {
					borrowedMaterialPopup = EasyOpac.popBox($('.borrowedMaterialTitle').html(), $('.borrowedMaterialContent'), ".borrowedMaterial");
				} 
				EasyOpac.updateLoanContent();
			});

			// Reserved material popup
			$('.reservedMaterial').click(function(e) {
				if(reservedMaterialPopup) {
					reservedMaterialPopup.show();
				} else {
					reservedMaterialPopup = EasyOpac.popBox($('.reservedMaterialTitle').html(), $('.reservedMaterialContent'), ".reservedMaterial");
				}
				EasyOpac.updateReservationsContent();
			});

			// Available material popup
			var availableMaterialPopup;
			$('.availableMaterial').click(function(e) {
				if(availableMaterialPopup) {
					availableMaterialPopup.show();
				} else {
					availableMaterialPopup = EasyOpac.popBox($('.availableMaterialTitle').html(), $('.availableMaterialContent'), ".availableMaterial"); // FIXME - put loading gif here;
				}
			});

			// Material payment popup
			var materialPaymentPopup;
			$('.materialPayment').click(function(e) {
				if(materialPaymentPopup) {
					materialPaymentPopup.show();
				} else {
					materialPaymentPopup = EasyOpac.popBox($('.materialPaymentTitle').html(), $('.materialPaymentContent'), ".materialPayment"); // FIXME - put loading gif here;
				}
			});

			// search history popup
			var searchHistoryPopup;
			$('.searchHistory').click(function(e) {
				if(searchHistoryPopup) {
					// reset the paging to the first page
					$('.searchHistoryPaging .offset').text(0);
					searchHistoryPopup.show();
				} else {
					searchHistoryPopup = EasyOpac.popBox($('.searchHistoryPopupTitle').html(), $('.searchHistoryPopupContent'), ".searchHistory");

					$('.searchHistoryPaging .searchHistoryPrev').click(function() {	
						EasyOpac.updateSearchHistory(parseInt( $('.searchHistoryPaging .offset').text())-1,$('.searchHistoryPaging .orderBy'));
					});

					$('.searchHistoryPaging .searchHistoryNext').click(function() {	
						EasyOpac.updateSearchHistory(parseInt($('.searchHistoryPaging .offset').text())+1,$('.searchHistoryPaging .orderBy'));
					});
					$('select.searchHistorySortBy').change(function(e) {
						$("select.searchHistorySortBy option:selected").attr('title');
						EasyOpac.updateSearchHistory(0,$("select.searchHistorySortBy option:selected").attr('title'));
						

					});
				}
				EasyOpac.updateSearchHistory(0,'lastUpdated');
			});

			// my lists popup
			var myListsPopup;
			$('.myLists').click(function(e) {
				if(myListsPopup) {
					myListsPopup.show();
				} else {
					myListsPopup = EasyOpac.popBox($('.myListsPopupTitle').html(), $('.myListsPopupContent')); // FIXME - put loading gif here;
				}
			});
		}

	},
	searchResultWikipedia : function() {
		return true;
		/*
			No progress on wikipedia integration yet
		*/
		$.inleadAjax('wikipedia', {author : 'suzanne br�gger'}, function(data) {
		});
	},
	extctlShowRecord : function() {
		ExtRender.getDataShowRecord();
	},
	
	faustNumsLapi : [],
	faustNumsAddi : [],
	faustNumsPeriodica : [],
	artistNames : [],
	searchResult : function() {
		
		// Update the document title
		$.addToDocumentTitle($('#searchQueryClean').html());
		$('.searchRecord').each(function() {
			var searchRecord = this;
			faustNum = $(this).getRecordInfo('faustNum');
			// Littteratursiden
			author = $(this).getRecordInfo('author');

			var recordType = $(searchRecord).find('.searchRecordTitle img:first').attr('src').split('/').pop().split('.')[0];

			/* Avoid doing lapi look up for certain item types */
			switch ( recordType ) {
				case 'netdokument': 
					//break;
				case 'tidsskrift':
					// periodica
					EasyOpacContexts.faustNumsPeriodica.push(faustNum);
					break;
				default:
					EasyOpacContexts.faustNumsLapi.push(faustNum);
			}
			
			if('node' != recordType && 'cd' != recordType) {
				EasyOpacContexts.faustNumsAddi.push(faustNum);
			}
		
			// bind "Add to my list" on all records
			$(this).find('.opacAddToListLink').bind('click', {
				foreignKey: $(this).find('.recordInfo:first').find('.faustNum').html(),
				positionAfterElement : ".opacAddToListLink",
				itemType: $(this).find(".ssRecordType").html()
			}, EasyOpac.addToMyList);

			ExtRender.getDataSearchResult(recordType, author, searchRecord);
		});


		if ( 0 < EasyOpacContexts.faustNumsAddi.length) {
			faustNumbers =  EasyOpacContexts.faustNumsAddi.join(",");
			$.inleadAjax('addi', {faust : faustNumbers}, function(resp) {
				for (faustNum in resp.data) {
					$('#faustnum_'+faustNum+' .searchRecordImageContainer img').attr('src', resp.data[faustNum]['thumbnail']);

				}
			});
		}
		
		// Print handling
		if(EasyOpac.isReferer == true) {
			$('#openPrintSelectionSeperator').show();
		}

		$('#openPrintSelection').click(function() {
			$(this).fadeOut();
			$('#printSelection').slideDown();
		});
		
		$('#closePrintSelection').click(function() {
			$('#printSelection').slideUp();
			$('#openPrintSelection').fadeIn();
		});
		
		$('#printNumOfArticlesButton').click(function() {
			window.open(printUrl+'&numOfRecords='+$('#printNoOfArticles').val());
		});
		
		$('#printAllArticlesButton').click(function() {
			window.open(printUrl+'&showAllRecords=true');
		});

		faustNumbers =  EasyOpacContexts.faustNumsLapi.join(",");
		$.inleadAjax('lapistatus', {faust : faustNumbers, homeBranch : EasyOpac.homeBranch}, Lapi.showItemsAvailability);

		// show static status information for periodica
		if ( 0 < EasyOpacContexts.faustNumsPeriodica.length) {
		

		}
		/* custom teasers in top of search result */

		var teaserNode = 'searchTeaser';
		var teasers = {};
		var currentQuery = unescape(curSearchVars);	
		var changeTeaser = function(teaser) {
				$('#searchTeaserHeadline').text(teaser.title);
				$('#siteTeaserRightText').html(teaser.desc);
				$('#siteTeaserRightReadmore a').attr('href',teaser.url);
				$('#searchTeaserLeft img').attr('src',teaser.img);
				$('#searchTeaserLeft').show();
				$('#'+teaserNode).show();
		}
		
		$.each(teasers, function() {	
			//asd = RegExp(this.match);
			if (currentQuery.match(RegExp((this.match),'i'))) {
				changeTeaser(this);
				/* we only want to show one teaser */
				return false;
			}
		});
		
		if (articlesFoundAmount != null && articlesFoundAmount > 0) {
			var a = $("#searchContainer .pagingContainer .articlesResult a");
			a.attr('href', linkToArticlesSearch);
			a.html(articlesFoundAmount);
			$("#searchContainer .pagingContainer .articlesResultContainer").show();
		}
		
	},
	myLists : function() {

		function bindTagLinks() {
			/* Load list when item in either slect box are clicked */	
			$('#personalPrivateTags,#personalSharedTags')
				.unbind('change')
				.bind('change',function(e) {
					var val = $(this).val();
					loadTaggedItems(val);
					document.getElementById('personalPrivateTags').selectedIndex = -1;
					document.getElementById('personalSharedTags').selectedIndex = -1;
					$('#personalPrivateTags,#personalSharedTags').val(val);
				}
			);

			/* move item to private */
			$('#myListMove2Privat').unbind('click').click(function() {
				var link = $(this);
				var loader = $(this).next();
				link.hide();
				loader.show();
				var k = $('#personalSharedTags option:selected');
				var element = {id: k.val(), name: k.html()};
				
				$.inleadAjax('SocialServicesMoveList', {
					tagId: element.id,
					creatorId: $('.ssUserId').html(),
					newType : 'personal_private'
				}, function(resp) {
					if(!resp.status) {
						EasyOpac.alert(resp.msg);
						return false;
					}
					if (resp.status == 0) {
						EasyOpac.alert(resp.data.response.error.description);
						return false;
					} else {
						$('#personalPrivateTags').append($('<option></option>').html(element.name).attr('value',element.id));
						k.remove();
						bindTagLinks();
					}
					loader.hide();
					link.show();
				});
				return false;
			});

			/* move item to public */
			$('#myListMove2Public').unbind('click').click(function() {
				var link = $(this);
				var loader = $(this).next();
				link.hide();
				loader.show();
				var k = $('#personalPrivateTags option:selected');
				var element = {id: k.val(), name: k.html()};
				
				$.inleadAjax('SocialServicesMoveList', {
					tagId: element.id,
					creatorId: $('.ssUserId').html(),
					newType : 'personal_shared'
				}, function(resp) {
					if(!resp.status) {
						EasyOpac.alert(resp.msg);
						return false;
					}
					if (resp.status == 0) {
						EasyOpac.alert(resp.data.response.error.description);
						return false;
					} else {
						$('#personalSharedTags').append($('<option></option>').html(element.name).attr('value',element.id));
						k.remove();
						bindTagLinks();
					}
					loader.hide();
					link.show();
				});
				return false;
			});
		}

		function loadTaggedItems(tagId) {  
            // prevent empty list loading
			if (!tagId) {
			    $('#myList').html('');
			    return false;
			}
			$('#myList').html('<p>Henter...</p>');

			$.inleadAjax('SocialServicesItemsTaggedByPersonalTag', {
				tagId: tagId,
				creatorId: $('.ssUserId').html()
			}, function(resp) {
				if(!resp.status) {
					EasyOpac.alert(resp.msg);
					return false;
				}

				var listContainer = $('#myList');

				// if this is an emty list with the dummy element - get it
				// taggingId, deceptively called "tagId", and add it to #myList
				// property, so we could later delete this empty list using
				// dummy taggingId. we can't delete it by tagId, since there is
				// a tagging for it, and we can't delete non-emty tags. doh.
				if (resp.data.length) {
					var fk = resp.data[0]["foreignKey"];
					var dummyId = resp.data[0]["tagId"];
				}

				if (fk && fk == "000000") {
					$('#myListName').attr('dummyTaggingId', dummyId);
				}

				listContainer.empty();

				/* grab title from one of the selectboxes, we don't get this in the ajax response.. */
				listTitle = $('#personalPrivateTags option[value='+tagId+'],#personalSharedTags option[value='+tagId+']').html();
				$('#myListName').html(listTitle).attr('listId', tagId);
				$('#myListName').html(listTitle).attr('listTitle', listTitle);

				/* loop over each element in the taglist and build html for each */	
				$.each(resp.data, function() {	
					var newItem = $('#myListItemTemplate').clone();
					newItem.removeAttr('id');
					newItem.attr('style','display:block');
					if (!this.title || !this.url)
						return true;
					newItem.find('.profileListTitle a').html(this.title).attr('href',this.url);
					newItem.find('.taggingId').val(this.tagId); 
					var title = this.title;
					var taggingId = this.tagId;
					newItem.find('.profileListDelete a').bind("click",function(e) {
						EasyOpac.popConfirm('Bekr&aelig;ft sletning af ' + title + ' fra listen ' + listTitle + '?', function() {
							$.inleadAjax('SocialServicesItemsTaggedByPersonalTagDelete', {
								tagId: tagId,
								creatorId: $('.ssUserId').html(),
								taggingId: taggingId
							}, function(resp) {
								if(!resp.status) {
									EasyOpac.alert(resp.msg);
									return false;
								}
								if (resp.data.response.status == 0) {
									EasyOpac.alert(resp.data.response.error.description);
									return false;
								} else {
									newItem.remove();
								}
							});
						});
						return false;
					});
					listContainer.append(newItem).show();
				});
			});
		}

		bindTagLinks();

        // Add to My List - Create new list
        // this is the real list creation, other ones are fake :)
        $('.createList').unbind('click'); //Prevent several calls;
		$('.createList').click(function(){
			var foreignKey = '000000';
			var tag = jQuery.trim($('.newListInputText').val());
			var tagType = jQuery("input[name='tagType']:checked").val();
			var itemType = 'catalog_item';
			$('.addToListContent #spinner').show();
			if (tag) {
				$.inleadAjax('SocialServicesAddTag', {
					foreignKey : foreignKey,
					tagName : tag,
					type : itemType,
					tagType: tagType
				}, function(resp) {
					$('.addToListContent .spinner').hide();
					if (!resp.status) {
						EasyOpac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
						if (popup) { popup.remove(); }
						return false;
					} 
					if (!resp.data) {
						EasyOpac.alert('Der skete en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
						return false;
					}

					// add value, to newly created list, since arp is getting
					// taggings for the list by option value of selected item
					var option = "<option title='" + ( tagType == "personal_private" ? "Private" : "Shared")  + "' class='personalTagOption' id='" + resp.data.id + "' value='" + resp.data.id + "'>" + resp.data.name + "</option>";
					// append and mark as selected
					if (tagType == 'personal_shared'){
						$('#personalSharedTags').append(option).find('option[id='+resp.data.id+']').attr('selected',true);
					} else if (tagType == 'personal_private'){
						$('#personalPrivateTags').append(option).find('option[id='+resp.data.id+']').attr('selected',true);
					}
					// empty input field
					$('.newListInputText').val('');
					return true;
				});
			}
            $('.addToListContent #spinner').hide();
		});

		$('#myListDelete').unbind('click').click(function() {
			var taggings = Array();
			var tagId = $('#myListName').attr('listId');
			var dummyTaggingId = $('#myListName').attr('dummyTaggingId');

			// get array of tagging ids
			$('#myList .taggingId').each(function() {
				taggings.push($(this).val());
			});

			// if we don't have any taggings - then it's an empty list, meaning
			// we have to delete it by list dummy tagging id
			if (!taggings.length && dummyTaggingId) { taggings.push(dummyTaggingId); }

			// remove non-empty list with taggings via ajax call with csv 
			// of taggings ids
			var ajaxRemovePersonalTag = function() {
			$.inleadAjax('SocialServicesDelTag',
				{ taggings: taggings.join(",") },
				removePersonalTagResult
				);
			}; 

 		    // callback for ajax call, with error checkings and visuals
 		    var removePersonalTagResult = function(resp) {
				if (!resp.status) {
					EasyOpac.alert(resp.data.msg);
					return false;
				}

				// we can have this error nesting, too
				if (resp.data.response.status == 0) {
					EasyOpac.alert(resp.data.response.error.description);
					return false;
				}

				$('#personalPrivateTags option[value='+tagId+'],#personalSharedTags option[value='+tagId+']').remove();
				loadTaggedItems($('#personalSharedTags option:first,#personalPrivateTags option:first').val());
 		    };

			// call this on "myListDelete" click
			EasyOpac.popConfirm('Bekræft sletning af listen ' +
								listTitle + '?', ajaxRemovePersonalTag);

		});
		
		var updateListTitlePopUp = null;
		
		$('#myListEdit').click(function() {

			tagId    =  $('#myListName').attr('listId');
			tagTitle =  $('#myListName').attr('listTitle');
			
			if (!updateListTitlePopUp)
				updateListTitlePopUp = EasyOpac.popBox('Rediger listenavn', $('.opacUpdateListTitle'));
			else
				updateListTitlePopUp.show();
			
			$('.opacUpdateListTitle').find('.opacUpdateListTitleText').val(tagTitle).select();
			
			$('.opacUpdateListTitle').find('.opacUpdateListTitleButtonCancel').unbind('click').click(
				function () {
					updateListTitlePopUp.hide();
				}
			);
			
			$('.opacUpdateListTitle').find('.opacUpdateListTitleButtonOk').unbind('click').click(
					function () {
						updateListTitlePopUp.hide();
						$.inleadAjax('SocialServicesUpdateTag', {
							tagId    : tagId,
							tagTitle : $('.opacUpdateListTitle').find('.opacUpdateListTitleText').val()
						}, function(resp) {
							if (!resp.status) {
								EasyOpac.alert(resp.msg);
								return false;
							}
							newTagId = parseInt(resp.data.response.data);
							/* update ourself in list */
							$('#personalPrivateTags option[value='+tagId+'],#personalSharedTags option[value='+tagId+']').html($('.opacUpdateListTitle').find('.opacUpdateListTitleText').val());
							$('#personalPrivateTags option[value='+tagId+'],#personalSharedTags option[value='+tagId+']').attr('value',newTagId);
							$("#personalPrivateTags option[selected='selected']").removeAttr("selected");
							$("#personalSharedTags option[selected='selected']").removeAttr("selected");
							$("#personalPrivateTags option[value='" + newTagId + "']").attr("selected","selected");
							$("#personalSharedTags option[value='" + newTagId + "']").attr("selected","selected");
							loadTaggedItems(newTagId);
							
						});
					}
				);
		});

		//Load the items for the first list;
		loadTaggedItems($('#personalSharedTags option:first,#personalPrivateTags option:first').val());

		var editListPopup = null;

		//Edit List
		$('.editTag').click(function(e) {
			if(false && editListPopup) {
				editListPopup.moveTo(e.clientX-50,e.clientY);
				editListPopup.show();
			} else {

				$('.editListContent').find('.editListInputText').attr('value', $(this).next().html());
			
				var tagId = $(this).next().attr('id');

				editListPopup = EasyOpac.popBox($('.editListTitle').html(), $('.editListContent'), $(this)); // FIXME - put loading gif here;

				$('.editListContent .deleteList').unbind('click');
				$('.editListContent .deleteList').click(function () {

					$.inleadAjax('SocialServicesDelTag', {
						tagId: tagId
					}, function(resp) {

						if(!resp.status) {
							EasyOpac.alert(resp.data.msg);
							return false;
						}

						$('#siteProfileListsContentRightPadding span[id='+tagId+']').fadeOut().prev().fadeOut().next().next().fadeOut();
						editListPopup.hide();
					});
				});
			}
		});
	},
	assignPrintOnShowArticle : function () {
		$('#printButtonShowArticle').unbind('click').bind('keypress click', 
			function(e) {
				var evt = window.event || e; 
				if (evt.keyCode && evt.keyCode == 9) 
					return true; 
				window.print(); 
					return false; 
			} 
		);
	},
	myStatusPage : function() {
		$("#spRenewSelectedLoans").unbind("click").bind('click',function() {
			var btn = $(this);
			var a = new Array();
			$(".myLoansContainerBody input:checkbox:visible:checked").each(function(){
				a.push($(this).attr("value"));
			});
			if (a.length > 0) {
				btn.hide();
						$('.sp_loans_ajax').css('display','inline');
				$('.myLoansContainerBody').fadeTo("normal",.2);

				$.inleadAjax('reservationctl', {func : 'renewLoans', copyno : a.join(",")}, function (resp) {
							$('.sp_loans_ajax').hide();
					$('.myLoansContainerBody').fadeTo("normal",1);
					btn.show();
					if (resp.status == false) {
						EasyOpac.alert(resp.msg);
						return false;
					}
					var failedRenews = 0;
					var y = $('<div></div>');
					y.addClass('renewErrors');
					var i,j;

					for (i in resp.data.failed) {
						var errorTitle = $("#loanNotRenewedTpl .red").clone();
						var error = resp.data.translate[i];
						errorTitle.html(error);
						y.append(errorTitle);
						for (j = 0; j < resp.data.failed[i].length; j++) {
							var title = $("#loanNotRenewedTpl .title").clone();
							title.html($("td#loan_" + resp.data.failed[i][j] + " a").html());
							y.append(title);
							failedRenews++;
						}
					}
					
					if (failedRenews > 0) {
						EasyOpac.alert(y.html());
							}						
							EasyOpac.statusPageLoansUpdate();
						});
			} 
					});

		$("#spRenewAllLoans").unbind("click").bind('click',function() {
			var btn = $(this);
			var a = new Array();
			$(".myLoansContainerBody input:checkbox:visible").each(function(){
				a.push($(this).attr("value"));
			});
			
			if (a.length > 0) {
				btn.hide();
				$('.sp_loans_ajax').css('display','inline');
				$('.myLoansContainerBody').fadeTo("normal",.2);
				$.inleadAjax('reservationctl', {func : 'renewLoans', copyno : a.join(",")}, function (resp) {
					$('.sp_loans_ajax').hide();
					$('.myLoansContainerBody').fadeTo("normal",1);
					btn.show();
					if (resp.status == false) {
						EasyOpac.alert(resp.msg);
						return false;
					}
					var failedRenews = 0;
					var y = $('<div></div>');
					y.addClass('renewErrors');
					var i,j;

					for (i in resp.data.failed) {
						var errorTitle = $("#loanNotRenewedTpl .red").clone();
						var error = resp.data.translate[i];
						errorTitle.html(error);
						y.append(errorTitle);
						for (j = 0; j < resp.data.failed[i].length; j++) {
							var title = $("#loanNotRenewedTpl .title").clone();
							title.html($("td#loan_" + resp.data.failed[i][j] + " a").html());
							y.append(title);
							failedRenews++;
						}
					}
					
					if (failedRenews > 0) {
						EasyOpac.alert(y.html());
					}
					EasyOpac.statusPageLoansUpdate();
				});
			} 
		});
		
		
		function deleteReservations(e, container, ajaxLoader) {
			e.preventDefault();
			e.stopPropagation();

			var a = new Array();
            var interurbans = new Array();
			container.find("input:checkbox:visible:checked").each(function(){
				a.push($(this).attr("value"));
                if($(this).hasClass("interurban")){
                    interurbans.push($(this).attr("value"));
                }
			});
            EasyOpac.popConfirm('Er du sikker p&aring; du vil slette reserveringen?', function(){
				if (a.length > 0) {
					ajaxLoader.css('display','inline');
					container.fadeTo("normal",.2);
					$.inleadAjax('reservationctl', {
						func: 'delete',
                        resno: a.join(","),
                        interurban: interurbans.join(",")
					}, function(resp) {
						ajaxLoader.hide();
						container.fadeTo("normal",1);
						if (resp.status == false) {
							EasyOpac.alert(resp.msg);
							return false;
						}
						if (!resp.expired && resp.data != false) {
							var failedDeletions = 0;
							var y = $('<div></div>');
							y.addClass('renewErrors');
							var i,j;
							for (i in resp.data) {
                                if (resp.data[i]['status'] == true) {
									$('.sp_res_' + i).hide(); // for my ready
                                    $('.loanTr_' + i).hide(); // for remote loans
								} else {
									var title = $('.sp_res_' + i + ' td.reservationTitle a').html();
									y.append('<span> - ' + title + '</span><br />');
									failedDeletions++;
								}
							}
                            if (failedDeletions > 0) {
								EasyOpac.alert('Følgende forbehold kunne ikke slettes: <br />' + y.html());
							} else {
								EasyOpac.alert('Reservationen blev slettet.');
							}
						} else {
							if (!resp.expired)
								EasyOpac.alert('Reservationen kunne ikke slettes.');
						}
					});
				} else {
					return false;
				}
			});
		}
		// delete reservation section
		$('#spDeleteReservations').unbind('click').bind('click', function(e){
			deleteReservations(e, $('.myReservationsContainerBody'), $('.sp_res_ajax'));
		});
		
		// delete remote reservation section
		$('#spDeleteRemoteReservations').unbind('click').bind('click', function(e){
			deleteReservations(e, $('.myRemoteReservationsContainerBody'), $('.sp_remote_res_ajax'));
		});
	
		// update reservation section
		$('#spUpdateReservations').each(function(){
            $(this).unbind('click').bind('click', function(e){
                e.preventDefault();
                e.stopPropagation();
				
				var a = new Array();
				$(".myReservationsContainerBody input:checkbox:visible:checked").each(function(){
					a.push($(this).attr("value"));
				});
				
				var days = $('.statisticReservations .days').val();
				var branch = $('.statisticReservations .branch').val();
				
				var re = /^\d+$/;
				if (!(re.test(days)) || (days < 1 || days > 365)) {
					EasyOpac.alert('Ugyldig indtastning. Indtast et tal mellem 1 og 365.');
					return false;
				} 
				
				if (a.length == 0) {
					EasyOpac.alert('Vælg forbehold for at opdatere.');
					return false;
				}
				
				$('.sp_res_ajax').css('display','inline');
				$('.myReservationsContainerBody').fadeTo("normal",.2);
				
				$.inleadAjax('reservationctl', {
					func: 'update',
					resno: a.join(","),
					branch : branch, 
					days : days
				}, function(resp) {
					$('.sp_res_ajax').hide();
					$('.myReservationsContainerBody').fadeTo("normal",1);
					if (resp.status == false) {
						EasyOpac.alert(resp.msg);
						return false;
					}
					if (!resp.expired && resp.data != false) {
						var failed = 0;
						var y = $('<div></div>');
						y.addClass('renewErrors');
						var i,j;
						for (i in resp.data) {
							if (resp.data[i] == true) {
								$('.sp_res_' + resp.data[i]).hide();
							} else {
								var title = $('.sp_res_' + i + ' td.reservationTitle a').html();
								y.append('<span> - ' + title + '</span><br />');
								failed++;
							}
						}
						if (failed > 0) {
							EasyOpac.alert('Følgende forbehold kunne ikke opdatere: <br />' + y.html());
						} else {
							EasyOpac.alert('Forbehold er blevet opdateret.');
						}
						EasyOpac.updateReservationsContent('static');
					} else {
						if (!resp.expired)
							EasyOpac.alert('Reservationer er ikke blevet opdateret.');
					}
				});
			});
		});
		
		// delete ready to pickup items
		$('#spDeleteReadyToPickup').unbind('click').bind('click', function(e){
			e.preventDefault();
			e.stopPropagation();

			var a = new Array();
			$(".myReadyToPickupItemsContainerBody input:checkbox:visible:checked").each(function(){
				a.push($(this).attr("value"));
			});
                EasyOpac.popConfirm('Er du sikker p&aring; du vil slette reserveringen?', function(){
				if (a.length > 0) {
					$('.sp_ready_ajax').css('display','inline');
					$('.myReadyToPickupItemsContainerBody').fadeTo("normal",.2);
                        $.inleadAjax('reservationctl', {
                            func: 'delete',
						resno: a.join(",")
                        }, function(resp) {
						$('.sp_ready_ajax').hide();
						$('.myReadyToPickupItemsContainerBody').fadeTo("normal",1);
                            if (resp.status == false) {
                                EasyOpac.alert(resp.msg);
                                return false;
                            }
						if (!resp.expired && resp.data != false) {
							var failedDeletions = 0;
							var y = $('<div></div>');
							y.addClass('renewErrors');
							var i,j;
                            for (i in resp.data) {
								if (resp.data[i] == true) {
									$('.sp_ready_' + resp.data[i]).hide();
								} else {
									var title = $('.sp_res_' + i + ' td.reservationTitle a').html();
									y.append('<span> - ' + title + '</span><br />');
									failedDeletions++;
								}
							}
                            if (failedDeletions > 0) {
								EasyOpac.alert('Følgende forbehold kunne ikke slettes: <br />' + y.html());
							} else {
                                EasyOpac.alert('Reservationen blev slettet.');
							}
                            } else {
                                if (!resp.expired)
                                    EasyOpac.alert('Reservationen kunne ikke slettes.');
                            }
                        });
                    } else {
                        return false;
                    }
                });
            });
		
		$('#myStatusDibsPopUp').submit(function(submitEvent) {
			var acctNumbers = $('.materialPaymentContent .acctNumbers').html();

			if(0 ==  acctNumbers.length ) {
				EasyOpac.alert('Der opstod en fejl!<br />Pr&oslash;v evt. igen eller kontakt webmasteren.');
				submitEvent.preventDefault();
				return false;
			}

			$.inleadAjaxSync('PaymentCtl', {method : 'prepare', acctno : acctNumbers}, function(resp) {

				if(!resp.status) {
					EasyOpac.alert('Der opstod en fejl!<br />'+resp.msg);
					submitEvent.preventDefault();
				return false;
				}

				var transnum = resp.data.transno;
				var sum = resp.data.sum; // Not sure what this should be used for

				/* Prep the form for dibs with transaction number from ILS */
				$('#myStatusDibsPopUp input[name=orderid]').val(transnum);

				return true; // this submits the form to dibs
			});

		});

	},
	searchDefaultText : function() {
		var searchField = $('#opacSearchInput');
		var defaultText = $(searchField).attr('defaultText');
		if (defaultText) {
			$(searchField).val(defaultText);
			$(searchField).unbind('click').bind('click',function() {
				$(searchField).val() == defaultText ? $(searchField).val('') : '';
			});
			$(searchField).unbind('blur').bind('blur',function() {
				$(searchField).val() == '' ? $(searchField).val(defaultText) : '';
			});
		}
	}
}

var popup = null;

$(document).ready(function() {
	EasyOpac.runContexts();

	/*
	* Function popup
	*/
	$('#opacInfoBoxClose').click(function() {
		$.opacInfoBoxClose();
	});


	//	$.inleadAjax('dcmeta', { key : easyOpacKey }, function(data) {
	//		alert(data);
	//	});

});


jQuery.fn.getRecordInfo = function(recordInfoKey) {
	return $(this).children('.recordInfo').children('.'+recordInfoKey).html();
}

/*
* Expand/hide an extended section
*/
$.opacToggle = function(clickElem, toggleElem, hidden) {

	if(!toggleElem) var toggleElem = '.recordExtendedData';

	$(clickElem).children('.recordGroupTitle').click(function() {
		$(this).toggleClass('arrowDown').toggleClass('arrowRight');
		$(this).next().slideToggle('fast');
	});
}
/*
*	inleadAjax
* - inleadmedia ajax wrapper
*
* activityElement: The element to show, before the ajax call and hide when complete
*/
$.inleadAjax = function(action, data, callback, port, mode, activityElement) {
	if (EasyOpac.debug) {
		console.log('Calling'+action+' with '+data);
	}
	var _action = action;
	var _data = data;
	var _callback = callback;
	$.ajax({
		url: '/ajaxResponder.php?action='+action
		, data: data
		, success: function(resp) {
			if (resp.expired && resp.expired == '1') {
				if (!confirmPinPopUp)
					confirmPinPopUp = EasyOpac.popBox('Din session er udløbet', $('.confirmPinPopupContent'));
				$('.confirmPinText').val('');
				$('.confirmPinText').focus();
				$('.confirmPinCancel').unbind('click').click(
					function() {
						confirmPinPopUp.hide();
						confirmPinPopUp = null;
					}
				);
				var sendReq = $('.confirmPinSend');
				sendReq.reqObj = this;
				var requestSent = false;
				var sendPin = function() {
					var pin = '' + $('.confirmPinText').val();
					if (pin) {
						if (requestSent) return false;
						requestSent = true;
						$.ajax({
							url: '/ajaxResponder.php?action=Loginctl&method=checkPin',
							data: {pin : pin},
							success: function(resp) {
								if (resp.status) {
									if (resp.data) {
										//EasyOpac.alert("ok");
										confirmPinPopUp.hide();
										confirmPinPopUp = null;
										var reload = $('.profileExpiredDiv');
										if (reload.length > 0)
											document.location.reload();
										else {
											// fix for "AddToMyList"
											if (popup && _action == 'SocialServicesCurrentUserPersonalTags') {
												popup.show();
											}
											$.inleadAjax(_action,_data,_callback);
										}
									} else {
										$('.confirmPinText').val('');
										EasyOpac.alert("Den indtastede PIN kode er ikke korrekt.");
									}
								} else {
									EasyOpac.alert("error");
								}
								requestSent = false;
							},
							dataType: 'json',
							error: function() {
								EasyOpac.alert("error");
								requestSent = false;
							}
						});
					}
					// We don't want to redirect the user to the location of the template
					return false;
				}				
				$('.confirmPinPopupContent form').submit(sendPin);
				sendReq.unbind('click').click(sendPin);
			}
			callback(resp);
		}
		, dataType: 'json'
		, port: port
		, mode: mode
		, beforeSend: function() {
			if(activityElement && 'undefined' != activityElement) {
				$(activityElement).show();
			}
		}
		, complete: function(resp) {
			if(activityElement && 'undefined' != activityElement) {
				$(activityElement).hide();
			}
		}
		, error: function() {
			if(EasyOpac.debug) {
				console.log('Error calling'+action+' with '+data);
			}
		}
	});
}

$.inleadAjaxSync = function(action, data, callback, port, mode) {
	if (EasyOpac.debug) {
		console.log('Calling'+action+' with '+data);
	}
	var _action = action;
	var _data = data;
	var _callback = callback;
	$.ajax({
		url: '/ajaxResponder.php?action='+action
		, data: data
		, success: function(resp) {
			if (resp.expired && resp.expired == '1') {
				if (!confirmPinPopUp)
					confirmPinPopUp = EasyOpac.popBox('Session expired', $('.confirmPinPopupContent'));
				$('.confirmPinText').val('');
				$('.confirmPinText').focus();
				$('.confirmPinCancel').unbind('click').click(
					function() {
						confirmPinPopUp.hide();
						confirmPinPopUp = null;
						return;
					}
				);
				var sendReq = $('.confirmPinSend');
				sendReq.reqObj = this;
				var sendPin = function() {
					var pin = '' + $('.confirmPinText').val();
					if (pin) {
						sendReq.unbind('click');
						$.ajax({
							url: '/ajaxResponder.php?action=Loginctl&method=checkPin',
							data: {pin : pin},
							success: function(resp) {
								if (resp.status) {
									if (resp.data) {
										//EasyOpac.alert("ok");
										confirmPinPopUp.hide();
										confirmPinPopUp = null;
										$.inleadAjax(_action,_data,_callback);
									} else {
										$('.confirmPinText').val('');
										EasyOpac.alert("wrong pin");
									}
								} else {
									EasyOpac.alert("error");
								}
								sendReq.unbind('click').click(sendPin);
							},
							dataType: 'json',
							error: function() {
								EasyOpac.alert("error");
								sendReq.unbind('click').click(sendPin);
							}
						});
					}
					// We don't want to redirect the user to the location of the template
					return false;
				}
				$('.confirmPinPopupContent form').submit(sendPin)
				sendReq.unbind('click').click(sendPin);
			}
			callback(resp);
			confirmPinPopUp = null;
		}
		, dataType: 'json'
		, port: port
		, mode: mode
		, async: false
		, error : function(XMLHttpRequest, textStatus, errorThrown) {
			//console.log(this);
			EasyOpac.alert("Error! call against '"+action+"' failed!<br />Error:<br />"+textStatus+"<br /><br />Please notify barfoed!");
		}
	});
}

// this marks the beginning of the scrollTo implementation
/**
 * jQuery.ScrollTo
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 9/11/2008
 *
 * @projectDescription Easy element scrolling using jQuery.
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.2/5 and Safari 3. on Windows.
 *
 * @author Ariel Flesler
 * @version 1.4
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object,Function} settings Optional set of settings or the onAfter callback.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @desc Scroll to a fixed position
 * @example $('div').scrollTo( 340 );
 *
 * @desc Scroll relatively to the actual position
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @dec Scroll using a selector (relative to the scrolled element)
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @ Scroll to a DOM element (same for jQuery object)
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @desc Scroll on both axes, to different values
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
 */
;(function( $ ){
	
	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$(window).scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'y',
		duration:1
	};

	// Returns the element that needs to be animated to scroll the window.
	// Kept for backwards compatibility (specially for localScroll & serialScroll)
	$scrollTo.window = function( scope ){
		return $(window).scrollable();
	};

	// Hack, hack, hack... stay away!
	// Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
	$.fn.scrollable = function(){
		return this.map(function(){
			// Just store it, we might need it
			var win = this.parentWindow || this.defaultView,
				// If it's a document, get its iframe or the window if it's THE document
				elem = this.nodeName == '#document' ? win.frameElement || win : this,
				// Get the corresponding document
				doc = elem.contentDocument || (elem.contentWindow || elem).document,
				isWin = elem.setInterval;

			return elem.nodeName == 'IFRAME' || isWin && $.browser.safari ? doc.body
				: isWin ? doc.documentElement
				: this;
		});
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		if( typeof settings == 'function' )
			settings = {onAfter:settings};
			
		settings = $.extend( {}, $scrollTo.defaults, settings );
		// Speed is still recognized for backwards compatibility
		duration = duration || settings.speed || settings.duration;
		// Make sure the settings are given right
		settings.queue = settings.queue && settings.axis.length > 1;
		
		if( settings.queue )
			// Let's keep the overall duration
			duration /= 2;
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this.scrollable().each(function(){
			var elem = this,
				$elem = $(elem),
				targ = target, toff, attr = {},
				win = $elem.is('html,body');

			switch( typeof targ ){
				// A number will pass the regex
				case 'number':
				case 'string':
					if( /^([+-]=)?\d+(px)?$/.test(targ) ){
						targ = both( targ );
						// We are done
						break;
					}
					// Relative selector, no break!
					targ = $(targ,this);
				case 'object':
					// DOMElement / jQuery
					if( targ.is || targ.style )
						// Get the real position of the target 
						toff = (targ = $(targ)).offset();
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					old = elem[key],
					Dim = axis == 'x' ? 'Width' : 'Height',
					dim = Dim.toLowerCase();

				if( toff ){// jQuery / DOMElement
					attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );

					// If it's a dom element, reduce the margin
					if( settings.margin ){
						attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
					}
					
					attr[key] += settings.offset[pos] || 0;
					
					if( settings.over[pos] )
						// Scroll to a fraction of its width/height
						attr[key] += targ[dim]() * settings.over[pos];
				}else
					attr[key] = targ[pos];

				// Number or 'number'
				if( /^\d+$/.test(attr[key]) )
					// Check the limits
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );

				// Queueing axes
				if( !i && settings.queue ){
					// Don't waste time animating, if there's no need.
					if( old != attr[key] )
						// Intermediate animation
						animate( settings.onAfterFirst );
					// Don't animate this axis again in the next iteration.
					delete attr[key];
				}
			});			
			animate( settings.onAfter );			

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target, settings);
				});
			};
			function max( Dim ){
				var attr ='scroll'+Dim,
					doc = elem.ownerDocument;
				
				return win
						? Math.max( doc.documentElement[attr], doc.body[attr]  )
						: elem[attr];
			};
		}).end();
	};

	function both( val ){
		return typeof val == 'object' ? val : {top:val, left:val};
	};

})( jQuery );
// this marks the end of the scrollTo implementation

// this marks the beginning of the SCF initialisation
jQuery(function( $ ){
return;
	/**
	 * Demo binding and preparation, no need to read this part
	 */
		//borrowed from jQuery easing plugin
		//http://gsgd.co.uk/sandbox/jquery.easing.php
		$.easing.elasout = function(x, t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			if (t==0) return b;if ((t/=d)==1) return b+c;if (!p) p=d*.3;
			if (a < Math.abs(c)) {a=c;var s=p/4;}
			else var s = p/(2*Math.PI) * Math.asin (c/a);
			return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
		};
		$('a.back').click(function(){
			$(this).parents('div.pane').scrollTo( 0, 800, {queue:true} );
			$(this).parents('div.section').find('span.message').text( this.title );
			return false;
		});
		//just for the example, to stop the click on the links.
		$('ul.links').click(function(e){
			e.preventDefault();
			var link = e.target;
			link.blur();
			if( link.title )
				$(this).parent().find('span.message').text(link.title);
		});
	
	//by default, the scroll is only done vertically ('y'), change it to both.
	$.scrollTo.defaults.axis = 'xy'; 			
	//this one is important, many browsers don't reset scroll on refreshes
	$('div.pane').scrollTo( 0 );//reset all scrollable panes to (0,0)
	$.scrollTo( 0 );//reset the screen to (0,0)
	
});

// this marks the end of the SCF initialisation

