/*
 * jQuery extend
 * Collection of jQuery plugins and functions
 * @author Zach Waugh <zwaugh@gmail.com>
 *
 */ 

/*
 * jQuery Easing embedded for convenience - 
 *
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 */

jQuery.extend(jQuery.easing,
{
	def: 'easeOutQuad',
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	}
});

// Adds functionality for clearing text input fields
jQuery.fn.clear = function()
{
	$('input[type=text],textarea', this).val('');
};

// Allow for a postJSON shorthand
jQuery.postJSON = function(url, data, callback) {
	$.post(url, data, callback, "json");
};

// Fade out and then remove element from DOM
jQuery.fn.fadeOutAndRemove = function(){
	$(this).fadeOut(300, function(){
		$(this).remove();
	});
};


/*
 * Plugin to swap input field text
 *
 */
(function($){
	$.fn.applyDefault = function()
	{
		// Remove default text on focus
		$(this).focus(function(){
		  if($(this).val() == $(this).attr('defaultValue'))
		  {
		  	$(this).val('');
		  }
		});
		
		// Replace text on blur if field is empty
		$(this).blur(function(){
			if($(this).val() == '')
			{
				$(this).val($(this).attr('defaultValue'));
			}
		});
	}
})(jQuery);


/*
 * Star rating plugin
 * v0.1 - allow whole star ratings to be viewed and set
 */
(function($){
	$.fn.rating = function()
	{
		$(this).each(function(){
			
			// if has class disabled
			// display only, don't bind rating events
			if(!$(this).hasClass('disabled'))
			{
				// cache current rating
				$(this).data('rating', $(this).find('a.selected').size());
			
				$(this).mouseleave(function(){
					// reset stars if no rating was made
					$(this).find('a').slice(0, $(this).data('rating')).addClass('selected');
					$(this).find('a').slice($(this).data('rating'), $(this).find('a').size()).removeClass('selected');
				});

				$(this).find('a.star').mouseover(function(){
					var $ratings = $(this).parents('.ratings');
					var index = $ratings.find('a').index($(this)) + 1;
					$ratings.find('a').slice(0, index).addClass('selected');
					$ratings.find('a').slice(index, $ratings.find('a').size()).removeClass('selected');
				});

				$(this).find('a.star').click(function(event){
					var url = $(this).attr('href');
					var $ratings = $(this).parents('.ratings');

					$.confirm('Are you sure you want to rate this item?', event, function(){
						$.getJSON(url, function(json){
							if(json.status == 'ok')
							{
								$ratings.data('rating', json.rating);
								$ratings.slice(0, json.rating).addClass('selected');
								$.alert.success();
							}
							else
							{
								$.alert(json.message, {duration: 5000});
							}

						});
					});
					return false;
				});
			}
			else
			{
				$(this).find('a.star').click(function(event){ return false; });
			}
		});
	};
})(jQuery);


/* 
 * Center plugin - center element on screen
 * v0.2 - 12/11/2008
 * - added ability to center in another element besides window
 */
(function($){
	$.fn.center = function(el)
	{
		// Get element dimensions
		var height = $(this).innerHeight();
		var width = $(this).innerWidth();
		
		// Figure out offset of container
		if(el)
		{
			var left = ($(el).innerWidth() - width) / 2;
			var top = ($(el).innerHeight() - height) / 2;
		}
		else
		{
			var scroll = $(window).scrollTop();
			var left = ($(window).width() - width) / 2;
			var top = (($(window).height() - height) / 2) + scroll;
		}

		$(this).css({left: left, top: top});
		
		return this;
	};
})(jQuery);


/* 
 * Alert plugin - display message/loading overlay
 * Depends on centering plugin
 * Acts like a singleton, there is only ever one alert on a page
 * v0.5 - 12/11/2008
 * - fixed bug when display loading if alert is already displayed
 * - changed name to Alert
 */
(function($){
	var alerttimer = null;
			
	$.alert = function(message, options){
		options = $.extend({
			loading: false,
			success: false,
			duration: 5000,
			image_path: WWW_ROOT + 'images/loading.gif',
			container: null
		}, options);
		
		// Already displaying a alert message, update text and reset timer
		if ($('#alertMessage').length > 0)
		{
			// Stop any current animations
			$('#alertMessage').stop().css({opacity: 1});
			
			if (alerttimer != null)
			{
				clearTimeout(alerttimer);
				alertTimer = null;
			}
			
			if (options.loading)
			{
				$('#alertMessage').addClass('loading');
			}
			else
			{
				$('#alertMessage').removeClass('loading');
			}
			
			if (options.success)
			{
				$('#alertMessage').addClass('success');
			}
			else
			{
				$('#alertMessage').removeClass('success');
			}
			
			$('#alertMessage p').html(message).center('#alertMessage').parent().center(options.container);
			setTimer(options.duration);
		}
		else
		{	
			setMessage(message);
			$('#alertMessage').center(options.container).css({visibility: 'visible'});
			setTimer(options.duration);
		}
		
		function setMessage(message)
		{
			if (options.loading)
			{
				$('body').append('<div id="alertMessage" class="loading" style="visibility:hidden"><p>' + message + '</p></div>');
			}
			else if (options.success)
			{
				$('body').append('<div id="alertMessage" class="success" style="visibility:hidden"><p>' + message + '</p></div>');
			}
			else
			{
				$('body').append('<div id="alertMessage" style="visibility:hidden"><p>' + message + '</p></div>');
			}
			
			$('#alertMessage p').center('#alertMessage');
			
			// Bind a one-time event to remove alert if user clicks
			$('body').one('click', function(){
				$.alert.hide();
			});
		};
	};
		
	$.extend($.alert, {
		hide: function()
		{
			alerttimer = null;
		  $('#alertMessage').fadeOutAndRemove();
		},
		loading: function(options)
		{
			$.alert(null, $.extend({loading: true, duration: 15000}, options));
		},
		success: function(options)
		{
			$.alert(null, $.extend({success: true, duration: 500}, options));
		},
		error: function(message)
		{ 
			$.alert(message, {duration: 5000});
		}
	});
		
	// Private functions
	function setTimer(duration)
	{
		if (duration != false)
		{
			clearTimeout(alerttimer);
			alerttimer = setTimeout($.alert.hide, duration);	
		}
	};
})(jQuery);

