/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/
 * ---------------------------------------------------------------------------
 *
 * The DHTML Calendar
 *
 * Details and latest version at:
 * http://dynarch.com/mishoo/calendar.epl
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 *
 * This file defines helper functions for setting up the calendar. They are
 * intended to help non-programmers get a working calendar on their site
 * quickly. This script should not be seen as part of the calendar. It just
 * shows you what one can do with the calendar, while in the same time
 * providing a quick and simple method for setting it up. If you need
 * exhaustive customization of the calendar creation process feel free to
 * modify this code to suit your needs (this is recommended and much better
 * than modifying calendar.js itself).
 */
 Calendar.setup=function(params){function param_default(pname,def){if(typeof params[pname]=="undefined"){params[pname]=def;}};param_default("inputField",null);param_default("displayArea",null);param_default("button",null);param_default("eventName","click");param_default("ifFormat","%Y/%m/%d");param_default("daFormat","%Y/%m/%d");param_default("singleClick",true);param_default("disableFunc",null);param_default("dateStatusFunc",params["disableFunc"]);param_default("dateText",null);param_default("firstDay",null);param_default("align","Br");param_default("range",[1900,2999]);param_default("weekNumbers",true);param_default("flat",null);param_default("flatCallback",null);param_default("onSelect",null);param_default("onClose",null);param_default("onUpdate",null);param_default("date",null);param_default("showsTime",false);param_default("timeFormat","24");param_default("electric",true);param_default("step",2);param_default("position",null);param_default("cache",false);param_default("showOthers",false);param_default("multiple",null);var tmp=["inputField","displayArea","button"];for(var i in tmp){if(typeof params[tmp[i]]=="string"){params[tmp[i]]=document.getElementById(params[tmp[i]]);}}if(!(params.flat||params.multiple||params.inputField||params.displayArea||params.button)){alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code");return false;}function onSelect(cal){var p=cal.params;var update=(cal.dateClicked||p.electric);if(update&&p.inputField){p.inputField.value=cal.date.print(p.ifFormat);if(typeof p.inputField.onchange=="function")p.inputField.onchange();}if(update&&p.displayArea)p.displayArea.innerHTML=cal.date.print(p.daFormat);if(update&&typeof p.onUpdate=="function")p.onUpdate(cal);if(update&&p.flat){if(typeof p.flatCallback=="function")p.flatCallback(cal);}if(update&&p.singleClick&&cal.dateClicked)cal.callCloseHandler();};if(params.flat!=null){if(typeof params.flat=="string")params.flat=document.getElementById(params.flat);if(!params.flat){alert("Calendar.setup:\n Flat specified but can't find parent.");return false;}var cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect);cal.showsOtherMonths=params.showOthers;cal.showsTime=params.showsTime;cal.time24=(params.timeFormat=="24");cal.params=params;cal.weekNumbers=params.weekNumbers;cal.setRange(params.range[0],params.range[1]);cal.setDateStatusHandler(params.dateStatusFunc);cal.getDateText=params.dateText;if(params.ifFormat){cal.setDateFormat(params.ifFormat);}if(params.inputField&&typeof params.inputField.value=="string"){cal.parseDate(params.inputField.value);}cal.create(params.flat);cal.show();return false;}var triggerEl=params.button||params.displayArea||params.inputField;triggerEl["on"+params.eventName]=function(){var dateEl=params.inputField||params.displayArea;var dateFmt=params.inputField?params.ifFormat:params.daFormat;var mustCreate=false;var cal=window.calendar;if(dateEl)params.date=Date.parseDate(dateEl.value||dateEl.innerHTML,dateFmt);if(!(cal&&params.cache)){window.calendar=cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect,params.onClose||function(cal){cal.hide();});cal.showsTime=params.showsTime;cal.time24=(params.timeFormat=="24");cal.weekNumbers=params.weekNumbers;mustCreate=true;}else{if(params.date)cal.setDate(params.date);cal.hide();}if(params.multiple){cal.multiple={};for(var i=params.multiple.length;--i>=0;){var d=params.multiple[i];var ds=d.print("%Y%m%d");cal.multiple[ds]=d;}}cal.showsOtherMonths=params.showOthers;cal.yearStep=params.step;cal.setRange(params.range[0],params.range[1]);cal.params=params;cal.setDateStatusHandler(params.dateStatusFunc);cal.getDateText=params.dateText;cal.setDateFormat(dateFmt);if(mustCreate)cal.create();cal.refresh();if(!params.position)cal.showAtElement(params.button||params.displayArea||params.inputField,params.align);else cal.showAt(params.position[0],params.position[1]);return false;};return cal;};
/*
 * 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) {
 var options = Object.extend({
 default_css: false,
 margin: "0px",
 padding: "5px",
 backgroundColor: "#d6d6fc",
 min_distance_x: 5,
 min_distance_y: 5,
 delta_x: 0,
 delta_y: 0,
 zindex: 1000
 }, 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 {
 this.tool_tip = $(document.createElement("div")); 
 document.body.appendChild(this.tool_tip);
 this.tool_tip.addClassName("tooltip");
 this.tool_tip.appendChild(document.createTextNode(tool_tip));
 }

 // hide the tool-tip by default
 this.tool_tip.hide();

 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);
 },

 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.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.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);
 },
 
 
 showTooltip: function(event) {
 Event.stop(event);
 this.moveTooltip(event);
 new Element.show(this.tool_tip);
 },
 
 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(){
 var innerHeight;
 if (navigator.appVersion.indexOf('MSIE')>0) {
 innerHeight = document.body.clientHeight;
 } else {
 innerHeight = window.innerHeight;
 }
 return innerHeight; 
 },
 
 getWindowWidth: function(){
 var innerWidth;
 if (navigator.appVersion.indexOf('MSIE')>0) {
 innerWidth = document.body.clientWidth;
 } else {
 innerWidth = window.innerWidth;
 }
 return innerWidth; 
 }

}

// Singleton class TooltipWindow
// This class works with special className. The tooltip content could be in your HTML page as an hidden element or
// can be retreive by an AJAX call.
//
// To work, You just need to set two class name on elements that should show tooltips
// - One to say to TooltipManager that this element must have a tooltip ('tooltip' by default)
// - Another to indicate how to find the tooltip content
// It could be html_XXXX if tootltip content is somewhere hidden in your page, XXX must be DOM ID of this hidden element
// It could be ajax_XXXX if tootltip content must be find by an ajax request, XXX will be the string send as id parameter to your server. 
// Check samples/tooltips/tooltip.html to see how it works
//
TooltipManager = {
 options: {cssClassName: 'tooltip', delayOver: 200, delayOut: 1000, shiftX: 10, shiftY: 10,
 className: 'alphacube', width: 200, height: null, 
 draggable: false, minimizable: false, maximizable: false, showEffect: Element.show, hideEffect: Element.hide},
 ajaxInfo: null,
 elements: null,
 showTimer: null,
 hideTimer: null,

 // Init tooltip manager
 // parameters:
 // - cssClassName (string) : CSS class name where tooltip should be shown. 
 // - ajaxOptions (hash) : Ajax options for ajax tooltip. 
 // For examples {url: "/tooltip/get.php", options: {method: 'get'}} 
 // see Ajax.Request documentation for details
 //- tooltipOptions (hash) : available keys
 // - delayOver: int in ms (default 10) delay before showing tooltip
 // - delayOut: int in ms (default 1000) delay before hidding tooltip
 // - shiftX: int in pixels (default 10) left shift of the tooltip window 
 // - shiftY: int in pixels (default 10) top shift of the tooltip window 
 // and All window options like showEffect: Element.show, hideEffect: Element.hide to remove animation
 // default: {className: 'alphacube', width: 200, height: null, draggable: false, minimizable: false, maximizable: false}
 
 init: function(cssClassName, ajaxInfo, tooltipOptions) {
 TooltipManager.options = Object.extend(TooltipManager.options, tooltipOptions || {});
 
 cssClassName = TooltipManager.options.cssClassName || "tooltip";
 TooltipManager.ajaxInfo = ajaxInfo;
 TooltipManager.elements = $$("." + cssClassName);
 TooltipManager.elements.each(function(element) {
 element = $(element)
 var info = TooltipManager._getInfo(element);
 if (info.ajax) {
 element.ajaxId = info.id;
 element.ajaxInfo = ajaxInfo;
 }
 else {
 element.tooltipElement = $(info.id);
 }
 element.observe("mouseover", TooltipManager._mouseOver);
 element.observe("mouseout", TooltipManager._mouseOut);
 });
 Windows.addObserver(this);
 },
 
 addHTML: function(element, tooltipElement) {
 element = $(element);
 tooltipElement = $(tooltipElement);
 element.tooltipElement = tooltipElement;
 
 element.observe("mouseover", TooltipManager._mouseOver);
 element.observe("mouseout", TooltipManager._mouseOut);
 },
 
 addAjax: function(element, ajaxInfo) {
 element = $(element);
 element.ajaxInfo = ajaxInfo;
 element.observe("mouseover", TooltipManager._mouseOver);
 element.observe("mouseout", TooltipManager._mouseOut); 
 },
 
 addURL: function(element, url, width, height) {
 element = $(element);
 element.url = url;
 element.frameWidth = width;
 element.frameHeight = height;
 element.observe("mouseover", TooltipManager._mouseOver);
 element.observe("mouseout", TooltipManager._mouseOut); 
 },
 
 close: function() {
 if (TooltipManager.tooltipWindow)
 TooltipManager.tooltipWindow.hide();
 },
 
 preloadImages: function(path, images, extension) {
 if (!extension)
 extension = ".gif";
 
 //preload images
 $A(images).each(function(i) {
 var image = new Image(); 
 image.src= path + "/" + i + extension; 
 });
 },
 
 _showTooltip: function(element) {
 if (this.element == element)
 return;
 // Get original element
 while (element && (!element.tooltipElement && !element.ajaxInfo && !element.url)) 
 element = element.parentNode;
 this.element = element;
 
 TooltipManager.showTimer = null;
 if (TooltipManager.hideTimer)
 clearTimeout(TooltipManager.hideTimer);
 
 var position = Position.cumulativeOffset(element);
 var dimension = element.getDimensions();

 if (! this.tooltipWindow)
 this.tooltipWindow = new Window("__tooltip__", TooltipManager.options);
 
 this.tooltipWindow.hide();
 this.tooltipWindow.setLocation(position[1] + dimension.height + TooltipManager.options.shiftY, position[0] + TooltipManager.options.shiftX);

 Event.observe(this.tooltipWindow.element, "mouseover", function(event) {TooltipManager._tooltipOver(event, element)});
 Event.observe(this.tooltipWindow.element, "mouseout", function(event) {TooltipManager._tooltipOut(event, element)});

 // Reset width/height for computation
 this.tooltipWindow.height = TooltipManager.options.height;
 this.tooltipWindow.width = TooltipManager.options.width;

 // Ajax content
 if (element.ajaxInfo) {
 var p = element.ajaxInfo.options.parameters;
 var saveParam = p;
 
 // Set by CSS
 if (element.ajaxId) {
 if (p)
 p += "&id=" + element.ajaxId;
 else
 p = "id=" + element.ajaxId;
 }
 element.ajaxInfo.options.parameters = p || "";
 this.tooltipWindow.setHTMLContent("");
 this.tooltipWindow.setAjaxContent(element.ajaxInfo.url, element.ajaxInfo.options);
 element.ajaxInfo.options.parameters = saveParam; 
 } 
 // URL content
 else if (element.url) {
 this.tooltipWindow.setURL(element.url);
 this.tooltipWindow.setSize(element.frameWidth, element.frameHeight);

 // Set tooltip size
 this.tooltipWindow.height = element.frameHeight;
 this.tooltipWindow.width = element.frameWidth;
 }
 // HTML content
 else
 this.tooltipWindow.setHTMLContent(element.tooltipElement.innerHTML);

 if (!element.ajaxInfo) {
 this.tooltipWindow.show();
 this.tooltipWindow.toFront();
 }
 },
 
 _hideTooltip: function(element) {
 if (this.tooltipWindow) {
 this.tooltipWindow.hide();
 this.element = null;
 }
 },
 
 _mouseOver: function (event) {
 var element = Event.element(event);
 if (TooltipManager.showTimer) 
 clearTimeout(TooltipManager.showTimer);
 
 TooltipManager.showTimer = setTimeout(function() {TooltipManager._showTooltip(element)}, TooltipManager.options.delayOver)
 },
 
 _mouseOut: function(event) {
 var element = Event.element(event);
 if (TooltipManager.showTimer) {
 clearTimeout(TooltipManager.showTimer);
 TooltipManager.showTimer = null;
 return;
 }
 if (TooltipManager.tooltipWindow)
 TooltipManager.hideTimer = setTimeout(function() {TooltipManager._hideTooltip(element)}, TooltipManager.options.delayOut)
 },
 
 _tooltipOver: function(event, element) {
 if (TooltipManager.hideTimer) {
 clearTimeout(TooltipManager.hideTimer);
 TooltipManager.hideTimer = null;
 }
 },
 
 _tooltipOut: function(event, element) {
 if (TooltipManager.hideTimer == null)
 TooltipManager.hideTimer = setTimeout(function() {TooltipManager._hideTooltip(element)}, TooltipManager.options.delayOut)
 },
 
 _getInfo: function(element) {
 // Find html_ for static content
 var id = element.className.split(' ').detect(function(name) {return name.indexOf("html_") == 0});
 var ajax = true;
 if (id)
 ajax = false;
 else 
 // Find ajax_ for ajax content
 id = element.className.split(' ').detect(function(name) {return name.indexOf("ajax_") == 0});
 
 id = id.substr(id.indexOf('_')+1, id.length)
 return id ? {ajax: ajax, id: id} : null;
 },
 
 onBeforeShow: function(eventName, win) {
 var top = parseFloat(win.getLocation().top);
 var dim = win.element.getDimensions();
 
 if (top + dim.height > TooltipManager._getScrollTop() + TooltipManager._getPageHeight()) {
 var position = Position.cumulativeOffset(this.element);

 var top = position[1] - TooltipManager.options.shiftY - dim.height;
 win.setLocation(top, position[0] + TooltipManager.options.shiftX)
 }
 },

 _getPageWidth: function(){
 return window.innerWidth || document.documentElement.clientWidth || 0;
 },
 
 _getPageHeight: function(){
 return window.innerHeight || document.documentElement.clientHeight || 0;
 },

 _getScrollTop: function(){
 return document.documentElement.scrollTop || window.pageYOffset || 0;
 },

 _getScrollLeft: function(){
 return document.documentElement.scrollLeft || window.pageXOffset || 0;
 } 
};

