/**
 * Controls the main functionality of the site
 */
function _Application ()
{
	this.EVENT_REGION_SELECTED = "regsel";
	this.EVENT_WRITE_REVIEW = "writerev";
	this.EVENT_EDIT_TAG = "edittag";
	this.EVENT_UPLOAD_IMAGE = "upimg";
	this.EVENT_UPLOAD_PROFILEIMAGE = "profileupimg";
	this.EVENT_EDIT_OBJECT = "editobj";

	this.PAGE_MAIN = "p_main";
	this.PAGE_BROWSE = "p_browse";
	this.PAGE_VIEWOBJECT = "p_view";
	this.PAGE_EDITOBJECT = "p_editobj";
	this.PAGE_EDITPROFILE = "p_editpro";
	this.PAGE_VIEWPROFILE = "p_viewpro";
	this.PAGE_VIEWMESSAGE = "p_viewmsg";
	this.PAGE_CONTENT = "p_viewcontent";
	this.PAGE_REGISTER = "p_reguser";
	this.PAGE_SEARCH = "p_search";
	
	this.ARGUMENTS_DELIMITER = "/";
	
	this.currentPage = "";
	this.lastClickedPage = "";
	this.pageData = new Object();
	this.pageConversion = new Object(); // Not necesary but gives us nice looking urls
	
	this.user = false;
	this.alias = '';
	this.company = false;
	
	/**
	 * Constructor
	 */
	this.run = function () {
		EventDispatcher.initialize(this);
		
		this.pageData[this.PAGE_MAIN] = [InFocus, RecentView, TopCategories, Categories];
		this.pageData[this.PAGE_BROWSE] = [Map, BrowseCategory];
		this.pageData[this.PAGE_VIEWOBJECT] = [Map, ObjectView, RelevanceView];
		this.pageData[this.PAGE_EDITOBJECT] = [Map, ObjectEditor];
		this.pageData[this.PAGE_EDITPROFILE] = [ProfileEditor];
		this.pageData[this.PAGE_VIEWPROFILE] = [ProfileView];
		this.pageData[this.PAGE_VIEWMESSAGE] = [MessageView];
		this.pageData[this.PAGE_CONTENT] = [ContentView];
		this.pageData[this.PAGE_REGISTER] = [RegisterUser];
		this.pageData[this.PAGE_SEARCH] = [SearchView, Map];

		WindowManager.initialize( _get("content") );
		
		XMLRequest.construct();
		RecentView.construct();
		TopCategories.construct();
		Categories.construct();
		Map.construct();
		ProfileEditor.construct();
		SearchView.construct();
		InFocus.construct();
		BrowseCategory.construct();
		ObjectView.construct();
		Legend.construct();
		ObjectEditor.construct();
		MessageView.construct();
		ProfileView.construct();
		Menu.construct();
		ContentView.construct();
		RegisterUser.construct();
		ImageView.construct();
		Alert.construct();
		RelevanceView.construct();
		
		UserInfo.update();
		this.initSearch();
		this.initListeners();
		this.initRegions();
		Menu.initialize();
		
		_get("topLogo").onclick = Utils.delegate(this, "navigate", this.PAGE_MAIN);
	}
	
	/**
	 * Check and make sure the user is logged in, if not display a message
	 * returns true if logged in
	 */
	this.checkLogin = function (showAlert) {
		if ( this.user != false && this.alias != '' ) 
			return true;
		
		if ( showAlert == true ) {
			//Alert.show("Login", "Du mÃ¥ste logga in fÃ¶rst");
			this.openLogin(null);
		}
		
		return false;
	}
	
	this.reload = function () {
		Utils.gotoLocation("/");
	}
	
	/**
	 * Show a fullscreen image
	 */
	this.showImage = function (img) {
		ImageView.show(img);
	}
	
	/**
	 * Custom jelpo alert box, cooler than the standard
	 */
	this.alert = function (title, msg) {
		Alert.show(title, msg, "Ok");
	}
	
	/**
	 * Send a xml request
	 */
	this.send = function (url, data, callback, method) {
		//try {
			XMLRequest.send( url, data, callback, method ? method : "POST" );
		//}
		//catch (e) {
		//	alert("XMLRequest error: " + e);
		//}
	}
	
	/**
	 * An extension of the navigate method, this is used for history and bookmark
	 * this not only navigates but sets the appropriate data for each specific module
	 * that should be shown
	 */
	this.onNavigate = function (page) {
		//alert("onNavigate: " + page);
		var args = page.split(this.ARGUMENTS_DELIMITER);
		var _page = this.fromExternal(args[0]);

		if ( this.lastClickedPage != page )
			this._setModuleValues(args);
		else 
			this.lastClickedPage = "";
		
		//alert("onNavigate: " + _page + "("+page+")");
		
		//try {
		var subs;
			// Hide the old page
			if ( this.currentPage != "" ) {
				subs = this.pageData[this.currentPage];
				for ( var i=0; i < subs.length; ++i ) {
					subs[i].hide();
				}
			}
			
			if ( _page == this.PAGE_MAIN ) {
				Legend.setMainPage();
			}

			if (GMap.Map) GMap.resetSetMarkerOnMapState();
			Map.removeAll();
			
			// Show the new page
			this.currentPage = _page;
			subs = this.pageData[this.currentPage];
			for ( var i=0; i < subs.length; ++i ) {
				subs[i].show();
				if ( !subs[i].is_initialized ) {
					subs[i].initialize();
				}
				else {
					subs[i].update();
				}
			}
		//} 
		//catch (e) {
		//	alert( "Navigate error ("+page+"): " + e );
		//}
	}
	
	/**
	 * Set the values of each module that is concerned about the value
	 */
	this._setModuleValues = function ( args ) {
		try {
			switch ( this.fromExternal(args[0]) ) {
				case this.PAGE_VIEWOBJECT: {
					//Map
					ObjectView.onObjectSelected( {id:args[1]} );
					RelevanceView.onObjectSelected( {id:args[1]} );
				} break;
				
				case this.PAGE_BROWSE: {
					//Map
					BrowseCategory.onCategorySelected( {id:args[1], p:args[2]} );
				} break;
				
				case this.PAGE_EDITOBJECT: {
					//Map
					ObjectEditor.objectSelected(args[1], args[2]);
				} break;
				
				case this.PAGE_SEARCH: {
					//Map
					if ( args[1] && args[1] != "" )
						SearchView.setQuery(args[1]);
					else if (args[2])
						SearchView.setTagid(args[2]);
				} break;
				
				case this.PAGE_VIEWPROFILE: {
					ProfileView.onProfileSelected( {id:args[1]} );
				} break;
				
				case this.PAGE_CONTENT: {
					ContentView.onFileChange( {file:args[1]} );
				}
				
				default:
					// page values not implemented yet
				break;
			}
		}
		catch (e) {
			alert("_setModuleValues: " + e);
		}
	}
	
	/**
	 * Navigate to a new page, meaning hide some stuff and show some new
	 */
	this.navigate = function (page) {
	  	var curPage = YAHOO.util.History.getCurrentState( "nav" );
	    
		// Build the new page string representation
		var newPage = this.fromInternal(page);
		var len = arguments.length;
		if ( len > 1 ) {
			for ( var i=1; i < len; ++i ) {
				newPage += this.ARGUMENTS_DELIMITER + arguments[i];
			}
		}
		
		//alert("navigate: " + newPage + " != " + curPage);
		if ( newPage != curPage ) {
			this.lastClickedPage = newPage;
	    	if( !YAHOO.util.History.navigate( "nav", newPage ) ) {
	    		this.onNavigate(newPage);
	    	}
	    }
	}
	
	this.update = function () {
		// Update current view
		//alert("update: " + this.currentPage);
		subs = this.pageData[this.currentPage];
		for ( var i=0; i < subs.length; ++i ) {
			//subs[i].show();
			if ( !subs[i].is_initialized ) {
				//skip
			}
			else {
				subs[i].update();
			}
		}
		
		UserInfo.update();
	}
	
	//
	// LISTENERS
	//
	this.initListeners = function () {
		BrowseCategory.addEventListener(this.EVENT_WRITE_REVIEW, Utils.delegate(this, "openWriteReview"));
		ObjectView.addEventListener(this.EVENT_WRITE_REVIEW, Utils.delegate(this, "openWriteReview"));
		ProfileEditor.addEventListener(this.EVENT_WRITE_REVIEW, Utils.delegate(this, "openWriteReview"));
		SearchView.addEventListener(this.EVENT_WRITE_REVIEW, Utils.delegate(this, "openWriteReview"));
		ObjectView.addEventListener(this.EVENT_UPLOAD_IMAGE, Utils.delegate(this, "openUploadImage"));
		ProfileEditor.addEventListener(this.EVENT_UPLOAD_PROFILEIMAGE, Utils.delegate(this, "openUploadProfileImage"));
		ObjectView.addEventListener(this.EVENT_EDIT_OBJECT, Utils.delegate(this, "onEditObject"));
		Menu.addEventListener(this.EVENT_EDIT_OBJECT, Utils.delegate(this, "onEditObject"));
		ObjectEditor.addEventListener(this.EVENT_EDIT_TAG, Utils.delegate(this, "openEditTag"))
		
		WindowManager.addEventListener(WindowManager.EVENT_MODAL_ENABLE, Utils.delegate(this, "enableModal"));
		WindowManager.addEventListener(WindowManager.EVENT_MODAL_DISABLE, Utils.delegate(this, "disableModal"));
		ImageView.addEventListener(WindowManager.EVENT_MODAL_ENABLE, Utils.delegate(this, "enableModal"));
		ImageView.addEventListener(WindowManager.EVENT_MODAL_DISABLE, Utils.delegate(this, "disableModal"));
		
		XMLRequest.addEventListener(XMLRequest.EVENT_SEQURITY_ERROR, Utils.delegate(this, "openLogin"));
	}
	

	this.onEditObject = function (evt) {
		if( !this.checkLogin(true) ) return;

		ObjectEditor.objectSelected(evt.id, evt.tabid);
		this.navigate(this.PAGE_EDITOBJECT, evt.id, evt.tabid);
	}
	
	this.enableModal = function (evt) {
		var arrayPageSize = getPageSize();
		Element.setHeight('overlay', arrayPageSize[1]);

		new Effect.Appear('overlay', { duration: 0.2, from: 0.0, to: 0.8 });
		
		_get('overlay').onclick = function() {  }
	}
	
	this.disableModal = function (evt) {
		new Effect.Fade('overlay', { duration: overlayDuration});
		_get('overlay').onclick = function() { myLightbox.end(); }
	}

	/**
	 * Setup the search form, handle input from search and tag click
	 */
	this.initSearch = function () {
		var cb = Utils.delegate(this, "searchClicked");
		_get("searchbutton").onclick = cb;
		_get("searchform").onsubmit = function () { cb(); return false; };
	}
	
	this.searchClicked = function () {
		var q = _get("searchtext").value;
		SearchView.setQuery(q);
		this.navigate(this.PAGE_SEARCH, q, "");
		Legend.appendLegend( {page:Application.PAGE_SEARCH, title:"Sök"} );
		
		return false; // to avoid a submit	
	}
	
	//
	// REGION SELECTION
	//
	this.initRegions = function () {
		var c = _get("regionform");
		Utils.removeChildrenFromNode(c);
		c.appendChild( _span("Laddar...") );
		Application.send("/service/browseregion/", "", Utils.delegate(this, "onInitRegions"));
	}
	
	this.onInitRegions = function (req) {
		var c = _get("regionform");
		Utils.removeChildrenFromNode(c);
		
		var select = _elem("select");
		select.id = "browseRegionSelect";
		select[0] = new Option("Alla regioner"); 
		select[0].value = "0";
		select.onchange = Utils.delegate( this, "onRegionSelected" );
		
		var data = Utils.xmlToObject( req.responseXML );
		for ( var _r in data ) {
			var len = select.options.length;
			var r = data[_r];
			
			select[len] = new Option(r.name); 
			select[len].value = r.id;
		}
		c.appendChild(select);
	}
	
	this.onRegionSelected = function ( id ) {
		var s = _get("browseRegionSelect");
		var id = s.options[s.selectedIndex].value;
		
		this.dispatchEvent( {type:this.EVENT_REGION_SELECTED, id:id} );	
	}
	
	//
	// Popup management
	//
	this.openLogin = function (evt) {
		WindowManager.createIFrame("loginwin", "Logga in", "300", "280", "login", "", {ismodal:true});
		
		WindowManager.show("loginwin");
	}
	
	this.openWriteReview = function (evt) {
		if( !this.checkLogin(true) ) return;

		WindowManager.createIFrame("revwin", "Recensera", "300", "280", "review", "mid="+evt.id, {ismodal:true});
		
		WindowManager.show("revwin");
	}

	this.openUploadImage = function (evt) {
		if( !this.checkLogin(true) ) return;

		WindowManager.createIFrame("upimg", "Ladda upp bild", "300", "100", "upload", "mid="+evt.id, {ismodal:true});
		
		WindowManager.show("upimg");
	}
	
	this.openUploadProfileImage = function (evt) {
		if( !this.checkLogin(true) ) return;

		WindowManager.createIFrame("profileupimg", "Ladda upp bild", "300", "100", "profileupload", "", {ismodal:true});
		
		WindowManager.show("profileupimg");
	}
	
	this.openEditTag = function (evt) {
		if( !this.checkLogin(true) ) return;
		
		var title = evt.tagId == -1 ? "Ny tag" : "Ändra tag"
		
		WindowManager.createIFrame("edittag", title, "300", "100", "edittag", "c="+evt.catId+"&t="+evt.tagId, {ismodal:true});
		
		WindowManager.show("edittag");
	}
	
	//
	//
	//
	this.onNewTagAdded = function () {
		setTimeout( Utils.delegate(this, "onNewTagAddedDelayed"), 1000 );
	}
	this.onNewTagAddedDelayed = function () {
		ObjectEditor.onNewTagAdded();
	}
	
	this.closeWindow = function (winid) {
		setTimeout( Utils.delegate(this, "_delayedCloseWindow", winid), 100 );
	}
	
	this._delayedCloseWindow = function (winid) {
		WindowManager.hide(winid);
		
		if ( YAHOO.util.History.checkForIFrameHistoryBug() )
			history.back();		
	}
	
	this.removeItem = function (id, type) {
		if( !this.checkLogin(true) ) return;
		
		var title = "";
		if (type == "review")
			title = "Ta bort recension";
		else if (type == "comment")
			title = "Ta bort kommentar";
		else if (type == "mapobject")
			title = "Ta bort objekt";
		else if (type == "request")
			title = "Ta bort förfrågan";
		else if (type == "requestanswer")
			title = "Ta bort svar";
		else if (type == "contact")
			title = "Ta bort kontakt";
					
		WindowManager.createIFrame("remwin", title, "300", "200", "removeitem", "id="+id+"&t="+type, {ismodal:true});
		
		WindowManager.show("remwin");
	}
	
	this.showRegistration = function () {
		this.navigate(this.PAGE_REGISTER);

		Legend.appendLegend( {page:Application.PAGE_REGISTER, title:"Registrering"} );
	}
	
	//
	// Add to contact list
	//
	this.addUserToContactList = function (userid) {
		if( !this.checkLogin(true) ) return;

		Application.send("/service/contactlist/", "a=ask&to="+userid, Utils.delegate(this, "onAddUserToContactList") );
	}
	
	this.onAddUserToContactList = function (req) {
		var data = Utils.xmlToObject(req.responseXML);

		if ( data.success == 1 ) {
			this.alert('Ok', 'Förfrågan är nu skickad');
		}
		else {
			this.alert('Fel', data.msg);
		}
	}
	
	/**
	 * Some page id conversions, from internal from external and vice versa
	 */
	this.fromExternal = function (internal) {
		switch(internal) {
			case "category": return this.PAGE_BROWSE;
			case "object": return this.PAGE_VIEWOBJECT;
			case "editobject": return this.PAGE_EDITOBJECT;
			case "editprofile": return this.PAGE_EDITPROFILE;
			case "profile": return this.PAGE_VIEWPROFILE;
			case "message": return this.PAGE_VIEWMESSAGE;
			case "content": return this.PAGE_CONTENT;
			case "register": return this.PAGE_REGISTER;
			case "search": return this.PAGE_SEARCH;
			default: return this.PAGE_MAIN;
		}
	}

	this.fromInternal = function (external) {
		switch(external) {
			case this.PAGE_BROWSE: return "category";
			case this.PAGE_VIEWOBJECT: return "object";
			case this.PAGE_EDITOBJECT: return "editobject";
			case this.PAGE_EDITPROFILE: return "editprofile";
			case this.PAGE_VIEWPROFILE: return "profile";
			case this.PAGE_VIEWMESSAGE: return "message";
			case this.PAGE_CONTENT: return "content";
			case this.PAGE_REGISTER: return "register";
			case this.PAGE_SEARCH: return "search";
			default: return "main";
		}
	}
}
var Application =  new _Application();function _Menu () {
	this.is_initialized = false;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("menubar"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.buildMenu();
	}

	//
	// TABS MENU
	//
	this.buildMenu = function () {
		var ul = _elem("ul", "", "menubarLeft");
		
		ul.appendChild( this.createTabItem("HEM", "showHome", false, "mainmenuitem1", false) );
		ul.appendChild( this.createTabItem("OM JELPO", "showAbout", false, "mainmenuitem1", false) );
		ul.appendChild( this.createTabItem("BLOGG", "showBlog", false, "mainmenuitem2", true) );
		this.content.appendChild( ul );


		if ( Application.checkLogin() ) {
			var ul = _elem("ul", "", "menubarRight");
			ul.appendChild( this.createTabItem("SKAPA NYTT STÄLLE", "showAddObject", false, "mainmenuitem4", false) );
			ul.appendChild( this.createTabItem("PROFIL", "showProfile", false, "mainmenuitem5", false) );
			ul.appendChild( this.createTabItem("BREVLÅDA", "showMessages", false, "mainmenuitem6", false) );
			ul.appendChild( this.createTabItem("LOGGA UT", "showLogout", false, "mainmenuitem7", true) );
			this.content.appendChild( ul );
		}
	}
	
	this.createTabItem = function (label, cb, selected, id, islast) {
		li = _elem("li");
		li.appendChild( _span(label) );
		if ( !islast )
			li.appendChild( _img("/g/menu_separator.gif") );
		
		li.id = id;
		li.islast = islast;
		li.className = "menuitem_normal" + (islast ? " menuitem_last" : "");
		
		var _this = this
		li.onclick = function () { _this[cb](); _this.onTabItemClicked(this); }
		li.onmouseover = function () {_this.onTabItemOver(this);}
		li.onmouseout = function () {_this.onTabItemOut(this);}
		li.itemSelected = false;
		
		if (selected ) {
			li.className = "menuitem_selected" + (islast ? " menuitem_last" : "");
			li.itemSelected = true;
			this.currentTabMenuItem = li;
		}
		
		return li;
	}	
	
	this.currentTabMenuItem = null;
	this.onTabItemClicked = function (item) {
		if ( this.currentTabMenuItem != null ) {
			this.currentTabMenuItem.className = "menuitem_normal" + (this.currentTabMenuItem.islast ? " menuitem_last" : "");
			this.currentTabMenuItem.itemSelected = false;
		}	
		
		item.className = "tab_selected" + (item.islast ? " menuitem_last" : "");
		item.itemSelected = true;
		this.currentTabMenuItem = item;
	}
	
	this.onTabItemOver = function (item) {
		if (item.itemSelected == false) item.className = "menuitem_over" + (item.islast ? " menuitem_last" : "");
	}
	
	this.onTabItemOut = function (item) {
		if (item.itemSelected == false) item.className = "menuitem_normal" + (item.islast ? " menuitem_last" : "");
	}
	
	//
	//
	//
	this.showHome = function () {
		Application.navigate(Application.PAGE_MAIN);
	}
	
	this.showAbout = function () {
		this.dispatchEvent( {type:ContentView.EVENT_SET_CONTENT, file:"aboutjelpo"} );
		Application.navigate(Application.PAGE_CONTENT, "aboutjelpo");
		
		Legend.appendLegend( {page:Application.PAGE_CONTENT, title:"Om jelpo"} );
	}

	this.showBlog = function () {
		Utils.gotoLocation("http://www.jelpo.com/blog/", true);
	}

	this.showFuture = function () {
		this.dispatchEvent( {type:ContentView.EVENT_SET_CONTENT, file:"future"} );
		Application.navigate(Application.PAGE_CONTENT, "future");
		
		Legend.appendLegend( {page:Application.PAGE_CONTENT, title:"På gång"} );
	}

	this.showAddObject = function () {
		if( !Application.checkLogin() ) return;
		
		this.dispatchEvent( {type:Application.EVENT_EDIT_OBJECT, id:-1, tabid:"1"} );
		Legend.appendLegend( {page:Application.PAGE_EDITOBJECT, title:"Skapa nytt ställe"} );
	}
	
	this.showProfile = function () {
		Legend.appendLegend( {page:Application.PAGE_EDITPROFILE, title:"Min profil"} );
		
		Application.navigate(Application.PAGE_EDITPROFILE);
	}
	
	this.showMessages = function () {
		Legend.appendLegend( {page:Application.PAGE_VIEWMESSAGE, title:"Meddelande"} );
		
		Application.navigate(Application.PAGE_VIEWMESSAGE);
	}

	this.showLogout = function () {
		Utils.gotoLocation("/process/logout/", false);
	}
}

