/*
 * Copyright (c) 2006 Jonathan Weiss <jw@innerewut.de>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */


/* tooltip-0.2.js - Small tooltip library on top of Prototype 
 * by Jonathan Weiss <jw@innerewut.de> distributed under the BSD license. 
 *
 * This tooltip library works in two modes. If it gets a valid DOM element 
 * or DOM id as an argument it uses this element as the tooltip. This 
 * element will be placed (and shown) near the mouse pointer when a trigger-
 * element is moused-over.
 * If it gets only a text as an argument instead of a DOM id or DOM element
 * it will create a div with the classname 'tooltip' that holds the given text.
 * This newly created div will be used as the tooltip. This is usefull if you 
 * want to use tooltip.js to create popups out of title attributes.
 * 
 *
 * Usage: 
 *	 <script src="/javascripts/prototype.js" type="text/javascript"></script>
 *	 <script src="/javascripts/tooltip.js" type="text/javascript"></script>
 *	 <script type="text/javascript">
 *		 // with valid DOM id
 *		 var my_tooltip = new Tooltip('id_of_trigger_element', 'id_of_tooltip_to_show_element')
 *
 *		 // with text
 *		 var my_other_tooltip = new Tooltip('id_of_trigger_element', 'a nice description')
 *
 *		 // create popups for each element with a title attribute
 *		Event.observe(window,"load",function() {
 *			$$("*").findAll(function(node){
 *				return node.getAttribute('title');
 *			}).each(function(node){
 *				new Tooltip(node,node.title);
 *				node.removeAttribute("title");
 *			});
 *		});
 *		
 *	 </script>
 * 
 * Now whenever you trigger a mouseOver on the `trigger` element, the tooltip element will
 * be shown. On o mouseOut the tooltip disappears. 
 * 
 * Example:
 * 
 *	 <script src="/javascripts/prototype.js" type="text/javascript"></script>
 *	 <script src="/javascripts/scriptaculous.js" type="text/javascript"></script>
 *	 <script src="/javascripts/tooltip.js" type="text/javascript"></script>
 *
 *	 <div id='tooltip' style="display:none; margin: 5px; background-color: red;">
 *		 Detail infos on product 1....<br />
 *	 </div>
 *
 *	 <div id='product_1'>
 *		 This is product 1
 *	 </div>
 *
 *	 <script type="text/javascript">
 *		 var my_tooltip = new Tooltip('product_1', 'tooltip')
 *	 </script>
 *
 * You can use my_tooltip.destroy() to remove the event observers and thereby the tooltip.
 */

var Tooltip = Class.create();