/*
 * Modal plugin - create and show modal window
 * depends on center plugin
 */
(function($){
	$.fn.modal = function(){
		// move to end of body
		var modal = $(this);
		modal.data('parent', modal.parent());
		modal.addClass('modal').appendTo('body');
		
		// add class button
		$('<br class="clear" /><a href="#" id="modal_close">close</a>').appendTo(modal);

		$('#modal_close').click(close_modal);
		modal.center().fadeIn(500);
	};
	
	// Private helper functions
	function close_modal(event)
	{
		// Fade out and move back to original place in DOM
		var modal = $(this).parents('.modal');
		var parent = modal.data('parent');
		modal.fadeOut(250, function(){
			$(this).removeClass('modal').appendTo(parent);
		})
		
		$(this).remove();
				
		return false;
	}
	
})(jQuery);


/*
 * Confirm plugin - custom javascript confirmation dialog
 * depends on center() plugin
 */
(function($){
	$.confirm = function(message, event, callback)
	{
		var html = '\
			<div id="confirm_dialog" style="display:none">\
				<p>' + message + '</p>\
				<a href="#" id="confirm_yes">YES</a> <a href="#" id="confirm_no">NO</a>\
			</div>';
			
		$('body').append(html);
		
		// Bind Yes/No buttons in confirmation dialog to just fadeOut the dialog box
		$('#confirm_no,#confirm_yes').click(function(event){
			$(this).parent().fadeOut(250, function(){
				$(this).remove();
			});
			return false;
		});
		
		$('#confirm_yes').click(callback);
		
		if (typeof(event.pageY) == 'undefined' || typeof(event.pageY) == 'undefined')
		{
			$('#confirm_dialog').center().fadeIn(250);
		}
		else
		{
			$('#confirm_dialog').css({top: event.pageY - 130, left: event.pageX - 150}).fadeIn(250);
		}
	};
})(jQuery);


/* 
 * Dropdown plugin - create custom dropdowns that behave like native dropdowns
 * v0.1 - 1/15/2009
 * - TODO: pass in options and callback
 */
(function($){
	var onchange = true;
	var speed = 300;
	
	$.fn.dropdown = function(){
		bindEvents(this);
	};	
	
	// Private functions
	function bindEvents(dropdown)
	{	
		// Hide dropdown when mouse leaves
		$(dropdown).mouseleave(function(){
			$(this).find('dd').slideUp(speed);
			$(this).removeClass('visible');
		});
		
		// Setup dropdown
		$(dropdown).find('dt a').click(didClickDropdown);
		
		if (onchange)
		{
			$(dropdown).find('.options a').click(didChooseDropdownOption);
		}
		
	}
	
	// Dropdown event
	function didClickDropdown(event)
	{
		event.preventDefault();
		
		var $dropdown = $(this).parents('.dropdown');

		if($dropdown.hasClass('visible'))
		{
			$dropdown.find('dd').stop().slideUp(speed, function () {
				$dropdown.parent().css('zIndex', 900);
			});
		}
		else
		{
			$('.dropdown.visible').removeClass('visible').end().find('dd').hide();
			$dropdown.parent().css('zIndex', 10000);
			$dropdown.find('dd').stop().slideDown(speed);
		}

		$dropdown.toggleClass('visible');

		return false;
	}

	
	function didChooseDropdownOption(event)
	{
		var $dropdown = $(this).parents('.dropdown');
		
		// Indicate selected option in list
		$dropdown.find('.options a.selected').removeClass('selected');
		$(this).addClass('selected');
		
		// Swap text with current selection
		$dropdown.find('dt a').text($(this).text());
		
		// Hide menu and toggle visibility
		$dropdown.find('dd').slideUp(300);
		$dropdown.toggleClass('visible');

		return false;
	}
})(jQuery);

/**
 * Glue Data Binding plugin
 * by Zach Waugh
 * v0.1 - 12/3/2008
 */

(function($){
	// Internal data structure
	var data = {};
	//var binded = [];
	
	$.fn.glue = function(){
		return this.each(function(){
			var key = $(this).attr('class').split(' ')[0];
			$.glue.update(key);
		});
	};
	
	$.glue = {
		'update' : function(key){
			$('.' + key).html(data[key]);
		},
		'setData' : function(key, value){
			data[key] = value;
			$.glue.update(key);
		},
		'debug' : function(){
			console.log(data);
		}
	}
	
	// Auto bind
	$(document).ready(function(){
		$('.bind').glue();
	});
	
})(jQuery);