/**
 * Tid Bits
 * A collection of small, useful, standalone scripts that enhance functionality on a page.
 * 
 * Requires at least the versions of Prototype and Scriptaculous found in /media/scriptaculous/
 */

var TidBits = {
	/**
	 * Creates an animated popup.  Typically used for small thumbnails, but can work with other
	 * types of elements.
	 * @param {JSON} params See lines 16-25.  Pretty self-explanatory.
	 */
	animatedPopup: function(params) {
		var options = Object.extend({
			element: null,
			text: null,
			link: null,
			hover_time: 0.1,
			hide_time: 0.2,
			grow_to: 1.5,
			grow_time: 1,
			original_width: 100,
			background_color: '#deebf8',
			text_color: '#000000'
		}, params || {});
		
		// options.element can be ID or object reference
		if (!options.element) {
			return false;
		} else if (Object.isString(options.element)) {
			options.element = document.getElementById(options.element);
		}
		
		options.element._popupTimeout = null;			// the timeout that shows the popup when fired
		options.element._showingPopup = false;			// whether we're showing a popup
		options.element._mouseOutTimeout = null;		// the timeout that hides the popup when fired
		options.element.style.position = 'relative';	// set for positioning reasons
		
		if (!TidBits.animatedPopup._activeElements) {
			TidBits.animatedPopup._activeElements = [];
		}
		TidBits.animatedPopup._activeElements.push(options.element);
		
		Event.observe(options.element, 'mouseover', function(event, options) {
			options.element._popupTimeout = setTimeout(function() {
				for (var i=0; i<TidBits.animatedPopup._activeElements.length; i++) {
					var el = TidBits.animatedPopup._activeElements[i];
					if (el._showingPopup) {
						el._showingPopup = false;
						if (el._mouseOutTimeout) {
							clearTimeout(el._mouseOutTimeout);
							el._mouseOutTimeout = null;
						}
						el._popupElement.parentNode.removeChild(el._popupElement);
					}
				}
				this._showingPopup = true;
				
				// create a copy of the element we're creating a popup for
				var clone = document.createElement(this.nodeName);
				if (this.src) {
					clone.src = this.src;
				} else {
					clone.innerHTML = this.innerHTML;
				}
				clone.style.width = clone.style.height = (options.original_width*options.grow_to)+'px';
				
				// a container that will hold the cloned element
				this._popupElement = document.createElement('div');
				this._popupElement.appendChild(clone);
				
				// fill the container with any popup text
				if (options.text) {
					this._popupElement.appendChild(document.createElement('br'));
					this._popupElement.innerHTML += options.text;
				}
				
				// styles and positioning
				this._popupElement.style.position = 'absolute';
				this._popupElement.style.overflow = 'hidden';
				this._popupElement.style.width = (options.original_width*options.grow_to)+'px';
				this._popupElement.style.backgroundColor = options.background_color;
				this._popupElement.style.color = options.text_color;
				this._popupElement.style.font = 'normal 7pt Verdana,sans-serif';
				this._popupElement.style.textAlign = 'center';
				
				if (options.link) {
					this._popupElement.style.cursor = 'pointer';
					Event.observe(this._popupElement, 'mouseup', function(event, options) {
						window.location.href = options.link;
					}.bindAsEventListener(this._popupElement, options));
				}
				
				document.getElementsByTagName('body')[0].appendChild(this._popupElement);
				
				// the centering calculations need to be done after appending the element to the DOM
				this._popupElement.style.top = (this.offsetTop-((this._popupElement.offsetHeight-this.offsetHeight)/2)+15)+'px';
				this._popupElement.style.left = (this.offsetLeft-((this._popupElement.offsetWidth-this.offsetWidth)/2))+'px';
				
				// Effect.Grow seems to work better when display is set to 'none'
				this._popupElement.style.display = 'none';
				if (Effect) {
					new Effect.Grow(this._popupElement, {duration:options.grow_time,transition:Effect.Transitions.spring});
				}
				
				// mouseover and mouseout listeners for the popup
				Event.observe(this._popupElement, 'mouseover', function(event, original) {
					original._showingPopup = true;
					if (original._mouseOutTimeout) {
						clearTimeout(original._mouseOutTimeout);
					}
				}.bindAsEventListener(this._popupElement, this));
				Event.observe(this._popupElement, 'mouseout', function(event, original) {
					original._showingPopup = false;
					original._mouseOutTimeout = setTimeout(function(original) {
						if (!original._showingPopup) {
							this.parentNode.removeChild(this);
						}
					}.bind(this, original), options.hide_time*1000);
				}.bindAsEventListener(this._popupElement, this));
			}.bind(this, options), options.hover_time*1000);
		}.bindAsEventListener(options.element, options));
		
		// mouseout listener for the original element
		Event.observe(options.element, 'mouseout', function(event) {
			if (!this._showingPopup && this._popupTimeout) {
				clearTimeout(this._popupTimeout);
			}
		}.bindAsEventListener(options.element));
	}
};
