/* popuplib.js
 * Version 1.2
 * December 13, 2007
 *
 * 1. Include script in header.
 * 		<script src="popuplib.js" type="text/javascript"></script>
 * 
 * 2. Create a block with the popup contents and a close button, each with a unique id.
 * 		<div id="jspopup">
 * 			<input type="button" id="jspopup_close" value="close" />
 * 		</div>
 * 
 * 3. Create CSS rules to hide and position the popup.
 * 		#jspopup {
 * 			display: none; position: absolute;
 * 			top: 100px; left: 100px; width: 300px; height: 200px;
 * 		}
 * 
 * 4. In the body's onload event or anywhere after the block, create a popup using the block.
 *    Pass the id of the div and optionally the id of a close control.
 * 		new Popup("jspopup", "jspopup_close").fadeIn().showOncePerUser();
 */

document.popuplibPopups = new Array();

function Popup(popupElement, closeElement) {
	
	// Public Methods
	this.show               = show;
	this.showWithoutDelay   = showWithoutDelay;
	this.showOncePerUser    = showOncePerUser;
	this.showOncePerSession = showOncePerSession;
	this.wait               = wait;
	this.hide               = hide;
	this.entranceSpeed      = entranceSpeed;
	this.fadeIn             = fadeIn;
	this.exitSpeed          = exitSpeed;
	this.fadeOut            = fadeOut;
	this.withPeer           = withPeer;
	this.animationCallback  = animationCallback;

	// Public Member Variables
	var cookie_expires = null;
	var cookie_path    = "/";   // domain-wide by default, null for current path
	var cookie_domain  = null;  // current by default
	var cookie_secure  = false;
	
	// Resovle id strings
	if (document.getElementById) {
		if (typeof popupElement == "string") {
			popupElement = document.getElementById(popupElement);
		}
		if (typeof closeElement == "string") {
			closeElement = document.getElementById(closeElement);
		}
	}
	
	// Add to global array
	var globalIndex = document.popuplibPopups.length;
	var selfRef = "document.popuplibPopups[" + globalIndex + "]";
	document.popuplibPopups.push(this);
	
	// Configure popup
	if (typeof popupElement == "object") {
		popupElement.popup = this;
	}

	// Configure close control
	if (typeof closeElement == "object") {
		closeElement.style.cursor = "pointer";
		closeElement.popup = this;
		closeElement.onclick = function() {
			this.popup.hide();
			return false;
		}
	}
	
	// Configure animations
	var showAnimation         = new DefaultAnimation();
	var showAnimationDelay    = 0;    // milliseconds
	var showAnimationDuration = 1500; // milliseconds
	var showAnimationSteps    = 15;
	var hideAnimation         = showAnimation;
	var hideAnimationDuration = 1000; // milliseconds
	var hideAnimationSteps    = 10;
	var animations            = new Array();
	var peers                 = new Array();

	function show() {
		if (showAnimationDelay > 0) {
			setTimeout(selfRef + ".showWithoutDelay()", showAnimationDelay);
		} else {
			showWithoutDelay();
		}
	}
	
	function showWithoutDelay() {
		if (showAnimation.inNow) {
			showAnimation.inNow(popupElement);
			for (var i = 0; i < peers.length; ++i) showAnimation.inNow(peers[i]);
		}
		if (showAnimation.step) {
			scheduleAnimation(showAnimation, showAnimationDuration, showAnimationSteps);
		}
	}
	
	function hide() {
		if (hideAnimation.outNow) {
			hideAnimation.outNow(popupElement);
			for (var i = 0; i < peers.length; ++i) hideAnimation.outNow(peers[i]);
		}
		if (hideAnimation.step) {
			scheduleAnimation(hideAnimation, hideAnimationDuration, -hideAnimationSteps);
		}
	}
	
	function scheduleAnimation(animation, duration, steps) {
		var prefix = selfRef + ".animationCallback(" + animations.length + ", ";
		var suffix = ", " + steps + ");";
		animations.push(animation);
		if (steps > 0) {
			for (var i = 0; i <= steps; ++i) setTimeout(prefix + i + suffix, duration * i / steps);
		} else { 
			for (var i = -steps; i >= 0; --i) setTimeout(prefix + i + suffix, duration * (steps + i) / steps);
		}
	}

	function animationCallback(animationIndex, step, max) {
		var animation = animations[animationIndex];
		var neg = (max < 0);
		if (neg) max = -max;
		
		if (step == 0 && !neg && animation.beginIn) {
			animation.beginIn(popupElement);
			for (var i = 0; i < peers.length; ++i) animation.beginIn(peers[i]);
		}
		if (step == max && neg && animation.beginOut) {
			animation.beginOut(popupElement);
			for (var i = 0; i < peers.length; ++i) animation.beginOut(peers[i]);
		}
		
		animation.step(popupElement, step, max);
		for (var i = 0; i < peers.length; ++i) animation.step(peers[i], step, max);
		
		if (step == max && !neg && animation.endIn) {
			animation.endIn(popupElement);
			for (var i = 0; i < peers.length; ++i) animation.endIn(peers[i]);
		}
		if (step == 0 && neg && animation.endOut) {
			animation.endOut(popupElement);
			for (var i = 0; i < peers.length; ++i) animation.endOut(peers[i]);
		}
	}
	
	function wait(delay) {
		showAnimationDelay = delay
		return this;
	}
	
	function entranceSpeed(speed) {
		showAnimationDuraction = speed;
		showAnimationSteps     = speed / 100;
		return this;
	}
	
	function withPeer(peerElement) {
		if (typeof peerElement == "string") {
			peerElement = document.getElementById(peerElement);
		}
		if (peerElement) peers.push(peerElement);
		return this;
	}
	
	function fadeIn() {
		showAnimation = new OpacityAnimation();
		return this;
	}
	
	function exitSpeed(speed) {
		hideAnimationDuraction = speed;
		hideAnimationSteps     = speed / 100;
		return this;
	}
	
	function fadeOut() {
		hideAnimation = new OpacityAnimation();
		return this;
	}
	
	function showOncePerUser() {
		var name = "popuplib_pu_" + (popupElement.id ? popupElement.id : globalIndex);
		if (!getCookie(name)) {
			this.show();
		}
		var exp = new Date();
		exp.setTime(exp.getTime() + 45 * 86400000);
		setCookie(name, "1", exp);
	}
	
	function showOncePerSession() {
		var name = "popuplib_pv_" + (popupElement.id ? popupElement.id : globalIndex);
		if (!getCookie(name)) {
			setCookie(name, "1");
			this.show();
		}
	}
		
	function getCookie(name) {
		var arg = name + "=";
		var c = document.cookie;
		var i = 0;
		do {
			var j = i + arg.length;
			if (c.substring(i, j) == arg) {
				var k = c.indexOf(";", j);
				if (k == -1) k = c.length;
				return unescape(c.substring(j, k));
			}
			i = c.indexOf(" ", i) + 1;
		} while (i != 0);
		return null;
	}
	
	function setCookie(name, value) {
		var argv = setCookie.arguments;
		var argc = setCookie.arguments.length;
		var expires = (argc > 2) ? argv[2] : cookie_expires;
		var path    = (argc > 3) ? argv[3] : cookie_path;
		var domain  = (argc > 4) ? argv[4] : cookie_domain;
		var secure  = (argc > 5) ? argv[5] : cookie_secure;
		
		var c = name + "=" + escape(value);
		if (expires != null) c += "; expires=" + expires.toGMTString();
		if (path    != null) c += "; path="    + path;
		if (domain  != null) c += "; domain="  + domain;
		if (secure  == true) c += "; secure";
		document.cookie = c;
	}

	function deleteCookie(name) {
		var exp = new Date();
		exp.setTime(exp.getTime() - 1);
		
		var c = name + "=" + escape(getCookie(name));
		c += "; expires=" + exp.toGMTString();
		document.cookie = c;
	}
	
	/*
	 * Animation Modules
	 */

	function DefaultAnimation() {
		this.inNow = function(element) {
			element.style.display = "block";
		}
		this.outNow = function(element) {
			element.style.display = "none";
		}
	}
	
	function OpacityAnimation() {
		this.beginIn = function(element) {
			this.step(element, 0, 1);
			element.style.display = "block";
		}
		this.endIn = function(element) {
			var s = element.style;
			s.opacity = s.MozOpacity = s.KhtmlOpacity = s.filter = "";
		}
		this.endOut = function(element) {
			element.style.display = "none";
		}
		this.step = function(element, i, max) {
			var s = element.style;
			s.opacity = s.MozOpacity = s.KhtmlOpacity = (i / max);
		    s.filter = "alpha(opacity=" + (i / max * 100) + ")";
		}
	}

}

