/* * * *
* uride.it client side javascript
* @author Dmitriy Golubtsov
* @date 10.07.09				
* * * */


/*------VARS ------ 
function(){ */
	
	//if object is clippable then object_clippable=true
	//var object_clippable = true;
		
	
	/*------FROM HTML------ 
    function(){ */







	//NEW!!! maybe there was something new before
	//set this variable only if it is true, getting this from map/list switching
	//map search ot not (after user switched to map twice for map search result we need to show map)
	//var sett_mapSearch = false;
	
	//settings for zoom min and max limits, we can leave it here, or move to langpack to control if
	//was 15 instead of 4
	//was 14 instead of 3
	
	//zoom for edit map, zoom for search map, minimum zoom (prolly 2), maximim zoom (i guess 18, you can see people with this zoom)
	//this should be in lp or settings file
	//var sett.map_zoom = [10, 8, 2, 18];
	
	
	//if we need to show new/edit/setting panel after refresh, need to pass 0/1/2, we may need this in some cases, for settings, for new...
	//if don't need to show anything, don't send this
	//var sett.show_plus = {'what': 2, 'tab': 1};
	
	
	
	
	//var sett.show_gal = true;
	
	
	//var comments_order = 1;
	//if last comment is first in list, else - 0 or undefined





			
	/*
	}
	------/FROM HTML------*/


	var bIE = ($.browser.msie)?true:false;
	var bO  = ($.browser.opera)?true:false;
	var bFF = ($.browser.mozilla)?true:false;


	//array for escape events
	//TODO: need to update this and make it not via eval, cause it can be a lil bit not secure as they said
	var esc_eStrs = ['alrt.hide()', 'Win.hideLast()', 'dialog.T.fadeOut(100);', 'Share.close()', 'Noti.close()']

	$(document).data('esc_ar', [])



	//TODO: need to group it in one array
    //animation effect speed
	var ae = (!sett.no_effects)?[0, 0, 50, 50, 50, 200]:[0, 100, 200, 300, 400, 500];
	//9, 66, 52, 21, 10
	
	
	if(!user_id){
		//fixing some issues for guest, guess it is better way than adding conditions
		var Win = false;
		var Plus = {};
		Plus.T = $('#Plus');
		Plus.pb = 1;
		Plus.attach = function(){}
	}

/*
}
------/VARS------*/

//console.log fix
function cl() {
    if (typeof(admin_debug)=='undefined' || typeof console == 'undefined') return;
    if(!bIE){
		console.log.apply(console, arguments);
	}else{
		console.log(console, arguments)
	}
}

