//var basePath = '/gamesdj/';
//var basePath = '/';
$(document).ready(function(){

	$(window).scroll(function(){
		
		var smartBanner = $(".smartBannerIdentifier");
		var offset = smartBanner.offset();

		
		$('.debugg span').html($(window).scrollTop()); 		
		$('.debugg strong').html(offset.top);

		var top = '';
		if($(window).scrollTop() > offset.top){
		   $(".floatBanner").css({"position": "fixed", "top": "0px", "padding-top": "5px"});
		}
		
		if($(window).scrollTop() <= offset.top){
		   $(".floatBanner").css({"position": "relative", "top": "0px", "padding-top": "0px"});
		}
		
	}); 
	
	$('.[rel="tooltip"]').tipsy({gravity:'s', html: true});
	
	//load addthis 
	$.getScript("http://s7.addthis.com/js/250/addthis_widget.js?domready=1",function(d,s){});

	//top dropdown menu
	$('.mainMenu > li').subMenu(); 
	
	//related games carousel
	$('.horizontalCarousel').jcarousel({
		wrap: 'last',
		visible: 5
	});
	
	//popularGamesCarousel
	$('.popularGamesCarousel').jcarousel({
		wrap: 'last',
		visible: 5,
		auto: 5
	});
	
	//game page tabs
	$("#topGames, #gameTabs").organicTabs();
					
	//game page desc truncate				
	$('.truncateTxt').truncate({max_length: 250});
	
	//game page ad box
	$('.closeAdBox').click(function(){
		count = 0;
		return false;
	});
	
	
	//show/hide embed code box
	$('.embedBtn').click(function(){
		$(".embedCode").toggle();
		$('.embedCode > textarea').select();
		return false;
	});
	
	$('.embedCode > textarea').click(function(){
		$(this).select();
		return false;
	});


	//get more games ajax
	$("#moreGames").click(function(){										 
		
		var catId = $('#cat_id').val();
		var dataString = 'catId=' + catId;
		
		$('#gDeveloper').html('<div class="loadingComments">Loading games...</div>');
		
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=getCategGames",
			data: dataString,
			success: function(data)
			{
				$('#gDeveloper').html(data);
				$('#gDeveloper').remove('.loadingComments');	
			}
		});
	});

	//input + textarea focus
	$('#subscriber_name').focus(function(){
		if($(this).val() == "Name")
		{
			$(this).val('');
		}
	});
	
	$('#subscriber_name').blur(function(){
		if($(this).val() == "")
		{
			$(this).val('Name');
		}
	});
	
	$('#subscriber_email').focus(function(){
		if($(this).val() == "E-mail")
		{
			$(this).val('');
		}
	});
	
	$('#subscriber_email').blur(function(){
		if($(this).val() == "")
		{
			$(this).val('E-mail');
		}
	});
	
	//contact us 
	$("#sendMessage").click(function(){										 
		contactUs();
		return false;	
	});		
		
	//newsletter subscribe ajax					
	$('.newsletter_form').keypress(function(e) {
        if(e.which == 13) {
			subscribeNewsletter();
        }
    });

	$(".okBtn").live("click", function(){										 
		subscribeNewsletter();
		return false;
	});
	
	//show/hide more box
	var Toggled=true
	$('.showMore, a.clsMrBox').click(function(){
	//$(".showMore, a.clsMrBox").live("click", function(){										 

		if(Toggled==false){
			Toggled=true;
			$('.showMore').removeClass('selectedMenu');
		}
		else{
			Toggled=false;
			$('.showMore').addClass('selectedMenu');
		}
		
		$('.moreBox').animate({
			//opacity: "toggle",
			height: "toggle"
	
		  }, {
			duration: 200
		 });
		return false;
	});
	

	//delay search
	var delay = (function(){
	  var timer = 0;
	  return function(callback, ms){
		clearTimeout (timer);
		timer = setTimeout(callback, ms);
	  };
	})();
	
	$('#inputString').keyup(function() {
		var object = this.value;							 
		delay(function(){
		  lookup(object); 
		  $('#inputString').removeClass('searchloader');
		}, 400 );
	});
	
	$('#inputString').keydown(function(){
		$(this).addClass('searchloader');
	});
	
	$('#inputString').focus(function(){
		if($(this).val() == 'Search for games')
		{
			$(this).val("");
		}
	});
	
	$('#inputString').blur(function(){
		if($(this).val() == '')
		{
			$(this).val("Search for games");
		}
		$(this).removeClass('searchloader');
		$("a.searchBtn").removeClass("searchBntBlack");
		$('#searchResults').fadeOut(); // Hide the suggestions box
		
	});
	
	//search btn click search
	$('.searchBtn').click(function(){
		var inputValue  = $('#inputString').val();						   
								   
		if(inputValue != 'Search for games' && inputValue != '')
		{
			$('.gSearch').submit();	
		}	
		return false;
	});
	
	//sWlktBtn click search
	$('.sWlktBtn').click(function(){
		var inputValue  = $('.sWlktInput').val();						   
								   
		if(inputValue != 'Search for walkthroughs' && inputValue != '')
		{
			$('.wlkSearch').submit();	
		}	
		return false;
	});
	
	//search walkthrough
	$('.sWlktInput').focus(function(){
		if($(this).val("Search for walkthroughs"))
		{
			$(this).val("");
		}
	});
	
	//COMMENTS
	$("#cmtMessage").keyup(function(){
		var limit = 400;
		var currentLength = $(this).val().length;
		var charsLeft = limit - currentLength;
		$('span.wordCount').html(charsLeft);
		if(currentLength >= limit){
			$(this).val($(this).val().substring(0, limit));
			$('span.wordCount').html('0');
			var textarea = document.getElementById('cmtMessage');
			textarea.scrollTop = textarea.scrollHeight + 9999;
		}
	});
	
	//
	$('.addComment').keypress(function(e) {
		if(e.which == 13 && e.ctrlKey) {
			postComment();
		}
	});
	
	//post comment
	$("#postComment").live("click", function(){										 
		postComment();
		return false;
	});
	
	//comments unsubscribe
	$('#unsubsCommAlert').click(function(){
		var c_uid = $("#c_uid").val();
		var gid = $("#game_id").val();
		
		var dataString = 'c_uid=' + c_uid + '&game_id='+ gid;
		
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=unsubscribeCommAlert",
			data: dataString,
			success: function(data)
			{	
				$('#cmtAlertsBoxUnsub').slideUp(400);
			}
		});
		return false;
	});
	
	//comments unsubscribe box close
	$('#unsubCommCls, .closeErBox').click(function(){
		$('#cmtAlertsBoxUnsub').slideUp(400);
		return false;
	});
	
	//game mode
	$('.gameModeOn').live('click', function() {
		gameModeOn();
		return false;					
	});
	
	$('.gameModeOff').live('click', function() {
		gameModeOff();
		return false;	
	});	
	
	$('.closeGameMode').live('click', function() {
		gameModeOff();
		return false;	
	});	
	
	$('#overlay').live('dblclick', function() {
		gameModeOff();
		return false;					
	});
	
});
	
	//ajax dropdown menu
	(function($){  
		$.fn.extend({   
			//plugin name - subMenu  
			subMenu: function(options) {  
				
				
				
				return this.each(function() {
					var cat_id = $(this).attr('id');
						
					$(this).hover(function(){
						$('.dropMenu', this).show();
						//$('.dropMenu', this).append(cat_id);
						$('.dropMenu', this).load(basePath + "library/ajax.php?action=loadSubMenu", {cat_id:cat_id});
						$('a.hasSubMenu', this).addClass('overMenuItem');
					},
					function(){
						$('.dropMenu', this).hide();
						$('a.hasSubMenu', this).removeClass('overMenuItem');
					})
					
				});
				
			}  
		});  
	})(jQuery);  
	
	//game mode on
	function gameModeOn()
	{	
		var gBoxHeight = $('#gameModeBox').height();
		var docHeight = $(window).height();		
		var scrollTop = 165 - ((docHeight/2) - (gBoxHeight/2)) / 2;
		//var scrollTop = ;
		if(gBoxHeight > docHeight - 50)
		{
			scrollTop = 165;
		}
		var elem = '.gameModeOn';
		var hash = location.hash.replace('#','');
		//$('#debugg').html(scrollTop);
		
		$("body").append("<div id='overlay'></div>");
		$('.gameModeOn span').html('Lights On');
		//$('#gameModeBox').append('<a href="#" class="closeGameMode"></a>');
		$("#overlay").height(docHeight).css({'opacity' : 0.95});
		$("#overlay").fadeIn('fast');
		$.scrollTo({top: scrollTop +'px', left:'0px'}, 500);
		$(elem).removeClass('gameModeOn').addClass('gameModeOff');
		$('#gameModeBox').addClass('gmActive');
		location.hash = 'lightsOff';
		$('.searchBox').hide();
	}
	
	//game mode off
	function gameModeOff()
	{				
		var elem = '.gameModeOff';
		var hash = location.hash.replace('#','');
		
		$(elem).removeClass('gameModeOff').addClass('gameModeOn');
		$('#gameModeBox').removeClass('gmActive');
		$('#overlay').fadeOut('fast', function() {
			$("#overlay").remove();
		});
		$('.gameModeOn span').html('Lights Off');
		//$(".closeGameMode").remove();
		//$.scrollTo({top:'0px', left:'0px'}, 500);
		location.hash = '#lightsOn';
		$('.searchBox').show();
	}
	//live search
	function lookup(inputString) {
		
		if(inputString.length == 0) {
			$('#searchResults').fadeOut(); // Hide the suggestions box
			$("a.searchBtn").removeClass("searchBntBlack");
			
		} else {
			$.post(basePath + "library/ajax.php?action=searchGame", {queryString: ""+inputString+""}, function(data) { // Do an AJAX call
				$('#searchResults').fadeIn(); // Show the suggestions box
				$("a.searchBtn").addClass("searchBntBlack");
				$('#searchResults').html(data); // Fill the suggestions box
				
				/*
				//search results
				$(".srGameBox").bind({
					keydown: function(e) {
						var key = e.keyCode;
						var target = $(e.currentTarget);
				 
						switch(key) {
							case 38: // arrow up
								target.prev().focus();
								e.preventDefault();
				         		return false;
								break;
							case 40: // arrow down
								target.next().focus();
								e.preventDefault();
				          		return false;
								break;
						}
					},
					 focus: function(e) {
						$(".srGameBox").removeClass("srGameBox_sel");
						$(e.currentTarget).addClass("srGameBox_sel");
					}
				});
				$(".srGameBox").first().focus();
				*/
			});
		}
	}
	
	//COMMENTS
	function getComments(gid, page){

		var dataString = 'game_id=' + gid +'&page='+ page;
		//$('#comments').html('');
		$('#comments').append('<div class="loadingComments">Loading comments...</div>');
		
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=loadComments",
			data: dataString,
			success: function(data)
			{
				$('#comments').html(data);
				var totalPages = $('#totalCPages').val();
				var currentPage = $('#currentPage').val();
				
				for (page=1; page<=totalPages; page++)
				{
					if(currentPage == page)
					{
						$('#comments').append("<span class='pageSel'>"+page+"</span>");	
					}
					else
					{
						$('#comments').append("<span class='page' onclick='getComments("+ gid +", "+ page +")'>"+page+"</span>");	
					}
					
				}			
				$('#comments').remove('.loadingComments');	
			}
		});
	}
	
	//GET LATESTS COMMENTS
	function getLatestsComments(message){
		if(message == undefined)
		{
			message = "Loading comments";
		}
		$('#latestComm').append('<div class="loadingComments">'+message+'</div>');
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=getLatestsComments",
			data: "",
			success: function(data)
			{	
				$('#latestComm').html(data);
			}
		});	
	}
	
	//POST COMMENT
	function postComment()
	{
		$(".loader").show();
		$("#postComment").hide().after('<div class="redBtnInactive">Post Comment</div>');

		var gameId = $("#game_id").val();
		var cmtEmail = $("#cmtEmail").val();
		var cmtName = $("#cmtName").val();
		var cmtMessage = $("#cmtMessage").val();
		
		// Store vars
		if($("#cmtAlert:checkbox:checked").val() == undefined)
		{
			cmtAlert = 0;
		}
		else
		{
			cmtAlert = 1;
		}
		var dataString = 'cmtMessage='+ cmtMessage + '&cmtName='+ cmtName + '&cmtEmail=' + cmtEmail + '&game_id='+ gameId + '&captha='+$("#captha").val() + '&cmtAlert='+cmtAlert;
	
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=addComment",
			data: dataString,
			success: function(data) {
				$('#cmtResult').html(data);
				$(".loader").hide();
				$("#postComment").show();
				$(".redBtnInactive").remove();

				//form ok
				if ($('#c_status').val() == "ok"){
					$("#cmtName, #cmtEmail, #cmtMessage").removeClass("inputError inputValid");
					$("#cmtName, #cmtEmail, #cmtMessage").val("");
					$('#cmtName').focus();
					$('.wordCount').html(300)
	
					getComments(gameId, 1);
					getLatestsComments("Updating comments");
					
					$(".okMsg").fadeIn(300).delay(6000).fadeOut(300);
					
					/*$('#postComment').unbind('click').click(function(){
						return false;
					});
					$('#postComment').addClass('redBtnInactive');
					
					$('#postComment').html('Your Comment Has Been Posted');
					*/
					
					//increment comments number
					var commentsNo = parseInt($('.cmtNo').html());  
					$('.cmtNo').html(parseInt(commentsNo) + 1);
					
					alertSubscribers(gameId, cmtEmail, cmtName, cmtMessage);
				}
				
				//form fail
				else {
					//check name
					if ($('#c_name_error').val() == "error")
					{
						$("#cmtName").addClass("inputError");
						$("#cmtName").removeClass("inputValid");
					}
					else 
					{ 
						$("#cmtName").removeClass("inputError");
						$("#cmtName").addClass("inputValid");
					}
					
					//check message
					if ($('#c_message_error').val() == "error")
					{
						$("#cmtMessage").addClass("inputError");
						$("#cmtMessage").removeClass("inputValid");
					}
					else 
					{ 
						$("#cmtMessage").removeClass("inputError"); 
						$("#cmtMessage").addClass("inputValid");
					}
					
					//check email
					if ($('#c_email_error').val() == "error")
					{
						$("#cmtEmail").addClass("inputError");
						$("#cmtEmail").removeClass("inputValid");
					}
					else 
					{ 
						$("#cmtEmail").removeClass("inputError"); 
						$("#cmtEmail").addClass("inputValid");
					}
				}	
			}
		}); 	
	}
	
	//ALERT SUBSCRIBERS
	function alertSubscribers(game_id, email, name, comment)
	{
		//alert('Message posted on game id ' + email);
		
		var dataString = 'game_id='+game_id + '&email='+email + '&name='+name + '&comment=' + comment;
		
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=alertSubscribers",
			data: dataString,
			success: function(data) 
			{
				$('#debuggTest').html(data);
			}
		});
	}
	
	//NEWSLETTER SUBSCRIBE
	function subscribeNewsletter()
	{
		$('.okBtn').hide();
		$('.loader_1').fadeIn(300);
		
		var dataString = 'name='+$("#subscriber_name").val() + '&email='+$("#subscriber_email").val();
		
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=subscribeNews",
			data: dataString,
			success: function(data) 
			{
				$('#ns_result').html(data);
				//alert(data);
				
				//form ok
				if ($('#ns_status').val() == "ok"){
					
					$('.newsletter_form').hide();
					$('.subscribed').fadeIn(500);
					
					$("#subscriber_name, #subscriber_email").removeClass("inputError");
				}
				
				//form fail
				else {
		
					if ($('#ns_name_error').val() == "error")
					{
						$("#subscriber_name").addClass("inputError");
						$("#subscriber_name").removeClass("inputValid");
					}
					else 
					{ 
						$("#subscriber_name").removeClass("inputError");
						$("#subscriber_name").addClass("inputValid");
					}
					
					if ($('#ns_email_error').val() == "error")
					{
						$("#subscriber_email").addClass("inputError");
						$("#subscriber_email").removeClass("inputValid");
					}
					else 
					{ 
						$("#subscriber_email").removeClass("inputError"); 
						$("#subscriber_email").addClass("inputValid");
					}
					
					$('.loader_1').hide();
					$('.okBtn').fadeIn(300);
					
				}
		
			}
		});  
	}
	
	//CONTACT US
	function contactUs()
	{
		var dataString = 'cName=' + $('#cName').val() + '&cEmail='+ $('#cEmail').val() + '&cSubject='+ $('#cSubject').val() + '&cMessage='+ $('#cMessage').val();
		
		$('.loader').show();
		$('#sendMessage').hide().after('<div class="redBtnInactive">Send message</div>');
		
		$.ajax({
			type: "POST",
			url: basePath + "library/ajax.php?action=contactUs",
			data: dataString,
			success: function(data)
			{
				$('#contactResult').html(data);
				$('.loader').hide();
				$("#sendMessage").show();
				$(".redBtnInactive").remove();
				
				//form ok
				if ($('#cStatus').val() == "ok"){
					
					$(".okMsg").fadeIn(300).delay(6000).fadeOut(300);
					
					$("#cName, #cEmail, #cSubject, #cMessage").removeClass("inputError inputValid");
					$("#cName, #cEmail, #cSubject, #cMessage").val("");
					$('#cName').focus();
				}
				
				//form fail
				else {
					//check name
					if ($('#cName_error').val() == "error")
					{
						$("#cName").addClass("inputError");
						$("#cName").removeClass("inputValid");
					}
					else 
					{ 
						$("#cName").removeClass("inputError");
						$("#cName").addClass("inputValid");
					}
					
					//check subject
					if ($('#cSubject_error').val() == "error")
					{
						$("#cSubject").addClass("inputError");
						$("#cSubject").removeClass("inputValid");
					}
					else 
					{ 
						$("#cSubject").removeClass("inputError"); 
						$("#cSubject").addClass("inputValid");
					}
					
					//check email
					if ($('#cEmail_error').val() == "error")
					{
						$("#cEmail").addClass("inputError");
						$("#cEmail").removeClass("inputValid");
					}
					else 
					{ 
						$("#cEmail").removeClass("inputError"); 
						$("#cEmail").addClass("inputValid");
					}
					
					//check message
					if ($('#cMessage_error').val() == "error")
					{
						$("#cMessage").addClass("inputError");
						$("#cMessage").removeClass("inputValid");
					}
					else 
					{ 
						$("#cMessage").removeClass("inputError"); 
						$("#cMessage").addClass("inputValid");
					}
				}	
				
			}
		});
	}
	
	//voting
	function updateVoteCount(gid){
		$.ajax({
			   type: "GET",
			   url: basePath + "library/ajax.php?action=voteGame",
			   data: "a=getVote&gid="+gid,
			   dataType : "json",
			   success: function(votes){
				   $("#votesNrUp").html(votes.good);
				   $("#votesNrDown").html(votes.bad);
				   if (votes.good=="0" && votes.bad=="0"){
					   $(".votingButtons span").html("Fii primul care voteaza!");
						}
				   }
		});
	}
	
	function disableVoting(){
		$("#voteUp").addClass("voteUpInactive");
		$("#voteDown").addClass("voteDownInactive");
	}
	
	function catchVoteStatus(status,gid){		
		switch(status){
			case "duplicatevote":
				$(".votingButtons span").html("Deja ai votat acest joc!");
			break;
		
			case "":
			default:
			case "errvote":
			case "errparams":
				$(".votingButtons span").html("Votul tau nu a fost inregistrat!<br/>Te rugam sa incerci mai tarziu!");
			break;
		
			case "ok":
				$(".votingButtons span").html("Votul tau a fost inregistrat!");
				disableVoting();
			break;				
		}
		updateVoteCount(gid);
	}	
	
	function setupVote(gid){
	
		$("#voteUp").click(function(){
			   if (!$(this).hasClass("up_h") ){
				$.ajax({
					   type: "GET",
					   url: basePath + "library/ajax.php?action=voteGame",
					   data: "a=postVote&gid="+gid+"&vote=good",
					   dataType : "json",	   
					   success: function(response){
							catchVoteStatus(response.status,gid);
					   }
				});
			}
			return false;
		});	
		
		$("#voteDown").click(function(){
			  if (!$(this).hasClass("down_h") ){
				$.ajax({
					   type: "GET",
					   url: basePath + "library/ajax.php?action=voteGame",
					   data: "a=postVote&gid="+gid+"&vote=bad",
					   dataType : "json",	   
					   success: function(response){
						   catchVoteStatus(response.status,gid);
					   }
				});
			}
			return false;
		});			
				
		
		$.ajax({
			   type: "GET",
			   url: basePath + "library/ajax.php?action=voteGame",
			   data: "a=isVoted&gid="+gid,
			   dataType : "json",	   
			   success: function(msg){
					if(msg.vote == false){
						disableVoting();
						$(".votingButtons span").html("Deja ai votat acest joc!");
						$(".votingButtons").toggle();
					} else {
						$(".votingButtons").toggle();
						}
						
				}
			});
		
	}
	
	
	/*///open window
	function openWindow(url)
	{
		myWindow = window.open (url, "mywindow","location=no, menubar=no, status=no, resizable=no, scrollbars=no, width=500, height=400");
		myWindow.focus();
	}
	*/
	
	
	/*
	Auto center window script- Eric King (http://redrival.com/eak/index.shtml)
	Permission granted to Dynamic Drive to feature script in archive
	For full source, usage terms, and 100's more DHTML scripts, visit http://dynamicdrive.com
	*/
	
	var win = null;
	function openWindow(url, pageName, w, h){
		LeftPosition = (screen.width) ? (screen.width-w)/2 : 0;
		TopPosition = (screen.height) ? (screen.height-h)/2 : 0;
		settings = 'height='+h+',width='+w+',top='+TopPosition+',left='+LeftPosition+',scrollbars=no,resizable=no, menubar=no, '
		win = window.open(url, pageName, settings)
		win.focus();
	}
	
	
		
	//organic tabs	
	(function($) {
	
		$.organicTabs = function(el, options) {
		
			var base = this;
			base.$el = $(el);
			base.$nav = base.$el.find(".nav");
					
			base.init = function() {
			
				base.options = $.extend({},$.organicTabs.defaultOptions, options);
				
				// Accessible hiding fix
				$(".hide").css({
					"position": "relative",
					"top": 0,
					"left": 0,
					"display": "none"
				}); 
				
				base.$nav.delegate("li > a", "click", function() {
				
					// Figure out current list via CSS class
					var curList = base.$el.find("a.current").attr("href").substring(1),
					
					// List moving to
						$newList = $(this),
						
					// Figure out ID of new list
						listID = $newList.attr("href").substring(1),
					
					// Set outer wrapper height to (static) height of current inner list
						$allListWrap = base.$el.find(".list-wrap"),
						curListHeight = $allListWrap.height();
					$allListWrap.height(curListHeight);
											
					if ((listID != curList) && ( base.$el.find(":animated").length == 0)) {
												
						// Fade out current list
						base.$el.find("#"+curList).fadeOut(base.options.speed, function() {
							
							// Fade in new list on callback
							base.$el.find("#"+listID).fadeIn(base.options.speed);
							
							// Adjust outer wrapper to fit new list snuggly
							var newHeight = base.$el.find("#"+listID).height();
							$allListWrap.animate({
								height: newHeight
							});
							
							// Remove highlighting - Add to just-clicked tab
							base.$el.find(".nav li a").removeClass("current");
							$newList.addClass("current");
								
						});
						
					}   
					// Don't behave like a regular link
					// Stop propegation and bubbling
					return false;
				});
				
			};
			base.init();
		};
		
		$.organicTabs.defaultOptions = {
			"speed": 300
		};
		
		$.fn.organicTabs = function(options) {
			return this.each(function() {
				(new $.organicTabs(this, options));
			});
		};
		
	})(jQuery);
	
	// HTML Truncator for jQuery
	// by Henrik Nyh <http://henrik.nyh.se> 2008-02-28.
	// Free to modify and redistribute with credit.
	(function($) {
	
	  var trailing_whitespace = true;
	
	  $.fn.truncate = function(options) {
	
		var opts = $.extend({}, $.fn.truncate.defaults, options);
		
		$(this).each(function() {
	
		  var content_length = $.trim(squeeze($(this).text())).length;
		  if (content_length <= opts.max_length)
			return;  // bail early if not overlong
	
		  var actual_max_length = opts.max_length - opts.more.length - 3;  // 3 for " ()"
		  var truncated_node = recursivelyTruncate(this, actual_max_length);
		  var full_node = $(this).hide();
	
		  truncated_node.insertAfter(full_node);
		  
		  findNodeForMore(truncated_node).append(' (<a href="#show more content">'+opts.more+'</a>)');
		  findNodeForLess(full_node).append(' (<a href="#show less content">'+opts.less+'</a>)');
		  
		  truncated_node.find('a:last').click(function() {
			truncated_node.hide(); full_node.show(); return false;
		  });
		  full_node.find('a:last').click(function() {
			truncated_node.show(); full_node.hide(); return false;
		  });
	
		});
	  }
	
	  // Note that the " (…more)" bit counts towards the max length – so a max
	  // length of 10 would truncate "1234567890" to "12 (…more)".
	  $.fn.truncate.defaults = {
		max_length: 100,
		more: 'more',
		less: 'less'
	  };
	
	  function recursivelyTruncate(node, max_length) {
		return (node.nodeType == 3) ? truncateText(node, max_length) : truncateNode(node, max_length);
	  }
	
	  function truncateNode(node, max_length) {
		var node = $(node);
		var new_node = node.clone().empty();
		var truncatedChild;
		node.contents().each(function() {
		  var remaining_length = max_length - new_node.text().length;
		  if (remaining_length == 0) return;  // breaks the loop
		  truncatedChild = recursivelyTruncate(this, remaining_length);
		  if (truncatedChild) new_node.append(truncatedChild);
		});
		return new_node;
	  }
	
	  function truncateText(node, max_length) {
		var text = squeeze(node.data);
		if (trailing_whitespace)  // remove initial whitespace if last text
		  text = text.replace(/^ /, '');  // node had trailing whitespace.
		trailing_whitespace = !!text.match(/ $/);
		var text = text.slice(0, max_length);
		// Ensure HTML entities are encoded
		// http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb
		text = $('<div/>').text(text).html();
		return text;
	  }
	
	  // Collapses a sequence of whitespace into a single space.
	  function squeeze(string) {
		return string.replace(/\s+/g, ' ');
	  }
	  
	  // Finds the last, innermost block-level element
	  function findNodeForMore(node) {
		var $node = $(node);
		var last_child = $node.children(":last");
		if (!last_child) return node;
		var display = last_child.css('display');
		if (!display || display=='inline') return $node;
		return findNodeForMore(last_child);
	  };
	
	  // Finds the last child if it's a p; otherwise the parent
	  function findNodeForLess(node) {
		var $node = $(node);
		var last_child = $node.children(":last");
		if (last_child && last_child.is('p')) return last_child;
		return node;
	  };
	
	})(jQuery);
	
	//tipsy tooltip
	(function($) {
		
		function fixTitle($ele) {
			if ($ele.attr('title') || typeof($ele.attr('original-title')) != 'string') {
				$ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
			}
		}
		
		function Tipsy(element, options) {
			this.$element = $(element);
			this.options = options;
			this.enabled = true;
			fixTitle(this.$element);
		}
		
		Tipsy.prototype = {
			show: function() {
				var title = this.getTitle();
				if (title && this.enabled) {
					var $tip = this.tip();
					
					$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
					$tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
					$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
					
					var pos = $.extend({}, this.$element.offset(), {
						width: this.$element[0].offsetWidth,
						height: this.$element[0].offsetHeight
					});
					
					var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
					var gravity = (typeof this.options.gravity == 'function')
									? this.options.gravity.call(this.$element[0])
									: this.options.gravity;
					
					var tp;
					switch (gravity.charAt(0)) {
						case 'n':
							tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
							break;
						case 's':
							tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
							break;
						case 'e':
							tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
							break;
						case 'w':
							tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
							break;
					}
					
					if (gravity.length == 2) {
						if (gravity.charAt(1) == 'w') {
							tp.left = pos.left + pos.width / 2 - 15;
						} else {
							tp.left = pos.left + pos.width / 2 - actualWidth + 15;
						}
					}
					
					$tip.css(tp).addClass('tipsy-' + gravity);
					
					if (this.options.fade) {
						$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
					} else {
						$tip.css({visibility: 'visible', opacity: this.options.opacity});
					}
					
				}
			},
			
			hide: function() {
				if (this.options.fade) {
					this.tip().stop().fadeOut(function() { $(this).remove(); });
				} else {
					this.tip().remove();
				}
			},
			
			getTitle: function() {
				var title, $e = this.$element, o = this.options;
				fixTitle($e);
				var title, o = this.options;
				if (typeof o.title == 'string') {
					title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
				} else if (typeof o.title == 'function') {
					title = o.title.call($e[0]);
				}
				title = ('' + title).replace(/(^\s*|\s*$)/, "");
				return title || o.fallback;
			},
			
			tip: function() {
				if (!this.$tip) {
				   this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
				}
				return this.$tip;
			},
			
			validate: function() {
				if (!this.$element[0].parentNode) {
					this.hide();
					this.$element = null;
					this.options = null;
				}
			},
			
			enable: function() { this.enabled = true; },
			disable: function() { this.enabled = false; },
			toggleEnabled: function() { this.enabled = !this.enabled; }
		};
		
		$.fn.tipsy = function(options) {
			
			if (options === true) {
				return this.data('tipsy');
			} else if (typeof options == 'string') {
				return this.data('tipsy')[options]();
			}
			
			options = $.extend({}, $.fn.tipsy.defaults, options);
			
			function get(ele) {
				var tipsy = $.data(ele, 'tipsy');
				if (!tipsy) {
					tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
					$.data(ele, 'tipsy', tipsy);
				}
				return tipsy;
			}
			
			function enter() {
				var tipsy = get(this);
				tipsy.hoverState = 'in';
				if (options.delayIn == 0) {
					tipsy.show();
				} else {
					setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
				}
			};
			
			function leave() {
				var tipsy = get(this);
				tipsy.hoverState = 'out';
				if (options.delayOut == 0) {
					tipsy.hide();
				} else {
					setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
				}
			};
			
			if (!options.live) this.each(function() { get(this); });
			
			if (options.trigger != 'manual') {
				
				var binder   = options.live ? 'live' : 'bind',
					eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
					eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
				this[binder](eventIn, enter)[binder](eventOut, leave);
				
			}        
			return this;
			
		};
		
		$.fn.tipsy.defaults = {
			delayIn: 0,
			delayOut: 0,
			fade: false,
			fallback: '',
			gravity: 'n',
			html: false,
			live: false,
			offset: 0,
			opacity: 1,
			title: 'title',
			trigger: 'hover'
			
		};
		
	   
		
		// Overwrite this method to provide options on a per-element basis.
		// For example, you could store the gravity in a 'tipsy-gravity' attribute:
		// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
		// (remember - do not modify 'options' in place!)
		$.fn.tipsy.elementOptions = function(ele, options) {
			return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
		};
		
		$.fn.tipsy.autoNS = function() {
			return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
		};
		
		$.fn.tipsy.autoWE = function() {
			return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
		};
		
	})(jQuery);

