/*
   SiteComponents version:
   $Id: tooltip.js,v 1.4 2011/04/04 14:08:15 maritos Exp $
   $Name:  $
   
   Disclaimer
   
   While we make every effort to ensure that this code is fit for its intended
   purpose, we make no guarantees as to its functionality. CoreTrek AS will
   accept no responsibility for the loss of data or any other damage or
   financial loss caused by use of this code.
   
   Copyright
   
   This programming code is copyright of CoreTrek AS. Permission to run this
   code is given to approved users of CoreTrek's publishing system CorePublish.
   
   This source code may not be copied, modified or otherwise repurposed for use
   by a third party without the written permission of CoreTrek AS.
   
   Contact webmaster@coretrek.com for information.
  
*/

/*

    ============================================================================
    IMPORTANT! This javascript is dependent on Prototype. If Scriptaculous is
               available the tooltip will use some nice effects.
    ============================================================================

    SiteComponents Tooltip

    Displays a nice looking tooltip instead of browser tooltip. The tooltip will
    be available for all a-tags that has a title attribute. The title attribute
    will be displayed in the tooltip popup.

    Just include this javascript file to enable.

    The script is dependent on Prototype, and optionaly on Scriptaculous.
    Scriptaculous is used to display an Appear effect when showing the tooltip.
    Use CSS to style the tooltip elements.

    The title can contain entity encoded HTML. IE6 behaves a bit off when using
    a absolute positioned div. The div will use all available width. We
    therefore explicitly set tooltip width to 50px and white-space to nowrap.
    Remember to manuallt set linebreaks in your tooltip using entity encoded
    <br>'s, <p>'s or whatever. If your site is using a custom theme, copy the
    IE6 tooltip css to your new theme folder.

    The tooltip is appended to body using using javascript:

    <div id="tooltip">
        <div id="tooltip-top"></div>
        <div id="tooltip-content">
            Content is added here...
        </div>
    </div>

    SiteComponents Configurations

    component:
        tooltip
    parameters:
        string positionby Supported values: 'element', 'mouse'
    example:
        var siteComponentsConfig = { 'tooltip': { 'positionby': 'element' }};
*/