/*------COMMON------ 
function(){ */


	//TODO: need to clean ajax part, and maybe make in as object
	//_action, _dataToSend, _function, _el, _error_function
	/*------AJAX------ 
	function(){	
	*/


	
		//TODO: after everith will be done with ajax need to rename ajax_n to ajax
		ajax_n = function(_action, _dataToSend, _function, _el, _error_function, _cache){
		
			//if sending id in _dataToSend then it will be sent, the same for type, if not - it is default object's data
			if(typeof(_dataToSend.id) == 'undefined')_dataToSend.id = object_id;
			if(typeof(_dataToSend.type) == 'undefined')_dataToSend.type = object_type;
			

			
			var dataToSend = {
				'action': _action, 
				'hash': hash
			}
			
			//#1 checking for additional params (in some cases we need this, when form was submitted
			//something was saved, but server side found some errors in the form, so we don't need to resend image again)
			
			
		  	//Run some code here
			/*if(_el && _el.data && _el.data('params')){
				$.extend(dataToSend, _el.data('params'));
				//and cleaning it so next time we won't send the same
				cl('date before cleaning: %o', _el.data('params'));
				_el.removeData('params');
				cl('date after cleaning: %o', _el.data('params'));
			}*/
				
				
			$.extend(dataToSend, _dataToSend)
	
			
			//adding some additional params from html's js vars
			if(typeof(api_extra)!='undefined')$.extend(dataToSend, api_extra);
			
			
			//var o_0 = encodeURI('http://www.'+domain+'/api?action=connect&what=like' + '&id=' + object_id + '&type=' + object_type)// + '&hash=' + hash)
			//ajax.' + type + '.php?' + str.replace(/#/g, '[num]') + ri + '&hash=' + hash);
			//it was str instead of o_1
	
			cl('\n\nsendData: %o', dataToSend);
			
			
		/*	$.each(dataToSend, function(i,v){
				cl('here: %o', decodeURIComponent(v));
			})*/
			
			
			cl('requested url: %o', 'http://' + domain + '/api?' + $.param(dataToSend));


			//console.log('here: %o', 'http://' + domain + '/api?' + $.param(dataToSend));
			
			//TODO: switch cache
			$.ajax({
				//ajax.comment.php
				url:  'http://www.' + domain + '/api',
				//url: 'http://www.'+domain+'/ajax/ajax.' + obj + '.php?method=delete&' + str,
				cache: (_cache)?true:false,
				data: dataToSend,
				dataType: 'json',
				type: 'POST',
				timeout: 15000, //maybe just default one?
		
				success: function(_d){
					//cl('requested url: %o', this.url);
					if(_d){
						//saving params see //#1 for more comments
						//if(_el && _el.data && _d.data && _d.data.params)_el.data('params') = _d.data.params;
						
						cl('reply: %o', _d);
						//calling function if the ok was 1 and function is defined
						if(typeof(_function)=='function'){
							if(_d.ok && typeof(_function)=='function'){
								_function(_el, _d);
							}else if(typeof(_error_function)=='function'){
								//calling error function in case when need to hide loaders
								_error_function(_el, _d);
							}
						}

						//if there is re (reply message), then show it as error
						//TODO: maybe in future will need  add ability to remove re for something
						//if(_d.re && typeof(_error_function)!='function')alrt.show(_d.re, _d.ok);
						//don't know for what there is check for functions, if something won't work need to make it clear
						//now if there is re then it will be shown anyway
						if(_d.re)alrt.show(_d.re, 1 /* _d.ok*/ );
						
						/*var h = ajax_StrToAr(str);
						if(h!='z' && foo)foo(el, h);
						ajax_RemoveLB(1, el)*/
					}
				},
				
				error: function(XMLHttpRequest, textStatus, errorThrown){
					//also need to make timeout or something like that so if it will be loading for like 10sec, then show error
				    alrt.show(lp.ajErr);//'0|Error no file found or maybe something else?! ' + textStatus + ' // ' + errorThrown);
					//lp here
					//ajax_RemoveLB(1, el);
					
					//calling error function in case when need to hide loaders
					if(typeof(_error_function)=='function'){
						_error_function(_el)
					}
					
				}
			});
			return true;
		}

	/*
	}
	------/AJAX------*/

	/*------ACTIONS------ 
	function(){
	*/

	Actions = {
	
		//_id passed from outside and contains id of object that action is applied to
		//aldo there is Actions.El that contains link to DOM object that was clicked
	
		/*init: function(){
			//init is only for authorised users
		},
	
		act: function(){
			//update number of likers/riders etc
			//draw rider/liker to some block
			//how to find that block - ?
			//later will assign this to sidebar
		},
	
		Data: function(){
			//attach loadbar for button or maybe without it, or maybe fist do then send data
		},
	
		events: function(){
			//attached for body and check all elements with 'actions' class, maybe live will be better or bind as always
		}*/
	
		add_media: function(){
			//TODO: need to add object_id somewhere
			Plus.show(0);
			Plus.changeType($('.types li:eq(3)', Plus.T));
		},
	
		add_event: function(){
			//TODO: need to add object_id somewhere
			Plus.show(false, true);
			Plus.changeType($('.types li:eq(1)', Plus.T));
		},
	
		vcont_play: function(){
			var t = this.El;
			var w = $('img', t.prev()).width();
			var h = $('img', t.prev()).height();
			var s = embedV(t.attr('rel'), w, h);
			t.parent().after('<div class="video">' + s + '<a class="vcont_back" title="' + lp.backToObj + '">' + lp.backToObj + '</a></div>').hide()
			//setting size of video container
			t.parent().next().width(w).height(h);
			//adding event for close button
			//it is a lil bit not common, don't want to make more difficult markup, or to fade more than 1 element
			$('.vcont_back', t.parent().next()).click(function(){
				$(this).parent().prev().show();
				$(this).parent().remove();
			});
		},
	
		vcont_n: function(){
			//TODO: WHAT?
			iWin.show(Actions.El);			
		},
		
		action: function(_t, _what, _id, _type, _moreDataToSend, _amount_dom, _reply_foo, _need){
			//_amount_dom - optional DOM with numbers
			var dataToSend = {'what': _what, 'id': _id, 'type': _type};
			
			if(_need)dataToSend.need = _need
			
			//extending dataToSend if there are additional params
			if(_moreDataToSend)$.extend(dataToSend, _moreDataToSend)
			
			//adding a class to clicked element
			if(_t)_t.toggleClass('a');
			
			//changing amount for action button
			if(_amount_dom){
				var a = parseInt(_amount_dom.text());
				
				
				//cl('here: %o', typeof(a));
				a += (_amount_dom.is('.a'))?1:-1;
				if(!isNaN(a))_amount_dom.text(a);
				
			}
			//sending ajax request
			//TODO: why attach?
			//var reply_foo = (!_reply_foo)?false:_reply_foo();
			ajax_n('connect', dataToSend, function(_what, _data){
				//focus pokus
				//calling reply_foo and passing what with data there, need this only to draw avatar in sidebar after like / ride / buddy
				if(typeof(_reply_foo)=='function'){
					var o_0 = (_data.data)?_data.data.html:0;
					_reply_foo(_what, o_0);
				}
			}, _what);
		},
		
		//TODO: doing like this for better look of code, maybe it is possible to do with method extend, dunno
		like: function(_id, _type, _reply_foo, _need){
			Actions.action(Actions.El, 'like', _id, _type, false, Actions.El, _reply_foo, _need);
		},
		
		buddy: function(_id, _type, _reply_foo, _need){
			Actions.action(Actions.El, 'buddy', _id, '', false, false, _reply_foo, _need);
			$('.avatar[rel=' + _id + ']').addClass('buddy');
		},
		
		ride: function(_id, _type, _reply_foo, _need){
			Actions.action(Actions.El, 'ride', _id, _type, false, Actions.El, _reply_foo, _need);
		},
		
		remove: function(_id, _type){
			cl("remove")
		},
	
		share: function(_id, _type){
			//alrt.show('share')
			//this.Data(true)
			Share.init(_id, _type);
		},
	
		Data: function(_o){//_what, _id, _type){
			cl('Need to change to Actions.action')
			/*var t = Actions.El;
			var n = Actions.Numbers;
			t.toggleClass('a');
		
			//changing amount
			//TODO: maybe later will need to move it to actions object
			if(n){
				var a = parseInt(t.text());
				a += (t.is('.a'))?1:-1;
				t.text(a);
			}
			
			//TODO: need to get type of object somehow
			*/

		}
	 }

	/*
	}
	------/ACTIONS------*/

	/*------LOCALSTORAGE------ 
	function(){e
	*/
	//TODO: cookies?
	var LS = {
	
		set: function(_p, _v){
			
			//TODO: later need to activate localstorage but now it can be better idea to keep it in cookie
			/*if(typeof(localStorage) != 'undefined'){
				localStorage.setItem(_p, _v);
			}else{*/
				var exdate = new Date();
				exdate.setDate(exdate.getDate()+30);
				document.cookie = _p + "=" + escape(_v) + '; expires=' + exdate.toUTCString() + '; path=/';
			//}
		},

		get: function(_p){
			/*if(typeof(localStorage) != 'undefined'){
				return 	localStorage.getItem(_p) || '';
			}else{*/
				if (document.cookie.length>0){
					c_start = document.cookie.indexOf(_p + "=");
					if (c_start != -1){
						c_start = c_start + _p.length + 1;
						c_end = document.cookie.indexOf(";",c_start);
						if (c_end == -1) c_end = document.cookie.length;
						return unescape(document.cookie.substring(c_start, c_end));
					}
				}
				return '';
			//}
		},

		clear: function(_p){
			/*if(typeof(localStorage) != 'undefined'){
				localStorage.removeItem(_p);
			}else{*/
				this.set(_p, '');
			//}
		}
	 }

	/*
	}
	------/LOCALSTORAGE------*/

	/*------SHARE-----
	function(){
	*/
		var Share = {
			opened: false,
			
			settings: {
				//TODO: maybe later will add ability to change zoom
				//zoom: 16,
				//need to check for size in local storage first
				size: LS.get('embed_size') || '500x300',
				//google string array
				//g: ['http://maps.google.com/maps/api/staticmap?center=' , '&zoom=', '&size=', '&markers=', '&sensor=false'],
				//array of markers with shorten urls
				//m: [0, 'http://bit.ly/9TNNO0', 'http://bit.ly/9TNNO0'],
				//different types of code to embed
				//@l = link, @t = title, @s = src, @b = bottom, @m = main marler content, @d = description, @i = id, @k - kind of object (or type of object), @wh - size of embed
			
				/*c: [
				
						'<div style="position: relative; width: @wpx"><a href="@l" title="@t"><img src="@s" alt="@t" style="border:1px solid #999" /></a><div style="position:absolute; bottom: @bpx; left: 50%; margin-left: -85px; width: 150px; height: 90px; padding: 10px; text-align: center; background: #000; -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; ">@m</div></div>',
						'<a href="@l" title="@t"><img src="@s" alt="@t" style="border:1px solid #999" /></a>'
						//dynamic will be with js, and all styles will be there, with document.write, in js there will be just id of object
						//'<div class="uride_it i_@i t_@k s_@wh"></div><script type="text/javascript" src="../i/i/api/e.js"></script>' //http://api.uride.it/
					],*/
				embed_type: LS.get('embed_type') || 0,
			
				share_btns_html: [
					'<li class="tw_share"><a href="https://twitter.com/share" class="twitter-share-button" data-url="@link?ref=tw" data-text="@tw_text" data-count="horizontal" data-via="urideit">Tweet</a><script type="text/javascript" src="//platform.twitter.com/widgets.js"></script></li>',
					'<li class="fb-like"><iframe src="//www.facebook.com/plugins/like.php?app_id=289849397697005&amp;href=@link&amp;send=false&amp;layout=button_count&amp;width=90&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;font&amp;height=21&amp;locale=en_US" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:90px; height:21px;" allowTransparency="true"></iframe></li>',
					'<li сlass="fb-share" id="gplus"><g:plusone size="medium" href="@link?ref=g"></g:plusone></li>',
					
					// Google+ is not rendering :(
					// HTML 5 FB-like is better (but not rendering/showing): <div class="fb-like" data-href="@link" data-send="false" data-layout="button_count" data-width="90" data-show-faces="false"></div>
				]
			},
		
			init: function(_id, _type){
				//share work so:
				//first we getting object's data - tweet text, image, link etc, also in this request we can get first map link, and share html code
				//then showing window with map
				//after changins some setting of embed code calling getObjData method and in it, on reply, we decide waht to do next
				var o = this;
				if(!o.opened){
					o.opened = true;
					//first time var
					o.ft = true;
					o.id = _id;
					o.type = _type;
				
					//getting object's data, like tweet text, link etc and drawing it into window
					o.getObjData();
				
				
					o.events();
				}else{
					o.close()
				}
			},
		
			getObjData: function(){
				var o = this;
				//first drawing empty window, after loading object data will show it here
				if(o.ft){
					o.T = $('<div id="share_win" class="loading"></div>').appendTo('body');
					//TODO: pretty bad fix for scrollTop - need to find way for all browsers, html for everyone except Safari
					o.T.fadeIn(ae[2]).css('top', $('html').scrollTop() + $('body').scrollTop() + 50);
				}
				
				//emulating ajax
				//api?action=share&type=spot&id=122&example=true&width=600&height=300&noimage=1&zoom=16
				//mybe need to make o.settings.size as an object, so wont need to split
				
				var s = o.settings.size.split('x');
				
				ajax_n('share', {'type': object_type, 'id': object_id, 'example': true, 'width': s[0], 'height': s[1], 'noimage': o.settings.embed_type}, function(_t, _data){
					
					//o.ft = true;
					//o.id = _id;
					//o.type = _type;
					//all after data is loaded
					//var d = {'data': {'url': 'LINK', 'message': 'Message', 'html': '<a href="!!!!"><img src="http://maps.google.com/maps/api/staticmap?center=55.7557860000,37.6176330000&zoom=16&size=500x300&markers=icon:http://i.uride.it/i/markers/r_o.png|55.7557860000,37.6176330000&sensor=false" title="!!!!" /></a>', 'bb': '<a href="!!!!"><img src="http://maps.google.com/maps/api/staticmap?center=55.7557860000,37.6176330000&zoom=16&size=500x300&markers=icon:http://i.uride.it/i/markers/r_o.png|55.7557860000,37.6176330000&sensor=false" title="!!!!" /></a>'}}
					
					var o = Share;
					
					//saving data
					o.objData = _data.data;
					
					if(o.ft){
						//drawing window
						o.show();
						o.T.removeClass('loading');
						//switching off first time var
						o.ft = false;
					}else{
						//this is used when we've changed something
						o.genHtml(_data.data)
					}
					
				})
			},
		
			show: function(_d){
				var o = this;
			
			
				
				var o_0 = o.settings.size.split('x');
		
				//adding fb and twitter buttons
				var o_1 = o.settings.share_btns_html[0] + o.settings.share_btns_html[1] + o.settings.share_btns_html[2];
				//replacing links and texts of share buttons
				o_1 = o_1.replace(/@link/g, o.objData.url);
				o_1 = o_1.replace(/@tw_text/, o.objData.message);
				//TODO: need to convert this to one line, also need to check everywhere
				//drawing share window
				o.T.html('<a class="close" title="' + lp.close + '">&times;</a><h1>' + 
						lp.shareTitle + 
						'</h1>' + 
						'<ul class="soc">' + o_1 + '</ul>' +
						'<p>' + lp.shareEmbed + '<p>' +
						'<div class="settings">' + 
							lp.size0 + ':' + 
							'<input type="text" name="width" value="' + o_0[0] + '" />&times;' + 
							'<input type="text" name="height" value="' + o_0[1] + '" />' + 
							'<input type="checkbox" id="ch_box" class="switch_type" /> <label for="ch_box" class="switch_type">' + lp.shareCheckbox + '</label>' +
							/*'<ul>' + 
								'<li class="switch_type">0</li>' + 
								'<li class="switch_type">1</li>' + 
								//'<li class="switch_type">2</li>' + 
							'</ul>' +*/
							'<a class="get_code">' + lp.getCode + '</a>' +
						'</div>' + 
						'<small>' + lp.shareHtmlCode + '</small>' +
						'<div class="loading"></div>' + 
						'<input type="text" class="select_text" value="" />' +
						'<small>' + lp.shareBbCode + '</small>' + 
						'<input type="text" class="select_text" value="" />' + 
						'<small>' + lp.willLook + '</small>' +
						'<div class="container"></div>');
       	

				//var w = o.settings.size.split('x')[0]
				//setting width and position, 30 is win padding
				//o.T.animate({'width':  w + 'px', 'marginLeft': -w/2 - 30}, ae[3])

				//setting width, position and code of window
				o.genHtml({'html': o.objData.html, 'bb': o.objData.bb})
			
			
				//checking checkbox if it was saved as 1 in cookie
				if((parseInt(o.settings.embed_type)==1))$('#ch_box').attr('checked', 'checked');
			
				// render google plus button
				gapi.plusone.go("gplus");
			
				//adding to esc array
				esc_add(3);
			},			
		
			setSize: function(_str){
				var s = this.settings.size.split('x');
				return _str.replace('@@', s[1]).replace('@', s[0]);
			},
			
			genHtml: function(_embed){
				var o = this;
				
				
				//size for conatiner (size of embed)
				var o_0 = Math.max(parseInt(o.settings.size.split('x')[0]), 250);
				
				
				//size for win
				var o_1 = Math.max(o_0, 450);
				
				
				//positioning share_win
				o.T.css({'marginLeft': -o_1/2 - 30, 'width': o_1, 'top1': $('body').scrollTop()})//, ae[3]);
			
				//changing embed code
				//TODO: maybe here, also need to change the size
				$('.select_text:first', o.T).val(o.setSize(_embed.html));
				$('.select_text:last', o.T).val(o.setSize(_embed.bb));
				//showing map
				$('.container', o.T).html(o.setSize(_embed.html)).css('width', o_0);
				//selecting textarea
				o.select_text();
			},
		
			//events functions //thats why the names are different a lil bit
			
			close: function(){
				this.T.fadeOut(ae[2], function(){$(this).empty()});
				//need this to check if share is opened
				this.opened = false;
			},
		
			switch_type: function(){
				var o = this;
				o.settings.embed_type = ($('#ch_box').is(':checked'))?1:0;
				
				LS.set('embed_type', o.settings.embed_type)
				
				//generating embed code and inserting it in to window and into textarea
				o.getObjData();
			},
		
			select_text: function(){
				//checking if input was clicked
				var o_0 = (Actions.El.is('.select_text'))?Actions.El:$('.select_text:first', this.T);
				o_0.focus().select();
			},
		
			get_code: function(){
				var o = this;
				//some arrays
				var inp = [$('input[name=width]', o.T), $('input[name=height]', o.T)];
				//also adding step minimum 50px
				//TODO: maybe make this better
				var s = [
							Math.min(600, Math.max(250, Math.round(inp[0].val()/50)*50)), 
							Math.min(600, Math.max(250, Math.round(inp[1].val()/50)*50))
						];
				//changing inputs value
				inp[0].val(s[0]);
				inp[1].val(s[1]);
				//gettin new size to send to google
				var new_size = s[0] + 'x' + s[1];
				if(o.settings.size!=new_size){
					//checking size
					//there is a limit for google static map - 640x640px
					o.settings.size = new_size;
					//saving size in cookies, so next time it will be the same
					LS.set('embed_size', o.settings.size);
					//getting embed code
					o.genHtml(o.objData)
					//o.getObjData();
				}else{
					o.select_text()
				}
			},
		
			events: function(){
				this.T.bind('click keyup focusout', function(e){
					var t = $(e.target);
					switch(e.type){
						case 'click':
							if(!t.is('.a')){
								Actions.El = t;
								var s = t.attr('class');
								if(typeof(Share[s])=='function')Share[s]()
							}
						break;
						case 'focusout':
							//getting code when blur
							//if(t.is('input[type=text]'))Share.get_code();
						break;
						default:
						//getting code when enter was pressed
							if(e.keyCode == '13')Share.get_code();
					}
				})
			}
		
		}
		
		
		//get object share data
		//show win with settings
		//generate code
			// - bit.ly
			// - our js in needed
		//copy to clipboard

	/*
	}
	------/SHARE------*/		
	
	/*------INPUTS------ 
	function(){
	*/
	//TODO: need to put textarea here too

	var Inputs = {
		
		init: function(){
			this.labeled($('.labeled'));
			//this.dated.init($('.dated'));
			this.spotted($('.spotted'));
			//req fileds to ajax validation and additional events
			this.req($('.validate'));
			//right now only for Plus
			this.active($('#plus input[type=text]'));
			
			//this.resizable($('.resizable'));
			//using events here cause inner function will be used for drawing some resizable inputs
			$('.resizable').live('keyup', function(e){Inputs.resizable($(this))})
		},

		//cleaning label in input fields
		labeled: function(_t){
			_t.live('focusin focusout focus', function(e){
				var t = $(this);
				t.removeClass('err');
				//if labeled
				if(!t.is('.not')){
					//getting current value
					var v = t.val();
					//getting prev value
					var pv = t.data('pv');
					if(e.type=='focus' || e.type=='focusin'){
						//saving label value
						if(!pv)t.data('pv', v);
						if(t.data('pv')==v)t.val('');
						//remove class of inputs with defined values
						t.removeClass('def');
					}else{
						if(pv==v || v==''){
							//if value wasn't changed comparing to pv then write pv
							t.val(pv);
						}else{
							//on focusout adding class def, which means that value is defined, and we can make text more bold
							t.addClass('def')
						}
					}
				}
			});
		},
		
		resizable: function(_t){
			//TODO: opensource
			//TODO: need to optimize this, this may be too heavy
			//_t.live('keyup', function(e){
				//var t = $(this);
				if(_t.is('textarea')){
					//setting height to 0 so it will resize both way
					_t.css('height', 0);
					if(_t[0].scrollHeight != _t.outerHeight()){
						//getting vertical padding
						var p = _t.outerHeight() - _t.height();
						if(bO || bFF) p=+20;
						_t.css('height', _t[0].scrollHeight + p);
					}
				}else{
					
					//ofcourse we can put text in span and calculate it's size, but it's too long story
					//so doing approximately calculation of width parseInt(t.css('fontSize'))/2
					var l = (_t.val())?_t.val().length:1;
					var w =  l * parseInt(_t.css('fontSize'))/2 + _t.outerWidth() - _t.width();
					_t.css('width', Math.min(150, w));
				}
			//});
		},
		
		spotted: function(_t){
			_t.live('change', function(e){
				var t = $(this);
				if(!t.data('boo')){
					Map.spotToLL({'map': Map.mapN, 'marker': Map.markerN, 'name': t.val(), 'id': t.next().val()})
					//fixing double change
					//in some cases change event called twice so we do timeout to fix this, timeout is necessary here
					setTimeout(function(){t.data('boo', false)}, 50);
				}
				t.data('boo', true);
			});
		},
		
		req: function(_t){
			_t.live('change', function(e){
				var t = $(this);
				//t.addClass('loading');
				ajax_n('validate', {'type': 'user', 'key': t.attr('name'), 'value': t.val()}, 
					function(_el, _data){
						_el.removeClass('err');
					}, t, function(_el, _data){
						_el.addClass('err');
					})
			});
		},
		
		trim: function(_str){
			var str  = _str || '';
			return str.replace(/^\s+|\s+$/g,'').replace(/\n\n/gm, '\n');
		},
	
		active: function(_t){
			//adding active class for any focused field
			_t.live('focusin focusout', function(e){
				$(this).toggleClass('active');
			})
		},
	
		transformToEdit: function(_str){
			//transforming html to textarea text
			return _str;
		},
	
		validate: function(_el){
			//simple validator for one input
			//dealing with labeled
			_el.focus().blur();
			if(_el.val()!=' ' && _el.val()!=_el.data('pv')){
				return true;
			}else{
				return false;
			}
		}
	
	 }

	/*
	}
	------/INPUTS------*/

	/*------EVENTS------ 
	function(){
	*/
		/*------KEY EVENTS------ 
		function(){
		*/
		
		//for cleaning escape key array
		esc_clean = function(ei){
			var d = $(document);
			var e_ar = d.data('esc_ar');
			//TODO: guess i can use something better here, match?
			for(var i=0, l = e_ar.length, s = esc_eStrs[ei]; i<l; i++){if(e_ar[i]==s)break;}
			e_ar.splice(i, 1);
			d.data('esc_ar', e_ar);
		}
	
		esc_add = function(_i){
			var d = $(document);
			var e_ar = d.data('esc_ar');
			//writing to array
			e_ar.push(esc_eStrs[_i])
		}

		//there is some problems in events for ul, or something else, so there will be only one event listener for document



		//need this for ctrl + enter
		//var ctrl; //if ctrl / cmd pressed

		//TODO: make this events via bind
		
		var currentKeyDown;
		
		$(document)
			.keydown(function(e){
				var t = $(this);
				var kc = e.keyCode;
				currentKeyDown = kc;

				
				//adding key listener for ctrl or cmd so scoll zoom will work
				//right now there is only onw key up/down event for document so we are making unbind
				if(!is_fullscreen && Map.map)Map.map.setOptions({'scrollwheel': true})
				
				//if(ctrl && kc==13)focusedform_Find()

				//if(kc==17 || kc==91)ctrl=true;
				//prevent spacebar press from scrolling down, need it for spacebar for plaing videos
				//if(kc == 32)event.preventDefault();
			/*	if(t.data('list')){
					//events for list
					if(kc==40 || kc ==38){
						var d = (kc==40)?1:-1;
						var sel = list.data('sel') || 0;
						$('li:nth-child('+sel+')', list).removeClass('h');
						sel+=d;
						var l = $('li', list).length;
						if(sel<1)sel = l;
						if(sel>l)sel = 1;
						var c = $('li:nth-child('+sel+')', list)
						c.addClass('h');
						list.data('sel', sel);
					}
					if(kc==37 || kc==39){
						list_LoadBar(kc-38);
					}
				}*/

			})
			.keyup(function(e){
				var t = $(this);
				var kc = e.keyCode;


				//if(kc==17 || kc==91)ctrl=false;		
				//uparrow play for videos
				//maybe put case here
				
				//adding key listener for ctrl or cmd so scoll zoom will work
				//right now there is only onw key up/down event for document so we are making unbind
				if(!is_fullscreen && Map.map)Map.map.setOptions({'scrollwheel': false})
				
				
				
				if($(document).scrollTop()<550){
					if(Gal.am && Gal.zoomed){

						//maybe make switch here
						//alrt.show(kc)
						switch(kc){
							case 27:
								//ESC
								Gal.zoomClose();
							break;
							case 37:
								//Z
								Gal.nextprev(false);
							break;
							case 39:
								//X
								Gal.nextprev(true);
							break;
							/*case 13:
								if(!Gal.zoomed){
									$('.v .zoom:first', Gal.T).click();
								}else{
									Gal.zoomClose();
								}
							break;*/
						}
					}



					//space is for zoom
					//up/down for images (next/prev) left/righ for scrolling
					//other actiona can be later like 1/2/3/4 for actions like ride/spectate/connect etc
				}
				if(t.data('list') && kc==13)$('.h', list).click();
				//event for sending win form by clicking enter
				if(t.data('win') && kc==13 && !t.data('list') && $('textarea', win).length==0)$('.win_submit', win).click();
			
				if($('body').data('search_focus') && kc==13)Search.submit.click();
			
				if(kc==27){
					//escape
					//TODO: why in documents data?!?!?!
					var e_ar = $(document).data('esc_ar');
					if(e_ar.length>0){
						e_str = e_ar.pop();
						//TODO: this should be done mush better, right now it is not so secure;
						eval(e_str);
					}
					//$(document).data('esc_ar', e_ar);
				}
			});


		/*
		}
		------/KEY EVENTS------*/

	/*
	}
	------/EVENTS------*/

	/*------SEARCH------ 
	function(){
	*/
	
	Search = {
			T 		: $('#pan'),
			focused : false,
			filters	: '',
			field 	: {T: $('#pan .search input:first'), pv: '', v: function(){return this.T.val()}},
			submit	: $('.submit', this.T),
			hasHash: false, 
			
			init: function(){
				
				var o = this;
				
				//field value
				o.field.fv = o.field.T.val();
				/*this.ajF;
				this.ajT;
				this.ajP;*/
				
				//$('body').prepend('<a href="/search/spots/like:23/par:value/map">11111</a> <a href="/sdfdsafdsf/">222222</a>')
				//reading hashtags and loading search if necessary
				
				if(is_fullscreen){
					//var url = window.location.toString();//'http://uride.it/spots/like:23/par:value/map';
					//searching for / after .it / .com etc....
					//and removind first part of url
					//url = url.substr(url.indexOf('/', 10));
					Search.urlToRequest('/search/' + object_type);
				}
				
				
				o.events();
				
				//returning true if there are search hashtags
				return Search.hasHash;
			},
			
			
			urlToRequest: function(_url){
				
				var ar = _url.substr(1).split('/');
				//cl('here: %o', _url);
				//object to send in ajax
				var d = {};
				
				var ar1 = [];
				//-1 need this for map
				var l = ar.length-1;
				
								
				d.type = ar[1];
				
				//checking if last letter is "s" then removing it, need this for /spots/ url
				if(ar[1].slice(-1)=='s')d.type = ar[1].slice(0, -1)
				//checking for map
				if(ar[l]=='map')d.map = 'true';
				
				//other vars for ajax request
				for(var i=2; i<=l; i++){
					ar1 = ar[i].split(':');
					d[ar1[0]] = ar1[1];
				}
				
				/*var d = {};
				var ar1 = [];
				//generating object _for:a_in:b, so it will be {for: a, in:b}
				var l = ar.length;
				for(var i=0; i<l; i++){
					ar1 = ar[i].split(':');
					d[ar1[0]] = ar1[1];
				}*/
				
				//need this for Search.init in init block of all js
				Search.hasHash = true;
				//passing data to 
				Search.load(d);
			},
			
			load: function(_d){
				var o = this;
				//saving data object in search in contains filters and everything
				
				o.D = _d;
				Gal.on('search', o.D);
				
				//gal_cPage = gal_mPage = gal_searchHTML = 0;
				//gal_Hide();
				///setTimeout('gal_Show()', 420);
				//setTimeout('gal_Load()', 420);

				scroller(0);
				notiClicked = 0;
			},
			
			search_a: function(_t, _e){
				
			},
			
			events: function(){
				var o = this;
				
				//adding event for all links that lead to search
				$('a[href^="/search/"]').live('click', function(e){
					var t = $(this);
					//detecting if user want to open link in new tab
					if(currentKeyDown == 17 || currentKeyDown == 91){
						//removing "/search" from url so it will look better in new tab
						var o_0 = t.attr('href').replace('/search', '');
						t.attr('href', o_0);
					}else{
						cl('Search.urlToRequest: %o', t.attr('href'));
						//gettin params and send ajax request;
						Search.urlToRequest(t.attr('href'));
						e.preventDefault();
					}
				})
				
				
				//draw test link
				//$('body').prepend('<a href="/search/everything/lastsearch:1/">11111</a> <a href="/sdfdsafdsf/">222222</a>')


				//search pan events
				$('.search a', o.T).bind('click', function(e){
					//e.preventDefault()
				    var t = $(e.target);
				    var tp = t.parent();
				    if(t.is('a')){
						//only with name, cause there also can be lst search link
						if(t.attr('name')){
							//TODO: can put siblings here
							$('.a', tp).removeClass('a');
							t.addClass('a');
							$('input:last', tp.prev()).val(t.attr('name'));
							Search.field.T.focus();
							if(Search.field.T.val().length>0)Search.submit.click();
						}
				    }else if(t.is('i')){
						//we don't have all now, so maybe cancel this
				        Search.field.T.val(':all');
					    tp.click();
				    }
				});
				
				
				/*
				function(){
    				//was a lil bit strange here
    					.click(function(){
    						var t = $(this);
    						var tp = t.parent();
    						$('.a', tp).removeClass('a');
    						t.addClass('a');
    						$('input:last', tp.prev()).val(t.attr('name'));
    						Search.field.T.focus();
    						if(Search.field.T.val().length>0)Search.submit.click();
    					})
    					//all
    					.find('u')
    						.click(function(){
					    
    							//Search.load('all', $(this).parent().attr('name'));
    						});
                }
                */
				this.submit.click(function(){
					var t = $(this);
					//if(Search.field.T.val()!=Search.field.fv){
						//or Search.field.T.is('.def')
					//|| Search.field.T.val()==''){
						//if(!t.data('cl')){
							var v = Search.field.T.val();
							//making data object for search request
							var d = {'search': v.replace(/&/g, '[amp]'), 'type': t.parent().next().find('input').val()}
							Search.load(d);
						//}
					//}
					return false;
				})
				.parent().parent().submit(function(){
					return false;
				});				
				
			}
			
	 	}
	/*
	}
	------/SEARCH------*/

	/*------PAN----- 
	function(){
	*/
	
		pan_menus = function(){
			//TODO: need to decide how to make this, it is good to have ability to return, but
			//1. it is bad if you miss search button or close search button, or switch to map
			//2. it is kind of slow
			
			//Slow fadeouts solve all problems if not -
			//Old version: need to caculate if mouse was for 500ms on the li, if so then when hiding need to make delay,
			//if not the hide right away
			$('#pan>li:not(.f)').bind('mouseenter mouseleave', function(e){
				var t = $(this);
				var div = $('>div:not(.h)', t);
		
				//var speed = ae[2];//(t.is('.search'))?0:ae[2];
		
				if(e.type=='mouseenter'){
					//checking if we need to show hover menu and showing it
					//var tO = setTimeout(function(){div.data('delay', true); }, 500);
					//fixing hover repeating, showing div with top z-index, and saving timout var
					div
						//.stop(true, true)
						//.css('opacity', 1)
						//.fadeIn(speed)
						//.delay(ae[2])
						.show()
						.css('zIndex', 11)
					//	.data('tO', tO);
			
				}else{
					//var tO = div.data('tO');
					//clearing timout in some cases it can be useful
					//clearTimeout(tO);
					//defining delay for fadeOut
					//var delay = (div.data('delay'))?100:0;
					//removing delay var from data, so next time it will work as new
					//div.data('delay', false)
					//checking if we need to hide menu and hiding it with delay
					div
						//.stop(true, true)
						//.css('opacity', 0)
						//.fadeOut(ae[3])
						.hide()
						.css('zIndex', 10)
				}
			})
			
			
		}
	
	/*
	}
	------/PAN------*/

	/*------DIALOG------ 
	function(){
	*/

	var dialog;
	
	
	
	if(user_id){
		dialog = {
			set: function(_t, _l){
				var o = this;
				var el = o.el;
				var top = _t || 0;
				var left = _l || 0;
				o.T
					.css('top', el.offset().top-3+top)
					.css('marginLeft', -Math.floor($(document).width()/2 - el.offset().left)-o.T.width()-23+left)
					.fadeIn(ae[2]);
			},
		
			show: function(_el, _type, _funct, _top, _left){
				var o = this;
			
				if(!o.T){
					$('body').append('<div id="dialog"></div>');
					o.T = $('#dialog');
				}
				o.el = _el;
				
				o.T.html(lp.dialog_html[_type] + ' <a class="yes">' + lp.dialog_yes + '</a><a class="no">' + lp.dialog_no + '</a>');
			
				//dialog.data('el', el).html(dialog_html[type]);

				if(o.T.is(':visible')){
					o.T.fadeOut(100, function(){dialog.set(_top, _left)});
				}else{
					o.set(_top, _left);
				}

				$('.yes', o.T).click(_funct);
				$('.no', o.T).click(function(){o.hide()});
				esc_add(2);
				$('body').bind('mouseup', dialog_hide)//.data('esc_ar', e_ar);
			},
		
			hide: function(){
				this.T.fadeOut(100); 
				esc_clean(6);
				$('body').unbind('mouseup', dialog_hide);	
			}
		}
	
		dialog_hide = function(){
			dialog.hide();
		}
	 }
	/*
	}
	------/DIALOG------*/

	/*------ALERT------
	function(){
	*/

		alrt = {
			//TODO: there can be error, when user will get note and a1ert at once, all of it will be written in one block
			show: function(_s, _t){
				var o = this;
				if(!o.T){
					//adding new a1ert element
					$('body').append('<div id="alert"><a class="close">&times;</a></div>');
					o.T = $('#alert');
					
					//not sure, maybe later need to make whole area clickable, but then there will be problem with link
					$('.close', o.T).click(function(){alrt.hide()});
				}
				
				var str = _s.toString();
				
				if(str!=$('p:last', o.T).html()){
					o.T.prepend('<p>' + _s.toString()  + '</p>').slideDown(ae[1]);
					//adding timout for note a1ert
					if(_t)setTimeout(function(){alrt.hide()}, 3000)
					//adding_to esc array
					esc_add(0);
				}
			},
		
			hide: function(){
				this.T.fadeOut(ae[2], function(){
					//cleaning a1ert block
					alrt.T.find('p').remove();
					esc_clean(0);
				});
			}
		}

	/*
	}
	------/ALERT------*/

	/*------SERIALIZE------
	function(){
	*/
		serialize = function(_form){
			var obj = {};
			var l = 0;
			$('*:visible', _form).each(function(i){
				var t = $(this);
				//checking if there is 'name' attr and 'value' is not empty, then adding it to object
				//also checking if the field was labeled so we don't need to send anything if the value==label
				if(t.attr('name') && t.attr('value') && ((t.data('pv') && t.attr('value')!=t.data('pv')) || !t.is('.labeled'))){
					obj[t.attr('name').replace('field_', '')] = t.attr('value');
					l++
				}
			});
			return (l==0)?false:obj;
		}
		
	/*
	}
	------/SERIALIZE------*/

	/*------FORMS------ 
	function(){
	*/

	//TODO: Clean here and make changes for edit form, they will be in Plus object

	/*form_err = function(t, b){
		t.animate({'opacity':0}, 50, 'swing', function(){$(this).addClass('err').animate({'opacity':1}, ae[3])});
		//(b)?t.bind('blur', editForm_check):t.bind('blur', form_check);
		t.bind('blur', form_check);
	}*/

	Forms = {
		//maybe later will add live validation for forms that's why this is an object
		validate: function(_t){
		
			var o = this;
			//TODO: too lazy to look for better way of coding, each is ugly
			o.mistakes = 0;
		
			//removing all err classes
			$('.err', _t).removeClass('err');

			//checking if required fields contain data
			$('.req:visible, .req_v', _t).each(function(i){
				var t = $(this);
				//cl('here: %o', t.attr('name'));
				//checking if input is empty which is almost impossible and if it is not the same as its previos val
				if(t.val().replace(/ /g, '')=='' || t.val()==t.data('pv') || typeof(t.data('pv'))=='undefined'){
					Forms.mistakes++;
					t.addClass('err');
				}
			});
			
			
			if(o.mistakes){
				return false;
			}else{
			
				Forms.stringToSend = '';
			
				$('input[type=text]:visible, textarea:visible', _t).each(function(i){
					var t = $(this);
					var v = t.val();
					//checking if val is not like pv, if so we don't need to send it, it will be empty
					if(v!=t.data('pv') && typeof(t.data('pv'))!='undefined')
					Forms.stringToSend += t.attr('name').substr(6) + '=' + t.val() + '&';
				})
				return o.stringToSend;
			}
		}
	 }

	/*form_check = function(foo, el){
		var d = $(document);
		d.data('err', 0)
		d.data('str', '');
		var t = win;
		if(t.css('display')=='block'){
			$('input', t).each(function(i){
				//textarea???
				var t = $(this);
				if(t.attr('type')!='button'){
					var d = $(document);
					//if checking list
					//also need to check if fields are empty or not
					//and highlight the input
					//can't understand if it is empty control or not - (!t.val() && t.attr('id'))
					//maybe substr class with 'not_req' or something, id  is not that good
					var a = t.attr('class').split('not_req');
					var am = 0;
					if((!t.val() || (t.val()!=t.data('val') && list_typeAr[t.attr('name')]>0)) && a.length==1){
						form_err(t);
						//if(t.attr('name')=='sports')alrt.show(lp.listSelectOnly);
						am++;
					}else{
						var str = '';
						if(list_typeAr[t.attr('name')]==0 && t.val()!=t.data('val')){
							str += d.data('str') + '&' + t.attr('name') + '=' + t.val().replace(/&/g, '[amp]');
						}
						if(t.attr('name') == 'tricks'){// && t.data('list_id')
							var tpp = t.prev().prev()
							if(tpp.val()==tpp.data('val') ){
								a = t.parent().data('s_lists');
								str += '&' + a[0].toString();

							}else{
								form_err(tpp);
								//tpp.addClass('err').bind('blur', form_check);
								am++;
							}
						}
						//if(t.attr('name') == 'tricks' && )am++;
					}
					if(am==0)t.removeClass('err').unbind('blur', form_check)
					d.data('err', d.data('err') + am).data('str', str);
				}
			});
		}
		alrt.show('errr' + d.data('err'))
		if(d.data('err')<1 && foo)foo(el, d.data('str'));
	}*/

	lng_change = function(){
		$('#footer select').change(function(){
			var str = window.location.toString().split('#')[0];
			var l = str.length;
			var str1 = str.substr(l-1, l);
			if(str1!='/')str += '/';
			//setting new lang
	 		window.location = str + '?lang=' + $('option:selected', $(this)).val();
		});
	}


	/*
	}
	------/FORMS------*/

	/*------SCROLLER------
	function(){
	*/
		scroller = function(_to){
			$('html, body').animate({'scrollTop': _to}, ae[2]);	
		}
	/*
	}
	------/SCROLLER------*/
		
	/*------WINDOW------
	function(){
	*/
		//not doing it as a part of Win object so object will be lighter
		//TODO: LPLPLP
		Win = {

			html: 	{
						'idea_win': '<textarea class="labeled resizable" name="text" rows="2" maxlength="144">' + lp.win.idea + '</textarea><input type="button" value="' + lp.win.post + '" class="submit" />',
						'message_win': '<textarea class="labeled resizable" name="text" rows="2" maxlength="1000">' + lp.win.message + '</textarea><input type="button" value="' + lp.win.send + '" class="submit" />',
						'user_win': '<h4><a href="_url">_name</a></h4><a class="send_message action hide" rel="_rel">' + lp.win.message + '</a><a class="buddy action _visible">' + lp.win.add_to_buddies + '</a>', 
						'list_win': '<a class="more">' + lp.more + '</a>',
						'sb_win': '<input type="text" value="" name="_name" class="listed" /><input type="button" value="' + lp.win.add + '" class="add" />',
						'calendar_win': '<ul id="calendar"><li class="time">' + lp.cal_at + '<input type="text" value="" maxlength="5" /><a class="change_time plus">+</a><a class="change_time">-</a><a class="save">' + lp.cal_set + '</a></li><li class="title"></li><li class="nav prev"></li><li class="nav next"></li></ul>'
					},
			windows: [],

			//TODO: maybe later need to add z-index changer so it will move all to back and clicked will be above all
			init: function(){
				var o = Win;

				//$('body').prepend('<input type="text" class="listed labeled" name="city" value="City" />')


				//calendar
				$('.datepicker').live('focusin click', function(e){
					//e.preventDefault();
					//why i'm adding event here?

					var t = $(e.target);

					if(!t.data('clicked')){
						//date object to get time
						var date = new Date();

						var d = {'type': 'calendar_win', 'outsideHide': true, 
									custom_event: function(){
										calendar.init($('#calendar'), t);
									}
								};
						var w = new Win.instance(t, d);
						Win.windows.push(w);
						//pretty bad fix doing this, so mouseup will be before setting this 
						setTimeout(function(){Win.outsideHide = {'win': w, 'el': t};}, 500)

						t.data('clicked', true);
					}

				})

				//message window
				$('.send_message, .report').live('click', function(e){
					e.preventDefault();
					//why i'm adding event here?
					var t = $(e.target);

					if(!t.data('clicked')){
						var d = {'type': 'message_win', 'data': {'action': 'post', 'receiver_id': parseInt(t.attr('rel')), 'post': 'message'},
									callBack: function(_o){
										//closing win after ajax success
										_o.hide();
									},
									custom_event: function(_o){
										Win.tools.enter_submit(_o.T)
									}
								};
						//checking if it is a user win then adding coordinates so window will be right under user_pic
						if(t.parent().is('.user_win')){
							//checking if avatar is on the left, then doing some adjustements, forgot why it is 9 and why it is 4
							d.x = (t.offset().left > $(window).width()/2)?(t.parent().width() - t.width() + 4):-9;
							d.y = -49;
						}
						Win.windows.push(new Win.instance(t, d));

						t.data('clicked', true);
					}
				});

				//status/idea
				$('#idea').live('click', function(e){
					var t = $(e.target);
					if(!t.data('clicked')){
						//http://dev.uride.it/api?action=post&post=idea&text=my%20knees%20can%20bend,%20useful3
						var w = new Win.instance(t, {	'type': 'idea_win', 
																'data': {'action': 'post', 'post': 'idea'}, 
																callBack: function(_o){
																	//closing idea win when clicking submit (adding another event for submit button)
																	Home.update();
																	_o.hide();
																},
																custom_event: function(_o){
																	Win.tools.enter_submit(_o.T)
																}
															});
						Win.windows.push(w);
						//saving reference to win in clicked button's data
						t.data({'win': w, 'clicked': true});

					}else{
						//hiding idea window when clicking the same button
						t.data('win').hide()
					}
				});

				$('.avatar').live('click', function(e){
					e.preventDefault();
					var t = $(this);
					//if elemet wasn't clicked before
					if(!t.data('clicked') && !t.is('.you')){
						//maybe not the best way, but the fastest one
						var rel = t.attr('rel');
						//adding last window to array to hide them with outside click

						var w = new Win.instance(t, {	'replace': {'_url': t.attr('href'),	'_name': t.attr('title'), '_visible': (t.is('.buddy'))?'hidden':'', '_rel': rel},
														'type': 'user_win', 'id': rel, 'outsideHide': true})
						Win.windows.push(w);
						//if there can be more than one outsideHide windows, what is impossible, then need o make array
						//el is an element that was clicked to clicking it again will just hide object

						Win.outsideHide = {'win': w, 'el': t};

						//need this to prevent close/open effect, when just need close
						t.data('clicked', true);
					}
				});

				$('.listed').live('focus focusout keyup keydown', function(e){

					var t = $(this);
					var et = e.type;
					var kc = e.keyCode;
					if(kc!=27){
						if(et=='keydown'){
							//using key down only for arrows up and down
							//38 - up
							//40 - down
							//37 - left for more
							//13 enter
							if(t.data('win')){ 
								var w = t.data('win');
								if(kc==38 || kc==40){
									//getting index of current .list
									var ci = $('.a', w.T).index() + 1;
									$('.a', w.T).removeClass('a');
									//selecting some .list
									var o_0 = $('a', w.T).eq(Math.max(ci + kc - 40, -1));
									o_0.addClass('a');
									//changing input value while user select list item with keyboard arrows
									//doing this only for list not for more button
									if(t.is('.list')){
										t
											.val(o_0.text())
											//need this to change so there will be no additional request after value will changed
											.data('cv', o_0.text())
											//need this to keep id of list item
											.next().val(o_0.attr('rel'));

									}
									//doing this to hide saved input values.
									e.preventDefault()	
								}else if(kc==39){
									w.more();
								}else if(kc==13){
									//hiding list after enter was pressed if enter on items not on more
									if($('.a.more', w.T).length==0)w.hide();
									$('.a', w.T).click();
								}
							}else if(kc==40){
								//if there is no win and user click arrow down, then we are asking for list
								t.data('cv', null);
							}


						}else if(et=='keyup' || et=='focus'){
							//adding active class to know if some field have lists
							t.addClass('active');
							//doing this only if not esc was presse
							//need to check if there is a new value in list if so then send request for new win
							if(et=='focusin'){
								t.data('cv', '');
								var changed = true;
							}else{
								//fixing isssue when clicking more and typing after
								Win.inside = false;

								var changed = (t.val()!=t.data('cv'))?true:false;
								t.data('cv', t.val());
								//checking if value was changed by typing something in it, if so we need to remove next field (the input we send to server) value to this value and remove it's rel
								//&& - fix for fast typing without it it will write text into button
								if(t.val()!=t.next().attr('rel') && t.next().is('input[type=hidden]')) t.next().val(t.val()).attr('rel', '');
							}

							//console.log('>>>>>>>>: %o', Win.inside + ' ' + changed + ' ' + t.data('no_focus'));
							//using no_focus so after list item was clicked it won't work like new focus and wont show list again
							if(!Win.inside && changed && !t.data('no_focus')){
								//waiting for prev win to hide then showing new, i know it can feel slow, but this way we minize ajax request i guess
								setTimeout(function(){
									//hiding prev window if it exists
									if(t.data('win'))t.data('win').hide();

									//creating instance of win
									//removeing "field" from name t.attr('name').replace(/field_/g, '')

									//data for ajax request
									var dataToSend = {'type': t.attr('name').replace('field_', ''), 'div': 'list', 'search': t.val()}

									if(t.is('.show_all'))dataToSend.show_all = 1;

									//creating list win instance
									w = new Win.instance(t, {'type': 'list_win', 'action': 'view', 'send': dataToSend, 'no_ae': 0})
								   	Win.windows.push(w);


									//saving i, so we can access list's window
									t.data('win', w)
									//adding hidden field to keep selected item id, and saving value in rel, we'll check if value and hidden's rel are the same, then we'll send id
									//if it was changed then sending value
									if(!t.next().is('.listed_id'))t.after('<input type="hidden" class="listed_id" rel="' + t.val() + '" name="' + t.attr('name') + '_id" />')

									//calling more method to load data
									//	http://dev.uride.it/api?action=view&type=country&div=list&search=is
									//var d = {'action': 'view', 'send': {'type': t.attr('name'), 'div': 'list', 'search': t.val()}};

									//this more wont make more bigger
									w.more();
									//removing close button need this for arrows to work with more button
									$('.hide', w.T).remove();

								}, ae[2]);
							}

						}else{
							//removing active class
							t.removeClass('active')
							//hiding win after blur / focusout
							//doing it with timout so mousedown will fire before and click should fire too
							//setTimeout(function(){
								//cl('Win.inside: %o', t.attr('name'));
								//as we can't have list and another win after it, so we just hiding last win
								//only if someone will be really fast
								if(!Win.inside){
									//closing win when loosing focus
									Win.hideLast(true);
								}else{
									//cl('!!!: %o', 1);
									t.focus();
									Win.inside = false;
								}

								//checking if t is resizable then need to resize it after focus out
								if(t.is('.resizable'))Inputs.resizable(t)

							//}, 500)

						}
					}
				});

				//windows for sidebar add buttons
				$('#sidebar .add, #v_cont .add').live('click', function(e){
					e.preventDefault();
					var t = $(this);
					//using this to fix fast dbclick issue for lists
					//if(!t.data('busy')){
						//if elemet wasn't clicked before
						if(!t.data('clicked')){
							//hiding all wins, this will fix issue when you click more in sb list and then click another plus is sb
							Win.hideAll()
							//maybe not the best way, but the fastest one
							//adding last window to array to hide them with outside click
							//using interval to fix fast dbclick issue
						//	setTimeout(function(){
								var id = t.attr('id').substr(4);
								var w = new Win.instance(t, {'type': 'sb_win', 'id': 'win_' + id, 'x': 0, 'replace': {'_name': t.attr('rel')},
									custom_event: function(_o){
										Win.tools.enter_submit(_o.T);
										//close event, if you click on other add - need to hide prev win
										//TODO: not sure that live here is good
										/*$('#sidebar .add, #v_cont .add').unbind('mouseup').live('mouseup', function(){
											//using timout so it wont hide and then open with another event on this element
											setTimeout(function(){_o.hide()}, 100)
										})*/

										//TODO: event for close, default is not working dunno why?
										$('.hide', _o.T).click(function(){_o.hide(); Win.hideLast()})
									}
								});
								Win.windows.push(w);
								//need this to prevent close/open effect, when just need close
								t.data({'win': w, 'clicked': true});



								//setTimeout(function(){t.data({'busy': 0})}, 10000)
								//focusing on input
								//setTimeout(function(){
									$('.listed', w.T).focus()
								//}, 400)

							//need this cause hide effect will take ae[2], so we'll do this after, it adds, some pause
							//but its fine i guess
						//	}, ae[2] + 20);

							//t.data('busy', 1);
						}else{
							//hiding win on second click
							t.data('win').hide();
						}
					///}
				});

				//init Win events;
				Win.events();
			},

			tools: {
				enter_submit: function(_t){
					//submit forms with enter and make <br> with shift/ctrl + enter

					//some fix for universal access
					//using search for .add for sb windows
					//TODO: need to check why it can bind to $('textarea', _t) but cant bind to $('textarea, .add', _t)

					if($('.add', _t).length>0){
						_t.bind('keydown', function(e){
							//checking if there is active list, if so we dont need to submit
							if (e.keyCode == 13){
								var t = $(this)
								//submitting sb_win
								setTimeout(function(){
									//if(!$('.list_win').length)cl('enter was pressed need to send')
									if(!$('.list_win').length)$('.add', t).click();
								}, 300);
							}
						})
					}else{
						//send message with pressing enter
						$('textarea', _t).bind('keydown', function(e){
							//TODO: maybe need to group this with next almost the same block of code
							if (e.keyCode == 13 && (e.ctrlKey || e.shiftKey)){
								var p = $(this).parent();
								$('.submit', p).click();
								//fixing labeled
								//$('textarea', p).blur()
								//so it wont do useless <br>
								return false;
							}
						})
					}
				}

			},

			//method for esc array
			hideLast: function(_list){
				//use _b for esc_string
				var o = this;
				//hiding only when we can, so there will be no conflict with hideAll
				if(!o.no_hide_last){
					//hiding last element of windows array
					if(o.windows.length){
						try{
							//TODO: there was a screenshot bug here, didn't fix it, dunno how to get it
							//fixing undefined issue, wo we won't use esc press to hide undefined window
							for(var i=0, l=o.windows.length, o_0; i<l; i++) {
								o_0 = o.windows.pop();
								if(typeof(o_0)!='undefined')break;	
							}
							//hiding found window
							//if(o_0.D.type=='list_win' || !_list)
							o_0.hide();
						}catch(err){
							//yeah i know there is some strange error
							//TODO: need to fix this later, how it can be, ii guess i put just objects in this array, but it said - no
						}
					}

					//hiding also outsideHide it can only be last
					Win.outsideHide = null;
				}
			},

			//method to hide all windows
			//need this when there are big changes in DOM so windows won't be in wrong positions
			hideAll: function(){
				//setting no hide to fix conflist between hideAll and hideLast
				this.no_hide_last = true;
				setTimeout(function(){Win.no_hide_last=false}, 100)
				//hiding windows and cleanin array
				for(var i=0, l = this.windows.length; i<l; i++){
					var el = this.windows.pop();
					if(el)el.hide();
				}
				Win.outsideHide = null
			},

			//win events like close with outside click
			events: function(){
				$('body').bind('mouseup', function(e){
					if(Win.outsideHide){
						//blocking message, so it won't close avatar when sending message
						var t = $(e.target);
						//getting outside win to hide
						var o = Win.outsideHide;
						//checking if click was inside the win
						if(!Win.inside && o.win){
							//cleaning Win.windows array so it won't contain wrong data
							try{
								Win.windows.splice([Win.windows.indexOf(o.win)], 1);
							}catch(e){
								cl('Strange: %o', e);
							}
							//removing 'clicked' bool from element, doing it after 50ms so it will be after the click on the same element
							setTimeout(function(){
								o.el.data('clicked', false);
								//hiding it
								o.win.hide();
							}, 50);

							//cleaning Win.outsideHide
							Win.outsideHide = {};
						}
						Win.inside = false;
					}
				});
			},

			instance: function(_el, _d){
				o = this;
				o.El = _el;
				o.D = _d;
				//because we haven't yet added o to Win.windows then no -1 is needed
				o.I = Win.windows.length;
				//main DOM for win
				o.T = null;
				o.curMore = 0;

				o.show = function(){
					var _o = this;

					//cleaning esc array for lists
					//if(o.D.type=='list_win'){cl('here: %o', 1);esc_clean(5)}

					//adding window to esc array
					//for list we use special type 5
					esc_add(1);

					//drawing window
					//main DOM object

					//will take html and replace some variables based on object
					//lets say _d = {'aa': 'bb'}, so in string we need to replace 'aa' to 'bb'
					//will take string from object's html
					//avatar +
					//message +
					//zoomer +
					//filters ?
					//sidebar wins ?
					//lists ?
					//also need to pass data id there is _d.data, then will save it to o.T.data
					//also i can pass event functions as an object, but maybe it is better to keep them in the Win object

					var html = Win.html[_o.D.type];
					//replacing some values in html, so window will have necessary content
					if(_d.replace){
						$.each(_d.replace, function(i, v){
							html = html.replace(i, v);
						});
					}
					var offset = [_o.D.x || 0, _o.D.y || 0];

					// cl('ml: %o', ml);
					// cl('offset[0]: %o', offset[0]);
					// cl('_o.El.offset().left: %o', _o.El.offset().left);
					// cl('$(window).width()/2: %o', $(window).width()/2);

					_o.T = $('<div class="' + _o.D.type + ' win">' + html + ' <a class="hide close">hide</a><p class="arrow"></p></div>')
						.appendTo('body')
						.css('top', _o.El.offset().top + _o.El.outerHeight() + offset[1])
						//need ae speed for lists, for it we use 0, cause it looks too slow with animation, when you type
						.fadeIn((o.D.no_ae)?0:ae[2]);

					//horizontal positioning
					var w = _o.El.outerWidth()/2;
					//getting left margin to position window
					var mar = _o.El.offset().left - $(window).width()/2 + offset[0];

					//need to set positioning of window so it will never create horizontal scroll

					if(mar<0){
						_o.T.css({'left': '50%', 'marginLeft': mar});
						//positioning arrow of window
						$('.arrow', _o.T).css('left', w);
					}else{
						_o.T.css({'right': '50%', 'marginRight': -mar-w*2});
						//positioning arrow of window
						//6 is with of arrow
						$('.arrow', _o.T).css('right', w - 6);
					}




					//changing position of win if it is on right side of window
					//TODO: for what i did this?
					//if(ml>100)_o.T.css('marginLeft', ml - _o.T.width()).find('.arrow').css('left', _o.T.width() - w)

					//focus for first input, if it is not labeled then need to think :)
					$('.labeled:first', _o.T).focus();
					//TODO: need to set good positioning, if it is more than 700px of content area then arrow should be on right, and ...
					//attaching class name based events
					_o.events();
				}

				o.hide = function(_t){

					var _o = this;
					_o.T.fadeOut(ae[2], function(){
						//don't know why i need to empty here, but remove doesn't help to clear dom of win
						$(this).empty().remove();
					});

					//cleaning Win.windows
					delete Win.windows[_o.I];
					//removing clicked bool
					if(_o.El.data('clicked'))_o.El.data('clicked', false);
					//removing win reference
					if(_o.El.data('win'))_o.El.data('win', false);

					//cleaning outsideHide
					//if(_o.D.outsideHide)Win.outsideHide = {};



				}

				o.submit = function(_t){
					//will send D.data and all serialiazed form 
					var d = serialize(_t.parent());
					//checking if there are elements in d, if so - sending necessary data
					if(d){
						var o = this;
						//maybe will need thos one day
						o.loading = true;
						//showing loadbar and disabling submit button
						$('.submit', o.T).attr('disabled', 'disabled').addClass('loading');
						$.extend(d, o.D.data);

						var act = d.action;
						delete d.action;
						//maybe doing it a lil bit dirty, need to call this.D.callback from o.ajaxCallBack, but dunno how to

						ajax_n(act, d, function(_o){
							//calling for this function to do some defined in Win.init action
							if(typeof(o.D.callBack)=='function')o.D.callBack(_o);
							//enabling submit
							$('.submit', _o.T).removeAttr('disabled').removeClass('loading');
							//clearing inputs
							$('input[type=text], textarea', _o.T).val('').text('');
							$('.labeled:first', _o.T).focus();
							//maybe will need this one day
							_o.loading = false;
						}, o, function(_o){
							$('.submit', _o.T).removeAttr('disabled').removeClass('loading');
						});
					}
				};

				o.add = function(_t){
					if(!_t.is('.loading')){
						//used only for sidebar add button
						var p = _t.parent();
						Sidebar.add_item(this.El, $('input[type=hidden]', p).val(), $('input[type=text]', p).val(), _t);
						//clearing all inputs
						$('input:not(.add)', p).each(function(){
							$(this).val('');
						});
						//$('input:first', p).focus();

						//hiding win, not sure if we need, but this way it looks faster
						this.hide();
					}
				}

				o.events = function(){
					var _o = this;
					_o.T.bind('click mousedown', function(e){
						var t = $(e.target);

						//toooo long condition, yeah
						//mousedown will work only for list and for more
						//if(((t.is('.list') || t.is('.more')) && e.type=='mousedown') || e.type=='click'){
						if(e.type=='click'){

						//if(e.type=='click'){
							if(t.is('a') || t.is('input')){
								//calling event based on <a> class name
								//we can assign more than 1 event so doing this
								var ar = t.attr('class').split(' ');
								for(var i=0; i<ar.length; i++) {
									if(typeof(_o[ar[i]])=='function')_o[ar[i]](t);	
								};

							}
						}


						//if mousedown in the window then blocking some events, like focus or click for body
						//TODO: before there was no !t.is('.listed'), so if there are some bugs in list prolly cause of this
						//onsole.log('here: %o', t.is('.list') + ' ' + t.is('.listed') + ' ' + t.closest('.list'));
						if((!t.is('.list') && !t.is('.listed')) || t.is('.more'))Win.inside = true;
						//TODO: too complicated
						//if(t.is('.listed.active'))Win.inside = false;
						//inside events should work while outside shouldnt

					});

					//custom event
					if(typeof(o.D.custom_event)=='function')o.D.custom_event(_o);

				},

				o.action = function(_t){
					//removing "action" from class
					var ar = _t.attr('class').replace(/ action/g, '').split(' ');

					//setting Actions ref to dom element, so "a" class will be added correctly
					Actions.El = _t;
					//calling Actions for each class we have in class attribute
					for(var i=0, l=ar.length; i<l; i++) {
						if(typeof(Actions[ar[i]])!='undefined')Actions[ar[i]](o.D.id, o.D.type);
					};
				},

				//two methods that are used only for lists
				o.list = function(_t){
					//using this for list's item click event
					//TODO: using list in this object is not supadupa cool, need to keep reference to some other object that will be created for list after new win is drawn
					var _o = this;
					//this is click inside but it should close window
					//Win.inside = false;
					//setting value of list's input and writing id to hidden input after visible one
					var n = _o.El.next();
					//setting next input (input we'll send) value and rel attribute, rel is to check if selected value was changed (like US with id X and then type UsA, then we don't need to send id, but UsA)
					//def class is to say that input is defined
					_o.El.val(_t.text()).addClass('def').next().val(_t.attr('rel')).attr('rel', _t.text())


					//setTimeout(function(){
					//fixing some strange bug

					//using no_focus so after list item was clicked it won't work like new focus and wont show list again
					_o.El.data('no_focus', 1).focus().data('no_focus', 0)//.data('no_focus', 0)//.removeClass('active');
					//}, 500)

					//saving new value, so we wont show list after item have been already selected
					_o.El.data('cv', _t.text());


					//sometimes we call this event twice, so this is more like a fix
					_o.El.change();

					//resizing input if it is resizable
					if(_o.El.is('.resizable')){
						//cl('here: %o', 222);
						Inputs.resizable(_o.El);
					}

					//TODO: not sure if we need to hide win, it will be hidden after focusout
					//_o.hide();
				},

				o.more = function(_t){

					//right now only for list but after can use it for something else
					var _o = this;
					if(!_t)_t = $('.more', _o.T);

					//cl('----------------------------------: %o', _t);

					if(!_t.is('.loading')){
						//hiding list so it won't be visible from the beggining this will minimize different user noise
						if(_o.curMore==0)_o.T.hide();

						_t.addClass('loading');
						//sending request when focus and more also need to send lists value of form in case they are connected to current

						//checking if list depends on others, it will have class = 'list_d'
						if(_o.El.is('.list_d')){
							//need to generate object of pairs name (-3 symbols from the end "_id") and value which is id
							//will do this only for hidden inputs
							var p = _o.El.parent();
							$('input[type=hidden]', p).each(function(){
								//setting object to send
								var t = $(this);
								var o_0 = t.attr('name');
								//checking if id!=0
								if(parseInt(t.val())!=0)_o.D.send[o_0.substr(0, o_0.length - 3)] = t.val()
							})
						}


						//some additional params
						_o.D.send.what = object_type;
						//_o.D.send.what_id = object_id;
						_o.D.send.more = o.curMore;
						_o.D.send.id = 0;

					//	cl('here: %o', _no_more);

						//this will tell us that we don't need to ++ more
					//	_o.no_more = _no_more;
						//cl('-------: %o', _o.no_more);

						//setting width of the list as the width of the input, 20 is lists padding
						//TODO: maybe later need to calculate it according to list item
						o.T.css('width', Math.max(120, _o.El.outerWidth() - 20));


						ajax_n(_o.D.action, _o.D.send, function(_o, _data){
							//TODO: when we'll do co work need to think how we'll get dependent field list's value
							//var _o = this;
							var D = _data.data.items;

							if(D && D.length>0){

								//removing all current items in list
								$('.list', _o.T).remove();
								var s = '';
								//rendering items
								for(var i =0, l = D.length; i<l; i++){
									s += '<a class="list" rel="' + D[i].id + '">' + D[i].name + '</a>';
								}


								//fixing issue with empty list after tons of arrow right
								//TODO: later need to think about blocking useless request with same content
								if(!$('.more', _o.T).length)_o.T.prepend(Win.html.list_win)


								//insterting list items before more button and removing .loading class
								$('.more', _o.T).removeClass('loading').before(s);



								//showing list if it is first more
								_o.T.show();

								//if we need we ++ more
								//if(!_o.no_more) 
								//_o.curMore++;

								if(_data.data.more){
									//we have more then it is new list, cause for secong we don't have it
									//o.max_more = _data.data.more  || 0;
									_o.curMore = _data.data.more
								}else{
									$('.more', _o.T).remove();
								}

								//cl('++++++++++++++++++++: %o', _o.curMore + ' /// ' + o.max_more);


								//hiding more if there are no more mores
								/*if(_o.curMore >= o.max_more){
									//$('.more', _o.T).slideUp(ae[2], function(){$(this).remove()});
									$('.more', _o.T).remove();
								}*/


							}else{
								$('.more', _o.T).remove();
							}
						//using cache for lists, i guess it is a good idea, to minimize tiny request
						}, _o, 0, true);

					}

				};

				o.show();
			}

		}

	/*
	}
	------/WINDOW------*/

		
	
	
