/**
 * base JavaScript for MoveFreely.com
 * requires: jquery.js
 */
 
// global page init functions

// enable styles for js-enabled browsers
if(document.getElementById && document.createTextNode) {
	document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className + ' js';
};
 
// prevent background image flicker in IE
try {
	document.execCommand("BackgroundImageCache", false, true);
} catch(err) {};

$(document).ready(function () {
	var log = KC.Util.log,
		cookie = KC.Util.cookie;
		
	// validation error
	var err = $(".error").siblings("label").addClass("error").end()[0];
	if (err) {
		$(function () {
			window.setTimeout(function () { KC.showErr(err); }, 100); // can't focus the field until it fades in!
		});
	}
		
	
	if (!KC.isIE) {
		// animate the nav transitions (non-IE browsers only!)
		$("#header li a:not(.on)").each(function () {
			var $this = $(this);
			
			// class this as a "crossfader" and clone the bgimage from the <a> to the parent <li>
			$this.parent().addClass("crossfader").css({backgroundImage: $this.css("backgroundImage")});
			
			// add hover on/off handlers to the <a> element
			$this.hover(function () {
				$(this).stop().fadeTo(400, 1, function () {
					// hide the parent's bgimage so it doesn't show through the transparent foreground image
					$(this).parent().addClass("crossfader-hide");
				});
			}, function () {
				$(this).stop().fadeTo(800, 0).parent().removeClass("crossfader-hide"); // restore the parent's bgimage so we can crossfade to it
			});
			
			
		});
	}
	
	// fade in specific elements
	if (!KC.isIE && !KC.Util.query.page && !KC.Util.query.thanks && !err) { // don't fade in the page if we need to display validation errors, or when paging through raves
		$(".fade").hide().removeClass("fade").each(function () {
			var $this = $(this), c = this.className, delay, speed;
			delay = (delay = c.match(/delay\-(\d+)/)) ? delay[1] * 1 : 10;
			speed = (speed = c.match(/speed\-(\d+)/)) ? speed[1] * 1 : 1000;
			
			window.setTimeout(function () {
				$this.fadeIn(speed);
			}, delay);
		});
	} else {
		$(".fade").css("visibility", "visible");
	}
	
	// simple hover effects on some buttons
	$("#home-rave a, #tell-friend a").hover(function () {
		$(this).stop().fadeTo(400, 0.5);
	}, function () {
		$(this).stop().fadeTo(800, 1);
	});
	
	if (!KC.isIE6) {
		var $hsg = $("#free-sample-glow");
		$("#free-sample a").hover(function () {
			if (!KC.isIE) {
				$hsg.stop().css({visibility: "visible", opacity: 0}).fadeTo(400, 1);
			} else {
				$hsg.hide().css({visibility: "visible"}).show();
			}
		}, function () {
			if (!KC.isIE) {
				$hsg.stop().fadeTo(800, 0);
			} else {
				$hsg.hide();
			}
		});
	}	
		
	// twinkling stars (except for IE on the raves page -- twinkling interferes with overflow:auto scrolling?!?)
	if (!KC.isIE || !location.href.match(/raves\.aspx/i)) {
		KC.Twinkle($("#twinkle-stars img"));
	}
	
	$("#tell-friend a").click(function () {
		KC.launchTellAFriend(this.href);
		this.blur();
		return false;
	});
	
	// class form fields
	$("input[type=text]").addClass("text");
	$("input[type=password]").addClass("password");
	
	// hide select elements in IE < 7 when the drop downs are visible
	if (KC.isIE6) {
		$(document).bind("show.KCmenu", function () {
			$("select").css("visibility", "hidden");
		});
		
		$(document).bind("hide.KCmenu", function () {
			$("select").css("visibility", "visible");
		});
	}
	
});
 
// namespace
var KC = {
	debug: true,
	isIE: $.browser.msie,
	isIE6: ($.browser.msie && $.browser.version < 7),
	launchTellAFriend: function (url) {
	    window.open(url, 'TellAFriend', 'width=460,height=600,scrollbars=1,resizable=1').focus();
	},
	showErr: function (el) {
		el.focus();
		alert("Please complete all required fields.");
	}
};