var Menu = new _Menu();/**
 * Displayed instead of login form at the page
 */
function _UserInfo () {
	this.update = function () {
		if ( Application.user != false ) {
			this.readScore();
			this.readMessages();
			
			var e = _get("uiDescription");
			Utils.removeChildrenFromNode(e);
			e.appendChild( _span("Du är inloggad som: ") );
			e.appendChild( _a("<b>"+Application.alias+"</b>", "", Utils.delegate(this, "onAliasClicked")) );
		}
	}
	
	this.onAliasClicked = function () {
		Legend.appendLegend( {page:Application.PAGE_EDITPROFILE, title:"Min profil"} );
		
		Application.navigate(Application.PAGE_EDITPROFILE);
	}
	
	this.onMessageClicked = function () {
		Legend.appendLegend( {page:Application.PAGE_VIEWMESSAGE, title:"Meddelande"} );
		
		Application.navigate(Application.PAGE_VIEWMESSAGE);
	}
	
	// score
	this.readScore = function () {
		Application.send("/service/profilegeneral/?a=read", "", Utils.delegate(this, "onReadScore"));
	}
	
	this.onReadScore = function (req) {
		var data = Utils.xmlToObject(req.responseXML.firstChild);
		var e = _get("uiScore");
		Utils.removeChildrenFromNode(e);
		e.appendChild( _span("Du har <b>" + data.user.points + "</b> jelpos") );
	}
	
	// mail
	this.readMessages = function () {
		Application.send("/service/message/?a=ping", "", Utils.delegate(this, "onReadMessages"));
		setTimeout( Utils.delegate(this, "readMessages") ,30000);
	}

	this.onReadMessages = function (req) {
		var data = Utils.xmlToObject(req.responseXML.firstChild);
		var e = _get("uiMessage");
		Utils.removeChildrenFromNode(e);
		e.appendChild( _span("Du har ") );
		e.appendChild( _a("<b>"+data.count+"</b>", "", Utils.delegate(this, "onMessageClicked")) );
		e.appendChild( _span(" meddelande") );
	}
}
var UserInfo =  new _UserInfo();function _TopCategories () {
	this.is_initialized = false;
	this.regionId = 0;

	this.construct = function() {
		BasicModule.initialize(this, _get("topCategories"));
		Application.addEventListener(Application.EVENT_REGION_SELECTED, Utils.delegate(this, "onRegionSelected"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/topcategories/", "r="+this.regionId, Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function( req ) {
		this.clear();
		this.layout( Utils.xmlToObject(req.responseXML) );
	}
	
	this.layout = function ( data )
	{
		var topCategoriesList = _elem("ul", "topCategoriesList");
		this.content.appendChild(topCategoriesList);
		
		for ( var _tc in data )
		{
			var categoryContainer = _elem("li", "", "categoryContainer");
			topCategoriesList.appendChild(categoryContainer);
			var tc = data[_tc];

			var h = _h1("");
			h.appendChild( _img("/g/icons/"+tc.icon+"o.gif"));
			h.appendChild( _a( tc.name, "category", Utils.delegate(this, "categoryClicked", tc.id, tc.name) ));
			categoryContainer.appendChild(h);
			
			for ( var _mo in tc.mapobjects )
			{
				var mo = tc.mapobjects[_mo];
				var category = _div("", "objectContainer");
				category.appendChild(_a(mo.name, "object", Utils.delegate(this, "mapObjectClicked", mo.id, tc.id, tc.name, mo.name)));
				categoryContainer.appendChild(category);
				categoryContainer.appendChild(Voting.buildCurrentRating(mo.rating, "", "w"));
				//categoryContainer.appendChild(_div("", "clearLeft"));
				categoryContainer.appendChild( _br("clearLeft") );
			}
		}
	}
	
	this.categoryClicked = function (categoryid, categoryname) {
		this.dispatchEvent( {type:Categories.EVENT_CATEGORY_SEL, id:categoryid} );
		Application.navigate(Application.PAGE_BROWSE, categoryid, 0);
		
		Legend.appendLegend( {page:Application.PAGE_BROWSE, title:categoryname, active:false} );
	}

	this.mapObjectClicked = function (mapobjectid, categoryid, categoryname, mapobjectname) {
		this.dispatchEvent( {type:Categories.EVENT_CATEGORY_SEL, id:categoryid} );
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_BROWSE, title:categoryname} );
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
	
	this.onRegionSelected = function (evt) {
		this.setRequestData("r="+evt.id);
		this.regionId = evt.id;
		this.update();
	}

}
var TopCategories = new _TopCategories();
function _Categories () {
	this.EVENT_CATEGORY_SEL = "catsel";
	this.is_initialized = false;
	this.regionId = 0;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("categories"));
		Application.addEventListener(Application.EVENT_REGION_SELECTED, Utils.delegate(this, "onRegionSelected"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/category/", "tc=-1&r="+this.regionId, Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function( req ) {
		this.clear();
		this.layout( Utils.xmlToObject(req.responseXML), req.responseXML);
	}
	
	this.layout = function (data, xmlNod)
	{
		var len = xmlNod.firstChild.childNodes.length;
		var maxCategoriesPerList = Math.floor( (len)/2 );
		this.content.appendChild( _h1("Alla kategorier") );
		var categoryList = _elem("ul");
		this.content.appendChild(categoryList);
		var displayedItems = 0;
		
		for (var _c in data)
		{
			var c = data[_c];

			if (displayedItems++ == maxCategoriesPerList )
			{
				categoryList = _elem("ul", "", "noMarginRight");
				this.content.appendChild(categoryList);
			}
				
			var category = _elem("li");
			category.appendChild( _a( c.name + " ("+c.children+")", "category", Utils.delegate(this, "categoryClicked", c.id, c.name) ) );
			categoryList.appendChild(category);
		}
	}
	
	this.categoryClicked = function (categoryid, categoryname) {
		this.dispatchEvent( {type:this.EVENT_CATEGORY_SEL, id:categoryid} );
		Application.navigate(Application.PAGE_BROWSE, categoryid, 0);
		
		Legend.appendLegend( {page:Application.PAGE_BROWSE, title:categoryname} );
	}
	
	this.onRegionSelected = function (evt) {
		this.setRequestData("tc=-1&r="+evt.id+"&p=0");
		this.regionId = evt.id;
		this.update();
	}
}
var Categories = new _Categories();function _BrowseCategory() {
	this.is_initialized = false;
	this.category = -1;
	this.regionId = 0;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("browsecategory"));
		Categories.addEventListener(Categories.EVENT_CATEGORY_SEL, Utils.delegate(this, "onCategorySelected"));
		TopCategories.addEventListener(Categories.EVENT_CATEGORY_SEL, Utils.delegate(this, "onCategorySelected"));
		Application.addEventListener(Application.EVENT_REGION_SELECTED, Utils.delegate(this, "onRegionSelected"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/browse/", "c="+this.category+"&p=0&r="+this.regionId, Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function( req ) {
		this.clear();
		Map.removeAll();
		this.layout( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layout = function ( data, xmlNod )
	{
		var index = 1;
		var objectList = _elem("ul", "", "categoryList");
		var maxObjectsPerList = Math.floor( Number(data.navsize)/2 );
		this.content.appendChild(objectList);
		var displayedItems = 0;

		// Layout the map objects
		for ( var _mo in data.mapobjects )
		{
			var mo = data.mapobjects[_mo];

			if (displayedItems++ == maxObjectsPerList)
			{
				objectList = _elem("ul", "", "categoryList");
				this.content.appendChild(objectList);
			}

			var object = _elem("li");

			object.appendChild( _a(index + ". " + mo.name, "object", Utils.delegate(this, "mapObjectClicked", mo.id, mo.name) ) );
			object.appendChild( _a('<img src="/g/icon_review.gif" alt="Recensera" label="Recensera" />', "", Utils.delegate(this, "onWriteReviewClicked", mo.id)) );
			object.appendChild( _br() );
			object.appendChild( _p( mo.desc, "", "" ) );
			var rating = Voting.buildCurrentRating(mo.avgscore, 13, "w");
			rating.className = "rating";
			object.appendChild( rating );			
			var reviewCount = _div("", "reviewCount");
			reviewCount.innerHTML = mo.numreview + " recensioner";
			object.appendChild( reviewCount );
			object.appendChild( _img("/g/separator.gif") );

			objectList.appendChild(object);
			Map.addMapObject( mo, index );
			
			++index;
		}
		
		this.content.appendChild( _br("clearLeft") );
		
		// Layout the navigation bar
		var navData = PageNavigation.calculate(Number(data.page)+1, Number(data.total), Number(data.navsize));
		for ( var i=0; i < navData.length; ++i ) {
			if ( navData[i].selected )
			{
				var navCurrentPage = _div("", "navCurrentPage");
				navCurrentPage.innerHTML = navData[i].label;
				this.content.appendChild(navCurrentPage);
			}
			else
				this.content.appendChild( _a( navData[i].label, "navLinkPage", Utils.delegate(this, "changePage", navData[i].pageid-1) ) );
		}
	}
	
	this.changePage = function (p) {
		//this.send("/service/browse/", "c="+this.category+"&p="+p, Utils.delegate(this, "onSend"));
		//this.setRequestData("c="+this.category+"&p="+p+"&r="+this.regionId);
		this.setRequestData("c="+this.category+"&p="+p+"&r="+this.regionId);
		Application.navigate(Application.PAGE_BROWSE, this.category, p);
	}
	
	this.onCategorySelected = function (evt) {
		this.category = evt.id;
		var page = evt.p ? evt.p : 0;;
		this.setRequestData("c="+this.category+"&p="+page+"&r="+this.regionId);
	}
	
	this.onWriteReviewClicked = function (id) {
		this.dispatchEvent( {type:Application.EVENT_WRITE_REVIEW, id:id} );
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
	
	this.onRegionSelected = function (evt) {
		this.setRequestData("c="+this.category+"&p=0&r="+evt.id);
		this.regionId = evt.id;
		this.update();
	}
}
var BrowseCategory = new _BrowseCategory();function _Map() {
	this.is_initialized = false;
	this.markers = null;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("googlemap"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.show();
		GMap.initialise( "googlemapcontent" );
		this.initIcons();
		
		this.markers = new Array();
	}
	
	this.initIcons = function () {
		if ( GMap.OfflineMode == false)
		{
			var icon;
			// Create the default markers
			for (var i=1; i < 11; ++i) {
				icon = new GIcon();
				icon.image = "http://www.jelpo.com/g/mapicons/icon_"+i+".png";
				icon.iconSize = new GSize(16, 30);
				icon.iconAnchor = new GPoint(8,30);
				icon.infoWindowAnchor = new GPoint(8,1);
				icon.shadow = "http://www.jelpo.com/g/mapicons/shadow.png";
				icon.shadowSize = new GSize(22,30);
				
				GMap.addIcon("icon_"+i, icon);			
			}		
			
			// Create the default selected marker
			icon = new GIcon();
			icon.image = "http://www.jelpo.com/g/mapicons/icon_sel.png";
			icon.iconSize = new GSize(16, 30);
			icon.iconAnchor = new GPoint(8,30);
			icon.infoWindowAnchor = new GPoint(8,1);
			icon.shadow = "http://www.jelpo.com/g/mapicons/shadow.png";
			icon.shadowSize = new GSize(22,30);
			
			GMap.addIcon("icon_sel", icon);
			
			// Create the relevance markers
			for (var i=1; i < 11; ++i) {
				icon = new GIcon();
				icon.image = "http://www.jelpo.com/g/mapicons/icon_blue_"+i+".png";
				icon.iconSize = new GSize(16, 30);
				icon.iconAnchor = new GPoint(8,30);
				icon.infoWindowAnchor = new GPoint(8,1);
				icon.shadow = "http://www.jelpo.com/g/mapicons/shadow.png";
				icon.shadowSize = new GSize(22,30);
				
				GMap.addIcon("icon_rel_"+i, icon);			
			}		
		}
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
	
	//
	// HANDLE MAP CONTENT
	//
	this.addMapObject = function ( objectdata, index, relevance ) {
		if ( Math.round(objectdata.latitude) == 0 || Math.round(objectdata.longitude) == 0 ) {
			return;
		}
		
		var marker = new MapMarker();
		marker.location.latitude = objectdata.latitude;
		marker.location.longitude = objectdata.longitude;
		if ( index ) {
			if ( relevance )
				marker.iconName = "icon_rel_" + index;
			else
				marker.iconName = "icon_" + index;
		}
		else
			marker.iconName = "icon_sel";
		
		marker.toolTip = objectdata.name;
		marker.id = objectdata.id;
		marker.index = index;
		
		GMap.addMarker(marker, Utils.delegate(this, "mapObjectClicked", marker.id, marker.toolTip));
		this.markers.push(marker);
	}
	
	this.currentMarker = null;
	this.selectMapObject = function ( id ) {
		if ( this.currentMarker != null ) {
			GMap.removeMarker(this.currentMarker.id);
			this.currentMarker.iconName = "icon_" + this.currentMarker.index;
			GMap.addMarker(this.currentMarker, Utils.delegate(this, "mapObjectClicked", this.currentMarker.id, this.currentMarker.toolTip));
		}
		
		this.currentMarker = this.getMarker(id);
		if ( this.currentMarker != null ) {
			GMap.removeMarker(this.currentMarker.id);
			this.currentMarker.iconName = "icon_sel";
			GMap.addMarker(this.currentMarker, Utils.delegate(this, "mapObjectClicked", this.currentMarker.id, this.currentMarker.toolTip));
		
			// Zoom in to this object	
			var loc = new Object();
			loc.longitude = this.currentMarker.location.longitude;
			loc.latitude = this.currentMarker.location.latitude;
			loc.zoom = 12;
			if ( GMap.Zoom != loc.zoom )
				GMap.gotoLocation(loc);
			else
				GMap.panToLocation(loc);
		}
	}
	
	this.getMarker = function (id) {
		for ( var i=0; i < this.markers.length; ++i ) {
			if ( this.markers[i].id == id )
				return this.markers[i];
		}
		return null;
	}
	
	this.removeAll = function () {
		GMap.clearMarkers();
		this.markers = new Array();
		this.currentMarker = null;
	}

	this.removeMapObject = function (id) {
		GMap.removeMarker(id);
		var ai = -1;
		for ( var i=0; i < this.markers.length; ++i ) {
			if ( this.markers[i].id == id ) {
				ai = i;
				break;
			}
		}
		if ( ai > 0 ) {
			this.markers.splice(ai,1);
		}
	}
}
var Map = new _Map();function _ObjectView () {
	this.EVENT_OBJECT_SELECTED = "mosel";
	
	this.is_initialized = false;
	this.mapobjectid = -1;
	this.mapobjectdata = null;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("objectview"));

		BrowseCategory.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		TopCategories.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		ProfileEditor.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		SearchView.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		Map.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		InFocus.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		RecentView.addEventListener(this.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		
		this.addEventListener(Categories.EVENT_CATEGORY_SEL, Utils.delegate(BrowseCategory, "onCategorySelected"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/mapobject/", "mi=" + this.mapobjectid, Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function( req ) {
		this.clear();
		this.layout( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layout = function ( data, xmlNode ) {
		// if the object is empty then return to the main screen
		if ( xmlNode.firstChild.childNodes.length == 0 ) {
			Application.navigate(Application.PAGE_MAIN);
			return;
		}
		
		this.mapobjectdata = data;
		
		this.content.appendChild( _h1( data.name ) );

		var ul = _elem("ul", "", "toolbar");
		var li = _elem("li");
		li = _elem("li");
		li.appendChild( _a('<img src="/g/icon_review.gif" alt="Skriv recension" title="Skriv recension">', "", Utils.delegate(this, "onWriteReviewClicked", data.id)) );
		ul.appendChild( li );
		//li = _elem("li");
		//li.appendChild( _a('<img src="/g/icon_add.gif" alt="Lägg till på min karta" title="Lägg till på min karta">', "", Utils.delegate(this, "onAddToPrivate", data.id)) );
		//ul.appendChild( li );
		li = _elem("li");
		li.appendChild( _a('<img src="/g/icon_mail.gif" alt="Tipsa en vän" title="Tipsa en vän">', "", Utils.delegate(this, "onSendTipClicked", data.id, data.name)) );
		ul.appendChild( li );
		li = _elem("li");
		li.appendChild( _a('<img src="/g/icon_image.gif" alt="Ladda upp en bild" title="Ladda upp en bild">', "", Utils.delegate(this, "onUploadClicked", data.id)) );
		ul.appendChild( li );
		li = _elem("li");
		li.appendChild( _a('<img src="/g/icon_edit.gif" alt="Ändra objektet" title="Ändra objektet">', "", Utils.delegate(this, "onEditClicked", data.id, "1")) );
		ul.appendChild( li );
		if (data.moderator == 1) {
			li = _elem("li");
			li.appendChild( _a('<img src="/g/icon_trashbin.gif" alt="Ta bort objektet" title="Ta bort objektet">', "", Utils.delegate(this, "onRemoveClicked", data.id, "mapobject")) );
			ul.appendChild( li );
		}
		this.content.appendChild( ul );

		this.content.appendChild( _elem("hr") );
		
		var tagsContent = _div( "tagsContent" );
		this.content.appendChild( tagsContent );
		
		var objectContactInfo = _div( "objectContactInfo" );
			objectContactInfo.appendChild( _h2( "Kontaktinfo" ) );
			if ( data.map_street == "" && data.map_streetnumber == "" && data.map_postal == "" && data.map_city == "" && data.contactphone == "") 
			{
				objectContactInfo.appendChild( _a("Lägg till kontaktinfo", "", Utils.delegate(this, "onEditClicked", data.id, "3") ) );
			}
			else {
				var contactInfoDetails = _p(data.map_street + " " + data.map_streetnumber);
				contactInfoDetails.innerHTML += "<br />";
				contactInfoDetails.innerHTML += data.map_postal + " " + data.map_city;
				contactInfoDetails.innerHTML += "<br />";
				contactInfoDetails.innerHTML += data.contactphone;
				objectContactInfo.appendChild( contactInfoDetails );
			}
			
			objectContactInfo.appendChild( _h2("Inlagd av") );
			objectContactInfo.appendChild( _a(data.alias, "user", Utils.delegate(this, "showProfile", data.alias, data.owner)) );			
						
			var ratingContent = _div("rating");
			var ratingContentL = _div("", "rating_l");
			var ratingContentR = _div("", "rating_l");
			
			if (data.avgscore == 0) {
				ratingContentL.appendChild( _span("<b>Inväntar första rösten</b>") );
			}
			else {
				var temp = data.votes == 1 ? "röst" : "röster";
				ratingContentL.appendChild( _span("Omdöme ("+data.votes + " "+temp+")") );
				ratingContentL.appendChild( _br() );
				ratingContentL.appendChild( Voting.buildCurrentRating(data.avgscore, 13, "w") );
			}
			
			if (data.userrating != -1) {
				ratingContentR.appendChild( _span("Din röst") );
				ratingContentR.appendChild( _br() );
				ratingContentR.appendChild( Voting.buildCurrentRating(data.userrating, 13, "w", this, "rateObject") );
			}
			else {
				ratingContentR.appendChild( _span("Rösta här") );
				ratingContentR.appendChild( _br() );
				ratingContentR.appendChild( Voting.buildVotingModule(this, "rateObject", "w") );
			}
			ratingContent.appendChild(ratingContentL);
			ratingContent.appendChild(ratingContentR);
			
			objectContactInfo.appendChild( ratingContent );
		
		this.content.appendChild( objectContactInfo );
		
		var objectInformation = _div( "objectInformation");
			objectInformation.appendChild( _h2( "Information" ) );
			if ( data.description == "" )
				objectInformation.appendChild( _a("Lägg till information", "", Utils.delegate(this, "onEditClicked", data.id, "2") ) );
			else
				objectInformation.appendChild( _p(Utils.convertNewline(data.description), "", "description") );
	
		this.content.appendChild( objectInformation );
		this.content.appendChild( _br("clearLeft") );
		

		var imgHead =  _h2( "Bilder" );
		imgHead.className = "clearLeft";
		this.content.appendChild( imgHead );
		this.content.appendChild( _elem("hr") );

		var mediaContent = _div("mediafiles");
		mediaContent.innerHTML = "Laddar...";
		this.content.appendChild(mediaContent);


		var reviewsContent;
		reviewsContent = _div("reviews");
		reviewsContent.innerHTML = "Laddar...";
		this.content.appendChild(reviewsContent);

		
		this.loadTags();
		this.loadImages();
		this.loadReviews();
		
		// If the object already exists on the map pan to it.
		// if not then add it
		if ( Map.getMarker(data.id) ) {
			Map.selectMapObject(data.id);
		}
		else {
			Map.addMapObject(data);
			Map.selectMapObject(data.id);
		}
	}
	
	this.onObjectSelected = function  (evt) {
		this.mapobjectid = evt.id;
		this.setRequestData("mi=" + this.mapobjectid);
	}
	
	//
	// REVIEWS
	//
	this.loadReviews = function () {
		Application.send("/service/reviews/", "mi=" + this.mapobjectid + "&c=0", Utils.delegate(this, "onLoadObjectReviews"));
	}

	this.onLoadObjectReviews = function (req) {
		var reviewContent = _get("reviews");
		reviewContent.innerHTML = "";
		
		var toolsDiv = _div("", "reviewsToolMenu");
		toolsDiv.appendChild( _a("Skriv recension", "", Utils.delegate(this, "onWriteReviewClicked", this.mapobjectid)) );
		
		reviewContent.appendChild( toolsDiv );
		reviewContent.appendChild( _h2("Recensioner:") );
		reviewContent.appendChild( _elem("hr") );
		//reviewContent.appendChild( _br() );
		
		var data = Utils.xmlToObject(req.responseXML);
		
		if (data == null) { // No reviews yet
			var s = _a("<b>Bli först med att recensera, tjäna 20 Jelpos</b>", "",  Utils.delegate(this, "onWriteReviewClicked", this.mapobjectid));
			s.style.margin = "10px 0px 0px 4px";
			reviewContent.appendChild( s );
		}
		else {
			var ul = _elem("ul", "", "reviewList");
			reviewContent.appendChild(ul);
			for ( var _r in data ) {
				var r = data[_r];
				var li = _elem('li', "", "reviewListItem");
				var leftPart = _elem("div", "", "reviewListColumnLeft");
				var rightPart = _elem("div", "", "reviewListColumnRight");
				
				leftPart.appendChild( _img("/g/review_bullet.gif") );
				
				// HEADING
				rightPart.appendChild(_h2(r.heading));
				// CONTENT
				rightPart.appendChild( _p(Utils.convertNewline(r.content)) );
				rightPart.appendChild( _span("<i>av ") );
				rightPart.appendChild( _a(r.alias, "", Utils.delegate(this, "showProfile", r.alias, r.owner)) );
				rightPart.appendChild( _span(", " +r.tstamp+"</i> "));
				if (r.myrev == "true")
					rightPart.appendChild( _a('<img style="margin:0px 0px 0px 3px;" src="/g/icon_trashbin.gif" alt="Ta bort" title="Ta bort" />', "", Utils.delegate(Application, "removeItem", r.id, "review")) );
				rightPart.appendChild( _br("clearLeft") );
				
				li.appendChild(leftPart);
				li.appendChild(rightPart);
				var img = _img("/g/review_spacer.gif");
				img.className = "reviewListSpacer";
				li.appendChild( img );
				li.appendChild( _br("clearLeft") );
				
				ul.appendChild(li);
			}
		}
		reviewContent.appendChild( _br("clearLeft") );
	}
	
	this.showProfile = function ( alias, userid ) {
		Legend.appendLegend( {page:Application.PAGE_VIEWPROFILE, title:alias+"s profil"} );
		
		this.dispatchEvent( {type:ProfileView.EVENT_PROFILE_SELECTED, id:userid} );
		
		Application.navigate(Application.PAGE_VIEWPROFILE, userid);
	}
	
	//
	// RATING
	//
	this.ratingClicked = false;
	this.rateObject = function (rating) {
		if ( Application.checkLogin(true) ) {
			this.ratingClicked = true;
			Application.send("/service/rating/", "mi=" + this.mapobjectid + "&r=" + rating, Utils.delegate(this, "onRateObject") );
		}
	}
	
	this.onRateObject = function (req) {
		this.update();
	}

	//
	// IMAGES
	//
	this.loadImages = function (p) {
		Application.send("/service/media/", "mi=" + this.mapobjectid, Utils.delegate(this, "onLoadImages"));
	}
	
	this.onLoadImages = function (req) {
		var imageContent = _get("mediafiles");
		imageContent.innerHTML = "";
		
		var data = Utils.xmlToObject(req.responseXML);
		
		if ( req.responseXML.firstChild.childNodes.length == 0) {
			imageContent.appendChild( _a("Bli först med att ladda upp en bild", "", Utils.delegate(this, "onUploadClicked", this.mapobjectid)) );
		}
		else {
			for ( var _i in data ) {
				var i = data[_i];
				//imageContent.appendChild( _a('<img src="/image_thumb/'+i.imagename+'" alt="Bild" />', "", Utils.delegate(Application, "showImage", i.imagename)) );
				var im = _a("", "", "", '/image_normal/'+i.imagename, "lightbox[objectimages]", i.alias);
				//var im = _a("", "", "", '/image_normal/'+i.imagename, "lightbox[objectimages]", '&lt;a onclick=&quot;this.showProfile('+i.alias+', '+i.userid+');&quot;&gt;'+i.alias+'&lt;/a&gt;');
				var img = _img("/image_thumb/"+i.imagename, "Bild", "", "", '.'+i.alias+'.', 'corner iradius5 ishadow20', "", function(){addCorners(this);});
				im.appendChild( img );
				imageContent.appendChild(im);
				//imageContent.appendChild( _br() );
			}
			refreshLightboxAnchors();
		}
	}
	
	//
	//
	//
	this.onWriteReviewClicked = function (id) {
		this.dispatchEvent( {type:Application.EVENT_WRITE_REVIEW, id:id} );
	}
	
	this.onAddToPrivate = function (id) {
		
	}
	
	this.onSendTipClicked = function (id, name) {
		var evt = new Object();
		evt.type = MessageView.EVENT_SEND_MESSAGE;
		evt.subject = "";
		evt.recipients = new Array();
		evt.attachment = {id:id, name:name};
		
		this.dispatchEvent( evt );
	}
	
	this.onUploadClicked = function (id) {
		this.dispatchEvent( {type:Application.EVENT_UPLOAD_IMAGE, id:id} );
	}
	
	this.onEditClicked = function (id, tabid) {
		if( !Application.checkLogin(true) ) return;
		
		this.dispatchEvent( {type:Application.EVENT_EDIT_OBJECT, id:id, tabid:tabid} );
		Legend.appendLegend( {page:Application.PAGE_EDITOBJECT, title:"Editera"} );
	}
	
	this.onRemoveClicked = function (id) {
		Application.removeItem(id, "mapobject");
	}
	
	//
	// TAGS
	//
	this.loadTags = function () {
		var content = _get("tagsContent");
		content.innerHTML = "Laddar...";
		Application.send("/service/tags/", "a=read&m=" + this.mapobjectid + "&c=" + this.mapobjectdata.catid + "&cor=-1", Utils.delegate(this, "onLoadTags") );
	}
	
	this.onLoadTags = function (req) {
		var tagsContent = _get("tagsContent");
		tagsContent.innerHTML = "";
		
		var data = Utils.xmlToObject(req.responseXML);
		
		var ul = _elem("ul");
		var li = _elem("li");
		li.appendChild(	_a(this.mapobjectdata.catname, "tagslink", Utils.delegate(this, "tagCategoryClicked")));
		ul.appendChild(li);

		for ( var _t in data ) {
			var t = data[_t];
			
			li.appendChild( _span(", ") );
			
			li = _elem("li");
			li.appendChild( _a(t.name, "tagslink", Utils.delegate(this, "tagTagClicked", t.id)) );
			ul.appendChild(li);
		}
		
		tagsContent.appendChild(ul);
	}
	
	this.tagCategoryClicked = function () {
		this.dispatchEvent( {type:Categories.EVENT_CATEGORY_SEL, id:this.mapobjectdata.catid} );
		Application.navigate(Application.PAGE_BROWSE, this.mapobjectdata.catid, 0);

		Legend.appendLegend( {page:Application.PAGE_BROWSE, title:this.mapobjectdata.catname} );
	}

	this.tagTagClicked = function (tagid) {
		SearchView.setTagid(tagid);

		Application.navigate(Application.PAGE_SEARCH, "", tagid);
		
		Legend.appendLegend( {page:Application.PAGE_SEARCH, title:"Sök tag"} );
	}
}
var ObjectView = new _ObjectView();
function _Legend() {
	this.content = null;
	this.legendData = null;
	
	
	this.construct = function () {
		return;
		
		this.content = _get("legend");
		this.legendData = new Array();
	}
	
	this.setMainPage = function () {
		return;
		
		this.clearLegend();
	}
	
	/**
	 * {
	 * 	page
	 *  title
	 *  active
	 * }
	 */
	this.appendLegend = function (legend) {
		return;
		
		for ( var i = 0; i < this.legendData.length; ++i ) {
			if ( this.legendData[i].page == legend.page )
				return;	
		}
		
		Utils.removeChildrenFromNode(this.content);
		
		this.content.appendChild( _a("Jelpo", "", Utils.delegate(this, "legendClicked", Application.PAGE_MAIN, 0 )) );
		
		for ( var i = 0; i < this.legendData.length; ++i ) {
			this.legendData[i].active = true;
		}
		legend.active = false;
		this.legendData.push(legend);
		
		for ( var i = 0; i < this.legendData.length; ++i )
			this.addElement( this.legendData[i], i+1 );
	}
	
	this.addElement = function(legend, index) {
		return;
		
		this.content.appendChild( _span(" / ") );
		
		var l;
		if (legend.active)
			l = this.content.appendChild( _a(legend.title, "", Utils.delegate(this, "legendClicked", legend.page, index)) );
		else
			l = _span(legend.title);
			
		this.content.appendChild(l);
	}
	
	this.clearLegend = function () {
		return;
		
		Utils.removeChildrenFromNode(this.content);
		this.legendData = new Array();
	}
	
	this.legendClicked = function (page, index) {
		return;
		
		Utils.removeChildrenFromNode(this.content);
		var tmpArray = this.legendData.slice(0, index);
		this.legendData = new Array();
		if ( tmpArray.length > 0 ) {
			tmpArray[tmpArray.length-1].active = false;
			for ( var i = 0; i < tmpArray.length; ++i ) {
				this.appendLegend( tmpArray[i] );
			}
		}
		Application.navigate(page);
	}
}
var Legend = new _Legend();
function _ObjectEditor () {
	this.is_initialized = false;
	this.mapobjectid = -1;
	this.localization = null;
	this.Criteria = new Object();
	this.pendingTabId = "1";
	
	this.construct = function() {
		var tabContent = _div("oeTabContent");
		var menuContent = _elem("ul", "oeTabMenu");
		_get("objecteditor").appendChild(menuContent);
		_get("objecteditor").appendChild(tabContent);
		
		TabModule.initialize(this, _get("objecteditor"), menuContent, tabContent);
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/editmapobject/?a=read", "mid=" + this.mapobjectid, Utils.delegate(this, "onSend"));
		
		this.buildMenu();
	}
	
	this.objectSelected = function  (id, tabid) {
		this.mapobjectid = id;
		this.pendingTabId = tabid;
		this.setRequestData("mid=" + this.mapobjectid);
	}
	
	//
	// TABS MENU
	//
	this.buildMenu = function () {
		var ul = _get("oeTabMenu");
		
		ul.appendChild( this.createTabItem("Allmän (Steg 1)", "showTab1", true, "oetab1", true) );
		ul.appendChild( this.createTabItem("Information (Steg 2)", "showTab2", false, "oetab2", false) );
		ul.appendChild( this.createTabItem("Kontakt & adress (Steg 3)", "showTab3", false, "oetab3", false) );
	}
	
	this.createTabItem = function (label, cb, selected, id, isfirst) {
		li = _elem("li");
		li.innerHTML = label;
		li.id = id;
		li.isfirst = isfirst;
		li.className = "tab_normal" + (isfirst ? " tab_first" : "");
		
		var _this = this
		li.onclick = function () { _this[cb]();}
		li.onmouseover = function () {_this.onTabItemOver(this);}
		li.onmouseout = function () {_this.onTabItemOut(this);}
		li.itemSelected = false;
		
		if (selected ) {
			li.className = "tab_selected" + (isfirst ? " tab_first" : "");
			li.itemSelected = true;
			this.currentTabMenuItem = li;
		}
		
		return li;
	}	
	
	this.currentTabMenuItem = null;
	this.onTabItemClicked = function (item) {
		if ( this.currentTabMenuItem != null ) {
			this.currentTabMenuItem.className = "tab_normal" + (this.currentTabMenuItem.isfirst ? " tab_first" : "");
			this.currentTabMenuItem.itemSelected = false;
		}	

		item.className = "tab_selected" + (item.isfirst ? " tab_first" : "");
		item.itemSelected = true;
		this.currentTabMenuItem = item;
	}
	
	this.onTabItemOver = function (item) {
		if (item.itemSelected == false) item.className = "tab_over" + (item.isfirst ? " tab_first" : "");
	}
	
	this.onTabItemOut = function (item) {
		if (item.itemSelected == false) item.className = "tab_normal" + (item.isfirst ? " tab_first" : "");
	}
	
	this.showTab1 = function () {
		this.validateCurrentTab( Utils.delegate(this, "onShowTab1") );
	}
	
	this.onShowTab1 = function (result) {
		if ( result == 1 ) {
			_get("oeTabContent1").style.display = "block";
			_get("oeTabContent2").style.display = "none";
			_get("oeTabContent3").style.display = "none";
			
			this.onTabItemClicked( _get("oetab1") );
		}
		else {
			this.objectForm.validate();
		}
	}

	this.showTab2 = function () {
		this.validateCurrentTab( Utils.delegate(this, "onShowTab2") );
	}
	
	this.onShowTab2 = function (result) {
		if ( result == 1 ) {
			_get("oeTabContent1").style.display = "none";
			_get("oeTabContent2").style.display = "block";
			_get("oeTabContent3").style.display = "none";
			
			this.onTabItemClicked( _get("oetab2") );
		}
		else {
			this.objectForm.validate();
		}
	}

	this.showTab3 = function () {
		this.validateCurrentTab( Utils.delegate(this, "onShowTab3") );
	}
	
	this.onShowTab3 = function (result) {
		if ( result == 1 ) {
			_get("oeTabContent1").style.display = "none";
			_get("oeTabContent2").style.display = "none";
			_get("oeTabContent3").style.display = "block";
			
			this.onTabItemClicked( _get("oetab3") );
		}
		else {
			this.objectForm.validate();
		}
	}
	
	this.validateCurrentTab = function ( tabCb ) {
		if ( _get("oeTabContent1").style.display == "block" ) {
			var name = _get('objectname').value;
			var elem = _get("objectcategory");
			var category = elem.options[elem.selectedIndex].value;
			var lan = this.localization.getLan();
			var kommun = this.localization.getKommun();
			
			x_validate_tab1(name, category, lan, kommun, tabCb );
		}
		else if ( _get("oeTabContent2").style.display == "block" ) {
			var desc = _get('objectdesc').value;
		
			x_validate_tab2(desc, tabCb );
		}
		else if ( _get("oeTabContent3").style.display == "block" ) {
			var country = this.localization.getCountry();
			var street = _get('objectstreet').value;
			var postal = _get('objectpostal').value;
			var city = _get('objectcity').value;
			var phone = _get('objectphone').value;
			var lat = _get("objectlat").value;
			var lng = _get("objectlng").value;
			
			x_validate_tab3(country, street, postal, city, phone, lng, lat, tabCb );
		}
	}
	
	//
	//
	//
	this.onSend = function  (req) {
		this.clear();
		Map.removeAll();
		GMap.resetSetMarkerOnMapState();

		this.layout( Utils.xmlToObject(req.responseXML) );

		this.onTabItemClicked( _get("oetab"+this.pendingTabId) );
		
		_get("oeTabContent1").style.display = "none";
		_get("oeTabContent2").style.display = "none";
		_get("oeTabContent3").style.display = "none";
		_get("oeTabContent"+this.pendingTabId).style.display = "block";
		
		this.pendingTabId = "1";
	}
	
	this.objectForm = null;
	this.layout = function ( data ) {
		
		var t1 = _div("oeTabContent1", "objectEditorTabs");
		var t2 = _div("oeTabContent2", "objectEditorTabs");
		var t3 = _div("oeTabContent3", "objectEditorTabs");
		var bottom = _div("oeBottomContent");
		
		this.objectForm = new Form();
		this.objectForm.begin("objecteditform", this);
		
		//
		// TAB 1
		this.objectForm.openTag("", "formStyle formStyleLeftColumn");
		var nameInput = this.objectForm.insertText("objectname", "Namn/Rubrik*", data.name, 40, "validate_name");
		this.objectForm.insertSelect("objectcategory", "Kategori*", "validate_locked_list");
		t1.appendChild(this.objectForm.closeTag());
		
		this.objectForm.openTag("", "formStyle formStyleRightColumn");
		var lanSelect = this.objectForm.insertSelect("objectlan", "Län*", "validate_locked_list");
		this.objectForm.insertSelect("objectkommun", "Kommun", "validate_list");
		t1.appendChild(this.objectForm.closeTag());
		
		this.objectForm.openTag("", "formStyleSingleColumn");
		this.objectForm.insertElement( _span("<b>Markera på kartan</b>") );
		this.objectForm.insertElement( _p("Klicka på kartan för att markera ut positionen på stället du vill skapa. Är du inte nöjd med placeringen flyttar du enkelt på ikonen genom att dra och släppa.") );
		t1.appendChild(this.objectForm.closeTag());
		
		//
		// TAB 2
		this.objectForm.openTag("", "formStyle formStyleSingleColumn");
		var descTextare = this.objectForm.insertTextarea("objectdesc", "Beskrivning* ", data.description, 512, "validate_desc");
		t2.appendChild(this.objectForm.closeTag());
		
		this.objectForm.openTag("", "formStyle formStyleLeftColumn");
		this.objectForm.insertCustom( "Generella tags", _div("generalTags") );
		t2.appendChild(this.objectForm.closeTag());

		this.objectForm.openTag("", "formStyle formStyleRightColumn");
		this.objectForm.insertCustom( "Kategori tags", _div("categoryTags") );
		t2.appendChild(this.objectForm.closeTag());
		
		//
		// TAB 3
		this.objectForm.openTag("", "formStyle formStyleLeftColumn");
		var countrySelect = this.objectForm.insertSelect("objectcountry", "Land*", "validate_locked_list");
		var streetInput = this.objectForm.insertText("objectstreet", "Gatuadress", data.map_street, 60, "validate_street");
		var postalInput = this.objectForm.insertText("objectpostal", "Postnummer", data.map_postal, 10, "validate_postal");
		var cityInput = this.objectForm.insertText("objectcity", "Postort", data.map_city, 50, "validate_city");
		t3.appendChild(this.objectForm.closeTag());

		this.objectForm.openTag("", "formStyle formStyleRightColumn");
		var phoneInput = this.objectForm.insertText("objectphone", "Telefon", data.contactphone, 30, "validate_phone");

		var loc;
		if (data.map_loc_WGS84 && data.map_loc_WGS84 != "") {
			loc = String(data.map_loc_WGS84).split(';');
		}
		else {
			loc = new Array();
			loc[0] = 0;
			loc[1] = 0;
		}
		
		var lat = Utils.convertDDToDMS(loc[0]);
		var latInput = this.objectForm.insertText("objectlat", "Latitude (N)  (d,m,s)", lat.d+" "+lat.m+" "+lat.s, 40, "validate_coord");
		latInput.onchange = Utils.delegate(this, "latitudeChange");

		var lng = Utils.convertDDToDMS(loc[1]);
		var lngInput = this.objectForm.insertText("objectlng", "Longitude (E)  (d,m,s)", lng.d+" "+lng.m+" "+lng.s, 40, "validate_coord");
		lngInput.onchange = Utils.delegate(this, "longitudeChange");

		t3.appendChild(this.objectForm.closeTag());
		
		// 
		// BOTTOM
		this.objectForm.openTag("", "formStyle");
		this.objectForm.insertHidden("objectid", data.id);
		bottom.appendChild(this.objectForm.closeTag());

		if ( false && this.mapobjectid == -1 ) {
			this.objectForm.openTag("privateContainer", "formStyle");
			this.objectForm.insertCheckbox("objectprivate", "Lägg till som favorit på min karta", "1", false);
			bottom.appendChild(this.objectForm.closeTag());
		}
		
		this.objectForm.openTag("", "formStyle formStyleSingleColumn");
		this.objectForm.insertSubmit("objectsubmitbutton", "", Utils.delegate(this, "saveMapObject"));
		bottom.appendChild(this.objectForm.closeTag());
		
		this.objectForm.openTag("", "formStyle formStyleSingleColumn");
		this.objectForm.insertElement( _span("* = <i>obligatoriska fält</i>") );
		bottom.appendChild(this.objectForm.closeTag());

		
		//
		this.objectForm.root.appendChild( t1 );
		this.objectForm.root.appendChild( t2 );
		this.objectForm.root.appendChild( t3 );
		this.objectForm.root.appendChild( bottom );
		
		this.content.appendChild(this.objectForm.root);
		
		this.storedTagObjects = new Array();
		
		this.updateTags("generalTags",-1);
		this.updateTags("categoryTags",data.category);
		
		this.objectForm.onInputChange("objectdesc", 512);
		this.objectForm.fillSelect("objectcategory", "/service/category/", "", data.category, "Välj kategori", "onCategoryChanged" );
		
		this.localization = new Localization();
		this.localization.buildLocalizationList("objectcountry", "objectlan", "objectkommun", data.map_country, data.map_lan, data.map_kommun);
		this.localization.addEventListener( this.localization.EVENT_COUNTRY_CHANGED, Utils.delegate(this, "onLocalizationChanged") );
		this.localization.addEventListener( this.localization.EVENT_LAN_CHANGED, Utils.delegate(this, "onLocalizationChanged") );
		this.localization.addEventListener( this.localization.EVENT_KOMMUN_CHANGED, Utils.delegate(this, "onLocalizationChanged") );
		this.selectLocationOnMap();
	}
	
	//
	// CALLBACKS
	//
	this.onLocalizationChanged = function (evt) {
		GMap.searchLocation( this.localization.getSearchString(), 10);
	}
	
	this.onCategoryChanged = function (categoryid) {
		this.updateTags("categoryTags", categoryid);
	}
	
	this.tagClicked = function (tagId, categoryId) {
		// if this object isn't created yet then save then tags along with all the other data instead
		if (this.mapobjectid == -1) return;
		
		var checkbox = null;
		if (categoryId == -1)
			checkbox = _get("tag_c_"+tagId);
		else
			checkbox = _get("tag_"+categoryId+"_"+tagId);
		
		var a = "rem";
		if ( checkbox.checked || checkbox.checked == "checked" )
			a = "add";
		
		this.showSave();
		Application.send("/service/tags/", "a="+a+"&t="+tagId+"&m="+this.mapobjectid, Utils.delegate(this, "onTagClicked"));
	}
	
	this.onTagClicked = function (req) {
		this.hideSave();
	}
	
	this.editTag = function (tagId, categoryId) {
		this.dispatchEvent( {type:Application.EVENT_EDIT_TAG, catId:categoryId, tagId:tagId} );
	}
	
	//
	// TAGS
	//
	this.storedTagObjects = new Array();
	
	this.onNewTagAdded = function () {
		var category = -1;
		try {
			var elem = _get("objectcategory");
			category = elem.options[elem.selectedIndex].value;
		} catch (e) {
			category = -1;
		}

		this.updateTags("generalTags",-1);
		this.updateTags("categoryTags", category);
	}
	
	this.updateTags = function (id, category) {
		if ( category == undefined ) return;
		
		var tagListContainer = _get(id);
		Utils.removeChildrenFromNode(tagListContainer);
		tagListContainer.appendChild( _span("Laddar...") );
		
		Application.send("/service/tags/", "a=readedit&c="+category+"&m="+this.mapobjectid, Utils.delegate(this, "onUpdateTags", id, category));
	}
	
	this.onUpdateTags = function (id, category, req) {
		var data = Utils.xmlToObject(req.responseXML);
		var tagListContainer = _get(id);
		Utils.removeChildrenFromNode(tagListContainer);
		
		var tagList = _elem("ul", "", "objectEditorTagList");
		
		for ( _t in data.tags ) {
			var t = data.tags[_t];
			
			var ldiv = _div("", "objectEditorTagInput");
			var rdiv = _div("", "objectEditorTagTools");
			
			var callback = Utils.delegate(this, "tagClicked", t.id, t.category);
			var checkbox = _input("checkbox", "tag_"+ (t.category == -1?"c":t.category) +"_"+t.id, "", callback);
			checkbox.className = "formStyleCheckbox";
			ldiv.appendChild( checkbox );
			ldiv.appendChild( _span(t.name) );
			
			if ( data.moderator == 1 )
				rdiv.appendChild( _a('<img src="/g/icon_edit.gif" alt="Ändra tag" title="Ändra tag">', "tagToolLink", Utils.delegate(this, "editTag", t.id, t.category) ) );
			
			if ( t.selid != "" )
				checkbox.checked = "checked";
			
			var tagListElement = _elem("li");
			tagListElement.appendChild( rdiv );
			tagListElement.appendChild( ldiv );
			
			tagList.appendChild(tagListElement);
			
			this.storedTagObjects[this.storedTagObjects.length] = checkbox;
		}
		tagListContainer.appendChild(tagList);
		tagListContainer.appendChild( _a('<img src="/g/button_nytag_small.gif" width="34" height="13" alt="Skapa ny tag" label="Skapa ny tag">', "", Utils.delegate(this, "editTag", -1, category)) );
	}
	
	//
	// SUBMIT STUFF
	//
	this.saveMapObject = function () {
		var postData = "objectname=" + _get('objectname').value;
	
		var category = -1;
		try {
			var elem = _get("objectcategory");
			category = elem.options[elem.selectedIndex].value;
		} catch (e) {
			category = -1;
		}
		
		postData += "&objectcategory=" + category;
		postData += "&objectcountry=" + this.localization.getCountry();
		postData += "&objectlan=" + this.localization.getLan();
		postData += "&objectkommun=" + this.localization.getKommun();
		postData += "&objectcity=" + _get('objectcity').value;
		postData += "&objectpostal=" + _get('objectpostal').value;
		postData += "&objectstreet=" + _get('objectstreet').value;
		postData += "&objectstreetnumber=" + "";
		postData += "&objectphone=" + _get('objectphone').value;
		postData += "&objectdesc=" + _get('objectdesc').value;
		postData += "&objectid=" + _get('objectid').value;
		
		var myReg = /(\d+).(\d+).(\d+\.\d+|\d+)/;
		var latval = _get("objectlat").value;
		var lngval = _get("objectlng").value;
		if( latval != "" && latval.match(myReg) != null &&
			lngval != "" && lngval.match(myReg) != null ) {
			var tmp = latval.match(myReg);
			postData += "&objectlat=" + Utils.convertDMSToDD(tmp[1], tmp[2], tmp[3]);
			tmp = lngval.match(myReg);
			postData += "&objectlng=" + Utils.convertDMSToDD(tmp[1], tmp[2], tmp[3]);
		}
		else {
			postData += "&objectlat=0";
			postData += "&objectlngs=0";
		}
		
		if (_get('objectprivate'))
			postData += "&objectprivate=" + (_get('objectprivate').checked ? "true" : "false");

		//Build the tag post data
		if ( _get('objectid').value == -1 ) {
			var numtags = 0;
			for ( var i=0; i < this.storedTagObjects.length; ++i ) {
				var checkbox = this.storedTagObjects[i];
				if (checkbox) {
					if (checkbox.checked || checkbox.checked == "checked") {
						var id = checkbox.id.substr( checkbox.id.lastIndexOf("_")+1 );
						postData += "&tagid"+numtags+"="+id;
						++numtags;
					}
				}
			}
			postData += "&numtags="+numtags;
		}
		
		this.showSave();
		Application.send("/service/editmapobject/?a=save", postData, Utils.delegate(this, "onSaveMapObject"));
	}
	
	this.onSaveMapObject = function (req) {
		var data = Utils.xmlToObject( req.responseXML );
		this.hideSave();
		
		if ( data.validate == 0 ) {
			this.objectForm.validate();
		}
		else {
			_get('objectid').value = data.objectid;
			this.mapobjectid = _get('objectid').value;
			
			if ( _get("privateContainer") )
				_get("privateContainer").style.display = "none";
		}
	}
	
	//
	// MAP LOCATION SELECTION
	//
	this.selectLocationOnMap = function () {
		var p = null;
		var myReg = /(\d+).(\d+).(\d+\.\d+|\d+)/;
		var latval = _get("objectlat").value;
		var lngval = _get("objectlng").value;
		if( latval != "" && latval.match(myReg) != null &&
			lngval != "" && lngval.match(myReg) != null ) {
			p = new Object();
			var tmp = latval.match(myReg);
			p.lat = Utils.convertDMSToDD(tmp[1], tmp[2], tmp[3]);
			tmp = lngval.match(myReg);
			p.lng = Utils.convertDMSToDD(tmp[1], tmp[2], tmp[3]);
		}
		
		var _this = this;
		GMap.enterSetMarkerOnMapState( function (gmapLocation) {_this.onMapLocationSelected(gmapLocation);}, p );
		
		if ( this.Criteria.loc_WGS84 && this.Criteria.loc_zoom ) {
			var loc = String(this.Criteria.loc_WGS84).split(';');
			p = new Object();
			p.latitude = loc[0];
			p.longitude = loc[1];
			p.zoom = Number(this.Criteria.loc_zoom);
			GMap.gotoLocation( p );
		}
		else {
			GMap.searchLocation( this.localization.getSearchString(), 10);
		}
	}
	
	this.onMapLocationSelected = function (gmapLocation) {
		var lat = Utils.convertDDToDMS(gmapLocation.lat());
		var lng = Utils.convertDDToDMS(gmapLocation.lng());
		
		_get('objectlat').value = lat.d + " " + lat.m + " " +lat.s;
		_get('objectlng').value = lng.d + " " + lng.m + " " +lng.s;
	}
	
	this.latitudeChange = function () {
		Utils.convertDMSPaste("objectlat");
		this.updateSelectLocationMarker();
	}

	this.longitudeChange = function () {
		Utils.convertDMSPaste("objectlng");
		this.updateSelectLocationMarker();
	}
	
	this.updateSelectLocationMarker = function () {
		// If a marker already have been placed update its poistion	
		// otherwise enter select on map state
		if ( GMap.SMMarker ) {
			var p = null;
			var myReg = /(\d+).(\d+).(\d+\.\d+|\d+)/;
			var latval = _get("objectlat").value;
			var lngval = _get("objectlng").value;
			if( latval != "" && latval.match(myReg) != null &&
				lngval != "" && lngval.match(myReg) != null ) 
			{
				p = new Object();
				var tmp = latval.match(myReg);
				p.lat = Utils.convertDMSToDD(tmp[1], tmp[2], tmp[3]);
				tmp = lngval.match(myReg);
				p.lng = Utils.convertDMSToDD(tmp[1], tmp[2], tmp[3]);
				
				if ( Math.round(p.lat) != 0 && Math.round(p.lng) != 0 )
					GMap.onEnterSetMarkerOnMapState(null, new GLatLng(p.lat, p.lng));
			}		
		}
		else {
			this.selectLocationOnMap()
		}
	}
}
var ObjectEditor = new _ObjectEditor();

		
		// remote scripting library
		// (c) copyright 2005 modernmethod, inc
		var sajax_debug_mode = false;
		var sajax_request_type = "GET";
		var sajax_target_id = "";
		var sajax_failure_redirect = "";
		
		function sajax_debug(text) {
			if (sajax_debug_mode)
				alert(text);
		}
		
 		function sajax_init_object() {
 			sajax_debug("sajax_init_object() called..")
 			
 			var A;
 			
 			var msxmlhttp = new Array(
				'Msxml2.XMLHTTP.5.0',
				'Msxml2.XMLHTTP.4.0',
				'Msxml2.XMLHTTP.3.0',
				'Msxml2.XMLHTTP',
				'Microsoft.XMLHTTP');
			for (var i = 0; i < msxmlhttp.length; i++) {
				try {
					A = new ActiveXObject(msxmlhttp[i]);
				} catch (e) {
					A = null;
				}
			}
 			
			if(!A && typeof XMLHttpRequest != "undefined")
				A = new XMLHttpRequest();
			if (!A)
				sajax_debug("Could not create connection object.");
			return A;
		}
		
		var sajax_requests = new Array();
		
		function sajax_cancel() {
			for (var i = 0; i < sajax_requests.length; i++) 
				sajax_requests[i].abort();
		}
		
		function sajax_do_call(func_name, args) {
			var i, x, n;
			var uri;
			var post_data;
			var target_id;
			
			sajax_debug("in sajax_do_call().." + sajax_request_type + "/" + sajax_target_id);
			target_id = sajax_target_id;
			if (typeof(sajax_request_type) == "undefined" || sajax_request_type == "") 
				sajax_request_type = "GET";
			
			uri = "/service/validate/?a=validate";
			if (sajax_request_type == "GET") {
			
				if (uri.indexOf("?") == -1) 
					uri += "?rs=" + escape(func_name);
				else
					uri += "&rs=" + escape(func_name);
				uri += "&rst=" + escape(sajax_target_id);
				uri += "&rsrnd=" + new Date().getTime();
				
				for (i = 0; i < args.length-1; i++) 
					uri += "&rsargs[]=" + escape(args[i]);

				post_data = null;
			} 
			else if (sajax_request_type == "POST") {
				post_data = "rs=" + escape(func_name);
				post_data += "&rst=" + escape(sajax_target_id);
				post_data += "&rsrnd=" + new Date().getTime();
				
				for (i = 0; i < args.length-1; i++) 
					post_data = post_data + "&rsargs[]=" + escape(args[i]);
			}
			else {
				alert("Illegal request type: " + sajax_request_type);
			}
			
			x = sajax_init_object();
			if (x == null) {
				if (sajax_failure_redirect != "") {
					location.href = sajax_failure_redirect;
					return false;
				} else {
					sajax_debug("NULL sajax object for user agent:\n" + navigator.userAgent);
					return false;
				}
			} else {
				x.open(sajax_request_type, uri, true);
				// window.open(uri);
				
				sajax_requests[sajax_requests.length] = x;
				
				if (sajax_request_type == "POST") {
					x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
					x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
				}
			
				x.onreadystatechange = function() {
					if (x.readyState != 4) 
						return;

					sajax_debug("received " + x.responseText);
				
					var status;
					var data;
					var txt = x.responseText.replace(/^\s*|\s*$/g,"");
					status = txt.charAt(0);
					data = txt.substring(2);

					if (status == "") {
						// let's just assume this is a pre-response bailout and let it slide for now
					} else if (status == "-") 
						alert("Error: " + data);
					else {
						if (target_id != "") 
							document.getElementById(target_id).innerHTML = eval(data);
						else {
							try {
								var callback;
								var extra_data = false;
								if (typeof args[args.length-1] == "object") {
									callback = args[args.length-1].callback;
									extra_data = args[args.length-1].extra_data;
								} else {
									callback = args[args.length-1];
								}
								callback(eval(data), extra_data);
							} catch (e) {
								sajax_debug("Caught error " + e + ": Could not eval " + data );
							}
						}
					}
				}
			}
			
			sajax_debug(func_name + " uri = " + uri + "/post = " + post_data);
			x.send(post_data);
			sajax_debug(func_name + " waiting..");
			delete x;
			return true;
		}
		
				
		// wrapper for validate_name		
		function x_validate_name() {
			sajax_do_call("validate_name",
				x_validate_name.arguments);
		}
		
				
		// wrapper for validate_locked_list		
		function x_validate_locked_list() {
			sajax_do_call("validate_locked_list",
				x_validate_locked_list.arguments);
		}
		
				
		// wrapper for validate_list		
		function x_validate_list() {
			sajax_do_call("validate_list",
				x_validate_list.arguments);
		}
		
				
		// wrapper for validate_city		
		function x_validate_city() {
			sajax_do_call("validate_city",
				x_validate_city.arguments);
		}
		
				
		// wrapper for validate_postal		
		function x_validate_postal() {
			sajax_do_call("validate_postal",
				x_validate_postal.arguments);
		}
		
				
		// wrapper for validate_street		
		function x_validate_street() {
			sajax_do_call("validate_street",
				x_validate_street.arguments);
		}
		
				
		// wrapper for validate_streetnumber		
		function x_validate_streetnumber() {
			sajax_do_call("validate_streetnumber",
				x_validate_streetnumber.arguments);
		}
		
				
		// wrapper for validate_phone		
		function x_validate_phone() {
			sajax_do_call("validate_phone",
				x_validate_phone.arguments);
		}
		
				
		// wrapper for validate_desc		
		function x_validate_desc() {
			sajax_do_call("validate_desc",
				x_validate_desc.arguments);
		}
		
				
		// wrapper for validate_coord		
		function x_validate_coord() {
			sajax_do_call("validate_coord",
				x_validate_coord.arguments);
		}
		
				
		// wrapper for validate_tab1		
		function x_validate_tab1() {
			sajax_do_call("validate_tab1",
				x_validate_tab1.arguments);
		}
		
				
		// wrapper for validate_tab2		
		function x_validate_tab2() {
			sajax_do_call("validate_tab2",
				x_validate_tab2.arguments);
		}
		
				
		// wrapper for validate_tab3		
		function x_validate_tab3() {
			sajax_do_call("validate_tab3",
				x_validate_tab3.arguments);
		}
		
		
function _ProfileEditor() {
	this.is_initialized = false;
	
	this.construct = function() {
		var tabContent = _div("peTabContent");
		var menuContent = _elem("ul", "peTabMenu");
		_get("profileeditor").appendChild(menuContent);
		_get("profileeditor").appendChild(tabContent);
		
		TabModule.initialize(this, _get("profileeditor"), menuContent, tabContent);
		
		this.buildMenu();
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.showTab1();
	}
	
	//
	// TABS MENU
	//
	this.buildMenu = function () {
		var ul = _get("peTabMenu");
		
		ul.appendChild( this.createTabItem("Allmänt", "showTab1", true, "petab1", true) );
		ul.appendChild( this.createTabItem("Recensioner", "showTab2", false, "petab2", false) );
		ul.appendChild( this.createTabItem("Ställen", "showTab3", false, "petab3", false) );
		ul.appendChild( this.createTabItem("Vännerlista", "showTab4", false, "petab4", false) );
	}
	
	this.createTabItem = function (label, cb, selected, id, isfirst) {
		li = _elem("li");
		li.innerHTML = label;
		li.id = id;
		li.isfirst = isfirst;
		li.className = "tab_normal" + (isfirst ? " tab_first" : "");
		
		var _this = this
		li.onclick = function () { 
								try {_this[cb](); _this.onTabItemClicked(this);} 
								catch (e) {alert("tab item not implemented: " + e);}}
		li.onmouseover = function () {_this.onTabItemOver(this);}
		li.onmouseout = function () {_this.onTabItemOut(this);}
		li.itemSelected = false;
		
		if (selected ) {
			li.className = "tab_selected" + (isfirst ? " tab_first" : "");
			li.itemSelected = true;
			this.currentTabMenuItem = li;
		}
		
		return li;
	}	
	
	this.currentTabMenuItem = null;
	this.onTabItemClicked = function (item) {
		if ( this.currentTabMenuItem != null ) {
			this.currentTabMenuItem.className = "tab_normal" + (this.currentTabMenuItem.isfirst ? " tab_first" : "");
			this.currentTabMenuItem.itemSelected = false;
		}	
		
		item.className = "tab_selected" + (item.isfirst ? " tab_first" : "");
		item.itemSelected = true;
		this.currentTabMenuItem = item;
	}
	
	this.onTabItemOver = function (item) {
		if (item.itemSelected == false) item.className = "tab_over" + (item.isfirst ? " tab_first" : "");
	}
	
	this.onTabItemOut = function (item) {
		if (item.itemSelected == false) item.className = "tab_normal" + (item.isfirst ? " tab_first" : "");
	}
	
	this.showTab1 = function () {
		this.clear();
		this.send("/service/profilegeneral/?a=read", "", Utils.delegate(this, "showGeneralTab"));
	}

	this.showTab2 = function () {
		this.clear();
		this.send("/service/profilereview/", "", Utils.delegate(this, "showReviewsTab"));
	}

	this.showTab3 = function () {
		this.clear();
		this.send("/service/profileobjects/", "p=0", Utils.delegate(this, "showObjectTab"));
	}
	
	this.showTab4 = function () {
		this.clear();
		this.send("/service/contactlist/", "a=read", Utils.delegate(this, "showContactTab"));
	}
	
	//
	// Show general tab
	//
	this.showGeneralTab = function (req) {
		this.layoutGeneralTab( Utils.xmlToObject(req.responseXML) );
	}
	
	this.pgForm = null;
	this.layoutGeneralTab = function (data) {
		this.clear();
		
		this.pgForm = new Form();
		this.pgForm.begin("profileeditform", this);
		
		this.pgForm.openTag("", "formStyle formStyleLeftColumnWide");
		this.pgForm.insertElement( _h1("Personlig profil") );
		this.pgForm.insertElement( _span("Du har "+data.user.points+" jelpos") );
		this.pgForm.insertElement( _br() );
		this.pgForm.insertTextarea("profiledesc", "Presentation", data.user.personaldesc, 512, "validate_general_desc");
		this.pgForm.insertElement( _br() );
		this.pgForm.insertElement( _label("Din bild") );
		this.pgForm.insertElement( _br() );
		if ( data.user.imagename ) {
			var im = _a("", "", "", '/image_normal/'+data.user.imagename, "lightbox[profileimage]", data.user.alias);
			var img = _img("/image_thumb/"+data.user.imagename, "Bild", "", "", '.'+data.user.alias+'.', 'corner iradius5 ishadow20', "", function(){addCorners(this);});
			im.appendChild(img);
			this.pgForm.insertElement( im );
		}
		else
			this.pgForm.insertElement( _img("/g/icon_no_avatar.gif", "Bild", "", "", '.'+data.user.alias+'.', 'corner iradius5 ishadow20', "", function(){addCorners(this);}) );
		
		this.pgForm.insertElement( _br("clearLeft") );
		this.pgForm.insertElement( _a("Ändra bilden", "", Utils.delegate(this, "showUploadProfileImage")) );		
		
		this.pgForm.root.appendChild(this.pgForm.closeTag());
		
		if ( data.company ) {
			this.pgForm.openTag("", "formStyle formStyleRightColumn");
			this.pgForm.insertElement( _h1("Företags profil") );
			this.pgForm.insertElement( _br() );
			this.pgForm.insertText("contactperson", "Kontakt person", data.company.contactperson, 60, "validate_general_name");
			this.pgForm.insertText("contactemail", "Elektroniskt post adress", data.company.contactemail, 60, "validate_general_mail");
			this.pgForm.insertText("contactperson", "Telefon", data.company.contactphone, 40, "validate_general_phone");
			this.pgForm.root.appendChild(this.pgForm.closeTag());
		}
		
		this.pgForm.openTag("", "formStyle formStyleSingleColumn");
		this.pgForm.insertSubmit("profilesubmit", "", Utils.delegate(this, "saveProfile"));
		this.pgForm.root.appendChild(this.pgForm.closeTag());
		
		this.content.appendChild( this.pgForm.root );
		this.content.appendChild( _br() );
		
		refreshLightboxAnchors();
		
		this.pgForm.onInputChange("profiledesc", 512);
	}
	
	this.saveProfile = function () {
		var postData = "profiledesc=" + _get('profiledesc').value;
		if ( _get("contactperson") ) {
			postData += "&contactperson=" + _get('contactperson').value;
			postData += "&contactemail=" + _get('contactemail').value;
			postData += "&contactperson=" + _get('contactperson').value;
		}
		postData += "";
		
		this.showSave();
		Application.send("/service/profilegeneral/?a=save", postData, Utils.delegate(this, "onSaveProfile"));
	}
	
	this.onSaveProfile = function (req) {
		var data = Utils.xmlToObject( req.responseXML );
		this.hideSave();
		
		if ( data.validate == 0 ) {
			this.pgForm.validate();
		}
		else {
		}
	}
	
	this.showUploadProfileImage = function () {
		this.dispatchEvent( {type:Application.EVENT_UPLOAD_PROFILEIMAGE} );
	}

	//
	// Show reviews
	//
	this.showReviewsTab = function (req) {
		this.layoutReviewsTab( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layoutReviewsTab = function (data, xmlNode) {
		this.clear();
		
		if ( xmlNode.firstChild.childNodes.length == 0 ) {
			this.content.appendChild( _span("Du har inte skrivit några recensioner") );
		}
		else {
			var reviewList = _elem("ul", "", "reviewList");
			
			for ( var _r in data ) {
				var r = data[_r];
				var li = _elem('li', "", "reviewListItem");
				var leftPart = _elem("div", "", "reviewListColumnLeft");
				var rightPart = _elem("div", "", "reviewListColumnRight");
				
				leftPart.appendChild( _img("/g/review_bullet.gif") );
				
				// HEADING
				rightPart.appendChild(_h2(r.heading));
				// CONTENT
				rightPart.appendChild( _p(Utils.convertNewline(r.content)) );
				rightPart.appendChild( _span("<i>" +r.tstamp+"</i> "));
				if (r.moderator == 1)
					rightPart.appendChild( _a('<img style="margin:0px 0px 0px 3px;" src="/g/icon_trashbin.gif" alt="Ta bort" title="Ta bort" />', "", Utils.delegate(Application, "removeItem", r.id, "review")) );
				rightPart.appendChild( _br("clearLeft") );
				
				li.appendChild(leftPart);
				li.appendChild(rightPart);
				var img = _img("/g/review_spacer.gif");
				img.className = "reviewListSpacer";
				li.appendChild( img );
				li.appendChild( _br("clearLeft") );
				
				reviewList.appendChild(li);
			}
			
			this.content.appendChild(reviewList);
		}
	}

	//
	// Show places
	//
	this.showObjectTab = function (req) {
		this.layoutObjectTab( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layoutObjectTab = function (data) {
		this.clear();
		
		var objectList = _elem("ul", "", "categoryList");
		var maxObjectsPerList = Math.floor( Number(data.navsize)/2 );
		this.content.appendChild(objectList);
		var displayedItems = 0;
		var index = 1;

		// Layout the map objects
		for ( var _mo in data.mapobjects )
		{
			var mo = data.mapobjects[_mo];

			if (displayedItems++ == maxObjectsPerList)
			{
				objectList = _elem("ul", "", "categoryList");
				this.content.appendChild(objectList);
			}

			var object = _elem("li");

			object.appendChild( _a(index + ". " + mo.name, "object", Utils.delegate(this, "mapObjectClicked", mo.id, mo.name) ) );
			object.appendChild( _a('<img src="/g/icon_review.gif" alt="Recensera" label="Recensera" />', "", Utils.delegate(this, "onWriteReviewClicked", mo.id)) );
			if (mo.moderator == 1) {
				object.appendChild( _a('<img src="/g/icon_trashbin.gif" alt="Ta bort objektet" title="Ta bort objektet">', "", Utils.delegate(Application, "removeItem", mo.id, "mapobject")) );
			}

			object.appendChild( _br() );
			object.appendChild( _p( mo.desc, "", "" ) );
			var rating = Voting.buildCurrentRating(mo.avgscore, 13, "w");
			rating.className = "rating";
			object.appendChild( rating );			
			var reviewCount = _div("", "reviewCount");
			reviewCount.innerHTML = mo.numreview + " recensioner";
			object.appendChild( reviewCount );
			object.appendChild( _img("/g/separator.gif") );

			objectList.appendChild(object);
			
			++index;
		}
		
		this.content.appendChild( _br("clearLeft") );
		
		// Layout the navigation bar
		var navData = PageNavigation.calculate(Number(data.page)+1, Number(data.total), Number(data.navsize));
		for ( var i=0; i < navData.length; ++i ) {
			if ( navData[i].selected )
			{
				var navCurrentPage = _div("", "navCurrentPage");
				navCurrentPage.innerHTML = navData[i].label;
				this.content.appendChild(navCurrentPage);
			}
			else
				this.content.appendChild( _a( navData[i].label, "navLinkPage", Utils.delegate(this, "changeObjectPage", navData[i].pageid-1) ) );
		}
	}
	
	this.changeObjectPage = function (page) {
		this.send("/service/profileobjects/", "p="+page, Utils.delegate(this, "showObjectTab"));
	}
	
	this.onWriteReviewClicked = function (id) {
		this.dispatchEvent( {type:Application.EVENT_WRITE_REVIEW, id:id} );
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}

	//
	// Show contact list
	//
	this.showContactTab = function (req) {
		this.layoutContactTab( Utils.xmlToObject(req.responseXML) );
	}
	
	this.layoutContactTab = function (data) {
		this.clear();
		
		var table = _elem("table");
		table.id = "profilefriendstable";

		var r = table.insertRow(0); r.className = "msgrow";
		
		var c1 = r.insertCell(0); c1.className = "hcol";
		var c2 = r.insertCell(1); c2.className = "hcol";
		var c3 = r.insertCell(2); c3.className = "hcol";
		
		c1.appendChild(_span("<b>Alias</b>"));
		c2.appendChild(_span("<b>Email</b>"));
		c3.appendChild(_span("<b>Verktyg</b>"));
		
		var index = 1;
		for ( var _c in data ) {
			var c = data[_c];
			
			r = table.insertRow(index); r.className = "msgrow";
			
			c1 = r.insertCell(0); c1.className = "col";
			c2 = r.insertCell(1); c2.className = "col";
			c3 = r.insertCell(2); c3.className = "col";
			
			c1.appendChild(_a(c.alias, "", Utils.delegate(this, "showProfile", c.alias, c.contactid)));
			c2.appendChild(_span(c.loginemail));
			
			c3.appendChild( _a('<img src="/g/icon_mail.gif" alt="Skicka meddelande" label="Skicka meddelande">', "", Utils.delegate(this, "sendMessage", c.contactid, c.alias)) );
			c3.appendChild( _a('<img src="/g/icon_trashbin.gif" style="margin:0px 0px 0px 4px;" alt="Ta bort kontakt" title="Ta bort kontakt">', "", Utils.delegate(Application, "removeItem", c.id, "contact")));
						
			++index
		}
		this.content.appendChild(table);
	}
	
	this.showProfile = function ( alias, userid ) {
		Legend.appendLegend( {page:Application.PAGE_VIEWPROFILE, title:alias+"s profil"} );
		
		this.dispatchEvent( {type:ProfileView.EVENT_PROFILE_SELECTED, id:userid} );
		
		Application.navigate(Application.PAGE_VIEWPROFILE, userid);
	}
	
	this.sendMessage = function ( userid, useralias) {
		var evt = new Object();
		evt.type = MessageView.EVENT_SEND_MESSAGE;
		evt.subject = "";
		evt.recipients = [ {id:userid, alias:useralias, isemail:false} ];
		
		this.dispatchEvent( evt );
	}
}
var ProfileEditor = new _ProfileEditor();

		
		// wrapper for validate_name		
		function x_validate_name() {
			sajax_do_call("validate_name",
				x_validate_name.arguments);
		}
		
				
		// wrapper for validate_locked_list		
		function x_validate_locked_list() {
			sajax_do_call("validate_locked_list",
				x_validate_locked_list.arguments);
		}
		
				
		// wrapper for validate_list		
		function x_validate_list() {
			sajax_do_call("validate_list",
				x_validate_list.arguments);
		}
		
				
		// wrapper for validate_city		
		function x_validate_city() {
			sajax_do_call("validate_city",
				x_validate_city.arguments);
		}
		
				
		// wrapper for validate_postal		
		function x_validate_postal() {
			sajax_do_call("validate_postal",
				x_validate_postal.arguments);
		}
		
				
		// wrapper for validate_street		
		function x_validate_street() {
			sajax_do_call("validate_street",
				x_validate_street.arguments);
		}
		
				
		// wrapper for validate_streetnumber		
		function x_validate_streetnumber() {
			sajax_do_call("validate_streetnumber",
				x_validate_streetnumber.arguments);
		}
		
				
		// wrapper for validate_phone		
		function x_validate_phone() {
			sajax_do_call("validate_phone",
				x_validate_phone.arguments);
		}
		
				
		// wrapper for validate_desc		
		function x_validate_desc() {
			sajax_do_call("validate_desc",
				x_validate_desc.arguments);
		}
		
				
		// wrapper for validate_coord		
		function x_validate_coord() {
			sajax_do_call("validate_coord",
				x_validate_coord.arguments);
		}
		
				
		// wrapper for validate_tab1		
		function x_validate_tab1() {
			sajax_do_call("validate_tab1",
				x_validate_tab1.arguments);
		}
		
				
		// wrapper for validate_tab2		
		function x_validate_tab2() {
			sajax_do_call("validate_tab2",
				x_validate_tab2.arguments);
		}
		
				
		// wrapper for validate_tab3		
		function x_validate_tab3() {
			sajax_do_call("validate_tab3",
				x_validate_tab3.arguments);
		}
		
				
		// wrapper for validate_general_desc		
		function x_validate_general_desc() {
			sajax_do_call("validate_general_desc",
				x_validate_general_desc.arguments);
		}
		
				
		// wrapper for validate_general_name		
		function x_validate_general_name() {
			sajax_do_call("validate_general_name",
				x_validate_general_name.arguments);
		}
		
				
		// wrapper for validate_general_mail		
		function x_validate_general_mail() {
			sajax_do_call("validate_general_mail",
				x_validate_general_mail.arguments);
		}
		
				
		// wrapper for validate_general_phone		
		function x_validate_general_phone() {
			sajax_do_call("validate_general_phone",
				x_validate_general_phone.arguments);
		}
		
		function _ProfileView () {
	this.EVENT_PROFILE_SELECTED = "pvsel";
	
	this.is_initialized = false;
	this.userid = -1;
	
	this.construct = function() {
		var topContent = _div("pvTabTopContent");
		var tabContent = _div("pvTabContent");
		var menuContent = _elem("ul", "pvTabMenu");
		
		_get("profileview").appendChild(topContent);
		_get("profileview").appendChild(menuContent);
		_get("profileview").appendChild(tabContent);
		
		TabModule.initialize(this, _get("profileview"), menuContent, tabContent);

		ProfileEditor.addEventListener(this.EVENT_PROFILE_SELECTED, Utils.delegate(this, "onProfileSelected"));
		MessageView.addEventListener(this.EVENT_PROFILE_SELECTED, Utils.delegate(this, "onProfileSelected"));
		ObjectView.addEventListener(this.EVENT_PROFILE_SELECTED, Utils.delegate(this, "onProfileSelected"));
		RecentView.addEventListener(this.EVENT_PROFILE_SELECTED, Utils.delegate(this, "onProfileSelected"));
		this.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(ObjectView, "onObjectSelected"));
		this.addEventListener( MessageView.EVENT_SEND_MESSAGE, Utils.delegate(MessageView, "onSendMessageEvent") );
		
		this.buildMenu();
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.showProfileInformation();
	}
	
	this.onProfileSelected = function  (evt) {
		this.userid = evt.id;
		this.setRequestData("uid=" + this.userid);
	}
	
	//
	// TABS MENU
	//
	this.buildMenu = function () {
		var ul = _get("pvTabMenu");
		
		ul.appendChild( this.createTabItem("Recensioner", "showTab1", true, "pvtab1", true) );
		ul.appendChild( this.createTabItem("Ställen", "showTab2", false, "pvtab2", false) );
	}
	
	this.createTabItem = function (label, cb, selected, id, isfirst) {
		li = _elem("li");
		li.innerHTML = label;
		li.id = id;
		li.isfirst = isfirst;
		li.className = "tab_normal" + (isfirst ? " tab_first" : "");
		
		var _this = this
		li.onclick = function () { 
								try {_this[cb](); _this.onTabItemClicked(this);} 
								catch (e) {alert("tab item not implemented: " + e);}}
		li.onmouseover = function () {_this.onTabItemOver(this);}
		li.onmouseout = function () {_this.onTabItemOut(this);}
		li.itemSelected = false;
		
		if (selected ) {
			li.className = "tab_selected" + (isfirst ? " tab_first" : "");
			li.itemSelected = true;
			this.currentTabMenuItem = li;
		}
		
		return li;
	}	
	
	this.currentTabMenuItem = null;
	this.onTabItemClicked = function (item) {
		if ( this.currentTabMenuItem != null ) {
			this.currentTabMenuItem.className = "tab_normal" + (this.currentTabMenuItem.isfirst ? " tab_first" : "");
			this.currentTabMenuItem.itemSelected = false;
		}	
		
		item.className = "tab_selected" + (item.isfirst ? " tab_first" : "");
		item.itemSelected = true;
		this.currentTabMenuItem = item;
	}
	
	this.onTabItemOver = function (item) {
		if (item.itemSelected == false) item.className = "tab_over" + (item.isfirst ? " tab_first" : "");
	}
	
	this.onTabItemOut = function (item) {
		if (item.itemSelected == false) item.className = "tab_normal" + (item.isfirst ? " tab_first" : "");
	}
	
	this.showTab1 = function () {
		this.clear();
		//this.showProfileInformation();
		Application.send("/service/profilereview/", "uid=" + this.userid, Utils.delegate(this, "showReviewsTab"));
	}

	this.showTab2 = function () {
		this.clear();
		//this.showProfileInformation();
		Application.send("/service/profileobjects/", "p=0&uid=" + this.userid, Utils.delegate(this, "showObjectTab"));
	}
	
	//
	// Show top content
	//
	this.showProfileInformation = function () {
		Utils.removeChildrenFromNode( _get("pvTabTopContent") );
		
		this.send("/service/viewprofile/", "uid=" + this.userid, Utils.delegate(this, "layoutProfileInformation"));
	}
	
	this.layoutProfileInformation = function (req) {
		var data = Utils.xmlToObject(req.responseXML);
		var container = _get("pvTabTopContent");

		Utils.removeChildrenFromNode( container );
		
		var imgDiv = _div("", "pvInfoContainer");
		if ( data.imagename ) {
			var im = _a("", "", "", '/image_normal/'+data.imagename, "lightbox[profileimage]", data.alias);
			var img = _img("/image_thumb/"+data.imagename, "Bild", "", "", '.'+data.alias+'.', 'corner iradius5 ishadow20', "", function(){addCorners(this);});
			im.appendChild(img);
			imgDiv.appendChild(im);
		}
		else {
			imgDiv.appendChild( _img("/g/icon_no_avatar.gif", "Bild", "", "", '.'+data.alias+'.', 'corner iradius5 ishadow20', "", function(){addCorners(this);}) );
		}
		
		container.appendChild(imgDiv);
		
		var infoDiv = _div("", "pvInfoContainer");
		infoDiv.appendChild( _h2(data.alias) );
		infoDiv.appendChild( _span(data.points + " poäng") );		
		infoDiv.appendChild( _a('<img src="/g/icon_friend.gif" alt="Lägg till som vän" title="Lägg till som vän">', "", Utils.delegate(Application, "addUserToContactList", data.id)) );
		infoDiv.appendChild( _a('<img src="/g/icon_mail.gif" alt="Skicka meddelande" label="Skicka meddelande">', "", Utils.delegate(this, "sendMessage", data.id, data.alias)) )
		container.appendChild(infoDiv);

		container.appendChild( _br("clearLeft") );
		container.appendChild( _p(data.personaldesc) );
		
		refreshLightboxAnchors();
		
		this.showTab1();
	}
	
	this.sendMessage = function ( userid, useralias) {
		var evt = new Object();
		evt.type = MessageView.EVENT_SEND_MESSAGE;
		evt.subject = "";
		evt.recipients = [ {id:userid, alias:useralias, isemail:false} ];
		
		this.dispatchEvent( evt );
	}
	
	//
	// Show reviews
	//
	this.showReviewsTab = function (req) {
		this.layoutReviewsTab( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layoutReviewsTab = function (data, xmlNode) {
		this.clear();
		
		if ( xmlNode.firstChild.childNodes.length == 0 ) {
			this.content.appendChild( _span("Användaren har inte skrivit några recensioner än.") );
		}
		else {
			var reviewList = _elem("ul", "", "reviewList");
			
			for ( var _r in data ) {
				var r = data[_r];
				var li = _elem('li', "", "reviewListItem");
				var leftPart = _elem("div", "", "reviewListColumnLeft");
				var rightPart = _elem("div", "", "reviewListColumnRight");
				
				leftPart.appendChild( _img("/g/review_bullet.gif") );
				
				// HEADING
				rightPart.appendChild( _a(r.heading, "object", Utils.delegate(this, "mapObjectClicked", r.objectid, r.name) ) );
				// CONTENT
				rightPart.appendChild( _p(Utils.convertNewline(r.content)) );
				rightPart.appendChild( _span("<i>" +r.tstamp+"</i> "));
				rightPart.appendChild( _br("clearLeft") );
				
				li.appendChild(leftPart);
				li.appendChild(rightPart);
				var img = _img("/g/review_spacer.gif");
				img.className = "reviewListSpacer";
				li.appendChild( img );
				li.appendChild( _br("clearLeft") );
				
				reviewList.appendChild(li);
			}
			
			this.content.appendChild(reviewList);
		}
	}

	//
	// Show places
	//
	this.showObjectTab = function (req) {
		this.layoutObjectTab( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layoutObjectTab = function (data) {
		this.clear();
		
		var objectList = _elem("ul", "", "categoryList");
		var maxObjectsPerList = Math.floor( Number(data.navsize)/2 );
		this.content.appendChild(objectList);
		var displayedItems = 0;
		var index = 1;

		// Layout the map objects
		for ( var _mo in data.mapobjects )
		{
			var mo = data.mapobjects[_mo];

			if (displayedItems++ == maxObjectsPerList)
			{
				objectList = _elem("ul", "", "categoryList");
				this.content.appendChild(objectList);
			}

			var object = _elem("li");

			object.appendChild( _a(index + ". " + mo.name, "object", Utils.delegate(this, "mapObjectClicked", mo.id, mo.name) ) );
			object.appendChild( _a('<img src="/g/icon_review.gif" alt="Recensera" label="Recensera" />', "", Utils.delegate(this, "onWriteReviewClicked", mo.id)) );
	
			object.appendChild( _br() );
			object.appendChild( _p( mo.desc, "", "" ) );
			var rating = Voting.buildCurrentRating(mo.avgscore, 13, "w");
			rating.className = "rating";
			object.appendChild( rating );			
			var reviewCount = _div("", "reviewCount");
			reviewCount.innerHTML = mo.numreview + " recensioner";
			object.appendChild( reviewCount );
			object.appendChild( _img("/g/separator.gif") );

			objectList.appendChild(object);
			
			++index;
		}
		
		this.content.appendChild( _br("clearLeft") );
		
		// Layout the navigation bar
		var navData = PageNavigation.calculate(Number(data.page)+1, Number(data.total), Number(data.navsize));
		for ( var i=0; i < navData.length; ++i ) {
			if ( navData[i].selected )
			{
				var navCurrentPage = _div("", "navCurrentPage");
				navCurrentPage.innerHTML = navData[i].label;
				this.content.appendChild(navCurrentPage);
			}
			else
				this.content.appendChild( _a( navData[i].label, "navLinkPage", Utils.delegate(this, "changeObjectPage", navData[i].pageid-1) ) );
		}
	}
	
	this.changeObjectPage = function (page) {
		this.send("/service/profileobjects/", "p="+page+"&uid=" + this.userid, Utils.delegate(this, "showObjectTab"));
	}
	
	this.onWriteReviewClicked = function (id) {
		this.dispatchEvent( {type:Application.EVENT_WRITE_REVIEW, id:id} );
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
}

var ProfileView = new _ProfileView();
function _MessageView () {
	this.EVENT_SEND_MESSAGE = "sendmsg";
	
	this.is_initialized = false;
	
	this.construct = function() {
		var tabContent = _div("msgTabContent");
		var menuContent = _elem("ul", "msgTabMenu");
		_get("messageview").appendChild(menuContent);
		_get("messageview").appendChild(tabContent);
		
		TabModule.initialize(this, _get("messageview"), menuContent, tabContent);
		
		ProfileEditor.addEventListener( this.EVENT_SEND_MESSAGE, Utils.delegate(this, "onSendMessageEvent") );
		ObjectView.addEventListener( this.EVENT_SEND_MESSAGE, Utils.delegate(this, "onSendMessageEvent") );
		this.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(ObjectView, "onObjectSelected"));
		
		this.buildMenu();
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.showTab1();
	}
	
	//
	// TABS MENU
	//
	this.buildMenu = function () {
		var ul = _get("msgTabMenu");
		
		ul.appendChild( this.createTabItem("Inkorg", "showTab1", true, "msgtab1", true) );
		ul.appendChild( this.createTabItem("Utkorg", "showTab2", false, "msgtab2", false) );
		ul.appendChild( this.createTabItem("Skicka", "showTab3", false, "msgtab3", false) );
	}
	
	this.createTabItem = function (label, cb, selected, id, isfirst) {
		li = _elem("li");
		li.innerHTML = label;
		li.id = id;
		li.isfirst = isfirst;
		li.className = "tab_normal" + (isfirst ? " tab_first" : "");
		
		var _this = this
		li.onclick = function () { 
								try {_this[cb](); _this.onTabItemClicked(this);} 
								catch (e) {alert("tab item not implemented: " + e);}}
		li.onmouseover = function () {_this.onTabItemOver(this);}
		li.onmouseout = function () {_this.onTabItemOut(this);}
		li.itemSelected = false;
		
		if (selected ) {
			li.className = "tab_selected" + (isfirst ? " tab_first" : "");
			li.itemSelected = true;
			this.currentTabMenuItem = li;
		}
		
		return li;
	}	
	
	this.currentTabMenuItem = null;
	this.onTabItemClicked = function (item) {
		if ( this.currentTabMenuItem != null ) {
			this.currentTabMenuItem.className = "tab_normal" + (this.currentTabMenuItem.isfirst ? " tab_first" : "");
			this.currentTabMenuItem.itemSelected = false;
		}	
		
		item.className = "tab_selected" + (item.isfirst ? " tab_first" : "");
		item.itemSelected = true;
		this.currentTabMenuItem = item;
	}
	
	this.onTabItemOver = function (item) {
		if (item.itemSelected == false) item.className = "tab_over" + (item.isfirst ? " tab_first" : "");
	}
	
	this.onTabItemOut = function (item) {
		if (item.itemSelected == false) item.className = "tab_normal" + (item.isfirst ? " tab_first" : "");
	}
	
	this.showTab1 = function () {
		this.clear();
		this.send("/service/message/?a=inbox", "", Utils.delegate(this, "showInbox") );
	}

	this.showTab2 = function () {
		this.clear();
		this.send("/service/message/?a=outbox", "", Utils.delegate(this, "showOutbox") );
	}

	this.showTab3 = function () {
		this.clear();
		this.showSend();
	}
	
	//
	// Events
	//
	this.onSendMessageEvent = function (evt) {
		if ( !Application.checkLogin(true) ) return;
		
		this.is_initialized = true;
		
		// Setup the send info
		this.layoutSend(evt.subject, evt.recipients, evt.attachment);
		
		// Navigate here		
		Legend.appendLegend( {page:Application.PAGE_VIEWMESSAGE, title:"Meddelande"} );
		Application.navigate(Application.PAGE_VIEWMESSAGE);
	}
	
	//
	// INBOX 
	//
	this.showInbox = function (req) {
		this.layoutInbox( Utils.xmlToObject(req.responseXML) );
	}
	
	this.openIndex = -1;
	this.layoutInbox = function (data) {
		this.clear();
		
		var table = _elem("table");
		table.id = "msginboxtable";

		var r = table.insertRow(0);
		
		var c1 = r.insertCell(0); c1.className = "hcol";
		var c2 = r.insertCell(1); c2.className = "hcol";
		var c3 = r.insertCell(2); c3.className = "hcol";
		
		c1.appendChild(_span("<b>Rubrik</b>"));
		c2.appendChild(_span("<b>Avsändare</b>"));
		c3.appendChild(_span("<b>Datum</b>"));
		
		var index = 1;
		for ( var _m in data ) {
			var m = data[_m];
			r = table.insertRow(index); r.className = "msgrow";
			
			c1 = r.insertCell(0); c1.className = "col";
			c2 = r.insertCell(1); c2.className = "col";
			c3 = r.insertCell(2); c3.className = "col";
			
			c1.appendChild( _a(m.subject, "", Utils.delegate(this, "openMail", m.id, index+1)) );
			c2.appendChild( _span(m.alias) );
			c3.appendChild( _span(m.sentdate) );
			
			++index
		}
		
		this.openIndex = -1;
		
		this.content.appendChild(table);
	}
	
	this.openIndex = -1;
	this.openMail = function ( mailid, index ) {
		if (this.openIndex != -1) {
			var table = _get("msginboxtable");
			table.deleteRow( this.openIndex );
		}
		
		this.openIndex = index;
		
		Application.send("/service/message/?a=readmail", "id="+mailid, Utils.delegate(this, "onOpenMail") );
	}
	
	this.onOpenMail = function (req) {
		var data = Utils.xmlToObject( req.responseXML );
		
		var table = _get("msginboxtable");
		
		var r = table.insertRow(this.openIndex); r.className = "msgrow";
		var c = r.insertCell(0); c.className = "mailcontent";
		c.colSpan = 3;
		
		if ( data.type == 1 ) { // Add to contact list 
			this.openContactInviteMail(data, c);
		}
		else if ( data.type == 2 ) { // Mapobject tips
			this.openObjectTipsMail(data, c);
		}
		else { // Just a normal mail
			c.appendChild( _span(data.body) );
		}
		
		c.appendChild( _br() );
		c.appendChild( _input("button", "mailreplybutton", "", Utils.delegate(this, "replyClicked", data.fromid, data.alias, data.subject) ) );
	}
	
	this.openObjectTipsMail = function (data, col) {
		var textDiv = _elem("div");
		textDiv.appendChild( _span(data.body) );
		col.appendChild( textDiv );
	
		col.appendChild( _br() );
		col.appendChild( _a(data.objectname, "", Utils.delegate(this, "mapObjectClicked", data.attachmentid, data.objectname)) );
	}

	this.openContactInviteMail = function (data, col) {
		var textDiv = _elem("div");
		textDiv.appendChild( _span(data.body) );
		col.appendChild( textDiv );
		
		if ( data.confirmed == 0 ) {
			col.appendChild( _input("button", "", "Godkänn", Utils.delegate(this, "sendContactAnswer", data.id, data.fromid, 1)) );
			col.appendChild( _input("button", "", "Godkänn inte", Utils.delegate(this, "sendContactAnswer", data.id, data.fromid, 0)) );
		}
		else {
			col.appendChild(_br());
			col.appendChild(_span("<i>Du har svarat</i>"));
		}
	}
	
	this.sendContactAnswer = function (mailid, userid, accept) {
		if (accept == 1) {
			Application.send("/service/contactlist/", "a=add&uid="+userid, Utils.delegate(this, "onSendContactAnswer") );
		}

		Application.send("/service/message/?a=confirm", "id="+mailid, null);
		
		this.openMail(mailid, this.openIndex);
	}
	
	this.onSendContactAnswer = function (req) {
		
	}

	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
	
	this.replyClicked = function (toid, alias, subject) {
		this.onTabItemClicked(_get("msgtab3"));
		var recipient = [ {id:toid, alias:alias, isemail:false} ];;
		this.layoutSend("Sv: " + subject, recipient);
	}
	
	//
	// OUTBOX 
	//
	this.showOutbox = function (req) {
		this.layoutOutbox( Utils.xmlToObject(req.responseXML) );
	}
	
	this.openOutboxIndex = -1;
	this.layoutOutbox = function (data) {
		this.clear();

		var table = _elem("table");
		table.id = "msgoutboxtable";

		var r = table.insertRow(0);;
		
		var c1 = r.insertCell(0); c1.className = "hcol";
		var c2 = r.insertCell(1); c2.className = "hcol";
		var c3 = r.insertCell(2); c3.className = "hcol";
		
		c1.appendChild(_span("<b>Rubrik</b>"));
		c2.appendChild(_span("<b>Mottagare</b>"));
		c3.appendChild(_span("<b>Datum</b>"));
		
		var index = 1;
		for (var _m in data) {
			var m = data[_m];
			r = table.insertRow(index); r.className = "msgrow";
			
			c1 = r.insertCell(0); c1.className = "col";
			c2 = r.insertCell(1); c2.className = "col";
			c3 = r.insertCell(2); c3.className = "col";
			
			c1.appendChild( _a(m.subject, "", Utils.delegate(this, "openOutboxMail", m.id, index+1)) );
			c2.appendChild( _span(m.alias) );
			c3.appendChild( _span(m.sentdate) );
			
			++index
		}
		
		this.openOutboxIndex = -1;
		
		this.content.appendChild(table);
	}
	
	this.openOutboxIndex = -1;
	this.openOutboxMail = function ( mailid, index ) {
		if (this.openOutboxIndex != -1) {
			var table = _get("msgoutboxtable");
			table.deleteRow( this.openOutboxIndex );
		}
		
		this.openOutboxIndex = index;
		
		Application.send("/service/message/?a=readmail", "id="+mailid, Utils.delegate(this, "onOpenOutboxMail") );
	}
	
	this.onOpenOutboxMail = function (req, data) {
		var data = Utils.xmlToObject( req.responseXML );
		
		var table = _get("msgoutboxtable");
		
		var r = table.insertRow(this.openOutboxIndex); r.className = "msgrow";
		var c = r.insertCell(0); c.className = "mailcontent";
		c.colSpan = 3;
		
		c.appendChild( _span(data.body) );
	}
	
	//
	// SEND 
	//
	this.showSend = function () {
		this.layoutSend("");	
	}

	this.sendForm = null;
	this.useEmail = false;
	this.layoutSend = function (subject, recipients, attachment) {
		this.clear();
		
		this.sendForm = new Form();
		this.sendForm.begin("msgsendform", this);
		
		var msgContent = _div("msgSendContent");
		var msgRecipients = _div("msgSendRecipients");
		var msgContactList = _div("msgSendContactList");

		// Form
		this.sendForm.openTag("", "formStyle");
		this.sendForm.insertText("msgsubject", "Ämne", subject, 60, "validate_subject");
		this.sendForm.insertTextarea("msgbody", "Meddelande", "", 255, "validate_body");
		msgContent.appendChild(this.sendForm.closeTag());
		
		var attachmentDiv = _elem("div");
		if ( attachment ) {
			attachmentDiv.appendChild( _span("<b>Bifogat ställe:</b>") );
			attachmentDiv.appendChild( _br() );
			attachmentDiv.appendChild( _span(attachment.name) );
			attachmentDiv.appendChild( _input("hidden", "attachid", attachment.id) );
			attachmentDiv.appendChild( _input("hidden", "msgtype", 2) );
			
			this.useEmail = true;
		}
		else {
			attachmentDiv.appendChild( _input("hidden", "attachid", 0) );
			attachmentDiv.appendChild( _input("hidden", "msgtype", 0) );
			
			this.useEmail = false;
		}
		msgContent.appendChild(attachmentDiv);
		
		this.sendForm.openTag("", "formStyle");
		this.sendForm.insertSubmit("msgsendsubmit", "", Utils.delegate(this, "sendMessage"));
		msgContent.appendChild(this.sendForm.closeTag());
				
		// Recipient list
		msgRecipients.appendChild( _label("Mottagare:") );
		msgRecipients.appendChild( _br() );

		var recipientsList = _elem("ul");
		recipientsList.id = "recipientsList";
		
		msgRecipients.appendChild( recipientsList );
		
		// finish it all up
		msgContactList.appendChild( _label("Vänner:") );
		msgContactList.appendChild( _br() );		

		this.sendForm.root.appendChild(msgContent);
		this.sendForm.root.appendChild(msgRecipients);
		this.sendForm.root.appendChild(msgContactList);
		
		this.content.appendChild( this.sendForm.root );
		
		// contact list
		this.buildContactList();

		
		// add recipients
		this.recipientElements = new Object();
		this.recipientObjects = new Object();
		if (recipients) {
			for (var i=0; i<recipients.length; ++i) {
				var o = recipients[i];
				this.addRecipient( o.id, o.alias, o.isemail );
			}
		}
	}
	
	this.recipientElements = new Object();
	this.recipientObjects = new Object();
	this.addRecipient = function (id, alias, isemail) {
		if ( this.recipientObjects[id] != null ) return;
		
		var li = _elem("li");
		
		var aliasDiv = _elem("div", "", "contantAliasRow");
		var toolsDiv = _elem("div", "", "contantToolsRow");
		
		toolsDiv.appendChild( _a('<img src="/g/icon_trashbin.gif" alt="Ta bort mottagare" title="Ta bort mottagare">', "", Utils.delegate(this, "removeRecipient", id)) );
		aliasDiv.appendChild( _span(alias) );
		
		li.appendChild(toolsDiv);
		li.appendChild(aliasDiv);
		
		this.recipientElements[id] = li;
		this.recipientObjects[id] = {id:id, alias:alias, isemail:isemail};
		_get("recipientsList").appendChild(li);
	}
	
	this.addEmailRecipient = function () {
		var mail = _get("msgemail").value;
		if ( Utils.validateEmail( mail) )
			this.addRecipient(mail, mail, true);
		else
			alert( mail + " är ingen giltig epost" );
	}
	
	this.removeRecipient = function (id) {
		if (this.recipientElements[id]) {
			_get("recipientsList").removeChild(this.recipientElements[id]);
			this.recipientElements[id] = null;
			this.recipientObjects[id] = null;
		}
	}
	
	this.getRecipients = function () {
		var retval = new Array();
		for ( var s in this.recipientObjects ) {
			if ( this.recipientObjects[s] != null )
				retval.push(this.recipientObjects[s]);
		}
		return retval;
	}
	
	this.buildContactList = function () {
		var rc = _get("msgSendContactList");
		var table = _elem("table");
		table.id = "msgcontacttable";
		var r = table.insertRow(0); r.className = "contactrow";
		var c = r.insertCell(0); c.className = "c_hcol";
		c.appendChild( _span( "Laddar..." ) );
	
		rc.appendChild(table);

		Application.send("/service/contactlist/", "a=read", Utils.delegate(this, "onBuildContactList") );
	}

	this.onBuildContactList = function (req) {
		var data = Utils.xmlToObject( req.responseXML );
		
		var table = _get("msgcontacttable");
		table.deleteRow(0);
		
		var r = table.insertRow(0); r.className = "contactrow";
		
		var c1 = r.insertCell(0); c1.className = "c_hcol";
		var c2 = r.insertCell(1); c2.className = "c_hcol";
		
		c1.appendChild(_span("<b>Alias</b>"));
		c2.appendChild(_span("<b>Verktyg</b>"));
		
		var index = 1;
		for ( var _c in data ) {
			var c = data[_c];
			r = table.insertRow(index); r.className = "contactrow";
			
			c1 = r.insertCell(0); c1.className = "c_col1";
			c2 = r.insertCell(1); c2.className = "c_col2";
			
			c1.appendChild( _a(c.alias, "", Utils.delegate(this, "showProfile", c.alias, c.contactid) ) );
			c2.appendChild( _a('Lägg till', "", Utils.delegate(this, "addRecipient", c.contactid, c.alias, false)) );
						
			++index
		}
		
		if ( this.useEmail ) {
			r = table.insertRow(index); r.className = "contactrow";
			c1 = r.insertCell(0); c1.className = "c_col1";
			c2 = r.insertCell(1); c2.className = "c_col2";

			formStyle = _span("", "", "formStyle");
			formStyle.appendChild( _label("Epost:") );
			formStyle.appendChild( _br() );
			formStyle.appendChild( _input("text", "msgemail", "", null, 60) );
			c1.appendChild(formStyle);
			c2.appendChild( _a('Lägg till', "", Utils.delegate(this, "addEmailRecipient")) );
		}
	}
	
	this.showProfile = function ( alias, userid ) {
		Legend.appendLegend( {page:Application.PAGE_VIEWPROFILE, title:alias+"s profil"} );
		
		this.dispatchEvent( {type:ProfileView.EVENT_PROFILE_SELECTED, id:userid} );
		
		Application.navigate(Application.PAGE_VIEWPROFILE, userid);
	}
	
	this.sendMessage = function () {
		var recipients = this.getRecipients();
		
		var postData = "&body=" + _get('msgbody').value;
		postData += "&subject=" + _get('msgsubject').value
		
		postData += "&numrecipients=" + recipients.length;
		for ( var i=0; i < recipients.length; ++i ) {
			var o = recipients[i];
			postData += "&rec"+i+"="+o.id+";"+o.alias+";"+o.isemail;
		}
		
		postData += "&attachid="+_get("attachid").value;
		postData += "&msgtype="+_get("msgtype").value;
		
		this.showSave();
		Application.send("/service/message/?a=send", postData, Utils.delegate(this, "onSendMessage"));
	}
	
	this.onSendMessage = function (req, data) {
		var data = Utils.xmlToObject( req.responseXML );
		this.hideSave();
		
		if ( data.validate == 0 ) {
			var recipients = this.getRecipients();
			if (recipients.length == 0) {
				Application.alert("Fel", "Du måste ha minst en mottagare");
			}
			else {
				this.sendForm.validate();
				this.validate_recipients();
			}
		}
		else {
			Application.alert("Klar!", "Skickat!");
					
			// Clear the recipients
			this.layoutSend("");
		}
	}
	
	// Validation methods

	// this is not exposed to php, wrapper for validate_recipient
	this.validate_recipients = function() {
		for ( var _s in this.recipientObjects ) {
			var s = this.recipientObjects[_s];
			this.validate_recipient( s.id, s.alias, s.isemail );
		}
	}
	
	this.validate_recipient = function (recipientId, alias, email) {
		x_validate_recipient(recipientId, alias, email, Utils.delegate(this, "on_validate_recipient", recipientId));
	}
	this.on_validate_recipient = function (result, recipientId) {
		if ( result == 1 ) recipientElements[recipientId].className = "";
		else recipientElements[recipientId].className = "inputError";
	}

}

var MessageView = new _MessageView();

		
		// wrapper for validate_name		
		function x_validate_name() {
			sajax_do_call("validate_name",
				x_validate_name.arguments);
		}
		
				
		// wrapper for validate_locked_list		
		function x_validate_locked_list() {
			sajax_do_call("validate_locked_list",
				x_validate_locked_list.arguments);
		}
		
				
		// wrapper for validate_list		
		function x_validate_list() {
			sajax_do_call("validate_list",
				x_validate_list.arguments);
		}
		
				
		// wrapper for validate_city		
		function x_validate_city() {
			sajax_do_call("validate_city",
				x_validate_city.arguments);
		}
		
				
		// wrapper for validate_postal		
		function x_validate_postal() {
			sajax_do_call("validate_postal",
				x_validate_postal.arguments);
		}
		
				
		// wrapper for validate_street		
		function x_validate_street() {
			sajax_do_call("validate_street",
				x_validate_street.arguments);
		}
		
				
		// wrapper for validate_streetnumber		
		function x_validate_streetnumber() {
			sajax_do_call("validate_streetnumber",
				x_validate_streetnumber.arguments);
		}
		
				
		// wrapper for validate_phone		
		function x_validate_phone() {
			sajax_do_call("validate_phone",
				x_validate_phone.arguments);
		}
		
				
		// wrapper for validate_desc		
		function x_validate_desc() {
			sajax_do_call("validate_desc",
				x_validate_desc.arguments);
		}
		
				
		// wrapper for validate_coord		
		function x_validate_coord() {
			sajax_do_call("validate_coord",
				x_validate_coord.arguments);
		}
		
				
		// wrapper for validate_tab1		
		function x_validate_tab1() {
			sajax_do_call("validate_tab1",
				x_validate_tab1.arguments);
		}
		
				
		// wrapper for validate_tab2		
		function x_validate_tab2() {
			sajax_do_call("validate_tab2",
				x_validate_tab2.arguments);
		}
		
				
		// wrapper for validate_tab3		
		function x_validate_tab3() {
			sajax_do_call("validate_tab3",
				x_validate_tab3.arguments);
		}
		
				
		// wrapper for validate_general_desc		
		function x_validate_general_desc() {
			sajax_do_call("validate_general_desc",
				x_validate_general_desc.arguments);
		}
		
				
		// wrapper for validate_general_name		
		function x_validate_general_name() {
			sajax_do_call("validate_general_name",
				x_validate_general_name.arguments);
		}
		
				
		// wrapper for validate_general_mail		
		function x_validate_general_mail() {
			sajax_do_call("validate_general_mail",
				x_validate_general_mail.arguments);
		}
		
				
		// wrapper for validate_general_phone		
		function x_validate_general_phone() {
			sajax_do_call("validate_general_phone",
				x_validate_general_phone.arguments);
		}
		
				
		// wrapper for validate_subject		
		function x_validate_subject() {
			sajax_do_call("validate_subject",
				x_validate_subject.arguments);
		}
		
				
		// wrapper for validate_body		
		function x_validate_body() {
			sajax_do_call("validate_body",
				x_validate_body.arguments);
		}
		
				
		// wrapper for validate_recipient		
		function x_validate_recipient() {
			sajax_do_call("validate_recipient",
				x_validate_recipient.arguments);
		}
		
		function _ContentView () {
	this.EVENT_SET_CONTENT = "setcontent";
	
	this.is_initialized = false;
	this.contentFile = "error";
	
	this.construct = function() {
		BasicModule.initialize(this, _get("contentview"));
		
		Menu.addEventListener(this.EVENT_SET_CONTENT, Utils.delegate(this, "onFileChange"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;

		this.send("/service/content/", "content="+this.contentFile, Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function (req) {
		this.content.innerHTML = req.responseText;
	}
	
	this.onFileChange = function (evt) {
		this.contentFile = evt.file;
		this.setRequestData( "content="+this.contentFile );
	}
}
var ContentView = new _ContentView();
function _RegisterUser() {
	this.construct = function() {
		BasicModule.initialize(this, _get("registeruserview"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.layout();
	}
	
	this.regForm = null;
	this.layout = function () {
		this.regForm = new Form();
		this.regForm.begin("reguserform", this);
		
		this.regForm.openTag("", "formStyle");
		
		var regemail = this.regForm.insertText("regemail", "E-post", "",60);
		this.regForm.insertElement( _span("", "regemail_msg") );
		this.regForm.insertElement( _br() );
		
		var regpw = this.regForm.insertPassword("regpw", "Lösenord", 32);
		var regpwrepeat = this.regForm.insertPassword("regpwrepeat", "Repetera lösenord", 32);
		this.regForm.insertElement( _span("", "regpw_msg") );
		this.regForm.insertElement( _br() );
		
		var regalias = this.regForm.insertText("regalias", "Alias", "", 20);
		this.regForm.insertElement( _span("", "regalias_msg") );
		this.regForm.insertElement( _br() );
		
		this.regForm.insertSubmit("regsubmitbutton", "", Utils.delegate(this, "submitRegistration"));
		this.regForm.root.appendChild( this.regForm.closeTag() );
		
		regemail.onblur = Utils.delegate(this, "validate_email");
		regalias.onblur = Utils.delegate(this, "validate_alias");
		regpw.onblur = regpwrepeat.onblur = Utils.delegate(this, "validate_pw");
		
		this.content.appendChild( this.regForm.root );	
	}
	
	this.submitRegistration = function () {
		var postData = "regemail=" + _get('regemail').value;
		postData += "&regpw=" + _get('regpw').value;
		postData += "&regpwrepeat=" + _get('regpwrepeat').value;
		postData += "&regalias=" + _get('regalias').value;
		
		this.showSave();
		Application.send("/service/register/?a=save", postData, Utils.delegate(this, "onSubmitRegistration"));
	}
	
	this.onSubmitRegistration = function (req) {
		var data = Utils.xmlToObject( req.responseXML );
		this.hideSave();
		
		if ( data.validate == 0 ) {
			this.pgForm.validate();
		}
		else {
			Utils.gotoLocation("/");
		}
	}
	
	//
	// validation
	//
	this.validate_email = function () {
		var value = _get("regemail").value;
		x_validate_email(value, Utils.delegate(this, "on_validate_email"));
	}	
	this.on_validate_email = function (result) {
		if ( result == 1 ) { 
			_get("regemail").className = "";
			_get("regemail_msg").innerHTML = "";
		}
		else {
			_get("regemail").className = "inputError";	
			if ( result == 2 )
				_get("regemail_msg").innerHTML = "Du måste ange en giltig epost";
			else if ( result == 3 )
				_get("regemail_msg").innerHTML = "Eposten används redan";
			else
				_get("regemail_msg").innerHTML = "";
		}
	}

	this.validate_alias = function () {
		var value = _get("regalias").value;
		x_validate_alias(value, Utils.delegate(this, "on_validate_alias"));
	}	
	this.on_validate_alias = function (result) {
		if ( result == 1 ) {
			_get("regalias").className = "";
			_get("regalias_msg").innerHTML = "";
		}
		else {
			_get("regalias").className = "inputError";	
			if ( result == 2 )
				_get("regalias_msg").innerHTML = "Ditt alias är upptaget";
			else
				_get("regalias_msg").innerHTML = "";
		}
	}

	this.validate_pw = function () {
		var pw = _get("regpw").value;
		var pwr = _get("regpwrepeat").value;
		
		x_validate_pw(pw,pwr, Utils.delegate(this, "on_validate_pw"));
	}
	
	this.on_validate_pw = function (result) {
		if ( result == 1 ){
			_get("regpw").className = "";
			_get("regpwrepeat").className = "";
			_get("regpw_msg").innerHTML = "";
		}
		else  {
			_get("regpw").className = "inputError";
			_get("regpwrepeat").className = "inputError";
			
			if ( result == 3 )
				_get("regpw_msg").innerHTML = "Lösenordet måste vara minst 5 tecken";
			else if ( result == 2 )
				_get("regpw_msg").innerHTML = "Lösenorden stämmer inte överens";
			else
				_get("regpw_msg").innerHTML = "";
		}
	}
}

var RegisterUser = new _RegisterUser();

		
		// wrapper for validate_name		
		function x_validate_name() {
			sajax_do_call("validate_name",
				x_validate_name.arguments);
		}
		
				
		// wrapper for validate_locked_list		
		function x_validate_locked_list() {
			sajax_do_call("validate_locked_list",
				x_validate_locked_list.arguments);
		}
		
				
		// wrapper for validate_list		
		function x_validate_list() {
			sajax_do_call("validate_list",
				x_validate_list.arguments);
		}
		
				
		// wrapper for validate_city		
		function x_validate_city() {
			sajax_do_call("validate_city",
				x_validate_city.arguments);
		}
		
				
		// wrapper for validate_postal		
		function x_validate_postal() {
			sajax_do_call("validate_postal",
				x_validate_postal.arguments);
		}
		
				
		// wrapper for validate_street		
		function x_validate_street() {
			sajax_do_call("validate_street",
				x_validate_street.arguments);
		}
		
				
		// wrapper for validate_streetnumber		
		function x_validate_streetnumber() {
			sajax_do_call("validate_streetnumber",
				x_validate_streetnumber.arguments);
		}
		
				
		// wrapper for validate_phone		
		function x_validate_phone() {
			sajax_do_call("validate_phone",
				x_validate_phone.arguments);
		}
		
				
		// wrapper for validate_desc		
		function x_validate_desc() {
			sajax_do_call("validate_desc",
				x_validate_desc.arguments);
		}
		
				
		// wrapper for validate_coord		
		function x_validate_coord() {
			sajax_do_call("validate_coord",
				x_validate_coord.arguments);
		}
		
				
		// wrapper for validate_tab1		
		function x_validate_tab1() {
			sajax_do_call("validate_tab1",
				x_validate_tab1.arguments);
		}
		
				
		// wrapper for validate_tab2		
		function x_validate_tab2() {
			sajax_do_call("validate_tab2",
				x_validate_tab2.arguments);
		}
		
				
		// wrapper for validate_tab3		
		function x_validate_tab3() {
			sajax_do_call("validate_tab3",
				x_validate_tab3.arguments);
		}
		
				
		// wrapper for validate_general_desc		
		function x_validate_general_desc() {
			sajax_do_call("validate_general_desc",
				x_validate_general_desc.arguments);
		}
		
				
		// wrapper for validate_general_name		
		function x_validate_general_name() {
			sajax_do_call("validate_general_name",
				x_validate_general_name.arguments);
		}
		
				
		// wrapper for validate_general_mail		
		function x_validate_general_mail() {
			sajax_do_call("validate_general_mail",
				x_validate_general_mail.arguments);
		}
		
				
		// wrapper for validate_general_phone		
		function x_validate_general_phone() {
			sajax_do_call("validate_general_phone",
				x_validate_general_phone.arguments);
		}
		
				
		// wrapper for validate_subject		
		function x_validate_subject() {
			sajax_do_call("validate_subject",
				x_validate_subject.arguments);
		}
		
				
		// wrapper for validate_body		
		function x_validate_body() {
			sajax_do_call("validate_body",
				x_validate_body.arguments);
		}
		
				
		// wrapper for validate_recipient		
		function x_validate_recipient() {
			sajax_do_call("validate_recipient",
				x_validate_recipient.arguments);
		}
		
				
		// wrapper for validate_email		
		function x_validate_email() {
			sajax_do_call("validate_email",
				x_validate_email.arguments);
		}
		
				
		// wrapper for validate_pw		
		function x_validate_pw() {
			sajax_do_call("validate_pw",
				x_validate_pw.arguments);
		}
		
				
		// wrapper for validate_alias		
		function x_validate_alias() {
			sajax_do_call("validate_alias",
				x_validate_alias.arguments);
		}
		
		function _SearchView () {
	this.is_initialized = false;
	this.query = "";
	this.tagid = "";
	
	this.construct = function() {
		BasicModule.initialize(this, _get("browsesearch"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		if ( this.query != "" )
			this.send("/service/search/", "query="+this.query+"&p=0", Utils.delegate(this, "onSend"));
		else
			this.send("/service/search/", "tagid="+this.tagid+"&p=0", Utils.delegate(this, "onSend"));
	}
	
	this.setQuery = function (query) {
		this.query = query;
		this.tagid = "";
		this.setRequestData("query="+this.query+"&p=0");	
	}
	
	this.setTagid = function (tagid) {
		this.query = "";
		this.tagid = tagid;
		this.setRequestData("tagid="+this.tagid+"&p=0");
	}
	
	//
	// LAYOUT STUFF
	// 	
	this.onSend = function( req ) {
		this.clear();
		Map.removeAll();
		this.layout( Utils.xmlToObject(req.responseXML), req.responseXML );
	}
	
	this.layout = function ( data, xmlNod )
	{
		// Show some search info
		var searchInfo = _elem("div");
		if ( data.results == 0 ) {
			if ( data.query != "" ) {
				searchInfo.appendChild( _span("Din sökning på: " + data.query + " gav inga träffar") );
			}
			else {
				searchInfo.appendChild( _span("Din sökning på: " + data.tagname + " gav inga träffar") );
			}
			this.content.appendChild(searchInfo);
			return;		
		}
		
		if ( data.query != "" ) {
			searchInfo.appendChild( _span("Din sökning på: " + data.query + " gav " + data.results + " träffar") );
		}
		else {
			searchInfo.appendChild( _span("Din sökning på: " + data.tagname + " gav " + data.results + " träffar") );
		}
		this.content.appendChild(searchInfo);
		
		// Show the search content
		var index = 1;
		var objectList = _elem("ul", "", "categoryList");
		var maxObjectsPerList = Math.floor( Number(data.navsize)/2 );
		this.content.appendChild(objectList);
		var displayedItems = 0;

		// Layout the map objects
		for ( var _mo in data.mapobjects )
		{
			var mo = data.mapobjects[_mo];

			if (displayedItems++ == maxObjectsPerList)
			{
				objectList = _elem("ul", "", "categoryList");
				this.content.appendChild(objectList);
			}

			var object = _elem("li");

			object.appendChild( _a(index + ". " + mo.name, "object", Utils.delegate(this, "mapObjectClicked", mo.id, mo.name) ) );
			object.appendChild( _a('<img src="/g/icon_review.gif" width="10" height="10" alt="Recensera" label="Recensera" />', "", Utils.delegate(this, "onWriteReviewClicked", mo.id)) );
			object.appendChild( _br() );
			object.appendChild( _p( mo.desc, "", "" ) );
			var rating = Voting.buildCurrentRating(mo.avgscore, 13, "w");
			rating.className = "rating";
			object.appendChild( rating );			
			var reviewCount = _div("", "reviewCount");
			reviewCount.innerHTML = mo.numreview + " recensioner";
			object.appendChild( reviewCount );
			object.appendChild( _img("/g/separator.gif") );

			objectList.appendChild(object);
			Map.addMapObject( mo, index );
			
			++index;
		}
		
		this.content.appendChild( _br("clearLeft") );
		
		// Layout the navigation bar
		var navData = PageNavigation.calculate(Number(data.page)+1, Number(data.total), Number(data.navsize));
		for ( var i=0; i < navData.length; ++i ) {
			if ( navData[i].selected )
			{
				var navCurrentPage = _div("", "navCurrentPage");
				navCurrentPage.innerHTML = navData[i].label;
				this.content.appendChild(navCurrentPage);
			}
			else
				this.content.appendChild( _a( navData[i].label, "navLinkPage", Utils.delegate(this, "changePage", navData[i].pageid-1) ) );
		}
	}
	
	this.changePage = function (p) {
		if ( this.query != "" )
			this.send("/service/search/", "query="+this.query+"&p="+p, Utils.delegate(this, "onSend"));
		else
			this.send("/service/search/", "tagid="+this.tagid+"&p="+p, Utils.delegate(this, "onSend"));
	}
	
	this.onWriteReviewClicked = function (id) {
		this.dispatchEvent( {type:Application.EVENT_WRITE_REVIEW, id:id} );
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
}
var SearchView = new _SearchView();﻿function _InFocus () {
	this.is_initialized = false;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("infocus"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/infocus/", "mid=96", Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function( req ) {
		this.clear();
		this.layout( Utils.xmlToObject(req.responseXML) );
	}
	
	this.layout = function ( data ) {

		var table = _elem("table");
		var tr = table.insertRow(0);
		var td0 = tr.insertCell(0);
		var td1 = tr.insertCell(1);
		
		var imglink = _a("", "infocusLink", "", "/image_normal/"+data.imagename, "lightbox", data.alias);
		var img = _img('/image_focus/'+data.imagename, "Bild", "", "", "", "corner iradius10 ishadow20", "focusImage");
		img.onload = function(){addCorners(img);};
		imglink.appendChild( img );
		td0.appendChild( imglink );
		
		td0.appendChild( _span(data.map_street) );
		td0.appendChild( _br() );
		td0.appendChild( _span(data.map_postal + " " + data.map_city) );
		td0.appendChild( _br() );
		td0.appendChild( _span(data.contactphone) );
		
		td0.appendChild( _br() );
		td0.appendChild( _a("Mer info", "infocusLink", Utils.delegate(this, "mapObjectClicked", data.id, data.name)) );
		
		td1.appendChild( _h1("Uteställe i fokus: ") );
		td1.appendChild( _a(data.name, "infocusH1Link", Utils.delegate(this, "mapObjectClicked", data.id, data.name)) );
		td1.appendChild( _br() );
		
		td1.appendChild( _p(data.description) );
		
		this.content.appendChild(table);
		td0.style.width = '171px';		
		
		refreshLightboxAnchors();
		//addCorners(); // TODO must wait until images have loaded!
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
}

var InFocus = new _InFocus();function _RecentView() {
	this.is_initialized = false;
	this.category = -1;
	this.regionId = 0;
	
	this.construct = function() {
		var content = _div("recentViewContent");
		var menu = _elem("ul", "recentViewMenu");
		_get("recentview").appendChild(menu);
		_get("recentview").appendChild(content);
		
		TabModule.initialize(this, _get("recentview"), menu, content);
		
		this.buildMenu();
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		
		this.send("/service/recent/", "action=objects", Utils.delegate(this, "onSend"));
	}
	
	//
	// TABS MENU
	//
	this.buildMenu = function () {
		var ul = _get("recentViewMenu");
		
		ul.appendChild( this.createTabItem("Nya ställen", "showObjects", true, "rvetab2", true) );
		ul.appendChild( this.createTabItem("Nya recensioner", "showReviews", false, "rvtab1", false) );
		ul.appendChild( this.createTabItem("Jelpo poäng", "showScore", false, "rvtab3", false) );
	}
	
	this.createTabItem = function (label, cb, selected, id, isfirst) {
		li = _elem("li");
		li.innerHTML = label;
		li.id = id;
		li.isfirst = isfirst;
		li.className = "tab_normal" + (isfirst ? " tab_first" : "");
		
		var _this = this
		li.onclick = function () { 
								try {_this[cb](); _this.onTabItemClicked(this);} 
								catch (e) {alert("tab item not implemented: " + e);}}
		li.onmouseover = function () {_this.onTabItemOver(this);}
		li.onmouseout = function () {_this.onTabItemOut(this);}
		li.itemSelected = false;
		
		if (selected ) {
			li.className = "tab_selected" + (isfirst ? " tab_first" : "");
			li.itemSelected = true;
			this.currentTabMenuItem = li;
		}
		
		return li;
	}	
	
	this.currentTabMenuItem = null;
	this.onTabItemClicked = function (item) {
		if ( this.currentTabMenuItem != null ) {
			this.currentTabMenuItem.className = "tab_normal" + (this.currentTabMenuItem.isfirst ? " tab_first" : "");
			this.currentTabMenuItem.itemSelected = false;
		}	
		
		item.className = "tab_selected" + (item.isfirst ? " tab_first" : "");
		item.itemSelected = true;
		this.currentTabMenuItem = item;
	}
	
	this.onTabItemOver = function (item) {
		if (item.itemSelected == false) item.className = "tab_over" + (item.isfirst ? " tab_first" : "");
	}
	
	this.onTabItemOut = function (item) {
		if (item.itemSelected == false) item.className = "tab_normal" + (item.isfirst ? " tab_first" : "");
	}
	
	/**
	 * Menu item callbacks
	 */
	this.showObjects = function () {
		this.clear();
		this.send("/service/recent/", "action=objects", Utils.delegate(this, "onSend"));
	}

	this.showReviews = function () {
		this.clear();
		this.send("/service/recent/", "action=review", Utils.delegate(this, "onSend"));
	}

	this.showUsers = function () {
		this.clear();
		this.send("/service/recent/", "action=users", Utils.delegate(this, "onSend"));
	}

	this.showScore = function () {
		this.clear();
		this.send("/service/recent/", "action=jelpos", Utils.delegate(this, "onSend"));
	}
	
	/**
	 * Layout the list
	 */	
	this.onSend = function( req ) {
		this.clear();
		this.layout( Utils.xmlToObject(req.responseXML) );
	}

	this.layout = function ( data ) {
		var ul = _elem("ul");
		
		// REVIEWS
		for ( var _d in data.reviews ) {
			var d = data.reviews[_d];
			var li = _elem("li");
			
			if ( d.imagename )
				li.appendChild( _a('<img onload="addCorners(this);" style="clear:left;" src="/image_mini/'+d.imagename+'" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "mapObjectClicked", d.objectid, d.name)) );
			else
				li.appendChild( _a('<img onload="addCorners(this);" src="/g/icon_no_image.gif" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "mapObjectClicked", d.objectid, d.name)) );
				
			li.appendChild( _a(d.heading, "", Utils.delegate(this, "mapObjectClicked", d.objectid, d.name)) );
			li.appendChild( _p(d.content) );
			li.appendChild( _br() );
			
			ul.appendChild(li);
		}
		
		// OBJECTS
		for ( var _d in data.mapobjects ) {
			var d = data.mapobjects[_d];
			var li = _elem("li");
			
			if ( d.imagename )
				li.appendChild( _a('<img onload="addCorners(this);" src="/image_mini/'+d.imagename+'" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "mapObjectClicked", d.id, d.name)) );
			else
				li.appendChild( _a('<img onload="addCorners(this);" src="/g/icon_no_image.gif" alt="Bild saknas"  class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "mapObjectClicked", d.id, d.name)) );

			li.appendChild( _a(d.name, "", Utils.delegate(this, "mapObjectClicked", d.id, d.name)) );
			li.appendChild( _p(d.description) );
			li.appendChild( _br() );
			
			ul.appendChild(li);
		}

		// USERS
		for ( var _d in data.users ) {
			var d = data.users[_d];
			var li = _elem("li");
			
			if ( d.imagename )
				li.appendChild( _a('<img onload="addCorners(this);" src="/image_thumb/'+d.imagename+'" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "showProfile", d.alias, d.id)) );
			else
				li.appendChild( _a('<img onload="addCorners(this);" src="/g/icon_no_avatar.gif" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "showProfile", d.alias, d.id)) );

			li.appendChild( _a(d.alias, "", Utils.delegate(this, "showProfile", d.alias, d.id)) );
			li.appendChild( _span(" "+d.points + " jelpos") );
			li.appendChild( _br() );
			
			ul.appendChild(li);
		}
		
		// JELPOS
		for ( var _d in data.jelpos ) {
			var d = data.jelpos[_d];
			var li = _elem("li");
			
			if ( d.imagename )
				li.appendChild( _a('<img onload="addCorners(this);" src="/image_thumb/'+d.imagename+'" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "showProfile", d.alias, d.id)) );
			else
				li.appendChild( _a('<img onload="addCorners(this);" src="/g/icon_no_avatar.gif" alt="Bild" class="corner iradius5 ishadow25" />', "recentviewlink", Utils.delegate(this, "showProfile", d.alias, d.id)) );

			li.appendChild( _a(d.alias, "", Utils.delegate(this, "showProfile", d.alias, d.id)) );
			li.appendChild( _span(" "+d.points + " jelpos") );
			li.appendChild( _br() );
			
			ul.appendChild(li);
		}
		this.content.appendChild(ul);
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
	
	this.showProfile = function ( alias, userid ) {
		Legend.appendLegend( {page:Application.PAGE_VIEWPROFILE, title:alias+"s profil"} );
		
		this.dispatchEvent( {type:ProfileView.EVENT_PROFILE_SELECTED, id:userid} );
		
		Application.navigate(Application.PAGE_VIEWPROFILE, userid);
	}
}

var RecentView = new _RecentView();function _ImageView () {
	
	this.imageElement = null;
	
	this.construct = function () {
		EventDispatcher.initialize(this);
	}
	
	this.show = function (imageName) {
		this.dispatchEvent( {type:WindowManager.EVENT_MODAL_ENABLE} );
		
		this.imageElement = new Image();
		this.imageElement.id = "imageFullscreen";
		this.imageElement.onload = Utils.delegate(this, "imageDone");
		this.imageElement.src = "/image_normal/"+imageName;
	}

	this.hide = function () {
		this.dispatchEvent( {type:WindowManager.EVENT_MODAL_DISABLE} );
		
		_get("content").removeChild(this.imageElement);
		this.imageElement = null;
		document.onmouseup = null;
	}
	
	this.imageDone = function() {
		var x = (Number(screen.availWidth)/2) - (Number(this.imageElement.width)/2);
		var y = 100;
		this.imageElement.style.left = x + "px";
		this.imageElement.style.top = y + "px";

		_get("content").appendChild(this.imageElement);
		
		document.onmouseup = Utils.delegate(this, "hide");
	}
}

var ImageView = new _ImageView();function _Alert() {
	
	this.windowData = null;
	
	this.construct = function () {
		this.windowData = WindowManager.createInternal("alertwin", "Alert", "200", "150", {ismodal:true});
	}
	
	this.show = function (title, body, buttonText) {
		Utils.removeChildrenFromNode(this.windowData.content);
		
		var content = this.windowData.content;
		content.appendChild( _p(body) );
		content.appendChild( _input("button", "alertokbutton", "", Utils.delegate(this, "hide")) );
		
		WindowManager.setTitle("alertwin", title);
		WindowManager.show("alertwin");
	}
	
	this.hide = function () {
		Utils.removeChildrenFromNode(this.windowData.content);
		WindowManager.hide("alertwin");
	}
}
var Alert = new _Alert();function _RelevanceView() {
	this.is_initialized = false;
	this.objectid = null;
	this.regionId = 0;
	
	this.construct = function() {
		BasicModule.initialize(this, _get("relevanceview"));
		
		BrowseCategory.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		TopCategories.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		ProfileEditor.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		SearchView.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		Map.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		InFocus.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		RecentView.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(this, "onObjectSelected"));
		
		this.addEventListener(ObjectView.EVENT_OBJECT_SELECTED, Utils.delegate(ObjectView, "onObjectSelected"));
		
		Application.addEventListener(Application.EVENT_REGION_SELECTED, Utils.delegate(this, "onRegionSelected"));
	}
	
	this.initialize = function () {
		this.is_initialized = true;
		this.send("/service/relevance/", "mi=" + this.objectid + "&r=" + this.regionId, Utils.delegate(this, "onSend"));
	}
	
	this.onSend = function( req ) {
		this.clear();
		this.layout( Utils.xmlToObject(req.responseXML) );
	}
	
	this.onRegionSelected = function (evt) {
		this.setRequestData("mi="+this.objectid+"&r="+evt.id);
		this.regionId = evt.id;
		this.update();
	}
	
	this.onObjectSelected = function (evt) {
		this.objectid = evt.id;
		this.setRequestData("mi="+this.objectid+"&r="+this.regionId);
	}
	
	this.layout = function ( data ) {
		var list = _elem("ul");
		
		var index = 1;
		for ( var _o in data.mapobjects ) {
			var o = data.mapobjects[_o];
			var li = _elem("li");
			
			li.appendChild( _a( index + ". " + o.name, "object", Utils.delegate(this, "mapObjectClicked", o.id, o.name) ) );
			
			list.appendChild(li);
			Map.addMapObject( o, index, true );

			++index;
		}
		
		this.content.appendChild( _h2("Se även:") );
		var img = _img("/g/relevance_spacer.gif");
		this.content.appendChild( img );
		
		this.content.appendChild(list);
		
		img = _img("/g/relevance_spacer.gif");
		this.content.appendChild( img );
	}
	
	this.mapObjectClicked = function (mapobjectid, mapobjectname) {
		this.objectid = mapobjectid;
		this.setRequestData("mi="+this.objectid+"&r="+this.regionId);	
	
		this.dispatchEvent( {type:ObjectView.EVENT_OBJECT_SELECTED, id:mapobjectid} );
		Application.navigate(Application.PAGE_VIEWOBJECT, mapobjectid);
		
		Legend.appendLegend( {page:Application.PAGE_VIEWOBJECT, title:mapobjectname} );
	}
}
var RelevanceView = new _RelevanceView();