/*
}
------/COMMON------*/


/*------HEADER------ 
function(){
*/

	/*------MAP------ 
	function(){
	*/

		var Map = {
			T: $('#map'),
			G: $('#gmap'),
			V: $('#v_cont'),
			loaded: false,
			changed: false,
			geocoder: null,
			//array of marker icons
			marker_i: [],
			//array of markers
			markers: [],
			gmarkers: [],
			pause_timeout: 500,
	
			map: null,
			//also here will be #editmap
		
			//TODO: need to work on methods order
			//first zoom then load js, then draw, then loadData
			
			init: function(){
				var o = this;
			
				//size of map, if fullscreen then making it full window
				o.W = $(window).width();
				o.w = (is_fullscreen)?o.W:922;
				o.h = (is_fullscreen)?($(document).height()-175):462;

				//init v_cont map
				$('img, a', o.T).click(function(){
					//cleaning Gal._D not to send bounds and search filters that may be set before
					Gal._D = {};
					Map.zoom();
				});
				o.events();
			},
			
			loadData: function(_d){
				//send ajax with _s request and on reply do
		
				//need data for
				//id
				//type photo (0), video (1) ...
				//title
	
				//description (20 comments / 10 likes)
				//link to object
				//image
				//target (link.html (0 if it is not video or photo), video.mov (id of video), photo.jpg)
		
				//possible actions (set default, unset default, remove, connect, disconnect,      like, unlike, ride, unride, make session ...)
				//like array
				//this will be something like numbers, each action will have it's own id, not so hightechprogrammsupercool
				//but fast
				//actions will be compared to array lp.searchItem
		
				var o = this;
			
				//removing all markers
				o.clearMap();
		
				//TODO: maybe need to send coordinates of center in search request
			
				//adding loadbar and showing it
				$('<div class="loading"></div>').show().appendTo(o.T);
			
			
			
				//setting Gal._D, so when will switch from default map view to grid, Gal will know what to show
				//so we are like passing Map._D to Gal._D, in Gal we have good switcher, know it is not the best :) 
				if(_d)Gal._D = _d;
				_d = Gal._D;
			
			
			
				var d = {'div': 'map', 'forcediv': 1};
				$.extend(d, _d);
			
			
				//fixing id for map search
				//TODO: need to make better fix, need this so server will know if this is map for search or form object
				if($('.gal_map_wrapper #map').is(':visible')) d.id=0;
				
				//requesting data
				//timeout makes it a lil bit more smooth
				setTimeout(function(){
					ajax_n('view', d, function(_el, _data){
						o.dataLoaded(_data.data);					
					});
				}, 500)
		
			},
	
			dataLoaded: function(_data){
				//TODO: why sometimes I use _d and sometimes _data
				//TODO: hide loader
				//TODO: draw markers and update maptools
		
				var o = this;
				
				
				
				
				
				$('.loading', o.T).fadeOut(ae[2], function(){$(this).remove()})
		
				//var ar = ajax_StrToAr('1|0|||<h2>Found <i>2</i> spots for <i>title</i></h2>, show <a rel="1" class="a">closest spots</a><a rel="2">shops</a><a rel="3">useful places</a>||101|1|title1|<b>23</b> likes<p><b>3</b> upcoming events</p>|link.html|1.jpg|40.721;-74.016|0,3,6||101|1|title1|description2|link.html|5.jpg|40.716;-73.999|6,4');
		
				//TODO: later we can show map tools here, like "show closest spots, users etc"
				//$('.map_tools', o.T).append('<div class="filters">' + 22222222 + '</div>')
		
		
		
				//drawing intro (search title with filters)
				Gal.tools.draw_intro(_data.intro, _data.filters);
			
			
			
				var items = _data.items
			
			
				/*items = [
				{'id': 0, 'x': 2, 'y': 22, 'name': 'NAME1 (99)', 'title': 'TITLE', 'amount': 99, 'type': 'group'}, 
				{'id': 1, 'x': 8, 'y': 78, 'name': 'NAME2', 'title': 'TITLE'}, 
				{'id': 2, 'x': 2, 'y': 60, 'name': 'NAME3 (88)', 'title': 'TITLE', 'amount': 88, 'type': 'group'},
				{'id': 3, 'x': 35, 'y': 30, 'name': 'NAME4', 'title': 'TITLE'}]*/
			
				//TODO: doing this only for o.map, maybe later will use it for o.mapN, to show close location so it will be easier to find some lace?!
				if(items){
					//TODO: need to clean all marker on map also need to clear group markers array
					
					//removing all markers
					o.clearMap();

					//cleaning o.markers
					o.markers = [];
				  	
				
				
					//showing max 10 items, later will change to 36 I guess
					var bounds = new google.maps.LatLngBounds();
					var ll;
					for(var i=0, l = items.length; i<l; i++) {
						//cl('here: %o', items[i].x + ' ' + items[i].y + ' ' + new google.maps.LatLng(items[i].x, items[i].y));
						ll = new google.maps.LatLng(items[i].y, items[i].x)
						//prelast argument is type of marker
						//all markers will be hidden, will show them in clearMap
						o.drawMarker(ll, items[i], items[i].type || 'm_common', i);
						bounds.extend(ll);
					};
					
					
					//drawing amount of group markers, it clears and draws 
//					o.drawAmount();
					
					//cl('here: %o', bounds.getCenter());
					//doing this for first time only, cause later user can move map and we don't really need it, ft is when you search or update filters
					if(o.ft){
						//TODO: need to check with good connection
						//setting map center and map zoom, that depends on markers, using timeout cause sometimes it doesn't work
						//setTimeout(function(){
							o.map.fitBounds(bounds, true);
							o.ft = false;
						//}, 500)
						
					}

				}
				
			},
	
			loadJS: function(_type){
				//_type = 1 for edit
				var o = this;
				if(!_type && !$('#gmap').length) {
					o.T = $('#map');
					o.T.append('<div id="gmap"><p>' + lp.loading_map + '</p></div><a class="close">&times;</a>');
					o.G = $('#gmap');
				
					
					if(o.loaded)Map.draw();
				
				
					//resizing map if it is fullscreen
					if(is_fullscreen){
						//width 100% doesn't work so we set width
						$('#map, #gmap').css({'height': $(window).height()-177, 'width': $(window).width()});
						//setting height again, arghhh, fullscreen mode
						$('#gal').css({'height': $(window).height()-90});
						
					}else if(!o.object_map){
						//if map is fr search
						$('#map, #gmap').css({'height': $(window).height()-177, 'width': $(window).width()});
						
						//fixing two "loading map" issue in search on map
						$('#map>p').hide()
						
					}else{
						//showing map for v_cont
						//TODO: maybe can do it better, and should be ae[...]
						setTimeout(function(){$('#gmap').show()}, 500)
					}
					
				
				
				}else{
					//some magic with timeout
					//TODO: later need to check why there are so many timeouts - think about animation order for #header
					//checking if the js was loaded and if map for new / edit wasn't set
					if(o.loaded && !o.mapN)setTimeout(function(){Map.draw(1)}, 1000);
				}
		
				
		
		
				if(o.loaded){
					//showing map for gallery
					if(!_type) $('#gmap, .close', o.T).show();
				}else{
					//adding scrpt to DOM
					var script = document.createElement("script");
					script.type = "text/javascript";
					script.src = "http://maps.google.com/maps/api/js?v=3.2&sensor=false&async=2&callback=Map.draw";
					//true for devices with sensor
					document.body.appendChild(script);
					o.loaded = true;
					//setting type, so after js was loaded we'll know what to do
					o.edit = _type;
				}
			},
		
			loadMarkers: function(_map, _drag){
				var o = Map;
				//_drag - boolean to detect if it was zoom or drag,
				//for drag we do additional check
			
				//method to call after there was map zoom_changed or center of the map was changed
				//bounds are the current zoom - 1, so when dragging it is almost two viewport in both directions, and while zooming
				//it is 1 zoom without load, and then another one with resetting bounds and load
			
			
			
				//getting current zoom
				var z = _map.getZoom();
			
			
				//getting screen bounds
				var c_bounds = _map.getBounds();
				//doing this so in zoom_changed event it wont call mapChange
				o.prevZoom = z-1;
				//zooming back, to make areay bigger, we'll load markers exactly for that area
				_map.setZoom(z-1);
				//cl('map.getBounds(): %o', _map.getBounds().toUrlValue(6));
			
				if(_drag){
				
					//first checking if Map.prevBounds is defined OR //checking if screen bounds main points are in previous loaded bound, if not - loading more
					if(!o.prevBounds || (!o.prevBounds.contains(c_bounds.getNorthEast()) || !o.prevBounds.contains(c_bounds.getSouthWest()))){
						var o_0 = true;
					}
				}else{
					//changing bounds
					var o_0 = true;
				}
				
				
				
				if(o_0 && Gal._D){
					
					/*rec = new google.maps.Rectangle({
						'map': _map,
						'bounds': _map.getBounds(),
						'strokeColor': '#00f',
						'strokeOpacity': 0.2,
						'strokeWeight': 2,
						'fillOpacity': 0
					})*/
					
					
					//TODO: need to make good here, without timout, to see problem - uncomment rectangles
					setTimeout(function(){
						/*rec = new google.maps.Rectangle({
							'map': _map,
							'bounds': _map.getBounds(),
							'strokeColor': '#f12b2b',
							'strokeOpacity': 0.2,
							'strokeWeight': 2,
							'fillOpacity': 0
						})*/
					
					
					
						
					
						cl('loading markers for points: %o', _map.getBounds().toUrlValue(6));

						var d = Gal._D
						
						//adding bounds var to Gal._D which contain all necessary data with filters
						d.bounds = _map.getBounds().toUrlValue(6);
					
						//sending zoom
						d.zoom = _map.getZoom();
					
					
						//TODO: need to make better fix
						if($('.gal_map_wrapper #map').is(':visible')) d.id=0;
					
						//some additional param for API
						d.div = 'map';
					
					
						ajax_n('view', d, function(_el, _data){
							var o = Map;
							//call dataLoaded to draw markers on map
							if(o.pause==1) o.dataLoaded(_data.data);
							o.pause = _data.data;	
						});
					
						//timeout to make a little pause, if loading will be faster then timout, if not - loading
						o.pause = 0;
					
					
						setTimeout(function(){
							if(typeof(o.pause)=='object') o.dataLoaded(o.pause);
							o.pause = 1;
						}, o.pause_timeout)
				
						//saving previous bounds to compare them after next drag end
						//changing bounds to new for loaded data
						o.prevBounds = _map.getBounds();
					}, 100)
				
				}
				
			
				/*var marker = new google.maps.Rectangle({
					bounds: c_bounds,
					map: _map,
					fillColor: '#ff0000',
					fillOpacity: 0.05,
					strokeColor: '#ff0000',
					strokeWeight: 1,
					strokeOpacity: 0.4
				});
			
				var marker = new google.maps.Rectangle({
					bounds: _map.getBounds(),
					map: _map,
					fillColor: '#000000',
					fillOpacity: 0.05,
					strokeColor: '#000000',
					strokeWeight: 1,
					strokeOpacity: 0.4
				});*/
			
				//doing this so in zoom_changed event it wont call mapChange
				o.prevZoom = z;
			
				//setting zoom to current, not sure if this is a good idea to change zoom so fast
				//TODO: need to check
				_map.setZoom(z)
		
			},
		
			//Geocoding block for map search and edit location
			textToLL: function(_text, _id){
				var o = this;
				o.searchMapId = _id
				if (o.geocoder) {
				    o.geocoder.geocode( { 'address': _text}, function(results, status) {
				   		if(status == google.maps.GeocoderStatus.OK) {
				    	   	var c = results[0].geometry.location;
							//TODO: maybe need to be smart and this like an copy of object?!
							var m = Map.map;
							if(Map.searchMapId == 'gmap_plus'){
								Map.llToText(c);
								Map.markerN.setPosition(c);
						
								m = Map.mapN
							}
						
						
							//setting zoom and center of the map
						    m.setCenter(c);
							//not sure if we need to set zoom, it is jumping when you don't want it to jump
							//m.setZoom(sett.map_zoom[0]);
				
					
							//TODO: maybe need to send coordinates in search request
							//adding marker to found location
							/*var marker = new google.maps.Marker({
					       		map: o.map, 
					       	    position: c
					       	});*/
						}else{
							//TODO: need to decide do we need to show error, for what, form another side, maybe user wants to know
							//alrt.show("Geocode was not successful for the following reason: " + status);
						}
					});
		   
				}
		
			},
	
			llToText: function(_ll, _b){
				//need _b to now if i need to change loaction input, don't need to do this when first loading edit, but after need it even in edit 
				var o = this;
				if (o.geocoder) {
				
					o.geocoder.geocode({'latLng': _ll, language: 'en'}, function(results, status) {
	    					if(status == google.maps.GeocoderStatus.OK) {
	    						if (results[0]) {
	    							var loc = results[0].formatted_address;
									var r = results[0].address_components;
									var l = r.length;
								
									//array of types we need, and address will be exactly in this order
									var types_ar = ['country', 'administrative_area_level_1', 'administrative_area_level_2', 'administrative_area_level_3', 'route', 'street_number']
									//types_ar[-1] = 'none';
								
									var j;
								
									var address = {}
									//generating array of address
									for(var i=0; i<l; i++) {
										if(r[i].types){
											j = $.inArray(r[i].types[0], types_ar);
											//taking values of address
											if(j>=0){
												//for state we do short_name
												if(j==1)address.state = r[i].short_name;
												address[types_ar[j]] = r[i].long_name;
											}
										}
									};
								
									//making final address object
									//country is fine
									//state is fine
									//route is fine
									//? address.street = ((typeof(address.street_number)=='undefined')?'':address.street_number) + ' ' + address.route;
									//now some magic :)
									//city
								
									//first we make arra from formatted_address and we remove numeric elements (in Russia they use postal code in the end of formatted_address)
									//comparing administrative_area_level_1/2/3 to second of formatted_address (without numbers) if yes then take it, if no - taking 3d last from location
									//removing all numbers
									loc = loc.replace(/\d/g, '');
									var ar = loc.split(', ');
									//if last element is empty - we using length - 3
									//using >2 cause there can be \s
									l = ar.length-((ar[ar.length-1].length>2)?2:3);
								
									//removing spaces from beggining and end of the string
									var o_0 = Inputs.trim(ar[l]);
								
								
									//renaming reoute to street, we want it good
									address.street = address.route;
								
									//comparing address.administrative_area_level_1/2/3 with  o_0, in some cases address's city is 2 or 3 from the end
									//taking -3 value, mostly for US, they have ..., city, state, country
									address.city = ar[l-1];
									for(i=1; i<4; i++){
										//TODO: NEED TO COMPARE NOT JUST o_0 but need to exclude numbers (v) and remove \s in the beginning if it exists
										if(address[types_ar[i]]==o_0){
											address.city = o_0;
											break;
										}
									}
								
									//in some cases city is "" so putting something instead
									if(!address.city)address.city = address.administrative_area_level_1
								
								
	    							//if edit of object then don't need to set location based on coordinates (only when init)
									if(Plus.pb!=1 || !_b){
										var t = $('#plus .location');
										//setting values of address inputs
										$.each(address, function(_i, _v){
											var o_0 = $('input[name="' + _i + '"]', t);
											if(typeof(_i) != 'undefined'){
												try{
												
													o_0.val(_v).addClass('def');
												}catch(err){}
											}
											//resizing inputs
											//some strange bug here, when init resizebale is faste than setting valut of fields
											//so, again, we are adding our favourite setTimeout :), but only for first time when init map for edit/new
											/*if(!Map.changed){
												cl('here: %o', 2);
											
											}else{
												Inputs.resizable(o_0);
											}*/
											setTimeout(function(){Inputs.resizable(o_0);}, 100)
										
										});
										//showing address inputs
										t.fadeIn(ae[2]);
									}
	    							//need to split array for edit
	    						}
	    					}else{
	    						//alrt.show("2|Geocoder failed due to: " + status);
	    					}
				    });
				}
				o.markerN.setPosition(_ll);
				o.mapN.panTo(_ll);
				//o.map.panTo(_ll);
			},
		
			spotToLL: function(_d){
				//_d can contain marker, map, name of spot, id of spot
				//calling this function when need to set marker position to some text/id defined spot
				var o = this;
			
				//not so good part, so passing everythin everytime
				/*if(!_d)var _d = {};
				//defining some default values
				if(!_d.marker)_d.marker = Map.markerN;
				if(!_d.map)_d.map = Map.mapN;*/
			
			
			
			
				//defining zoom of map if it is not defined
				if(!_d.zoom)_d.zoom = _d.map.getZoom();
			
				_el = _d;
			
				//http://dev.uride.it/api?action=view&type=spot&id=uride.it%20hq&coordinates=
				ajax_n('view', {'type': 'spot', 'id': _d.name, 'uride': 1}, function(_el, _data){	
					//setting position of marker
					if(_data.data && _data.data.object){
						var o = _data.data.object;
						var ll = new google.maps.LatLng(o.y, o.x);
						_el.marker.setPosition(ll);
						_el.map.setCenter(ll);
					}
				}, _d);
			},
		
			llToSpot: function(_ll, _t){
				var o = this;
				//_t - elemnt to write name
				//getting what we need
				//http://dev.uride.it/api?action=view&type=spot&id=uride.it%20hq&coordinates=
				ajax_n('view', {'type': 'spot', 'coordinates': _ll.lat() + ',' + _ll.lng(), 'uride': 1}, function(_el, _data){	
					//printing recieved value
					//maybe here we need to check if it is input then val, no - text
					if(_data.data)_el.val(_data.data.object.name).addClass('def');
				}, _t);
			},
		
			mapSearchInit: function(_t){
				_t.submit(function(){
					Map.textToLL($('input:first', $(this)).val(), $(this).prev().attr('id'));
					return false;
				});
				//submitting form when a was clicked
				$('a', _t).click(function(){$(this).parent().submit()})
			},
	
			zoom: function(_d){
				//zoom is not the best name
				var o = this;
			
				//setting ft variable, so we'll center map on bounds only after zoom method is called, maybe will use it for something else
				o.ft = true
			
			
				//setting bool to know if this map is for search or for object's map
				o.object_map = ($('#v_cont #map').length)?true:false;
			
				//setting search request in the object, cause we need to call draw function as callback of google maps, and need to pass argument there
				o.D = _d
				//loading all gmaps scripts from google
				Map.loadJS();
				//effects
				//o.T.animate({height: o.h}, ae[2]);
				//if(is_fullscreen){
					//$('#gmap', o.T).css({'height': o.h - 130});
					//TODO: have no idea why i need timeout here, but it doesn't work without
					//setTimeout(function(){$('#gal').css({'height': o.h-125, 'width': Gal.W + 15});}, 200)
				//}
			
			
				$('.p', o.T)
					.fadeOut(ae[3])
					//adding faded class so after it will be easier to select it
					.toggleClass('faded');
		
		
				if(!$('#map_h', o.V).length){
					//doing something with description only if there is no #map_h in it, this fixes bug when you switch to search map
					//getting height to save it for next animation (show it)
					var h = $('.info', o.V).height();
					$('.info', o.V)
						.data('h', h)
						.animate({'height': 320}, ae[2], 'swing', function(){$(this).hide()})
						.toggleClass('faded');
				}
		
				
				//showing map after hiding .info, i know setTimout is ...
				setTimeout(function(){
					//var h = if($('.fullscreen').length>0)
					//too sleepy today to try to remove this timeout, later need to try
					Map.T.animate({'width': (Map.object_map)?o.w:o.W, 'height': (Map.object_map)?380:o.h}, ae[3], 'swing', function(){
						Map.G
							.css({
								'height': (Map.object_map)?380:o.h,
								'visibility': 'visible',
							})
							.next().next().fadeIn(ae[2]);
				
							//fixing resize bug, sometimes google define map area before it is completely set
							try{
								if(google)google.maps.event.trigger(Map.map, "resize");
							}catch (err){}
				
						//show loader and setting it's position
						if(Map.object_map){
							$('.loading', Map.T).css('top', Map.T.height()/2 - 10).show();
						}else{
							$('.loading', Map.T).css({'top': Map.T.height()/2 - 24, 'left': o.W/2}).show();
						}
					});
				}, ae[2]);
			},
	
			unzoom: function(){
				var o = this;
				//hiding gmap
				o.G.fadeOut(ae[2]);
				//hiding map tools
				$('.map_tools', o.V).fadeOut(ae[2]);
				//TODO: doing it a lil bit lazy here, better just to pass what i'm going to animate
				o.T.animate({width: 274, height: 300}, ae[4], 'swing', function(){
				
				
					//animating object's media, so there won't be any jump
					var h = $('.faded:last', $(this).parent()).data('h')
					$('.faded:last', $(this).parent()).animate({'height': h}, ae[2]);
				
					//showing static map and object's photo
					$('.faded', $(this).parent()).fadeIn(ae[2]).toggleClass('faded')
					//showing photo (yeah, can do it in one select, but too lazy now)
					//$('.faded:last', $(this).parent()).slideDown(ae[4]).toggleClass('faded')
				
					o.G.css('visibility', 'hidden');
				});
			},
		
			//draw has some events for map, for zoom and for drag
			draw: function(_type){
			
				var o = this;
				//in some cases google is empty, so doing try catch
				try{
					//Run some code here
		
					//some save space var
					var gm = google.maps;
			
					//setting type - plus / map search
					if(!_type){
						_type = o.edit;
						o.edit = null;
					}
	
					if(!o.geocoder){
						//some google settings for markers
						o.geocoder =  new gm.Geocoder();
						var mSize =   new gm.Size(23, 34);
						var mPoint0 = new gm.Point(0, 0);
						var mPoint1 = new gm.Point(11, 34);
						//setting up markers
						var o_0 = 'http://www.' + domain + '/i/i/markers/';
						o.marker_i[0] =     new gm.MarkerImage(o_0 + 'shad.png', new gm.Size(43, 36), mPoint0, mPoint1);
						o.marker_i['m_common'] =  new gm.MarkerImage(o_0 + 'r.png', mSize, mPoint0, mPoint1);
						o.marker_i['new'] = new gm.MarkerImage(o_0 + 'd.png', mSize, mPoint0, mPoint1);
						o.marker_i['group'] = new gm.MarkerImage(o_0 + 'g.png', new gm.Size(44, 65), mPoint0, new gm.Point(22, 65));
			        }


					//map search html
					var o_0 = '<div class="map_tools"><form><input type="text" value="' + lp.search_on_map + '" class="labeled" /><a class="find">go</a></form></div>';
				
					if(_type){
						//map for plus
						//o.mapT = $('#gmap_plus');
						var el = document.getElementById("gmap_plus");
						var map = $('#gmap_plus');
						//draw and init map search, only if it is not already set
						$('.map_tools', map.parent()).remove();
						map.after(o_0);
						//checking if map is visible, if so showing map tools
						if(map.offset().top>0)map.next().css('top', 69);
						o.mapSearchInit(map.next());
					}else{
						//map for v_cont
						o.G.show().after(o_0);
				
						//showing map search and close 
						//delay can't help, timeout again, too many animations, that's why
						//TODO: later need to make something with animation, so there will be no timeouts
						setTimeout(function(){
							//checking if map is in v_cont
							if(!o.object_map){
								//if not show map search
								$('.close, .map_tools', o.T).fadeIn(ae[3]);
							}
						}, 1000)
				
						var el = document.getElementById("gmap");
				
						//$('#map').prepend('<div id="gmap" style="width: 300px; height: 300px; display: block; visibility: visible; overflow: none;"></div>')
						o.mapT = $('#gmap');
						//loading data only after some timeout, so the map will be ready
						//setTimeout(function(){
							o.loadData(o.D);
						//}, 200)
						//hiding loader so it won't be visible on preview of map
						$('.loading', o.T).hide();

						//init search on map, maybe TODO: need to add search field here too
						o.mapSearchInit($('form', o.T))
					}
			
					//getting coordinates of current object or of user to center the map
					var a = [obj_y || user_y, obj_x || user_x];
			

					var s = {
						zoom: (_type)?sett.map_zoom[0]:sett.map_zoom[1],
						mapTypeControlOptions: {'style': gm.MapTypeControlStyle.DROPDOWN_MENU},
						//zoomControlOptions: {style: gm.ZoomControlStyle.SMALL},
						navigationControlOptions: {'style': gm.NavigationControlStyle.SMALL},
						streetViewControl: false,
						panControl: false,
						mapTypeId: gm.MapTypeId.ROADMAP
					};
					
					//centering only for plus maps, so it wont jump for not plus
					if(_type)s.center = new gm.LatLng(a[0], a[1])
	
					//TODO if for edit map
	
					//need this variable to send it for location logic
					o.changed = false;
					//adding draggable marker if plus
			
			
			
					if(_type){
						//map for plus
						s.mapTypeControlOptions = {
														style: gm.MapTypeControlStyle.DROPDOWN_MENU, 
														position: gm.ControlPosition.RIGHT_BOTTOM
													}
						//o.mapN.zoomControlOptions.position = ;
						s.navigationControlOptions = {position: google.maps.ControlPosition.LEFT_BOTTOM};
				
						o.mapN = new gm.Map(el, s);
						//setting coordinates for map, by default it will be spot's coordinates
						o.drawMarker(new gm.LatLng(a[0], a[1]), {'name': lp.setMarkerPosition}, 'new');
						o.llToText(new gm.LatLng(a[0], a[1]), true);
			
						//cl('here: %o', o.mapN);
						//changing position of map controls for new/edit object, need this so address will be on top and will look good
					
					}else{
						//map for v_cont
						var map = o.map = new gm.Map(el, s);
				
				
						/*setTimeout(function(){
							//!!! removing some google messy html
							//layer of infowin shadow
							$('>div:eq(0)>div:eq(0)>div:eq(4)', o.G).addClass('google_infowin_shadow')
							//layer of infowin
							$('>div:eq(0)>div:eq(0)>div:eq(6)', o.G).addClass('google_infowin_layer')
						}, 100)*/
				
						//now not using it for mapN, later to make it easier for user to find the place we can do for both maps
						//limitiong the zoom
						var inProcess = false;
			
						//setting prev zoom variable to compare it to current zoom
						Map.prevZoom = map.getZoom();
			
			
			
						gm.event.addListener(map, 'zoom_changed', function(){
							try{
								//using try, cause there were cases where it returns some errors, when you load map first time ever (without cache)
								//code from stackoverflow
								if (inProcess) return;
								//zoom limit array
								var a = sett.map_zoom;
							    if (o.map.getZoom() > a[3]) {
							        inProcess = true;
							        o.map.setZoom(a[3]);
							        inProcess = false;
							        return
							    }else if (o.map.getZoom() < a[2]) {
							        inProcess = true;
							        o.map.setZoom(a[2]);
							        inProcess = false;
							        return;
							    }
						
								//current zoom
							
							
								//if (map.getZoom()<sett.map_zoom[2])map.setZoom(sett.map_zoom[2]); 
							
								var z = map.getZoom();
							
							
								//if(Map.prevZoom != z){
									//dong something only when zoom was changed, because o.map.fitBounds(bounds, true); makes a lot of zoom at once
								
								
									//zoom limit array
									var a = sett.map_zoom;
						
									//TODO: later need to think about these limits
								    /*if (z>a[3] || z<a[2]){
								       	//map.setZoom(a[(z>a[3])?3:2]);
								        return;
								    }*/
							
									//detecting if zoom was changes if so we need to send additional request for better markers
									//was if(Map.prevZoom-1 > map.getZoom() || Map.prevZoom + 1 < map.getZoom()){
									//but we need for each zoom i guess
									if(Map.prevZoom != z && !Map.ft){
										//prolly we need to load some new stuff, so calling
										Map.loadMarkers(map);
										Map.prevZoom = z;
									}
								//}
					
								//Map.loadData()
					
								/*for(var i=0, l=Map.markers.length; i<l; i++) {
									Map.markers[i].setVisible(false);
									Map.markers[i].setVisible(true);
								};*/
					
								/*
								redrawing markers
								if (Map.markers) {
								    for (i in Map.markers) {
								      Map.markers[i].setMap(null);
										Map.markers[i].setMap(Map.map);
								    }
							  	}*/
				
								/*
					
								In order to remove the marker, you may need to remove the listeners.

								google.maps.event.clearInstanceListeners(marker);
								marker.setMap(null);
								markers.remove(marker);
								delete marker;
					
								*/
							}catch (error){
								cl('uride.it: RangeError: Maximum call stack size exceeded. %o', error);
							}
						});

						gm.event.addListener(map, 'dragend', function(){
							//cl('here: %o', map.getCenter());
							//here need to put some limit so not every drag we'll send data
							//the best way is to compare bounds and if current will be out of unzoomed one (the bi bound with current markers), then we need to load markers
							Map.loadMarkers(map, true);
						});
					
						/*gm.event.addListener(map, 'scroll', function(){
							cl('here: %o', 1);
						})*/

						//o.map.setCenter(new google.maps.LatLng(obj_lat, obj_lng))
						//"refreshing" map, so there will be no halfmap bug
						//$('#gmap_plus').hide().show();
						//setting
					
				
						//scrollwheel zoom
						if(!is_fullscreen){
							//we'll switch scrollzoom on when some key was pressed
							map.setOptions({'scrollwheel':false});
						}
					
					
						//fixing something :)
						setTimeout(function(){Map.mapT.css('zIndex', 1)}, 1000);
					
					
					}
				
				}catch(err){
					//Handle errors here
				}
			},
		
			drawMarker: function(_pos, _d, _type, _i){
				var o = this;
				//How to add another
				var gm = google.maps
				
				//need this to take  object's data rom Gal.D
				_d.i = _i
			
			
				var marker = new gm.Marker({
					position: _pos, 
					map: (_type == 'new')?o.mapN:o.map,
					//animation: google.maps.Animation.DROP, only for v3.3+?
					icon: o.marker_i[_type], //need to do something for icon , if it is not new or current then uride's default
					shadow: o.marker_i[0],
					draggable: (_type == 'new')?true:false,
					title: _d.name,
					data: _d,
					type: _type
				});
	
				//TODO: need to clean variable o.markers[_type] when there is a new search, for edit and when first time opening
				/*if(!o.markers[_type]){
					o.markers[_type] = [];
				}*/

				//if new / edit
				if(_type=='new'){
				
					o.markerN = marker;
					gm.event.addListener(marker, 'dragstart', function(){mdownE = true;});
					gm.event.addListener(o.mapN, 'dragstart', function(){mdownE = true;});
					gm.event.addListener(marker, 'dragend', function(event) {
						Map.llToText(event.latLng);
						Map.changed = true;
					
						//adding pretty stupid condition 
						//TODO: later need to decide - send everytime or make good fix?
						//converting ll to spot and writing it to spot's field
						if($('.spotted:visible', Plus.T).length)Map.llToSpot(event.latLng, $('input[name=field_spot]', Plus.T));
					
					
					});
					gm.event.addListener(o.mapN, 'click', function(event) {
						Map.llToText(event.latLng);
						
						
						//var ar = event.latLng.toUrlValue(6).split(',')
						//cl('coordinates: %o', 'y(lat)=' + (parseInt(ar[0]) + 90) + '  x(lng)=' + (parseInt(ar[1])+180));
						Map.changed = true;
						//adding pretty stupid condition 
						//TODO: later need to decide - send everytime or make good fix?
						//converting ll to spot
						if($('.spotted:visible', Plus.T).length)Map.llToSpot(event.latLng, $('input[name=field_spot]', Plus.T));
					});
				}else{
					
					if(_type=='group'){
						//if amount then adding marker to group markers array
						o.gmarkers[marker.data.id] = marker;


						//cl('marker.data.zoom: %o', marker.data);
						//adding click to zoom
						gm.event.addListener(marker, 'click', function(event) {
							cl('marker zoom // current map zoom: %o', marker.data.zoom + ' // ' + Map.map.getZoom());
							
							//not sure if this is the coolest way to zoom
							Map.map.setZoom(marker.data.zoom);
							Map.map.setCenter(this.getPosition());
						
						});
						
						
						//drawing infowin with numebr
						//for first it wors, but after we need to fix it with some method called from dataLoaded
						Map.drawWin(marker, marker.data, true);
						
						//cl('marker: %o', marker);
						
						//removing all group markers
						//$('.google_infowin_layer .number').remove();
						//drawing numbers for goup markersas infowindows
						
						//setTimeout(function(){Map.drawWin(marker, marker.data, true);}, 1000)
						
						
						
					}else{
						gm.event.addListener(marker, 'click', function(event) {
							Map.drawWin(this, this.data);
						});	
					}
				
				
					marker.setVisible(false);
					//pushing marker to markers array
					o.markers.push(marker);
				
					//fixing bug when part of map is hidden after fast show
					gm.event.trigger(Map.map, "resize");
				
				}
	
	
			},
		
			resetMarkerN: function(p){
				if(!p)var p = new google.maps.LatLng(obj_lat, obj_lng);
				this.markerN.setPosition(p);
				this.mapN.setCenter(p);
			},
	
			//all map manipulation that can hide something or remove are here
			drawWin: function(_marker, _d, _group){
				
				
				var o = this;
				//using global infowin so there will be only one on the screen
				//if(o.infowindow && !_group)o.infowindow.close();
			
				//if(!$('.google_infowin_layer').length){
				o.infowindow = new google.maps.InfoWindow({content: '<div class="last_infowin">' + _d.id + '</div>', 'disableAutoPan': _group});
				o.infowindow.open(Map.map, _marker);
				//}
				
				
				
				//removing default content of info window and showing what we need
				google.maps.event.addListener(o.infowindow, 'domready', function () {
					
					//detecting the window div, so later we'll change style of our infowin
					if(!$('.google_infowin_layer').length){
						$('.last_infowin')
							//parent of all infowindows
							.parent().parent().parent().parent().parent().addClass('google_infowin_layer')
							//parent of all shadows for infowindows
							.prev().prev().hide()
					}
				
				    if (Map.infowindow.get("isdomready")) {
				        //show the infowindow by setting css 
				        //$('.infowin-content').css('visibility', 'visible');                   
				    }else{
				        //trigger a domready event again.
				        google.maps.event.trigger(Map.infowindow, 'content_changed');
				        Map.infowindow.set("isdomready", true);
						//setTimeout(function(){
							//doing pretty risky if google will change something we need to change it too
							//also we can get infowins element by
							//var t = $('#last_win', Map.T).parent().parent().parent().parent();
							//var t = $('.google_infowin_layer>div:last');
						
							//closing all infowins
							
							var o_0 = '.google_infowin_layer>';
							
							
							
							//checking if there is no infowin for this marker
							if(_d.type != 'group'){
							
								if(!$(o_0 + '.marker' + _d.id).length){
								
									//removing all infowindows
									$(o_0 + '.infowin:not(.number)').remove()
								
								
								
									//drawing new
									var t = $(o_0 + 'div:not(.infowin):last')
								
									var s = '<a class="win_close">&times;</a><a class="win_close_1">&times;</a>' + 
											'<a href="http://www.' + domain + '/' + _d.object_type + '/' + _d.id + '" class="img"><img src="http://i.' + domain + '/m/' + _d.pic + '" /></a>' + 
											'<h1><a href="http://www.' + domain + '/' + _d.object_type + '/' + _d.id + '">' + _d.name + '</a></h1>';
									//actions for map item
									//s += drawActions(_a[7].split(','))
									//drawing actions
									if(_d.actions){
										s += '<ul class="actions">'
										$.each(_d.actions, function(_i, _v){
											//cl('here: %o', _i);
											s += '<li class=" ' + _i + ((_v==2)?' a':'') + '">' + _i + '</li>'
										})
										s += '</ul>';
									}
									s += '</div>';
								
									t
										.html(s)
										//.css('z-index', 301)
										.data('m', _marker)
										//need this to get object's data from Gal.D
										//TODO: do we need this?
										//.data('d', [0, _d.i])
										.data('data', _d)
								
									//cl('>>>>>>>: %o', _d.id);
									t.hide().fadeIn(ae[2]).addClass('infowin marker' + _d.id);
								
								}else{
									//if win is opened, then removing google infowin without modifing it
									$(o_0 + '.marker' + _d.id + ', ' + o_0 + 'div:not(.infowin):not(.number)').remove()
								
								}
							}
							
							
						//}, 50)
				    }
				})

		
			},
	
			drawAmount: function(){
				
				
				//after all markers are drawn we call drawWin to draw numbered markers
				//we reading doing it after 500 (guess 500 is in google)
				//setTimeout(function(){
					
					//removing all numbered wins
					$('.google_infowin_layer>.number').remove();
					
					//getting all opened infowins
					$('.google_infowin_layer>div:not(.infowin)').each(function(i){
						var t = $(this);
						
						//getting object for each opened win, before we save id as a text
						d = Map.gmarkers[parseInt($('.last_infowin', t).text())];
						
						if(d){
							//adding click event to zoom
							t
								//.attr('title', d.data.name)
								.click(function(){
										google.maps.event.trigger(Map.gmarkers[$(this).data('id')], 'click');
									})
								.data('id', d.data.id)
								.addClass('number infowin marker' + d.id)
								.html(d.data.amount);
						
							//with css it doesnt work, setted in style
							//also setting zIndex so numbers will always be under infowins, can't do anything without timeout
							setTimeout(function(){t.css({'cursor': 'pointer', 'zIndex': 50})}, 100)
						}
					});
				//}, 500)
			},
			
			clearMap: function(){
				var o = this;
				if (o.markers) {
					var markers_r = o.markers;
					setTimeout(function(){
							//showing hidden markers
						  	for (var i = 0, l = o.markers.length; i<l; i++) {
						  	  	o.markers[i].setVisible(true);
						  	}
						

							
							//removing old markers, doing timout so it wont blink, now just shadow is blinking
							setTimeout(function(){
								//$('.gmnoprint', o.T).remove()
							  	for (var i = 0, l = markers_r.length; i<l; i++) {
							  	  	markers_r[i].setMap(null);
									//TODO: it can be better to remove shadows first
							  	}
								delete markers_r;
								
								//drawing amount of group markers, it clears and draws
								o.drawAmount();
							}, 50);
					}, 500)
				}
				$('.map_tools div', o.T).fadeOut(ae[2], function(){$(this).remove()})
			},
	
			events: function(){
				//TODO: need to make this nicer
				//not sure that live is the best way here
				this.T.live('click', function(e){
						
						var t = $(e.target);
						//events for actions
						var tp = t.parent()
						var a = ['z-index']; 


						if(tp.is('.actions')){
							//infoWindow actions
							//getting data for marker
							var d = t.closest('.infowin').data('data');
							//sending action request
							//TODO: yeah need to learn regex, note - there is another double replace in the code
							Actions.action(t, t.attr('class').replace(/\ba\b/i, '').replace(/\s/g, ''), d.id, d.object_type);
						}/*else if(tp.is('.filters') && t.is('a')){
							//for filters
							t.toggleClass('a');
							Map.loadData('string');
						}*/else if(t.is('.close')){
							//close zoomed map
							Map.unzoom();
							t.fadeOut(ae[2]).next().fadeOut(ae[2]);
						}
						//for infowindow
						else if(t.is('.win_close') || t.is('.win_close_1')){
							//closing infoWindow
							tp.fadeOut(ae[2], function(){
								Map.infowindow.close();
							});
						}/*else if(t.is(a[0])){
							//changing z-index for info windows
							$(a[0], Map.T).css(a[1], 300);
							t.css(a[1], 301);
						}else if(tp.parent().is(a[0])){
							//changing z-index for info windows if click is on some of inner elements
							$(a[0], Map.T).css(a[1], 300);
							tp.parent().css(a[1], 301);
						}*/
				})
			},
		
		}

		

	/*
	}
	------/MAP------*/

	/*------GALLERY------ 
	function(){
	*/

	/*function(){*/


	//TODO
	//if(!Search.filters)Search.filters = [];

	//var gal_vimeoEmbedStr = '<object width="@" height="@@"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=@@@&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=f12b2b&amp;fullscreen=1&amp;autoplay=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=@@@&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=f12b2b&amp;fullscreen=1&amp;autoplay=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="@" height="@@"></embed></object>';
	var gal_vimeoEmbedStr = '<iframe src="http://player.vimeo.com/video/@@@?title=0&amp;byline=0&amp;portrait=0&amp;color=f12b2b&amp;autoplay=1" width="@" height="@@" frameborder="0"></iframe>';
	var gal_ytEmbedStr	  = '<iframe width="@" height="@@" src="http://www.youtube.com/embed/@@@?autoplay=1" frameborder="0" allowfullscreen></iframe>'
	//var gal_ytEmbedStr    = '<object width="@" height="@@"><param name="movie" value="http://www.youtube.com/v/@@@&hl=en&amp;fs=1&amp;autoplay=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/@@@&hl=en&fs=1&autoplay=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="@" height="@@"></embed></object>';
	
	//vimeo starts with v, youtube with y
	
	embedV = function(_id, _w, _h, _no_autoplay){
		//cl('here: %o', _no_autoplay);
		//if(_id.substr(1))
		//var id = _id.replace(/y/, '');
		var s = (_id.substr(0, 1)=='v')?gal_vimeoEmbedStr:gal_ytEmbedStr;
		s = s.replace(/@@@/g, _id.substr(1)).replace(/@@/g, _h).replace(/@/g, _w);
		return (_no_autoplay)?s.replace(/autoplay=1/g, 'autoplay=0'):s;
	}


	/*
	}*/
	
	
	
	
	var Gal = {
	
		//some settings
		//if we want to save previusly selected search type
		//also we'll need var map_for = ['spot', 'user', 'event'];
		mapSearch: false, //(typeof(sett_mapSearch)!='undefined')?sett_mapSearch:false,
		//maybe later need to remove hidden elements, so it will be infinity scroll
		load_img_ar: [],
		//sizes of box
		w: 225,
		//height will be changed for fullscreen
		h: 160,
		v: [],
		cI: null,
		am: 0,
		D: [],
		vars: {},
		more: 0,
		//type - search, gal, ... show 3 rows of gallery or 1
		ty: 0,
		galType: 0,
		//offset for removed / added items to load correct more
		offset: 0,
		//content of object
		V: $('#v_cont'),
		//if more then show advice to search again
		//TODO: this data should be taken from php or calculated according to amount of items
		showAdvice: true,
		//need to write all variables here, so i'll know what's there
		
		//where to insert after sorting
		dropAfterId: null, 
		
		//need this for cliped items, it will grow each time we add something from clip - -1,-2,-3 ...
		add_item_i: -1,
		
		
		//how it works
		// 1) - init (init + open the gallery to load, set scroll events on/off etc)
		// 2) - loadData (add loader and send ajax request)
		// 3) - dataLoaded (draw header and every item)
		// 4) - draw (draw item and add events for it, load images)
		// Map view integration is pretty complicated, it works mainly near Map.unzoom() and there is also Gal.mapOn method
		//there are two ways of map_switcher cleaning one in original map view (when Gal.mapSearch is true) and in regular search view
		//in this case we switch off the map that can be on for v_cont, and we are doing this so it will look the same v_cont to mapSearch and v_cont to regular Search, and anyway we need to hide map for mapSearch
		//cause there is only one instance of gmap :)

		//TODO: when sending ajax need to send filters too
		//TODO: new item will be added in the beggining of the gal

  	
    
   		init: function(){
			var o = this; 

			//setting all variables, especially for genereting ajax string

			var p = $('#header');

			//adding back to obj button
			var o_0 = '<div class="back_to_obj" title="' + lp.backToObj + '">' + lp.backToObj + '</div>';
			//adding map switcher
			//and switching it if map is visible from the beginning
			o_0 += '<div class="switch_to_map" title="' + lp.switchToMap + '"><span></span>' + lp.switchToMap + '</div>';

			p.append('<div class="intro"></div>' + o_0 + '<div id="gal"><div><div class="all"></div></div></div><div class="scroll"><div></div></div>');
			o.T = $('#gal');
			o.A = $('.all', o.T);
			//adding scroll function
			o.A.parent().scroll(function(){Gal.scrolling()});
			o.W = $(window).width();
			//amount of visible cols in one direction
			//435 was a padding for .all
			o.nI = Math.ceil(((o.W)/o.w)/2) + 3;
			o.scrollW = o.T.next().width();




			//events for tabs (red line)
			$('#tabs li', p).click(function(){
				if(!Gal.loading){

					var t = $(this);
					//working with tab only if there is more than 1 item in it
					if(parseInt($('small', t).text())>0){
						//unselecting all
						//selecting current

						if(!t.is('.a')){
						    $('#tabs .a').removeClass('a');
						    t.addClass('a');
						}else{
						    $('#tabs .a').removeClass('a');
						}

						//making some focus for gallery
						if(Gal.galType==0 || !t.is('.a')){
						    Gal.on(t.attr('id').substr(4));
						}else{
							//why we need this
						    Gal.off(true);
						    setTimeout(function(){
						        t.click()
						    }, ae[5] + 50);
						}
						//selecting one of tabs
					//	$('#tabs .a0').addClass('a').removeClass('a0');
					}
				}
			});

			//$('#tab_media').click()
			//TODO: events are a lil bit messy here, need to put them in o.events

			//switching grid to map if default is map
			if(o.mapSearch)o.tools.switcher(o.T.prev())

			o.T.prev().click(function(){
				var t = $(this);
				//switching map / grid search
				Gal.tools.switcher(t)

				Gal.off(false, true);
				Gal.mapSearch = !Gal.mapSearch;
				//need to add forcediv to fix some issues on server
				setTimeout(function(){Gal.on('search', Gal._D/*, {'forcediv': 1}*/)}, ae[3]);

			}).prev().click(function(){
				//back to object
				// $('#tab_des').click();
				//$('#tabs .a').click();
				Gal.off(true);
			});


			//maybe need to add scroll event, and when it is firing acceleration will stop
			//adding draggable scroll for all gallery
			var of = o.T.next().offset();
			var w = o.T.next().width() + 4;
			var a = [o.A.parent(), o.T.next()]
			for(var i = 0; i<2; i++){
				a[i].draggable({
					axis: 'x',
					containment: (i==0)?[0, 0, 0, 0]:[of.left+w/2, of.top, of.left+w/2, of.top],
					start: function(e){

						var o = Gal;
						o.accelerate = false;
						clearInterval(o.accelerating_i);
						var t = $(this);
						o.scrollK = (t.data('i'))?-o.A.width()/t.width():1
						t.data('x', e.pageX + Math.floor(o.A.parent().scrollLeft()/o.scrollK));
						o.accelerating_i = setInterval(function(){Gal.accelerating()}, ae[3]/10);
						//fix for no click if dragging
						o.scrolling_boo = true;
					},
					drag: function(e){
						if(!Gal.elDrag){
							//scroll this with drag only if there is no connector
							var n = $(this).data('x') - e.pageX;
							Gal.A.parent().scrollLeft(n*Gal.scrollK);
						}
					},
					stop: function(e){
						Gal.accelerate = true;
					}
				}).data('i', i);
				if(i==1){
					//scrollbar click event
					//where you click - there you scroll
					a[i].click(function(e){
						var t = $(this);
						var w = $('div', t).width()/2
						var n = t.offset().left - e.pageX + w;
						var s = Math.floor(-n*o.am*220/(t.width()-w))
						Gal.A.parent().animate({scrollLeft: s}, ae[3]);
					})
				}
			}


			this.events()
		},

		loadData: function(_d){
			//somewhere here need to detect how many mors to load
			//2-5 screens (for not map type)
			//for map
			var o = Gal;
			if(!o.loading && o.galType!=0){
				
				//need to show loader at the end of the Gal.A, if it is just beggining it will be centered cause of margin
				o.loading = true;
				
				///if i'm sending more need to check the size of more it depends on o.nI
			
				//mr: AJAX
				/*ajax(a, '', _aj_req , function(el, ar){
						Gal.dataLoaded(Gal.more, ar);
						Gal.more++;
				});*/

				//setting gal width, so it will be in center when there is a loader
				if(o.ft){
					//o.A.html('<div class="loading_g"></div>');
					//$('.loading_g').css('top', Math.max(40, o.T.parent().height()/2 - 58 - (150 - o.ty*50)));
				//	setTimeout(function(){
					    o.A.html('<div class="loading_g"></div>');
					    //some tricky top calculation 255 - 3*85 = 0 / 255 - 1*85 = ... 
   						$('.loading_g').css('top', Math.max(45, o.T.parent().height()/2 - 20)); //- 40 - (255 - o.ty*85)
					//}, 500)
					o.A.width(50);
					o.more = 0;
					
					
					//TODO: need to check this, before there was no Gal.T.show
					Gal.T.show();
				}

				//need data for
				//id
				//type photo (0), video (1) ...
				//title

				//description (20 comments / 10 likes)
				//link to object (?)
				//image
				//target for video - vimeo/youtube id, for photo - big photo for others - 0 (link.html (0 if it is not video or photo), video.mov (id of video), photo.jpg)

				//possible actions (set default, unset default, remove, connect, disconnect,      like, unlike, ride, unride, make session ...)
				//like array
				//this will be something like numbers, each action will have it's own id, not so hightechprogrammsupercool
				//but fast
				//actions will be compared to array lp.searchItem


				//var ar = ajax_StrToAr('1|0|||Only <u>one</u> media is attached <a>add new photo</a>||     101|1|title1|description|link.html|1.jpg|11733079|0,2,4,11');
				//for 1+ more there will be no intro
				
				
			
				//standard data to send
				var d = {'div': 'gallery', 'more': o.more}
				
				//TODO: need to add filters
				
				/*
				&what=spot (тип текущего объекта)
				&what_id=14 (ID текущего)
				&order_by=media_order (TAB + '_order')
				&connected=1 (всегда нужно для галлереи)
				&type=media (TAB)
				*/
				
				if(o.galType!='search'){
					d.type = o.galType;
					d.what = object_type;
					d.what_id = object_id;
					d.offset = o.offset;
					d.order_by = o.galType + '_order';
					d.connected = 1;
					//amount of items in more for gallery
					d.limit = 15;
				}else{
					//don't need to send id of object for search
					//TODO: need to thinks about analytics, maybe it is better to send this data, so we'll know
					//in which object user asks for search
					d.id = 0;
					//detecting how many items we need to have in more
					//width of screen / width of item * 1.5
					//o.ty - numeric type that have amount of items in one column
					if(!o.limit)o.limit = Math.round(o.W*1.5/o.w)*o.ty
					d.limit = o.limit;
					
					//saving search request in _D, so when we'll need to load another more for Gal
					//we'll take it from o._D
					if(_d)o._D = _d;
					_d = o._D;
					
					//we need this so server will know about possible connections between objects
					d.what = object_type;
					d.what_id = object_id;
					
					
					//d.order_by =  'O_order';
					//removing some useless data, and this thing fix 
					//cl('!!!!!: %o', 1);
					//delete d.order_by;
				}
				
				//extending d with _d let's say for search standard d is not enough
				if(_d)$.extend(d, _d)
				//requesting gallery items
				ajax_n('view', d, function(_el, _data){	
					Gal.dataLoaded(o.more, _data.data);
				}, 0, function(){
					//we need this in case when nothing was found
					Gal.off();
					Gal.loading = false;
				});
				
				
				//var ar = 
				
				//TODO: some problem when there is 100ms in timout, need to make it able to work right away
				/*
				var ar = ajax_StrToAr('1|0|||Found <u>2</u> spots for <u>title</u> <p>in <input type="text" class="list_a f" name="countrys" value="all countries" /><input type="text" class="list_a" name="citys" value="all cities" /><input type="text" class="list_a" name="sports" id="all_sports" value="all sports" /> sorted by<input type="text" class="list_a f" name="order" value="newest" /></p>||     101|1|title1|description|link.html|1.jpg|11733079|0,2,4,11||102|3|title2|description|link.html|5.jpg||103|0|title3|description|link.html|7.jpg|big1.jpg|2,0,6,4');
				
				setTimeout(function(){
					var intro = ar.shift();
					Gal.dataLoaded(Gal.more, ar, intro);
					Gal.more++;
				}, 1500);*/
			
			}
		},

		dataLoaded: function(_more, _data){
			//removing last, so it will be sent only for last search, and won't be saved
			if(Search.D)delete Search.D.last
			
			
			var o = Gal;
			
			//removing loading things
			o.loading = false;
			if(o.ft)$('.loading_g', o.A).remove();
			
			
			//setting o.D to keep all data
			o.D[_more] = _data.items || [1];
			if(_data.items){
				var l = Math.ceil(o.D[_more].length/o.ty);
				o.am += l;
				for(var i = 0; i < l; i++){
					o.draw(i, _more);
				}
			}
			/*var l = 0;
			$.each(_data, function(){
				o.draw(this);
				l++;
			});
			//setting length param, so later we can use it without tricks
			o.D[_more].length = l;
			o.am += l;*/
			
		
			
			//setting width of gallery container
			var w = o.am*o.w + 10;
			if(w>o.T.width()){
				//$('.scroll', o.T.parent()).fadeIn(ae[3]);
				w += 40;	
			}

			//setting width of all
			o.A.width(w);
			//saving o.A.width to var so it won't resize it every time
			o.vars.W = w;
			
			if(o.ft){
				//first time, specially for load function
				//need to show loader somewhere here
				o.refresh(o.nI);
				
				//working with scrollbar
				//TODO: need to check why +1
				//showing scrollbar if there are enought elements
				if(o.nI <= $('div', o.A).length){
					setTimeout(function(){Gal.T.next().css('visibility', 'visible')}, ae[4]);
				}
				//setting height of the gallery;
				var h = 0;
				//height of gallery
				//10 is fix for animation after load for gallery
				//there was 12 instead of 50
				var H = Math.min(o.D[0].length*o.h + h + 40,  o.ty*o.h + ((o.ty==3)?47:7) + 15 - o.ty*5 + h + 10);
				
				o.vars.H = H;
				
				//setting height of gallery
				o.T
					.animate({height: H}, ae[4])
					//.slideDown(ae[4])
				

				//good animation that works for epmty header and for any other
				o.A
					.css('left', o.W)
					.animate({left: 0}, ae[5]);
            
            

				o.ft = false;

			
			
				//TODO: need to init lists
				
				o.maxMore = parseInt(_data.more) + 1 || 1;
				o.amount = parseInt(_data.amount);
				
				
				
				if(o.galType == 'search'){
					//setting hashtag
					if(typeof(_data.search) != 'undefined')window.location.hash = _data.search;
					
					
					//generating intro if search
					//checking if amount of found items is bigger than max items to show
					
					if(o.amount >= o.showMax){
						//if so  need to change o.amount
						//and o.maxMore
						var am = o.amount = o.showMax;
						o.maxMore = Math.ceil(o.amount / o.limit);
						am += '+';						
					}else{
						var am = o.amount;
					}
					
					
					//drawing intro with filters and title
					o.tools.draw_intro(_data.intro, _data.filters);
					
					//showing back_to_obj and search intro
    				o.T
						.prev()
						.prev().fadeIn(ae[3])
						.prev().fadeIn(ae[3]);
						
					//showing switch_to_map only for some types of object and only if there are some results
					if(_data.items && _data.map) o.T.prev().fadeIn(ae[3]);
					
					
					//hiding map of v_cont properly
					Map.unzoom();
					//removing map tools after unzooming map, can't do it there cause of error in case when you just on/off the map in v_cont
					$('.map_tools', Map.T).hide();
					
                }
				
				
				//FIX FOR NOSCROLL
				//fixing bug when the window width = gallery width, in this case there is no scroll, so it doesn't allow to load more
				//setting width of o.A to window width + 50 so there will be ability to scroll
				//if(w<o.T.width() && o.maxMore>1)o.A.width(o.W + 50);
				
				
				
				
				
				//Centering for gallery
				/*if(o.ty==1){
				    cl(Math.max(0, o.W - o.A.width())/2 - o.W + ' ' + o.A.offset().left)
				    o.A.css('marginLeft', Math.max(0, o.W - o.A.width())/2 - o.W/2);
			    
				}*/
			}
			
			/*else{
				
				//TODO: need to make it better or remove it at all, as an idea twitter load on iPhone
				//scroll a lil bit after second loadData
				//current scroll
				/*var cs = o.A.parent().scrollLeft();
				//calulating new scrollTo, if adding new then to 0, if loadin more then go to next more
				var ns = (_more>0)?cs+220:0;
				//if new scroll and current are the same then changing new, so it will scroll anyway
				if(ns==cs)ns+=1;
				o.A.parent().animate({scrollLeft: ns}, ae[3]);*/
			//}
			
			
			//changing current more
			o.more++
		},
		
		loadImg: function(){
			var o = Gal;
			if($('.v .noimg', o.T).length){
				//checking if there are loaders, if 2 then don't do nothing
				var l = 2 - $('p.loading', o.T).length;
				for(var i=0; i<l; i++){

					//need to find new element here
					//there is problem in detecting if there is another loader
					//can solve it by adding loading class for <p>
					//so if there is no more loading, then need to loadingImG = false


					///some bug with detecting first image
					var el = $('.v .noimg:eq(0)', o.T);
					
					
					
					//if there is image
					var D = el.data('d');
					
					//need to check if D is not empty, it can happend if there are no images to load
					if(D){
						if(Gal.D[D[0]][D[1]].pic){
							el.attr('class', 'loading');
							var img = new Image();
							$(img)
								.data('el', el)
								.load(function () {
									var t = $(this);
									t.hide();
									var el = t.data('el');
									if(el) el.removeAttr('class').append(t);
									t.fadeIn(ae[3]);
									
									if(bIE){
										//fix for IE, so it won't show stackoverflow...
										setTimeout(function(){Gal.loadImg();}, 100)
									}else{
										Gal.loadImg();
									}
									
								})
								.error(function () {
									//removing loader so it won't stop loading with two empty images
									$(this).data('el').removeAttr('class');
									Gal.loadImg();
								})
								//TODO: need to change directory for new image that i get from edit/new
								.attr('src', 'http://i.' + domain + '/m/' + Gal.D[D[0]][D[1]].pic)
						}
					}
				}
			}
		},

		draw: function(_i, _more){
			///Toooooo big method
			var o = this;
			//26|0|title|description|link.html|1.jpg|11733079|0,2,5

			//if it is already default there will be class itemA_1, if it is not then itemA_2 etc.
			var gal_classes = ['zoom', 'zoom p', 'link'];
			//TODO: maybe optimize it here make just one for, with +'</div> every 3 times
			//TODO: make it better for less then 3 items
			//TODO: make infinity scroll
			var s = '<div class="h">';
			var l = Math.min(_i*o.ty + o.ty, o.D[_more].length);
			var a, o_1, o_2, o_3;
			
			
			for(var i = _i*o.ty; i<l; i++){
				a = Gal.D[_more][i];
				s += '<p class="noimg" id="si_' + parseInt(a.id) + '">';

				//adding action buttons to search item
				//o1 = 
				//TODO: not sure if this is the best way to check js object
				if(a.actions){
					s += '<span class="actions">';
					//second param is for default buttons classes
					s += o.drawActions(a.actions);//o1.split(','), ['remove', 'default']);
					s += '</span>';
				}
				
				//if it is event we add days left
				
				if(a.object_type=='event'){
					//TODO: not sure if it is good to call another object method, maybe just to add that method here?, or some unknown oop magic
					//getting days left for event 
				
					//o.date = 'February 28, 2011' ;
					//adding 24 hours so it will say correct today is till 24 of today, the same for tomorrow, but not like if it's less then(a? what do i mean here :) 24 hours it today
					a.date += ' 23:59';
					var days = Vcont.ticker.get(a.date, 0);
					//TODO: not sure if this is the fastest way, will check later	
					//what we are doing for day, we write lp value if it is <2, and we use ar[2].replace if there are more than 1 day left
					
					var o_0 = ((days<2)?lp.days[days]:lp.days[2].replace('*', days)); 
					
					if(a.object_type=='event') s += '<span class="date">' + ((days>0)?o_0:lp.finished) + '</span>'
				}
				
				//var ar = ajax_StrToAr('101|1|title1|description|link.html|1.jpg|11733079|0,2,4,11||102|3|title2|description|link.html|2.jpg||103|0|title3|description|link.html|5.jpg|big1.jpg|2,0,6,4||     101|1|title1|description|link.html|6.jpg|11733079|0,3,5,10||102|3|title2|description|link.html|9.jpg||103|0|title3|description|link.html|3.jpg|big1.jpg|2,0,6,4||      101|1|title1|description|link.html|1.jpg|11733079|0,2,4,11||102|3|title2|description|link.html|2.jpg||103|0|title3|description|link.html|5.jpg|big1.jpg|2,0,6,4||     101|1|title1|description|link.html|6.jpg|11733079|0,3,5,10||102|3|title2|description|link.html|9.jpg||103|0|title3|description|link.html|3.jpg|big1.jpg|2,0,6,4||103|0|title3|description|link.html|3.jpg|big1.jpg|2,0,6,4||103|0|title3|description|link.html|3.jpg|big1.jpg|2,0,6,4||103|0|title3|description|link.html|3.jpg|big1.jpg|2,0,6,4||103|0|title3|description|link.html|3.jpg|big1.jpg|2,0,6,4');
				//detecting type of item
				o_1 = Math.min(parseInt(a.target), 2);
				//link for object
				o_2 = a.object_type + '/' + a.id;
				//remove link for not videos and photos
				o_3 = (o_1 > 1)?'href="/' + o_2 + '"':'';
				
				//making description (likes / rides / etc)
			/*	if(a.description){
					var des = '<i>';
					$.each(a.description, function(_i, _v){
						des += lp.itemsDes[_i] + ': ' + _v;
					});
					des += '</i>';
				}else{
					//need to add empty element here
					des = '';
				}*/
				//hiding title if there is nothing or Untitled
				// if(a.name!='Untitled' && a.name)s += '<span class="bottom"><a href="/' + o_2 + '">' + a.name + '</a>' + des + '</span>';
				if(a.name!='Untitled' && a.name)s += '<span class="bottom"><a href="/' + o_2 + '">' + a.name + '</a></span>';
				
				//draw hover zoom / play / go icon
				s += '<a ' + o_3 + ' class="' + gal_classes[o_1] + ' lnk" rel="/' + o_2 + '">' + a.name + '</a></p>';
			}

			s + '</div>'
			
			

			//prepend in case if there is a new image for gallery
			//appending only if more is loaded
			$('.all', o.T)[(_more<0)?'prepend':'append'](s);
			//dealing with element data
			var t = $('.all div:' + ((_more<0)?'first':'last'));
			
			for(i=_i*o.ty; i<l; i++){
				$('p:nth-child(' + (i - _i*o.ty + 1) + ')', t)
					//d is to get all info of current search item, like src, zoom ...
					.data('d', [_more, i])
					//setting the zoom target
					//need to check here if it is image then write url of image instead od .code
					//.data('zoom', Gal.D[_more][i].code || 0)
			}
			
		},
		
		//using it in gallery
		drawActions: function(_a){
			//drawing actions buttons
			var o_1;
			var s = '';
			var i = 0;
			$.each(_a, function(_i, _v){
				o_1 = lp.searchItem[_i];
				//generating string for actions button
				if(_v!=0)s += '<a class="' + _i + ((_v==2)?' a':'') + '" title="' + o_1.title + '">' + o_1.name + '</a>';
				i++;
			});
			return s;
		},
		
		refresh: function(_i){
			_i-=2;
			var o = Gal;
			o.cI = _i;
			var b = _i-o.nI, e = _i+o.nI, s = '', v;
			//generating hide array
			//need to check somehow where is the current, if it is at the end / beginning then 
			//need to do something special
			$('.v', o.A).each(function(i){
				var id = $(this).attr('id').substr(2)*1 - 1;
				if(Gal.cI-Gal.nI>id || Gal.cI+Gal.nI<=id){
					$(this).attr('class', 'h');
				}
			})
			//maybe will need this for not thu view, if there will be click centering
	        //o1 = 'div:eq(';
			//if(!$(o1 + b + ')', o.A).length)e+=2;
			//if(!$(o1 + e + ')', o.A).length)b-=2;

			for(var i=b; i<=e; i++){
				v = 'div:eq(' + i + ')';
				if($(v).attr('class')!='v'){
					s += v;
					if(i<e)s += ', ';
				}
			}


			//calling for image loader
			//there need to check if it is already running, if yes then do nothing



			//need to start loading all images from visible elements


			//need to load current images here, so everytime user scroll he will see loading of latest images
			//loaders will be on first vsible column
			//after loaded need to put data or find the better way to check if image is already loaded


			$(s, o.A).attr('class', 'v');

			//loading images for each cell
			o.loadImg();
		},

		zoom: function(_t){
			//play video, for video it will be nice if it will do everything inside and then return the result, for not gallery
			//zoom
			//go to link
			//maybe more
			var o = Gal;
			o.zoomed = _t;
			var s = o.A.parent().scrollLeft();
			var x = _t.offset().left;
			//timout variable
			var to = 0;
			//scrolling the gallery so if image is on the border it will be fully visible
			if(x<5 || x + 225 > o.T.width()){
				to = ae[4];
				//if the clicked image is a lil bit out of the screen
				var ns = (x<5)? s+x-105 : s+325-o.T.width()+x;
				o.A.parent().animate({scrollLeft: ns}, to);

			}


			var t = $('.zoomed', o.T);

			if(t.length){
				t.fadeOut(ae[4], function(){$(this).remove()})
			}
			//append zoomer
			o.T.append('<div class="zoomed loading"></div>');
			//there is a bug, if click on box on the border and roll out then loader appears from 0;0 ...



			setTimeout(function(){
				var el = $('.zoomed:last', o.T);
				var win = $(window);
				el
					//set coordinates of zoomer
					.offset({left: _t.offset().left, top: _t.offset().top + win.scrollTop()})
					//do some magic after scroll
					
				//without animation
					.stop()
					.show()
					.css({
						'top': win.scrollTop() + win.height()/2 - 70 - $('#header').offset().top,
						'left': win.width()/2 - 35,
						'width': 10,
						'height': 10,
						'opacity': 1
					})
				
				//with animation
					
					/*.show()
					.css('opacity', 0)
					.animate({
						//adding $('#header')... so with opened edit / new / setting zoomer will work fine
						top: win.scrollTop() + win.height()/2 - 70 - $('#header').offset().top, //Gal.T.offset().top + Gal.T.height()/2 - 35,
						left: win.width()/2 - 35, //Gal.T.width()/2 - 35,
						width: 10,
						height: 10,
						opacity: 1
					}, ae[3]);*/

				
				//checking if Plus is visible if so then need to move zoomer a lil bit, cause of position: relative
				if(Plus && Plus.T.height>100)el.css('marginTop', -Plus.T.height())

			//	setTimeout(function(){
					


					//this depends on data and rights
					//adding active class for default button, if it is on
					var c = 'default';
					if($('.default.a', Gal.zoomed).length)c+=' a';
					//drawing buttons and adding events
					var str = 	'<a class="close" title="' + lp.close + '">' + lp.close + '</a>';
					
					
					//TODO: need to check i guess i have there variables
					//all gallery amount
					var gal_am = $('.v', Gal.A).length;
					//current index
					var gal_cur = $('.v .zoom', Gal.A).index($('.zoom', Gal.zoomed)) + 1;
					
					if(gal_cur<gal_am*3)str += '<a class="next" title="' + lp.next0 + '">' + lp.next0 + '</a>';
					if(gal_cur>1)str += '<a class="prev" title="' + lp.prev + '">' + lp.prev + '</a>';
					
					str += '<a href="' + $('.lnk', _t).attr('rel') + '" class="original">' + lp.viewOriginal + '</a>';
					
					
					
					$('.zoomed:last', o.T).append(str);
					//<a class="remove" title="' + lp.remove + '">' + lp.remove + '</a><a class="' + c + '" title="' + lp.setAsDefault + '">' + lp.setAsDefault + '</a>');
					$('.close', el).click(function(){Gal.zoomClose()})
					$('.next', el).click(function(){Gal.nextprev(true)})
					$('.prev', el).click(function(){Gal.nextprev(false)})
						/*.next().click(function(){
							dialog.show(Gal.zoomed, 'obj_del', function(){
								Gal.removeItem(Gal.zoomed);
							})
						})
						.next().click(function(){Gal.defaultItem($(this), $('.default', Gal.zoomed))});*/
			//	}, ae[4])
				
				
				//need to check what type of data should be here
				//if video then embed maybe it won't be so good, image befor?
				//if no image for video then need to hide loader and make the zoomer correct size right away
				//or maybe it will look good
				//and load image



					

					var D = _t.data('d');

					//checking type of zoom, image or video
					if($('a:last', _t).is('.zoom.p')){
						//video
						Gal.zoomEf(el, 600, 338);
						//TODO: need to add youtube
						setTimeout(function(){el.append(embedV(o.D[D[0]][D[1]].code, 600, 338, false))}, ae[3]*2);
						$('a', el).fadeIn(ae[3]);
						
					}else if($('a:last', _t).is('.zoom')){
						//if there will bugs with fast arrow, then need to add timeOut, now it can work fine cause of loading speed
						//setTimeout(function(){
							//cl('>>>>>: %o', Gal.D[D[0]][D[1]]);
							//cl('|||||: %o', D);
							//if image
							var img = new Image();
							$(img)
								//making it here so after it won't replace another image
								.data('el', el)
								.load(function () {
									var t = $(this);
									var el = t.data('el');
									t.hide();
									el.append(t);
									t.click(function(){Gal.zoomClose()});
									Gal.zoomEf(el, t.width(), t.height());
								})
								//.attr('src', '1/big1.jpg')
								.attr('src', 'http://i.' + domain + '/b/' + Gal.D[D[0]][D[1]].pic);
						//}, 200)
					}

			}, to);	
		},

		zoomEf: function(_el, _w, _h){
			//positioning zoomed showing image
			//width animation
			
			var win = $(window);
			_el.animate({
					width: _w,
					height: _h,
					//adding $('#header')... so with opened edit / new / setting zoomer will work fine
					top: win.scrollTop() + 30 - $('#header').offset().top,//Math.max(80, Gal.T.offset().top + Gal.T.height()/2 - h/2 - 35),
					left: win.width()/2 - _w/2 - 30
				}, ae[2], 'swing', 
				function(){
					$(this).removeClass('loading').addClass('shadow');
					$('img, div', $(this)).fadeIn(ae[2]);
					$('a', $(this)).fadeIn(ae[2]);
				});
				
			
			//no animation
			/*_el
				.css({'width': _w, 'height': _h, 'top': win.scrollTop() + 30 - $('#header').offset().top, 'left': win.width()/2 - _w/2 - 30})
				.removeClass('loading')
				.addClass('shadow');
			$('img, div', _el).fadeIn(ae[2]);
			$('a', _el).fadeIn(ae[2]);*/
		},

		zoomClose: function(){
			$('.zoomed:last', Gal.T).removeClass('shadow').fadeOut(ae[2], function(){$(this).remove()});
			Gal.zoomed = null;
		},

		nextprev: function(d){
			//getting index of current
			var i = $('.v .zoom', Gal.A).index($('.zoom', Gal.zoomed));
			i += (d)?1:-1;

			//looking for current.index ±1
			$('.v .zoom:eq(' + i + ')', Gal.A).click();


			//$($('.v .zoom')[0]).remove();//next('.v .zoom').click()
			/*if(d){
				var n = $('.zoom', Gal.zoomed.next());
				if(!n.length)n = $('.zoom:first', Gal.zoomed.parent().next());
			}else{
				var n = $('.zoom', Gal.zoomed.prev());
				if(!n.length)n = $('.zoom:last', Gal.zoomed.parent().prev());
			}
			if(n.length)n.click()*/
		},
		
		defaultItem: function(_t, _t1, _D){
			if(_t1)cl('!!! need t1');
			//first need to remove all .defaults in Gal
			//then need to set class for current gallery item and for button
			//TODO: it is not so cool, i need to add some condition for already active button
			$('.actions .default.a', Gal.T).removeClass('a');
			//$('.default', Gal.T).removeClass('default');
			_t.addClass('a');
			//adding class to default button in zoomed
			if(_t1)_t1.addClass('a');
			
			
			ajax_n('reorder', {'what': _D.object_type, 'what_id': _D.id});

			//TODO #def: Later need to change v_cont media block picture too.
			var v = $('#v_cont .info')
			if($('img', v).length){
				//changing src if an image exists
				$('img', v)
					.attr('src', 'http://i.' + domain + '/b/' + _D.pic)
					.removeAttr('width')
					.removeAttr('height')
					.parent().attr('href','/' + _D.object_type + '/' + _D.id);
				//removing play button
				$('.play', v).remove();
				//if there is back button then video is playing now, so need to click back and do the same
				$('.vcont_back', v.next()).click()
				//if item has code then adding play button
				if(_D.code)$('img', v).parent().after('<a class="vcont play" rel="' + _D.code + '"></a>')
			}
		},

		removeItem: function(_t, _D){
			dialog.show(_t, 'remove', function(){
				Gal.offset--;
				_t.parent().parent()
					.animate({opacity: 0.2}, ae[3])
					.find('span, a').remove();
					
				Gal.zoomClose();
			
				ajax_n('delete', {'id': _D.id, 'type': _D.object_type});
				//this.actionsAjax(_t, 0);
				//hiding the zoomed
				//making removed image more transparent
			});
		},
		
		addItem: function(_data){
			
			/*_data.items = [
			{'actions': 
			{
				'clip': 2,
				'default': 1,
				'like': 1,
				'remove': 1
			},
			'id': 125,
			'name': "Clipped photo",
			'object_type': "media",
			'pic': "p125_1TdOC.jpg",
			'target': 0
			}
			]*/
			//checking it, but almost sure that we always have it
			if(_data){
				var o = this;
				
				
				cl('addItem: %o', _data.items);
				
				
				if(_data.items && !$('#tab_' + _data.items[0].object_type).is('.a')){
					//closing gallery if current gallery type is not the same as item to add
					setTimeout(function(){o.off()}, 200);
					var o_1 = 1000;
				}else if(o.T.is(':visible')){
					var o_1 = 0;
					//this ,method is called after data is already loaded
					//drawing item to gallery
					//doing this only if necessary type is opened
					
					//changin gallery offset, so in next more it won't load the same first item as last for prev
					o.offset++;
					o.dataLoaded(o.add_item_i, _data);
					
					//we need this add more than one item from clip to gallery
					o.add_item_i--;
					
					//dealing with effects and with hidden media bug, now everything is perfect
					var o_0 = o.A.parent();
					
					
					
					o_0.scrollLeft(Math.max(o_0.scrollLeft()-220, 220))
					//checking if there is no scroll then loading image without effects
					if(o_0.scrollLeft()==0){
						//showing not loaded images
						o.refresh(0)
					}else{
						//loading with effects
						o_0.animate({scrollLeft: 0}, ae[3]);
						//showing scrollbar
						o.T.next().css('visibility', 'visible');
						
					}
					
				}
				
				setTimeout(function(){
					if(_data.items){
						var o_0 = _data.items[0].object_type;
						//updating redline numbers
						//TODO: need to fix isssue with fileuploader, first small is there 
						var t = $('#tabs #tab_' + o_0 + ' small:last');
						var am = parseInt(t.text()) + 1;
						//cl('>>>: %o', am);
						t.text(am);
						//Vcont.tabs();
					
						//if it is the first image then it should be set as default
					
						
					
						if(am==1){
							$('#v_cont .info img')
								.attr('src', 'http://i.' + domain + '/b/' + _data.items[0].pic)
								.removeAttr('width')
								.removeAttr('height')
								.parent().attr('href','/' + o_0 + '/' + _data.items[0].id);
						}
						//showin gallery after clip
						if(!o.is_on)o.on(o_0);
					
						//adding "a" class for tab, this will fix noclose issue
						$('#tab_' + o_0).addClass('a');
					}
				}, o_1)
			}
		},
		
		mapOn: function(_d){
			//_d - object to send for search request
			var o = this;
			//hiding map properly
			Map.unzoom();
			//dealing with ids, don't want to make a lot of maps so we have only two for edit and another (search and description)
		
			if($('#map').length){
				$('#map').attr('id', 'map_h');
				$('#gmap').remove();
				$('#map_h .map_tools, #map_h .close').remove();
			}
			
			o.T.prepend('<div class="gal_map_wrapper"><div id="map"><p>' + lp.loading_map + '</p></div></div>');
			if(is_fullscreen){
				//setting height of draggable div, so we won't see scrollbar
				$('>div', o.T).css('height', $(window).height());
			}else{
				o.T.animate({height: 541}, ae[4])
				$('.gal_map_wrapper #map').css('left', o.W).animate({left: 0}, ae[5]);
			}
			//showing back_to_obj and switch_to_map and intro
			o.T
				.prev().fadeIn(ae[3])
				.prev().fadeIn(ae[3])
				.prev().fadeIn(ae[3]);
		
			//TODO: need to pass search arguments to map object so it will show markers.
			//there are two loads if there was a switch between views (map / list), maybe later we can do only one
			Map.zoom(_d);
			
		},

		//on: function(_type, _d, _a){

		on: function(_type, _d){
			
			
			//_a - additional data
			//in gallery we check if we need to show results in gal or on map
			var o = this;
        
            if(o.galType!=_type){
                if(o.galType!=0){
                    //everytime if there is something in gallery we'll hide id
                    o.off();
                    //then will show new gal after everything is hidden
                    setTimeout(function(){o.on(_type, _d)}, ae[4] + 100);
						
                }else{
					
					
					//need this to know if gallery is on
					o.is_on = true;

					
					
					o.galType = _type;
					
                    //reseting some variables
                    o.ft = true;
    				o.am = 0;
    				o.more = 0;
    				o.maxMore = 1;
					o.amount = 1;
					o.offset = 0;
			    	//maximum amount of items to show
					o.showMax = 150;
				
                    if(_type!='search'){
                        o.ty = 1;
                        //changing top padding so ot will look better
                        o.A.css('paddingTop', 8);
                        o.T.slideDown(ae[3]);
        				o.loadData(_d);

    			    }else{
						
						
						
						

						//hiding random object button
						$('#header .random').fadeOut(ae[2]);
						//clearing random button timeout
						clearTimeout(o.randomTimeout);
						
						
						//type of items to search for
						o.galSType = _d.type;

						//adding additional data to send, need this only for forcediv for search type switcher (tools.switcher)
						//$.extend(_d, _a);
						
						
						if(is_fullscreen){
							o.h = 163;
							//if fullscreen search
							//calculating rows
							//120 is height of header
							o.ty = Math.max(1,Math.floor(($(window).height() - 145)/(o.h-15)));
							
							//for #gal it works only for first time
							$('#header, #gal').css({'height': $(window).height()-90, 'overflow': 'hidden'});
							
							//$('body').css('overflow', 'hidden');
							//setting height of draggable div, so we won't see scrollbar
							$('>div', o.T).css('height', $(window).height());
							//maximum amount of items to show
							o.showMax = Math.min(150, o.ty*50);
						}else{
							o.ty = 3;
						}
						
                        //changing top padding so it will look better
                        o.A.css('paddingTop', 45);
                        //hiding v_cont
                        o.V.animate({left: -o.W}, ae[4], 'swing', function(){
							//TODO: it is jumping a lil bit here, dunno how to fix
							//if we'll remove then on first seacrh with opened object it jusmps
							//if we'll leave it jumps when switching map to grid or grid to map
							//Gal.T.show().animate({'height': $(this).height() + 35}, 200);
							//this case fixes second issur but makes first a lil bit not cool
                            Gal.T.show().height($(this).height() + 35);
                            $(this).hide();
                        });


						//so all search request are coming via Gal, here we detect what we need to do, show map o show gallery
						
						//TODO: later need to make detection in data recieve, so it will be easy to set what to show
						//TODO: need to think on this, or maybe send this array from server
						if(!o.mapSearch){
							//TODO: if there will be idea on how to load and if it is faster than animation - to wait
							//right now waiting for o.V to hide then sending request for new gal content
							//better - hide o.V and load the same time, but it is loaded faster than o.V is hidden then wait
							setTimeout(function(){o.loadData(_d)}, ae[4] + 100);
						}else{
							//TODO: this animation looks too complicated
							
							if(is_fullscreen)o.T.slideDown(ae[4])
							
							//cl('here: %o', _d);
						//	o.T.show();
							//showing map only when v_cont is hidden
							//150 = delay + 50
							setTimeout(function(){o.mapOn(_d);}, ae[4] + 100);
						}


    			    }
			    
    			    //fix for loadbar, so it will always be visible
				    o.A.css('left', 0)
			    
    			    //o.galType = _type;
				
				
					//if(Search.ajF=='spot')$('.switch_to_map', Gal.T).show()
				
                }
            }else{
                //TODO: so many ifs here =( , but it's working perfectly
                o.off();
                if(_type=='search'){
                    setTimeout(function(){
                        //some messy magic
                        o.T
                            .height(o.V.height())
                            .hide().slideDown(ae[3]);
                        
                        o.A.css('paddingTop', 48);
                        o.on(_type, _d);
                    }, ae[5] + 200);
                }
            }
			

			//hiding windows
			if(Win)Win.hideAll();
		},

		off: function(_back, _no_hash){
			
			//_no_hash it wont remove hashtag 
			
			
			/*if($('#map_h').length){
				$('#map').remove();
				$('.gal_map_wrapper').remove();
				$('#map_h').attr('id', 'map');
			}*/
		
		
		
			//TODO: here need to add something that will show object, so if it is closed it will go back to object
			var o = this;

			//this case is for v_cont, so it will show v_cont after hiding gallery
			//TODO: not sure if there is any case without o.V, maybe community, need to check this
			if(o.V.length && o.ty==3 && _back){
			    o.T.animate({height: o.V.height() + 27}, ae[3]);
				var o_0 = o.A;
				
				//why no comments
				if(o.mapSearch)o_0 = $('.gal_map_wrapper');
				o_0.animate({left: o.W}, ae[3], 'swing', function(){
						Gal.V.show().animate({left: 0}, ae[4]);
						Gal.T.hide();
					});
			}else{
				
			
			    o.T.slideUp(ae[3]);
			}
		
			//cleanin gallery, from one side it can be bad - load again, but it will work faster
			setTimeout(function(){
				$('.all>div', Gal.T).remove();
				Gal.T.css('height', 187);
				//setting scrollbar to 0
				$('div', Gal.T.next()).css('left', 0);
			
			
		
				//returning id name of prev map
				$('#map_h').attr('id', 'map');
				//removing search map 
				$('.gal_map_wrapper').remove();
				//Unzooming map
				//Map.unzoom();
			
			}, ae[3] + 100);
        

			//scrollbar?
			o.T.next().css('visibility', 'hidden');
        
			//closing zoomer
			o.zoomClose();
			
			//cleanin hash tags it it was search
			if(o.galType=='search' && !_no_hash)window.location.hash = '';
			
			
			//hiding back_to_obj and search description
			Gal.T
				.prev().fadeOut(ae[2])
				.prev().fadeOut(ae[2])
				.prev().fadeOut(ae[2]);
        
            o.galType = 0;
           // o.am = o.galType = 0;
			//o.ft = true;
		
			//deselecting tabs
			$('#tabs .a').removeClass('a');
			
			
			//showing random object button
			o.randomTimeout = setTimeout(function(){$('#header .random').fadeIn(ae[2]);}, 3000);
		
			//need this to know if gallery is on
			o.is_on = false;
		},

		scrolling: function(){
			var o = this;
			
			
			var i = Math.abs(Math.floor((o.A.offset().left - o.W/2)/o.w))-2;
			if(o.cI != i)o.refresh(i);

			var s = $('div', o.T.next());
			var k = o.W / o.A.width();
			//435 is a padding-left of .all
			s.css('left', 159*o.A.parent().scrollLeft()/(o.A.width() - o.W - 32));
			//32 = 50 (padding-right to hide scrollbar) - 18 (scrollbar width)
			//299 = 400 (scrollbar width) - 100 (scroll slider width) - 1 (border of slider)
			//.css('width', o.scrollW / o.scrollK)

			//when reached right border of gallery
			if(o.A.parent().scrollLeft() - o.W/2 > o.A.width() - o.W*2){
				//need to load more here, then need to move scroll and add elements
				//also need to show loader (maybe)
				//checking more here so we wont use more limit for map
				if(o.more<o.maxMore){	
					o.loadData();
				}/*else if(o.more>1){

					//if scrolled till the end
					if(o.showAdvice){
						alrt.show(lp.searchAdvice);
						o.showAdvice = false;
					}
				}*/
			}
			
			
			
			
			
			//after scrolling stops need to load more, that more that is opened
			//problems - if between more, what if there are a lot of more (maybe put max 10 more, then button for more?)
			//need to set intervak here for loading, actually maybe timout is even better?

		},
	
		accelerating: function() {
			var o = Gal;
			//some bug
			if(!o.speed)o.speed=0;
			if(o.accelerate){
				//
				var t = o.A.parent();
				var s = t.scrollLeft();
				o.speed*=0.95;
				t.scrollLeft(s + o.speed);
				if(Math.abs(o.speed)<2 || s == o.A.width() - t.width() - 35){
					clearInterval(Gal.accelerating_i);
					//fix for no click if dragging
					o.scrolling_boo = false;
				}
			}else{
				o.speedLastX = o.speedCurrX;
				o.speedCurrX = o.A.parent().scrollLeft();
				o.speed = o.speedCurrX - o.speedLastX
			}
		},
	
		sortScroll: function(){
			var o = Gal; 
			var t = o.A.parent();
			t.scrollLeft(t.scrollLeft() + o.sortScrollSpeed);
		},
	
		tools: {
			switcher: function(t){
				//click on switch_to_map and switch to list it is the same button, just different icon
				t.toggleClass('a');
				//changing text of button
				var b = (t.is('.a'))?true:false;
				t.attr('title', (b)?lp.switchToGrid:lp.switchToMap);
				//changing name of button
				t.html('<span' + ((b)?' class="a"':'') + '></span>' + ((b)?lp.switchToGrid:lp.switchToMap));
			},
			
			draw_intro: function(_txt, _filters){
				
				//setting search title
				var intro = _txt;
				
				var replace = ['', '']
				//drawing all list which are filters or order by
				
				
				
				if(_filters){
					$.each(_filters, function(_i, _v){
						//string that contains filters
						replace[(_i=='sort')?1:0] += '<input type="text" name="' + _i + '" value="' + _v.name + '" class="listed list_d labeled show_all" /><input type="hidden" name="' + _i + '_id" value="' + _v.id + '" class="listed_id">'  
					});
					//adding filters
					intro += replace[0] + ' ';
					
					//adding sorting
					//TODO: no lp.intro???
					if(_filters.sort) intro += lp.intro.sort + ' ' + replace[1];
				}

				//adding submit button
				intro += '<input type="submit" value="submit" class="submit" />';
				
				$('#header .intro').html(intro);
				
				//adding event for submit button
				$('#header .intro .submit').click(function(){
					var t = $(this);
					
					//need to call gal load method and change some data in it
					//filters will be saved cause we'll get them again after they are changed and submitted
					
					$('input[type=hidden]', t.parent()).each(function(){
						var t = $(this);
						//writing in Gal._D right away
						Gal._D[t.attr('name').slice(0, -3)] = (t.val()!='0')?t.val():0;
					})
					//extending filters with current search criterias of gallery
					//$.extend(d, Gal._D);
					
					//setting ft so gallery will refresh like it is first time
					Gal.ft = true;
					Gal.am = 0;
					//loading what we need for map or for gallery
					Gal[(Gal.mapSearch)?'mapOn':'loadData'](Gal._D)
					
				});
			}
		},

		events: function(){
			this.T.bind({

				//event for zoom
				click: function(e){
					var t = $(e.target);
					
					//need to exclude map
					if(!t.closest('#map').length){
					
						if(t.is('.zoom')){
							if(!Gal.scrolling_boo)Gal.zoom(t.parent());
							//doing it here so .link will work
							e.preventDefault();
						}else if(t.parent().is('.actions')){
							Actions.El = t;
							//Action.Numbers = DOM for numbers
							//actions of search item
							var p = t.parent().parent();
							//getting type of action
							//don't know regex that good so adding condition
							var what = t.attr('class').replace(/\ba\b/i, '').replace(/\s/g, '');

							var o_0 = p.data('d');
							//getting item object
						
							var D = Gal.D[o_0[0]][o_0[1]];
						
						
						
							var id = D.id;
							var type = D.object_type;
							var moreDataToSend = false;
						
							switch(what){
								case 'clip':
									//changing variables for connect request
									what = type;
									moreDataToSend = {'what_id': id};
									id = object_id;
									type = object_type;

									//if this is gallery then need to ++
									Gal.offset++;
									break;
								case 'default':
									//need to pass another agrument if there was click in zoom win
									Gal.defaultItem(t, false, D);
									break;
								case 'remove':
									Gal.removeItem(t, D);
									Gal.offset--;
									break;
							}

							if(what!='default' && what!='remove')Actions.action(t, what, id, type, moreDataToSend);
						
							//
							//removeItem()
							//Gal.actionsAjax(p.data('d'), t);
						
							//doing it here so link will work
							e.preventDefault();
						}
					}
				},
				//events for gallery item drag
				mousedown: function(e){
					
					
					var t = $(e.target);
					
					//TODO: need to check if it is connectable
					if (t.is('.zoom, .link')) {
						var o = Gal;
						
						//need this to scroll gallery while dragging
						//positioning for order
						//getting top and bottom border of gallery
						o.hPos = [o.T.offset().top];
						//in some cases there can be no H?? if so then use old method
						o.hPos[1] =  o.hPos[0] + ((o.vars.H)?o.vars.H:o.T.height());


						//some variables so it wont clculate them during drag
						var y = o.T.offset().top;
						//setting borders for drop areas
						//if Plus is opened then all its area is a dropzone
						o.elDragV = {y1: $(window).height()-100, y2: 100, c: false};
						o.elDragT = t.parent();


						//TODO: need to check if it is possible to drag this item
						//so prolly there will be variable like 1/2/3 1- can't drag, 2 - can't connect to current, 3 - ok
						
						if(user_id){
							$(document).mousemove(function(e){
								var t = $(this);
								if(!o.elDrag){
									var d = t.data('d')
									if(Math.abs(d._y - e.pageY)>50){
										//here need to make some effect showing that dragging has started
										//after need to drag something
										//if mouseup then something will fadeOut
										//TODO: here need to draw only one if this type of object can't be connected to current (this variable comes from PHP)
									
										//checking if object is already connected, then do disconnect, not actually sure this is a good idea
										var o_0 = d.el.data('d');
										
										var txt = (o.D[o_0[0]][o_0[1]].actions.clip==2)?lp.disconnectFrom:lp.connectTo;
										
										//genereating html of dropzones
										$('body').append('<div id="connector"><img src="' + $('img', d.el).attr('src') + '" alt="' + $('.bottom a', d.el).text() + '"/></div><div id="dz1" class="dropzone">' + txt + '</div><div id="dz2" class="dropzone">' + lp.connectTo + lp.newObj + '</div>');
										o.elDrag = $('#connector');
										o.elDrag.fadeIn(ae[3]);

										//show both dropzones
										if(!is_fullscreen)o.elDrag.next().slideDown(ae[2]);
										o.elDrag.next().next().slideDown(ae[2]);

											
										//here need to show two divs on top and on bottom
										//with text and reaction if dragging over
									}
								}else{
									//need to change color if it is going to be attached
									//there are some params so maybe later need to make it universal


									//effects for resizing draggable to make it look nice
									/*var w = 220;
									var h = 150
									var img = $('img', o.elDrag);
									var o = o.T
									var y = o.offset().top;
									if(e.pageY > y + o.height() + 50 ||  e.pageY < y - 20){
										if(img.width()==w/2)img.animate({width: w, height: h}, ae[3])
									}else{
										if(img.width()==w)img.animate({width: w/2, height: h/2}, ae[3]);
									}*/
									var y = e.pageY - $('body').scrollTop();
									var _c = (y > o.elDragV.y1 ||  y < o.elDragV.y2)?true:false;


									//maybe for some browsers will need 'html's scrollTop
									if(_c != o.elDragV.c){
										if(y > o.elDragV.y1 ||  y < o.elDragV.y2){
											o.elDragV.c = true;
											if(y < o.elDragV.y2){
												o.elDrag.next().next().animate({paddingTop: 10}, ae[2]);
											}else{
												o.elDrag.next().animate({paddingBottom: 10}, ae[2]);
											}
										}else{
											o.elDragV.c = false;
											o.elDrag
												.next().animate({paddingBottom: 0}, ae[2])
												.next().animate({paddingTop: 0}, ae[2])
										}
									}
							
									//sorting only for gallery not for search
									if(o.ty==1){
										//SORTING
										var di_p = o.dropAfterId;
						
						
										//maybe pretty heavy for cpu
							
						
										//here need to check if over gallery then scroll horizontaly
										if(e.pageY>o.hPos[0] && e.pageY<o.hPos[1]){
											//getting id of element to insert after
										
											var di = Math.floor((-o.A.offset().left + e.pageX - 110)/225);
										
										
											//doing something only for new di
											if(di!=o.dropAfterId){
									
												if(di_p!=null){
													$('div', o.A).eq(Math.max(0, di_p)).css({'borderLeftWidth': 0, 'borderRightWidth': 0});
												}
												//detection before first case
												if(e.pageX<100)di = -1;

												var o_0 = 'border'  + ((di<0)?'Left':'Right');
											
												//some fix in case o.A.width is exactly like all items width, in this case last item jump lower
												//so we just add border's width - see next lines of code
												o.A.width(o.vars.W + 50)
											
												//TODO: maybe put animate and stop before, dunno how now&
												$('div', o.A).eq(Math.max(0, di))
													.css('border'  + ((di<0)?'Left':'Right') , '50px solid transparent')
						
												//setting id for mouseup event and for next time mousemove
												o.dropAfterId = di;
												//scrolling when on the vertiсal borders
												var dif = o.W/2 - e.pageX;
												o.sortScrollSpeed = Math.floor(-dif*Math.max(Math.abs(dif)-300, 0)/5/Math.abs(dif));
												if(!o.sortScroll_i)o.sortScroll_i = setInterval(function(){Gal.sortScroll()}, ae[3]/10);
											}
										}
									}
									//making offset so it won't go out of window to right (so there will be no scroll)
									//TODO: need to make something like this for left side
									var x = (e.pageX+70 < o.W)?e.pageX-60:o.W-130;
									o.elDrag.offset({left: x, top: e.pageY-47});

								}
							})
							.data('d', {_x: e.pageX, _y: e.pageY, el: t.parent()})
							.mouseup(function(e){
						
								var o = Gal;
							
								if(o.elDrag){
									//maybe for some browsers will need 'html's scrollTop
									var y = e.pageY - $('body').scrollTop()

									var d = $(this).data('d');
							
									//clearing sortscroll interval
									clearInterval(o.sortScroll_i);
									o.sortScroll_i = false;
								
								
									//removing border in case if drop on the same element as atarted
									$('div', o.A).eq(Math.max(0, o.dropAfterId)).css('border', 0);
							
									//TODO: need to remove sort borders
									if(y > o.elDragV.y1 ||  y < o.elDragV.y2){
										//added							
										if(y < o.elDragV.y2){
											//attaching dragged object to new, sending id and name
										
											var dd = d.el.data('d');
											Plus.attach(Gal.D[dd[0]][dd[1]]);
											//ajax
										}else{
											//console.log$('.top a[rel="2"], .top a[rel="3"] ', o.elDragT).attr('rel') )
											$('.actions .clip', o.elDragT).click();
										}
										o.elDrag.fadeOut(ae[3], function(){$(this).remove()});
									}else{
										//DROP for SORTING
								
								
										//return back when drop
										//need to check if drop is in gallery area, for this need to get position (top border)
										//and position + height (bottom border)
										//if there getting position of all and calculating the ID according to _x of element and all
										//insertAfter
										//done
										//if over gallery then prolly sort
								
										//SORTING
										if(e.pageY>o.hPos[0] && e.pageY<o.hPos[1] && o.ty==1){
											//inserting element after defined in mouseUp element
											//need to check if o.dropAfterId is not o.elDragT.parent()
									
											var p = o.elDragT.parent();
											
											
											//checking if dragging item is not the drop on one
											if(p.index()!=o.dropAfterId){
												var o_0 = $('div', o.A).eq(Math.max(0, o.dropAfterId));
												o_0.css('border', 0);
												//if not the adding visible class, it can be hidden
												p.attr('class', 'v').css('width', 50);
												//variable to send to api
												var curr = p.index();
												if(o.dropAfterId<0){
													//if <0 then it will be before first element
													//TODO: can be slow
													p.insertBefore(o_0).animate({'width': 220}, ae[2]);
												}else{
													//TODO: can be slow
													p.insertAfter(o_0).animate({'width': 220}, ae[2]);
												}
											
												//AJAX
												o_0 = $('p:first', p).data('d');
												var D = Gal.D[o_0[0]][o_0[1]];
											
												//target its new element sort_id, curr is sort_id that was before
												ajax_n('reorder', {'what': D.object_type, 'what_id': D.id, 'curr': Gal.am - curr, 'target': Gal.am - p.index()});
											
											
												$('div', o.A).css('borderColor', '#fff')
												//alrt.show('sending ajax here dont know what to send can get order that was and current?');
												//scrolling so it won't just somewhere and will be at the same place where you mouseup
												o.A.parent().scrollLeft(o.A.parent().scrollLeft() - 220);
											}
									
											o.dropAfterId = null;
											o.elDrag.fadeOut(ae[3], function(){$(this).remove()});
										}else{
											//returning item back
											var of = d.el.offset();
											o.elDrag.animate(
												{top: of.top+27, left: of.left+45, opacity: 0}, 
												ae[4],
												'swing', 
												function(){
													$(this).remove()
												}
											);
										}
									}

									//removeing dropzones
									//doing next next prev for trick, so it wont stop even if there is no next,
									//next is a connect to current dropzone, maybe it was better idea to change there order in DOM
									
									if(!is_fullscreen)o.elDrag.next().slideUp(ae[2], function(){$(this).remove()})
									o.elDrag.next().next().slideUp(ae[2], function(){$(this).remove()});

									o.elDrag = o.elDragT = false;
									//TODO:need to check here if it is attached

								    }
								
								
								
								$(this).unbind('mousemove').unbind('mouseup');
				    
						    })
						}

						e.preventDefault();
					}
				}

			})
		}

	 }

	/*
	}
	------/GALLERY------*/

	/*------OBJECT'S TOP (with red line) ------ 
	function(){
	*/
	
		//map is in Map object
		
		Vcont = {
		
			init: function(){
				var o = this;
				o.T = $('#v_cont .info')
				o.events();
				//showing tabs on red line
				//o.tabs();
				//adding sctions for main buttons on the redline
				o.actions();
				
				
				//switching ticker
				switch(object_type){
				    case 'event':
							o.ticker.init();
				        break;
				    default:
			    
				}
				//TODO: need to init timer here
				//timer: will get current time from first spot location and will calculate difference between
				//session date and that time, the minutes and seconds can be based on user timer maybe even all
				//time can be taken from user data if it is the same as spot's time
				//then every secong i'll change the time and every minute will check if it's the same as user's time
				//cause there can be really slow operations in gallery
			},
			
			//gallery tabs on red line
			//tabs: function(){
				
				//checking all small that contains number, if number > 0 then show tab
				
				
				
				/*$('#tabs small').each(function(i){
					var t = $(this);
					var p = t.closest('li')
					var am = parseInt(t.text());
					//if media then show icon only if there are more than one
					if(p.is('#tab_media'))am--;
					if(am>0)p.css('display', 'inline-block');
				});*/
				
				//guess i need this only for media?
				//#tm_1 TODO: maybe need to draw these tabs, so html will be more compact
				/*$('#tabs li').each(function(){
					var t = $(this);
					var am = parseInt(t.find('small').text());
					
					var o_0 =  t.is('#tab_media')
					//if media then show icon only if there are more than one
					if((!o_0 && am>0) || am>1 || (o_0 && object_type=='event' && am>0))t.css('display', 'inline-block');
				});*/
			//},
			
			//red line actions with report
			actions: function(){
				
				//adding event and removing .actions class, to simply use it with Actions
				$('#line .actions').click(function(){
					var t = $(this);
					//setting Actions EL
					Actions.El = t;
					//calling Actions method and passing some main variables
					//cl('here: %o', $(this).attr('class'));
					
					//TODO #re: need to make this better, again - need to learch regexp
					var cl = t.attr('class').split(' ')[0];
					
					
					if(typeof(Actions[cl]) == 'function')Actions[cl](object_id, object_type, function(_type, _html){
						
						//var _html = '<a href="http://dev.uride.it/dip" rel="3" style="background-image: url(http://i.dev.uride.it/as/av3_U1htL.jpg)" title="dip" class="avatar you">dip</a>';
						//_html = false;
						
						var t = $('#sidebar .' + _type + '_avatars');
						//changing amount in sidebar
						var am = parseInt($('small', t.prev()).text()) + ((!_html)?-1:1);
						
						

						//need this to exlude your new avatar from mores
						if(_html){
							var o_0 = $('.more', t.prev());
							var rel = o_0.attr('rel') + ',' + user_id;
							o_0.attr('rel', rel)
						}							
							
						/*}else{
							//removing user_id from exclude, yeah, doing it not the best regexp way
							var o_0 = rel.split(',');
							o_0.splice($.inArray(user_id.toString(), o_0), 1);
							rel = o_0.toString();
						}*/
						
						
						t
							.find('.avatar.you').remove().end()
							.prev().find('small').text(am)
							
							
							
						//adding avatar to sidebar
						if(_html)t.prepend(_html)
					}, 'html_output' /*need*/);
				}).removeClass('actions');
			},
			
			ticker: {
				
				//array to get days / hours / minutes / seconds
				div: [24*60*60, 60*60, 60, 1], 
				
				set: function(attribute){
					var o = Vcont.ticker;
					o.d--;
					if(o.d<0){
						clearInterval(o.timer_int);
						o.timer.parent().parent()
							.parent().find('.late').fadeIn(ae[2]);
					}else{
						var d = o.d;
						

						for(var i=0; i<4; i++){
							o.digits[i] = Math.floor(d / o.div[i]);
							d -= o.digits[i] * o.div[i];
						}

						o.timer.each(function(i){
							//writing digit, if less than 10 then 0 in the beggining
							$(this).text((Vcont.ticker.digits[i]<10 && i!=0)?('0'+Vcont.ticker.digits[i]):Vcont.ticker.digits[i]);
						})
					}
				},
				
				get: function(_d, _i){
					//method to get time left, if _i - is a number to get seconds / minutes / hours / days (as a vars from div array) in return
					//cl('date>>>>> %o', _d)
					var a = new Date(_d);
					//user date
					//difference in seconds
					return Math.floor((a-new Date())/1000/this.div[_i]);
				},			
				
				init: function(){
					//get time
	                var o = this;
	                o.digits = [];

					//element with ticker
					o.timer = $('#timer i');
					//TODO: actually need to take numbers from date and from spot time
					//max will be 99 days

					//TODO: need to check with computer time
	                //o.timer.each(function(i){
	                //    o.digits[i] = parseInt($(this).text());
	                //});



	                //we can get local time of coordinates here
					//$.ajax({ url: "http://www.earthtools.org/timezone/40.71417/-74.00639", dataType: 'xml', success: function(data){
					        //cl($('localtime', data).text())
					//}});

					//date of object
					
					//Passing element with date, to get time left
					o.d = o.get($('.e_da', o.T).attr('date'), 3);
					
					
					//showing ticker'e dom element
					if(o.d>0)$('#timer').fadeIn(ae[2]).prev().fadeIn(ae[2]);
					//setting interval
					o.timer_int = setInterval(function(){Vcont.ticker.set()}, 1000);
					o.set();
				}
				
			},

			events: function(){
				var o = this;
				//TODO: need to make all events the same with the fastest way like in gallery
				o.T.bind({
				    click: function(e){
   						var t = $(e.target);
   						//class no is to switch off Actions
   						if(t.is('a') && !t.is('.no')){
   							Actions.El = t;
   							//calling function from Actions object, the name of function is based on class
   							var s = t.attr('class').replace(/\s/, '_');
							if(typeof(Actions[s])=='function')Actions[s]();
   						}
				    }
				});
			}
					
			
		}
	
		
	
	
	/*
	}
	------/OBJECTS TOP------*/