Tooltip.prototype = {

	initialize: function(element, tool_tip) {
		
		if (!tool_tip) { return false; }
		
		var options = Object.extend({
		
			default_css: false,
			margin: "0px",
			padding: "8px",
			backgroundColor: "#FFF",
			min_distance_x: 5,
			min_distance_y: 5,
			delta_x: 0,
			delta_y: 0,
			zindex: 1000,
			el_padding: 0,
			show_title: false,
			show_file_name: false,
			show_caption: false
			
		}, arguments[2] || {});

		this.element = $(element);

		this.options = options;
		
		// use the supplied tooltip element or create our own div
		if ($(tool_tip)) {
		
			this.tool_tip = $(tool_tip);
			
		} else {

			if (tool_tip) {
				
				try {
					
					this.element.removeAttribute('title');
					this.element.removeAttribute('alt');
					
					toolTipData = tool_tip.evalJSON();
					
					this.tool_tip = $(document.createElement("div"));
					document.body.appendChild(this.tool_tip);
					
					this.tool_tip.addClassName("tooltip");
					this.tool_tip.setAttribute('rel',toolTipData.image_url);
					
					if (toolTipData.width) {
						html = '<div class="loadingbg" style="width:'+toolTipData.width+'px; height:'+toolTipData.height+'px;"></div>';
					} else {
						html = '<div style="max-width:320px; height:'+toolTipData.height+'px;"></div>';
					}
					
					if (toolTipData.title && this.options.show_title) {
						html += '<strong>'+toolTipData.title+'</strong>';
					}
					
					if (toolTipData.file_name && this.options.show_file_name) {
						html += '<br /><span class="small">'+toolTipData.file_name+'</span>';
					}
					
					if (toolTipData.caption && this.options.show_caption) {
						html += '<br /><span class="small">'+toolTipData.caption+'</span>';
					}
					
					this.tool_tip.update(html);
					
					if (toolTipData.width) {
						this.tool_tip.setStyle({width:toolTipData.width+'px'});
					}
					
					// hide the tool-tip by default
					this.tool_tip.hide();
			
				} catch (e) {
				
				}
				
			}
			
		}

		this.eventMouseOver = this.showTooltip.bindAsEventListener(this);
		this.eventMouseOut	= this.hideTooltip.bindAsEventListener(this);
		this.eventMouseMove	= this.moveTooltip.bindAsEventListener(this);

		this.registerEvents();
		
	},

	destroy: function() {
		Event.stopObserving(this.element, "mouseover", this.eventMouseOver);
		Event.stopObserving(this.element, "mouseout", this.eventMouseOut);
		Event.stopObserving(this.element, "mousemove", this.eventMouseMove);
	},

	registerEvents: function() {
		Event.observe(this.element, "mouseover", this.eventMouseOver);
		Event.observe(this.element, "mouseout", this.eventMouseOut);
		Event.observe(this.element, "mousemove", this.eventMouseMove);
	},

	showTooltip: function(event) {
		Event.stop(event);
		this.moveTooltip(event);
		image_url = this.tool_tip.readAttribute('rel');
		this.tool_tip.down().update('<img src="'+image_url+'" /><br />');
		new Element.show(this.tool_tip);
	},
	
	moveTooltip: function(event){
		Event.stop(event);
		// get Mouse position
		var mouse_x = Event.pointerX(event);
		var mouse_y = Event.pointerY(event);
	
		// decide if wee need to switch sides for the tooltip
		var dimensions = Element.getDimensions( this.tool_tip );
		var element_width = dimensions.width;
		var element_height = dimensions.height;
	
		if ( (element_width + mouse_x + (this.options.el_padding * 2)) >= ( this.getWindowWidth() - this.options.min_distance_x ) ) { // too big for X
			mouse_x = mouse_x - element_width;
			// apply min_distance to make sure that the mouse is not on the tool-tip
			mouse_x = mouse_x - this.options.min_distance_x;
		} else {
			mouse_x = mouse_x + this.options.min_distance_x;
		}
	
		if ( (element_height + mouse_y + (this.options.el_padding * 2)) >= ( this.getWindowHeight() - this.options.min_distance_y) ) { // too big for Y
			mouse_y = mouse_y - element_height;
			// apply min_distance to make sure that the mouse is not on the tool-tip
			mouse_y = mouse_y - this.options.min_distance_y;
		} else {
			mouse_y = mouse_y + this.options.min_distance_y;
		} 
	
		// now set the right styles
		this.setStyles(mouse_x, mouse_y);
	},
	
		
	setStyles: function(x, y){

		// set the right styles to position the tool tip
		Element.setStyle(this.tool_tip, {
		
			position:'absolute',
			top:y + this.options.delta_y + "px",
			left:x + this.options.delta_x + "px",
			zindex:this.options.zindex
		
		});
		
		// apply default theme if wanted
		if (this.options.default_css) {
		
			Element.setStyle (this.tool_tip, {
			
				margin:this.options.margin,
				padding:this.options.padding,
				backgroundColor:this.options.backgroundColor,
				zindex:this.options.zindex
			});	
			
		}
	
	},

	hideTooltip: function(event){
		new Element.hide(this.tool_tip);
	},

	getWindowHeight: function(){
		return document.viewport.getHeight() + window.pageYOffset;
	},
 
	getWindowWidth: function(){
		return document.viewport.getWidth();
	}

}