function searchKeywords(referrer) {
	if (!referrer) referrer = document.referrer;
	referrer = decodeURIComponent(referrer);
	var param = null, query = null;
	
	if (referrer.match(/^https?:\/\/(www\.)?google\.com\//i)) param = "q";         // Google
	else if (referrer.match(/^https?:\/\/search\.yahoo\.com\//i)) param = "q";     // Yahoo
	else if (referrer.match(/^https?:\/\/search\.msn\.com\//i)) param = "q";       // MSN
	else if (referrer.match(/^https?:\/\/search\.aol\.com\//i)) param = "query";   // AOL
	else if (referrer.match(/^https?:\/\/(www\.)?ask\.com\//i)) param = "q";       // Ask
	else if (referrer.match(/^https?:\/\/(www\.)?alltheweb\.com\//i)) param = "q"; // AllTheWeb
	else if (referrer.match(/^https?:\/\/search\.lycos\.com\//i)) param = "query"; // Lycos

	if (param) {
		var rem = new RegExp("(\\?|&)" + param + "=", "i");
		var rer = new RegExp("^.*(\\?|&)" + param + "=([^&]+).*", "i");
		if (referrer.match(rem)) query = referrer.replace(rer, '$2');
	}

	if (query) {
		query = query.replace(/'|"/g, '');
		query = query.split(/[\s,\+\.]+/);
	}
	
    return query;
}

function formattedSearchKeywords(defaultOutput, referrer) {
	var keywords = searchKeywords(referrer);
	if (keywords instanceof Array && keywords.length > 0) {
		var output = '';
		for (var i = 0; i < keywords.length; ++i) {
			var word = keywords[i].toLowerCase();
			if (word.length > 1) {
				word = word.substring(0,1).toUpperCase() +
						word.substring(1, word.length);
			}
			output += word;
			if (keywords.length - i > 1) output += ' ';
		}
		return output;
	}
	else return defaultOutput;
}