KC.Twinkle = function ($els) {
				
	if (!$els.length) {
		return;
	}
	
	var stopped = false;

	function on ($el) {
		if (!stopped) {
			var sh = shift(), op = Math.min(1, $el.css("opacity") * 1 + sh), int = interval();
			$el.stop().fadeTo(int, op, function () {
				window.setTimeout(function () { off($el); }, int * 2);
			});
		}
	}
	
	function off ($el) {
		if (!stopped) {
			var sh = shift(), op = Math.max(0.1, $el.css("opacity") * 1 - shift()), int = interval();
			$el.stop().fadeTo(int, op, function () {
				window.setTimeout(function () { on($el); }, int * 2);
			});
		}
	}
	
	function interval () {
		return Math.floor(Math.random() * 250 + 250);
	}
	
	function shift () {
		return Math.floor(Math.random() * 4 + 2) / 10;
	}
	
	function stop ($el) {
		stopped = true;
		$el.fadeTo(500, 1);
	}
	
	$els.each(function () {
		var $this = $(this);
		if (!KC.isIE) { // IE uses the 8-bit PNG stars, other browsers use the 24-bit versions
			this.src = this.src.replace(/_8/, "");
		}
		window.setTimeout(function () { off($this); }, interval() * 2);
		window.setTimeout(function () { stop($this); }, 15000); // stop the animations after 30 seconds to reduce chance of memory leaks
	});
	
};

KC.Util = {
	log: function () {
		if (KC.debug || location.hash.indexOf("debug") > -1) {
			try {
				console.log(arguments);
			} catch (err) {}
		}
	},
	
	query: (function () {
		var qString, queryStart, query, parts, bits, subbits, returnVals = {};
		qString = window.location.toString();
		queryStart = qString.indexOf('?');
		if (queryStart==-1) {
			return returnVals;
		}
		query = qString.substring(queryStart + 1, qString.length);
		parts = query.split("&");
		for (var i=0; i<parts.length; i++) {
			bits = parts[i].split("=");
			if (bits[1]) {
				subbits = bits[1].split("#");
				returnVals[bits[0].toLowerCase()] = subbits[0]; // query properties are lowercase!
			}
		}
		return returnVals;
	}) (), // self-invoking!
	
	cookie: function (name, value, options) { // adapted from http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/
	    if (typeof value != 'undefined') { // name and value given, set cookie
	        options = options || {};
	        if (value === null) {
	            value = '';
	            options.expires = -1;
	        }
	        var expires = '';
	        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
	            var date;
	            if (typeof options.expires == 'number') {
	                date = new Date();
	                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
	            } else {
	                date = options.expires;
	            }
	            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
	        }
	        var path = options.path ? '; path=' + options.path : '';
	        var domain = options.domain ? '; domain=' + options.domain : '';
	        var secure = options.secure ? '; secure' : '';
	        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
	    } else { // only name given, get cookie
	        var cookieValue = null;
	        if (document.cookie && document.cookie !== '') {
	            var cookies = document.cookie.split(';');
	            for (var i = 0, l = cookies.length; i < l; i++) {
	                var cookie = cookies[i].replace(/^\s+|\s+$/g, "");
	                // Does this cookie string begin with the name we want?
	                if (cookie.substring(0, name.length + 1) == (name + '=')) {
	                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
	                    break;
	                }
	            }
	        }
	        return cookieValue;
	    }
	},
	
	getPageSize: function () {
		var x = Math.max(document.documentElement.scrollWidth || document.body.scrollWidth, document.body.offsetWidth);
		var y = Math.max(document.documentElement.scrollHeight || document.body.scrollHeight, document.body.offsetHeight);
		return {"x": x, "y": y};
	},
	
	getViewportSize: function () {
		var x = self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
		var y = self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
		return {"x": x, "y": y};
	},
	
	getScrollOffset: function () {
		var x = self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
		var y = self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
		return {"x": x, "y": y};
	},
	
	getElemPosition: function (el) {
		var x = 0, y = 0;
		if (el.offsetParent) {
			do {
				x += el.offsetLeft;
				y += el.offsetTop;
			} while (el = el.offsetParent);
		}
		return {"x": x, "y": y};
	},
	
	makeTooltip: function ($el, text) {
		var $tooltip, t;
		
		$el.hover(function (e) {
			window.clearTimeout(t);		
			t = window.setTimeout(function () {							  
				$tooltip = $("<p id='tooltip'>"+ text +"</p>")
					.css("top",(KC.Util.getElemPosition(e.target).y) + "px")
					.css("left",(KC.Util.getElemPosition(e.target).x + e.target.offsetWidth) + "px")
					.css({opacity: 0, display: "block"});
				$tooltip.appendTo("body").fadeTo("fast", 1);
			}, 200);
			$(document).trigger("show.KCmenu");
	    },
		function () {
			window.clearTimeout(t);
			if ($tooltip) {
				t = window.setTimeout(function () {
					$tooltip.remove();
					$tooltip = null;
				}, 200);
				$(document).trigger("hide.KCmenu");
			}
	    });	
	    
	}
};

// jQuery plugins

// from http://gsgd.co.uk/sandbox/jquery/easing/
jQuery.extend( jQuery.easing, 
{
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	}
});

/**
 *
 * Copyright (c) 2007 Tom Deater (http://www.tomdeater.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 */
 
