/*
 * jQuery New Tooltip2 plugin 0.1
 * 
 * history
 * : 2009-01-17 Fixed basic architecture to support method chain
 * : 
 * : -old version -
 * : 2009-01-12 Set target ID to existing object if exists
 * : 2008-10-22 Initial release
 *
 * http://jamadam.com/blog/
 *
 * Copyright (c) 2008 Sugama Keita
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
;(function($) {
	
	// the newtooltip element
	var div_array   = [];
	// IE 5.5 or 6
	var IE          =
        $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent);
	var track       = false;
	var status      = null;
    var ajax_cache  = [];
    
	$.newtooltip = {
		defaults: {
            in_json     : false,
            auto        : true,
            handler_on  : 'mouseover',
            handler_off : 'mouseout',
            track		: true,
			fade		: 200,
			top			: 15,
			left		: 15,
			id			: "TOOLTIP",
            fixPNG      : true,
            auto_css    : true,
            loading_image: '/lib/js/img/loadingAnimation2.gif',
            css         : {
                'position'        : 'absolute',
                'z-index'         : '3000',
                'padding'         : '10px',
                'font-size'       : '12px',
                'font-family'     : 'monospace, Courier New',
                'border'          : '1px solid #678',
                'background'      : '#abc',
                'opacity'         : '0.95',
                'color'           : '#222'
            }
		}
	};
    
	$.fn.extend({
        
		tooltip_setup: function(args) {
            
            args     = args ? args : {};
			args.css = $.extend({}, $.newtooltip.defaults.css, args.css);
			args     = $.extend({}, $.newtooltip.defaults, args);
			
            if (args.auto) {
                
                return $(this).filter('[title]').each(function() {
                    
                    if (typeof(this.title) != 'string') {
                        
                        return;
                    }
                    
					var local_args =
						(args.in_json)
							? $.extend({}, args, eval('tmp=' + this.title))
							: args;

                    var original_title  = this.title;
                    var original_alt    = this.alt;
                    
                    $(this).bind(local_args.handler_on, function () {
                        
                        this.title  = null;
                        this.alt    = null;
                        
                        if (local_args.in_json) {
                            
                            $(this).tooltip_open(
                                $.extend({}, local_args, {in_json: false})
                            );
                        }
                        
                        else {
                            
                            $(this).tooltip_open({text: original_title});
                        }
                    });
                    
                    $(this).bind(local_args.handler_off, function () {
                        
                        this.title  = original_title;
                        this.alt    = original_alt;
                        
                        $(this).tooltip_close();
                    });
                });
            }
            
			return this;
		},
		
		tooltip_open: function(args) {
			
            args     = args ? args : {};
			args.css = $.extend({}, $.newtooltip.defaults.css, args.css);
			args     = $.extend({}, $.newtooltip.defaults, args);
            
            function get_handler() {
                
                return get_handler.caller.caller.arguments;
            }
            
            var handler = get_handler();
            
			return this.each(function() {
				
                text = args.in_json ? eval('tmp=' + args.text) : args.text;
                
                args = $.extend({}, args, {text: text});
                
                $("#"+args.id).each(function() {
                    
                    div_array[args.id] = $(this);
                });
                
                if (! div_array[args.id]) {
                    
                    div_array[args.id] =
                        $('<div id="' + args.id + '"></div>')
                        .appendTo(document.body)
                        .hide();
                    
                    if (args.auto_css) {
                        
                        div_array[args.id].css(args.css);
                    }
                }
                
                // apply bgiframe if available
                if ($.fn.bgiframe) {
                    
                    div_array[args.id].bgiframe();
                }
                
    			$.data(this, 'newtooltip', args);
                
                open(this);
                
                $(this).bind('mousemove', update);
                
                update.apply(this, handler);
            });
		},
		
		tooltip_close: function () {
			
			return this.each(function() {
                
    			if ($.data(this, 'newtooltip')) {
                    
        			close(this);
                }
            });
		},
		
		fixPNG: IE
			? function() {
				
				return this.each(function () {
                    
					var image = $(this).css('backgroundImage');
					if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
						
						image = RegExp.$1;
						$(this).css({
							'backgroundImage': 'none',
							'filter':
								"progid:" +
								"DXImageTransform.Microsoft.AlphaImageLoader" +
								"(enabled=true, sizingMethod=crop, src='" +
								image +
								"')"
						}).each(function () {
							
							var position = $(this).css('position');
							
							if (position != 'absolute'
                                && position != 'relative') {
								
								$(this).css('position', 'relative');
							}
						});
					}
				});
			}
			: function() {
                
                return this;
            },
		
		unfixPNG: IE
			? function() {
                
				return this.each(function () {
                    
					$(this).css({'filter': '', backgroundImage: ''});
				});
			}
			: function() {
                
                return this;
            }
	});
	
	function args(element) {
		
		return $.data(element, "newtooltip");
	}
	
	function divobj(element) {
		
		return div_array[$.data(element, "newtooltip").id];
	}
	
	// save elements title before the newtooltip is displayed
	function open(obj) {
        
        status = true;
        
        if (divobj(obj).is(":animated")) {
            
            divobj(obj).stop().css('opacity', '');
        }
		
        var fix_open = function() {
            
            if (status == true) {
                
                if ((!IE || !$.fn.bgiframe) && args(obj).fade) {
                    
                    divobj(obj).fadeIn(args(obj).fade);
                }
                
                else {
                    
                    divobj(obj).show();
                }
            }
        }
		
        // Ajax
		if (args(obj).url) {
            
            if (args(obj).url in ajax_cache && ! ajax_cache[args(obj).url]) {
                
                return; // Other proccess exists
            }
            
            if (ajax_cache[args(obj).url]) {
                
                divobj(obj).html(ajax_cache[args(obj).url]);
                fix_open();
            }
            
            else {
                
                ajax_cache[args(obj).url] = 
                '<div style="width:100%; text-align:center"><img src="%1" style="margin:20px; width:auto"></div>'
                    .replace('%1', $.newtooltip.defaults.loading_image);
                
                divobj(obj).html(ajax_cache[args(obj).url]);
                fix_open();
                
                // Get outer html file
                divobj(obj).load(args(obj).url, function () {
                    
                    ajax_cache[args(obj).url] = divobj(obj).html();
                });
            }
		}
		
		else if (args(obj).text) {
			
			divobj(obj).html(args(obj).text);
            fix_open();
		}
        
        // fix PNG background for IE
        if (args(obj).fixPNG) {
            
            divobj(obj).fixPNG();
        }
        
        // if selected, update the div_array position when the mouse moves
        track = !!args(obj).track;
	}
	
	/**
	 * callback for mousemove
	 * updates the div_array position
	 * removes itself when no current element
	 */
	function update(event)	{
        
		if (event && event.target.tagName == "OPTION") {
            
            return;
		}
		
		// stop updating when tracking is disabled and the newtooltip is visible
		if ( !track && divobj(this).is(":visible")) {
			
			$(this).unbind('mousemove', update);
		}
        
		// remove position div_array classes
		divobj(this)
            .removeClass("viewport-right").removeClass("viewport-bottom");
		
		var left    = divobj(this)[0].offsetLeft;
		var top     = divobj(this)[0].offsetTop;
        
		if (event) {
            
            // position the div_array 15 pixel to bottom right,
            // starting from mouse position
            left = event.pageX + args(this).left;
            top = event.pageY + args(this).top;
            
            var right = 'auto';
            
            if (args(this).positionLeft) {
                
                right = $(window).width() - left;
                left = 'auto';
            }
            
            divobj(this).css({
                
                left:  left,
                right: right,
                top:   top
            });
		}
		
		var v = viewport();
		var h = divobj(this)[0];
		
		// check horizontal position
		if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			
			left -= h.offsetWidth + 20 + args(this).left;
            
			divobj(this).css({left: left + 'px'}).addClass("viewport-right");
		}
		
		// check vertical position
		if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
			
			top -= h.offsetHeight + 20 + args(this).top;
            
			divobj(this).css({top: top + 'px'}).addClass("viewport-bottom");
		}
	}
	
	function viewport() {
		
		return {
			x: $(window).scrollLeft(),
			y: $(window).scrollTop(),
			cx: $(window).width(),
			cy: $(window).height()
		};
	}
	
	// hide div_array and restore added classes and the title
	function close(obj) {
		
        status = false;
		
		var close_fix = function () {
            
            if (status == false) {
                
                divobj(obj)
                    .removeClass(args(obj).extraClass)
                    .hide()
                    .css("opacity", "")
                    .empty();
                
                if (args(obj).fixPNG) {
                    
                    divobj(obj).unfixPNG();
                }
            }
		}
		
		if ((!IE || !$.fn.bgiframe) && args(obj).fade) {
			
			divobj(obj).stop().fadeOut(args(obj).fade, close_fix);
		}
		
		else {
			
			close_fix();
		}
	}
})(jQuery);