/*
}
------/HEADER------*/


/*------BODY------ 
function(){
*/

	/*------COMMENTS------ 
	function(){
	*/	
	var O;
	
	function Comments(_el, _instance_name, _oType, _oId, _type){
		var o = this;
		
		//for messages and feeds we need 0 to get first comments
		o.curMore = 1;
		//o.maxMore = 0;
		o.offset = 0;
		o.T = _el;
		o.I = _instance_name;
		//reference from jQuery DOM object to our object
		o.T.data('R', this);
		o.oType = _oType || object_type;
		o.oId = _oId || object_id;
		o.type = _type || 'comment';
		
		//TODO: need to remove _type;
		o.draw = function(_d, _no_actions, _next){
			
			// the last one is class of comment - reply or comment ("r" or empty)
			//drawing one comment or reply
			var cl = (_d.reply)?' class="r"':''
			var s = '<li' + cl + ' id="comment_' + _d.id + '">';
			//TODO: need to add click function for avatar
			if(_d.user_id){
				s += '<a href="/' + _d.user_id + '" style="background-image: url(http://i.' + domain + '/as/' + _d.user_pic + ')" title="' + _d.user_name + '"';
				//if this is your avatar then we don't need avatar window
				s += ' class="avatar' + ((_d.buddy)?' buddy':'') + ((_d.user_id != user_id)?' you':'') + '" ></a>'
				//s += '<img src="" alt="" class="avatar" onmousedown="uip(' + _d.buddy + ', ' + _d.user_id + ')" />';
				//not sending name fro reply
				if(_d.user_name){
					s += '<p>';
						s += '<a href="' + _d.user_id + '" title="' + _d.user_name + '">' + _d.user_name + '</a> ';
						if(_d.date)s += '<small>' + _d.date + '</small>';
					
						if(_d.actions && user_id && !_no_actions){
							//TODO: don't really like these double conditions, also it can be pretty bad for API
							//drawing edit and remove buttons
							if(_d.actions.edit && o.type!='message'){
								s += ' <small>[ <a class="edit" title="' + lp.edit + '">' + lp.edit + '</a>';
								if(!_next)s += ' | <a class="remove" title="' + lp.remove + '">&times;</a>';
								s += ' ]</small>';
							}
						}
					s += '</p>';
				}
			}
			//text of comment
			s += '<div><div class="cont">' + _d.text + '</div>';

			if(user_id && !_no_actions && !_next  && o.type!='message'){
				s += '<a class="reply" title="' + lp.reply + '">' + lp.reply + '</a>';
			}else if(_no_actions){
				s += '<a class="comment" title="' + lp.postReply + '">' + lp.postReply + '</a>'
			}
			s += '</div></li>';
			return s;
		}

		o.drawF = function(){
			var s = '<li class="form"><a style="background-image: url(http://i.' + domain + '/as/' + user_pic + ')"class="avatar you"></a>';
			s += '<div><div class="cont"><textarea class="labeled resizable" maxlength="1000">' + lp.writeCommentHere + '</textarea></div><a class="comment">' + lp.say + '</a></div></li>';
			var t = $(s).prependTo(o.T)
			//again some strange thing with focus right after creating DOM
			setTimeout(function(){$('textarea', t).focus()}, 100)
			//.prepend(s)
		}
	
		o.comment = function(){
			//send request to publish
			var o = this;
			//if this is a reply or comment
			var tp = o.El.closest('li');
			
			var r = (tp.is('.r'))?true:false;
			
			var D = {};
			
			if(r){
				//need to find parent comment id
				var p = tp.prev();
				while(p.attr('class')!=''){
					//this should work
					p = p.prev();
				}
				//making string for Data method
				//var s = '&parent_id=' + p.attr('id').substr(8);
				D.parent_id = p.attr('id').substr(8);
			}
			D.text = $('textarea', tp).val();
			//check if this is comment form or reply form
			D.post = (r)?'reply':o.type;
			
			//changing more offset
			if(!r)o.offset++;

			o.Data('post', D);
			//this class should contatin loadbar for all inner <a> with defined classes - reply, comment, remove, edit
	
			
		}
	
		o.reply = function(){
			//drawing reply form
			var o = this;
		
			var tp = o.El.closest('li');
			tp.after(o.draw({'text': '<textarea class="req labeled resizable" maxlength="1000">' + lp.yourReply + '</textarea>', 'reply': true, 'user_id': user_id, 'user_pic': user_pic}, true, true));
			tp.next()
				.addClass('form')
				/*.hide().slideDown(0, function(){
						$(this)
							//.find('.comment').fadeIn(ae[1]).end()
							.find('textarea').focus();
					})
				.find('.comment').hide();*/
				.find('textarea').focus();
		
			//removing reply button
			o.El.remove()
			///??????
			//it was 
			//o.El = o.EL.next()
			tp = $('.comment', tp.next());
			//send request and change dom
			//there are two stages - drawing reply forms, and drawing reply, first here, second is in Data
		}
	
		o.edit = function(){
			//change dom of current comment and sed request after via Data method with some param
			var t = this.El;
			var tp = t.closest('li');
		
			if(tp.is('.form')){
				t.text(lp.edit);
				$('.reply, .cont', tp).show();
				$('.editor, .save', tp).remove();
			}else{
				//hiding original div, and drawing textarea with save button
				var el = $('.cont', tp);
				//hiding what we dont' need
				$('.reply, .cont', tp).hide();
			
				el
					.after('<div class="editor cont"><textarea class="edit_ta resizable" maxlength="1000">' + Inputs.trim(el.text()) + '</textarea></div>')
					.after('<a class="save">' + lp.save + '</a>')
				
				var o_0 = $('textarea', el.parent())
				o_0.focus();
				
				//doing this to resize textarea
				Inputs.resizable(o_0);
			
				t.text(lp.dontEdit);
			}
			tp.toggleClass('form')
		
		
			//changinf dom and calling comment for button
			//in comment need to add additional cases
		}
	
		o.save = function(){
			var o = this;
			var tp = o.El.closest('li');
			
			//type = comment, id = id, action = edit
			o.Data('edit', {'type': o.type, 'text': $('textarea', tp).val(), 'id': tp.attr('id').substr(8)}, true);
		}
	
		o.remove = function(){
			//send request and remove dom
			//doing it with global var can't pass it into dialog.show :(
			O = this;
			dialog.show(this.El, 'remove', function(){
				//TODO: need to make something to use in any example of the class
				var o = O;
				var tp = o.El.closest('li');
				cl('here: %o', tp.attr('id'));
				
				//sending request
				o.Data('delete', {'type': o.type, 'id': tp.attr('id').substr(8)}, true)//'id=' + tp.attr('id').substr(8));
				tp.slideUp(ae[1], function(){$(this).remove()});
				if(!tp.is('.r'))o.offset--;
			})
		
		}
	
		o.more = function(_limit){
			//for more need to keep amount of mores\
			var o = this;
			//TODO: need to add limit, so it will be possible to show any amount of comments, if there is limit then don't need more
			if(!o.limit)o.limit = _limit || 0
			o.Data('view', {'type': o.type, 'more': o.curMore, 'offset': o.offset, 'limit': o.limit, 'what': o.oType, 'what_id': o.oId}, true);
		}
	
		o.Data = function(_action, _data, _boo){
			//TODO: why i'm sending _boo, it is true always
			//TODO: need to make something so it will work with any example of class, see "COmments" lower
		
			//checking textarea content if necessary 
			var boo = true;
			if(!_boo){
				var ta = $('textarea', this.El.parent());
				(!Inputs.validate(ta))?boo=false:ta.attr('disabled', 'disabled');
			}
		
			if(boo){
				
				var o = this;
				//addin loading class, to show loadbar
				o.El.closest('li').addClass('loading');
			
				//this is the function that will send ajax request
				/*ajax('type???', '', _data, function(_el, _ar){
				
				}, o.El);*/
				//test variables this should be in ajax
			
				//TODO: here need to use el.data('R') istaed of o  
				
				if(_action=='view')_data.id = 0;
				
				if(_data.type!='comment' && o.type!='message'){
					//TODO: why it is so complicated here?
					//rewriting some default for ajax_n variables, so it will take and save comments not for global object_type and object_id
					_data.id = o.oId;
					_data.type = o.oType;
				}else if(o.type=="message" && _action!='view'){
					//fixing some data for messages
					_data.receiver_id = o.oId;
					_data.id = user_id;
					_data.need = 'output';
				}
				
				//for new comments / replies
				ajax_n(_action, _data, function(_el, _data){
					//{'post': _type /*reply / message*/, 'text': _data.text /*parent_id for reply; receiver_id for messages*/})
					//O = o;
					//setTimeout(function(){
					//for new comment
					//7th value - 1 for reply empty for comment
					//var _ar = ajax_StrToAr('1|0|||id|http://i.uride.it/ar/8.png|user_id|user_name|Location or smthng else|Comment/reply|days ago|1||101|');

					
					//id, user_pic, user_id, user_name, buddy, description, text, date, remove, type

					//when will move to ajax it will be el instead of o.El
					//so just need to remove this line
					//_el = o.El;
					//getting comment object

					var o = _el.data('R');

					var ep = _el.closest('li');

					//working with textarea here
					var ta = $('textarea', ep)
					if(ta.length)ta.removeAttr('disabled');


					ep.removeClass('loading');


					if(_data.data){
						
						//TODO: don't really like these double conditions, also it can be pretty bad for API
						if(_data.data.items){
							var D = _data.data.items

							var l = D.length;
							//generating string to add in DOM
							var s = '';
							var n;
							for(var i=0; i<l; i++){
								//to get next reply param doing this
								n = D[i+1];
								s += o.draw(D[i], 0, (n)?n.reply:0)
							}
						}
						
					}

					//TODO (???): some problems here, need to take parent but also element by iteself 
					var cl = _el.attr('class'); 

					if(cl=='more'){
						ep.show().before(s);
						//defining more ammount for comments, doing double check
						if(_data.data && _data.data.more){
							//setting more left
							o.curMore = _data.data.more;
							//TODO: maybe make it a lil bit smoother, now it's jump pretty ugly
							//maybe need to put it somewhere as absolute when curMore=0/1
							//if(o.curMore==o.maxMore)ep.remove();
						}else{
							//removing more button
							ep.remove();
						}

						
						
					}else{
						//adding DOM for some types
						if(cl=='comment' || cl=='save' || cl=='reply'){
							ep.after(s);
							ep.next();//.hide().fadeIn(ae[5])
						}
						//removing DOM for some types
						if(cl=='save' || cl=='remove' || cl=='reply')ep.remove();
						//cleaning textarea for new comment and removing input area
						if(cl=='comment'){
							$('textarea', ep).val('');
							if(ep.is('.r'))ep.find('.comment').hide().end().remove()
						}
					}


					//TODO: for more need to put before in case there are more mores
				//}, 2000)
				}, o.El, function(_el){
					//error function
					//returning functionality of comment area
					var ep = _el.parent();

					//working with textarea here
					var ta = $('textarea', ep)
					if(ta.length)ta.removeAttr('disabled');
					ep.removeClass('loading');
				});
				
				
			}
		}

		o.events = function(){
			//when clicking on .reply - Comments.reply, edit - Com...edit...
			//and taking parent
			this.T.bind({
				click: function(e){
					var o = $(this).data('R');
					var t = $(e.target);
					if((t.is('a') || t.is('.more')) && !t.parent().is('.loading')){
						//here need to make something so it will assign params not for Comments, but for every existence of this class
						o.El = t;
						//passing reference of js object to jQuery dom object
						o.El.data('R', o);
						var s = t.attr('class');
						if(t.attr('class') && typeof(o[s])=='function'){
							o[s]();
						}
					}
				}
				//event on pressing enter
				,
				keydown: function(e) {
					if (e.keyCode == 13 && (e.ctrlKey || e.shiftKey)){
						$('.comment, .save', $(e.target).closest('li')).click();
						//so it wont do useless <br>
						return false;
					}
				}
			});
		}
 
		//init events
		o.events();
	 }

	if($('#comments')){
		var objects_comments = new Comments($('#comments'), 'comments', object_type, object_id)
	}


	/*
	}
	------/COMMENTS------*/

	/*------SIDEBAR------ 
	function(){
	*/

		Sidebar = {
			
			T: $('#sidebar'),
			
			init: function(){
				var o = this;
				
				//cl('here: %o', 1);
				//$('#tags li a').after('<a class="remove" rel="AAAAA">remove</a>')
				
				o.events()
			},
			
			add_item: function(_t, _id, _name, _el){
				//adding loadbar to _el
				//TODO: need to add loading function to make everything easy
				if(_el)_el.addClass('loading');
				
				//this will always add item
				ajax_n('connect', 
						{
							'type': object_type, 
							'id': object_id,
							'what': _t.attr('rel'), 
							'name': _name,
							'what_id': _id,
							'need': 'html_output',
							'force': 'add'
						}, 
						function(_t, _data){
							//removing loadbar
							if(_t[1])_t[1].removeClass('loading');
							
							//yeah, too cool, to write comment here
							t = _t[0];
							if(_data && _data.data){
								//sending request and inserting reply to dom element
								var data = _data.data;
								//data.html = '<li class="trick"><a class="remove">&times;</a><a href="">True Makio</a></li><li><small>Rollerblading</small> by you</li>';
								//_html = false;
								//var exclude = '2';

								//TODO: later need to generate html here
							
								//changing amount in sidebar
								var am = parseInt($('small', t).text()) + ((!data.html)?-1:1);
								$('small', t).text(am);


								//TODO: too lazy to exclude and make it unique later need to fix
								var o_0 = $('.more', t);
								var rel = o_0.attr('rel') + ',' + data.id;
								o_0.attr('rel', rel);


								//first need to find if item alreadt exists if yes - remove it
								//can put this logic to redraw and call it everytime


								//adding html to dom
								t.next().prepend(data.html);
								
							}
						},
						
				 		[_t.parent(), _el || 0],
				
						function(_t){
							//if error - need to remove loadbar
							_t[1].removeClass('loading')
						}
				);
				
				
			},
			
			remove: function(_t){
				//sending remove request and calling Sidebar.redraw
				var t = _t.closest('li');
				
				//some fixes for tricks
				if(t.is('.trick'))t.next().remove();
				
				//sending remove request
				ajax_n('connect', {'what': t.parent().attr('id').slice(0, -1),'what_id': _t.attr('rel'), 'force': 'delete'});		
				//removing item
				t.remove()
			},
			
			more: function(_t){
				//getting items and appedning them
				var o = this;
				var T = _t.parent().next();
				
				if(_t.is('.a')){
					//removing items when closing more
					$('.from_more', T).remove();
				}else{
					//if loaded then just show items from data
					if(_t.is('.loaded')){
						//drawing items from T.data
						Sidebar.more_draw(T, T.data('data'));
					}else{
						_t.addClass('loading')
						//loading more
						ajax_n('view', 
							{
								//exclude will be in rel
								'connected': _t.attr('rel'),
								'type': _t.attr('rel'),//_t.parent().next().attr('id').slice(0, -1),
								'div': 'sidebar',
								'what': object_type,
								'what_id': object_id,
								'more': 1,
								'id': 0
							}, 
							function(_t, _data){
								if(_data.data){
									var t = _t.parent().next()
									//saving data
									t.data('data', _data);
									//removing loading class
									_t.removeClass('loading');
									//drawing items
									Sidebar.more_draw(t, _data);
								}
							},
					 		_t
						);
						_t.addClass('loaded');
					}
					
				}
				//toggle opened or closed
				_t.toggleClass('a');
			},
			
			more_draw: function(_t, _data){
				//will draw items in _t and for each will add special class, to hide it after
				//var items = _data.items;
				//items = ['<li class="trick">aaa</li>', '<li class="trick">bbb</li>', '<li class="trick">ccc</li>'];
				
				//TODO: maybe this is too greedy, need to put good regex and check the speed
				if(_data.data.items)_t.append(_data.data.items.toString().replace(/<\/li>,/g, '').replace(/<\/a>,/g, '').replace(/class="/g, 'class="from_more ').replace(/<li/g, '<li class="from_more"'));
			},
			
			events: function(){
				$('#sidebar, #v_cont .remove').bind('click', function(e){
					var t = $(e.target);
					if(t.is('a, u')){
						//calling event based on <a> class name
						//we can assign more than 1 event so doing this
						var ar = t.attr('class').split(' ');
						for(var i=0; i<ar.length; i++) {
							if(typeof(Sidebar[ar[i]])=='function')Sidebar[ar[i]](t);	
						};
					}
					
				})
			}
			
			
		}
	
	

	/*
	}
	------/SIDEBAR------*/

/*
}
------/BODY------*/


/*------INIT------ 
function(){
*/

//TODO delete this
		

	//TODO: check
	//team link at the buttom of the page
	/*$('#about p a:nth-child(3)').click(function(){
		Search.load('&admin=1', 'users')
	});*/


	//click event for document to close some windows

	
	//TODO: need to add this in html for special page so user settings will be opened
	//Plus.show(0)
	
	


	
	
	
	//checking if fullscreen fullwindow
	if($('body').is('.fullscreen')){
		var is_fullscreen = true;
		//showing terms, so nothing will jump
		$('#footer').show();
	}else{
		var is_fullscreen = false;
	}
	
	Gal.init();
	lng_change();
	Vcont.init();
	Map.init();
	Sidebar.init();
	Inputs.init();
	
	
	//checking if there is "search" in hash tags
	var o_1 = window.location.hash;
	if(o_1 && o_1.match('search')){
		//sending search request
		Search.urlToRequest('/search/user/search_id:' + o_1.split(':')[1]);
		//doing this to init submenus
		Search.init()
	}else{
		//showing gallery if it is on in user settings
		//and if there are more than 1 photo
		//also init hashtags for search
		if(!Search.init() && sett.show_gal && parseInt($('#tab_media small').text())>1)$('#tab_media').click();
	}

	
	//init menus in pan 
	pan_menus()
	
	
/*
}
------/INIT------*/

//5070 lines before update #1


/*jQuery.unbindall = function () { jQuery('*').unbind(); }
//
$(document).unload(function() { 
  jQuery.unbindall()
});*/

//6885

//7228

//TODO: report
//TODO: need to add unload event for online/offline status
//TODO: need to make all names proper way add_trick, so we can read classes from html




//8526 (14.07.2011)