var CtTooltip = Class.create({
    
    /**
     * Initialize function
     *
     * @param string positionBy Valid values are "mouse" (default) and "element"
     */
    initialize: function(positionBy) {
        switch(positionBy) {
            case 'mouse':
                positionBy = 'mouse';
                break;
            default:
            case 'element':
                positionBy = 'element';
                break;
        }
        this.positionBy = positionBy;

        objBody = document.getElementsByTagName('body').item(0);

        // Add the tooltip html structure to end of page
        var tooltipObj = document.createElement('div');
        tooltipObj.setAttribute('id', 'tooltip');
        tooltipObj.style.display = 'none';
        tooltipObj.style.position = 'absolute';
        tooltipObj.style.zIndex = '100';
        objBody.appendChild(tooltipObj);

        var tooltipTopObj = document.createElement('div');
        tooltipTopObj.setAttribute('id', 'tooltip-top');
        tooltipObj.appendChild(tooltipTopObj);

        var tooltipContentObj = document.createElement('div');
        tooltipContentObj.setAttribute('id', 'tooltip-content');
        tooltipObj.appendChild(tooltipContentObj);
        
        var tooltipBottomObj = document.createElement('div');
        tooltipBottomObj.setAttribute('id', 'tooltip-bottom');
        tooltipObj.appendChild(tooltipBottomObj);

        this.tooltip = $('tooltip');
        this.content = $('tooltip-content');
        this.topDiv = $('tooltip-top');
        this.bottomDiv = $('tooltip-bottom');

        $$("a").each(function(element) {
            this.addTooltipToElement(element);
        }.bind(this));
        
        if(Prototype.Browser.IE && navigator.appVersion.match(/MSIE 6\.0/)) {
	        this.tooltip.setStyle({
	            position: 'absolute',
	            width: '50px',
	            whiteSpace: 'nowrap'
	        });
        }
    },

    addTooltipToElement: function(element) {
        try {
            title = element.getAttribute('title');
            if(title != null && title.length > 0) {
	            element.observe('mouseover', function(event) {
	                //event.stop();
	                 if(element.hasClassName('lightbox') == true) {
                         // If class name lightbox exists, remove title from element since it should not be viewed.
                         // This title is for lightbox links used for image text	                     
                         // The title is kept in a variable to set it back when clicking on the link, so it is available 
                         // in lightbox.
	                     this.tooltipText = element.getAttribute('title');
	                     element.setAttribute('title','');
	                     // Create a new attribute on the element with title text. This is to prevent problems when we get
	                     // race condition in javascript on the click event the element both in tooltip and lightbox
	                     element.setAttribute('imagetext', this.tooltipText);
	                 }
	                 else {
	                     // Only display tooltip for links that should not be opened in lightbox
	                     tooltip.show(element, event);
	                 }
	                
	            });

	            element.observe('mouseout', function(event) {
	                if(element.hasClassName('lightbox') == true) {
	                    // If lightbox link, set title back on element t be able to use it in lightbox
	                     element.setAttribute('title',this.tooltipText);
	                 }
	                tooltip.hide();
	            });
	            
	            // The js-function for showing tooltip (mouseover-event) sets the title attribute to an empty string, and the function for hiding tooltip set the title text
	            // back on the attribute.
	            // Because of this, we must set title back on clicked element to be able to display it in lightbox it the element has the classname lightbox. 
	            // The reason is that lightbox make use to the title attribute when an single image is viewed in lightbox, and since lightbox is viewed after clicking on the link
	            // the tooltip can be removed.
	            element.observe('click', function(event) {
	                if(element.hasClassName('lightbox') == true) {
	                    // If lightbox link, set title back on element t be able to use it in lightbox
	                     element.setAttribute('title',this.tooltipText);
	                 }
	            });
	            
                if(this.positionBy == 'mouse') {
		            element.observe('mousemove', function(event) {
		                tooltip.moveTo(event.pointerX(), event.pointerY());
		            });
	            }
            }
        } catch(Exception) { }
    },

    show: function(element, event) {
        // If the tooltip source attribute is missing an exception is
        // thrown, catch and release...
        try {
	        if(element.getAttribute('title').length > 0) {
	            // If the tooltip is already visible, hide it
                if(this.visible) {
                    this.hide();
                }
                // Store the title attribute (the tooltip text), then reset the
                // element title to nothing. This prevents the browser tooltip
                // from appearing. The title text is set back to the element
                // when were hiding our tooltip
                this.element = element;
	            this.tooltipText = element.getAttribute('title');
	            element.setAttribute('title', '');
	            
	            // Move to mouse or element position, the moveTo contains a small offset
	            switch(this.positionBy) {
	               case 'element':
	                   this.moveTo(element.cumulativeOffset()[0],element.cumulativeOffset()[1]);
	                   break;
	               case 'mouse':
	               default:
	                   this.moveTo(event.pointerX(), event.pointerY());
	                   break;
	            }

		        // Set tooltip content to the element title
		        this.content.update(this.tooltipText);

		        // Try using appear effect if scriptaculous is available,
		        // if not we fallback to just showing the tooltip without any
		        // effects
		        try {
		            this.effect = Effect.Appear('tooltip', {
                        duration: .25,
		                afterFinish: function() {
                            tooltip.effect = null;
                        }
                    });
		        } catch (Exeption) {
		            this.tooltip.show();
		        }
		        this.visible = true;
	        }
        } catch(Exception) { }
    },

    hide: function() {
        if(this.visible) {
            // if there is an ongoing effect, cancel it
            if(this.effect != null) {
                this.effect.cancel();
                this.effect = null;
            }

	        this.tooltip.hide();
	        this.element.setAttribute('title', this.tooltipText);
	        this.tooltipText = null;
	        this.visible = false;
        }
    },

    moveTo: function(x, y) {
        // Move to a given position. The position is the current mouse
        // position, so were adding a small offset so that the mouse cursor
        // is not in the way. Also we check if the tooltip will overflow the
        // visible viewport. If it does, we reposition it so that it will fit
        // add initial offset from pointer
        x -= 10;
        y += 20;
        
        var width = this.tooltip.getWidth();
        var height = this.tooltip.getHeight();

        scrollOffsets = document.viewport.getScrollOffsets();

        var viewportWindow = {
            top: scrollOffsets['top'],
            bottom: scrollOffsets['top'] + document.viewport.getHeight(),
            left: scrollOffsets['left'],
            right: scrollOffsets['left'] + document.viewport.getWidth()
        };

        flipX = false;
        if(x + width > viewportWindow['right']) {
            x = viewportWindow['right'] - width;
            flipX = true;
        }
        
        // If the tooltip extends beyond the bottom of the visible viewport,
        // we reposition it above the pointer. We also hide the top
        flipY = false;
        if(y + height > viewportWindow['bottom']) {
            y = y - height - 30;
            flipY = true;
        }
        
        if(flipY) {
            this.tooltip.addClassName('flipped-y');
        } else {
            this.tooltip.removeClassName('flipped-y');
        }
        
        this.tooltip.setStyle({
            left: x + 'px',
            top: y + 'px'
        });
    }
    
});

document.observe('dom:loaded', function() {
    window.tooltip = new CtTooltip(getSiteComponentsConfig('tooltip', 'positionby'));
});