(function($) {
	/**
	 * equalizes the heights of all elements in a jQuery collection
	 * thanks to John Resig for optimizing this!
	 * usage: $("#col1, #col2, #col3").equalizeCols();
	 */
	 
	$.fn.equalizeCols = function(){
		var height = 0,
			reset = $.browser.msie ? "1%" : "auto";
  
		return this
			.css("height", reset)
			.each(function() {
				height = Math.max(height, this.offsetHeight);
			})
			.css("height", height)
			.each(function() {
				var h = this.offsetHeight;
				if (h > height) {
					$(this).css("height", height - (h - height));
				};
			});
			
	};
	
})(jQuery);

/**
 *
 * Copyright (c) 2008 Tom Deater (http://www.tomdeater.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * uses an iframe, sized in ems, to detect font size changes then trigger a "fontresize" event
 * heavily based on code by Hedger Wang: http://www.hedgerwow.com/360/dhtml/js-onfontresize.html
 *
 * "fontresize" event is triggered on the document object
 * subscribe to event using: $(document).bind("fontresize", function (event, data) {});
 * "data" contains the current size of 1 em unit (in pixels)
 * 
 */
 
$.onFontResize = (function ($) {
	var $resizeframe = null;
		
	// initialize
	$(document).ready(function () {
		$resizeframe = $("<iframe />")
			.attr("id", "frame-onFontResize" + Date.parse(new Date))
			.css({width: "100em", height: "10px", position: "absolute", borderWidth: 0, top: "-5000px", left: "-5000px"})
			.appendTo("body");
			
		if ($.browser.msie) {
			// use IE's native iframe resize event
			$resizeframe.bind("resize", function () {
				$.onFontResize.trigger($resizeframe[0].offsetWidth / 100);
			});
		} else {
			// everyone else uses script inside the iframe to detect resize
			var doc = $resizeframe[0].contentWindow || $resizeframe[0].contentDocument || $resizeframe[0].document;
			doc = doc.document || doc; 
			doc.open();
			doc.write('<div id="em" style="width:100em;height:10px;"></div>');
			doc.write('<scri' + 'pt>window.onload = function(){var em = document.getElementById("em");window.onresize = function(){if(parent.$.onFontResize){parent.$.onFontResize.trigger(em.offsetWidth / 100);}}};</scri' + 'pt>');
			doc.close();
		}
	});
	
	return {
		// public method, so it can be called from within the iframe
		trigger: function (em) {
			$(document).trigger("fontresize", [em]);
		}
	}
}) (jQuery);

/**
 *
 * Copyright (c) 2007 Tom Deater (http://www.tomdeater.com)
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 */
 
(function($) {
	/**
	 * attaches a character counter to each textarea element in the jQuery object
	 * usage: $("#myTextArea").charCounter(max, settings);
	 */
	
	$.fn.charCounter = function (max, settings) {
		max = max || 100;
		settings = $.extend({
			container: "<span></span>",
			classname: "charcounter",
			format: "(%1 characters remaining)",
			pulse: true,
			delay: 0
		}, settings);
		var p, timeout;
		
		function count(el, container) {
			el = $(el);
			if (el.val().length > max) {
			    el.val(el.val().substring(0, max));
			    if (settings.pulse && !p) {
			    	pulse(container, true);
			    };
			};
			if (settings.delay > 0) {
				if (timeout) {
					window.clearTimeout(timeout);
				}
				timeout = window.setTimeout(function () {
					container.html(settings.format.replace(/%1/, (max - el.val().length)));
				}, settings.delay);
			} else {
				container.html(settings.format.replace(/%1/, (max - el.val().length)));
			}
		};
		
		function pulse(el, again) {
			if (p) {
				window.clearTimeout(p);
				p = null;
			};
			el.animate({ opacity: 0.1 }, 100, function () {
				$(this).animate({ opacity: 1.0 }, 100);
			});
			if (again) {
				p = window.setTimeout(function () { pulse(el) }, 200);
			};
		};
		
		return this.each(function () {
			var container = (!settings.container.match(/^<.+>$/)) 
				? $(settings.container) 
				: $(settings.container)
					.insertAfter(this)
					.addClass(settings.classname);
			$(this)
				.bind("keydown", function () { count(this, container); })
				.bind("keypress", function () { count(this, container); })
				.bind("keyup", function () { count(this, container); })
				.bind("focus", function () { count(this, container); })
				.bind("mouseover", function () { count(this, container); })
				.bind("mouseout", function () { count(this, container); })
				.bind("paste", function () { 
					var me = this;
					setTimeout(function () { count(me, container); }, 10);
				});
			if (this.addEventListener) {
				this.addEventListener('input', function () { count(this, container); }, false);
			};
			count(this, container);
		});
	};

})(jQuery);