﻿/*========================================================================================================================
* Description:         Control for attaching a preview box to provide additional info on hover of a thumbnail
* Author:              Oli
* Created:             30/04/08
* Last Modified:       -
*========================================================================================================================*/
if (!window.Bauer) { window['Bauer'] = {} }
if (!window.Bauer.Controls) { window['Bauer']['Controls'] = {} }
window['Bauer']['Controls']['PreviewBox'] = Class.create();

Bauer.Controls.PreviewBox.prototype = {

    /*========================================================================
    ** Options that can be set to control behaviour
    **========================================================================*/
    options: {

        // set this to a css selector to identify the items for which to hook up preview behaviour
        previewItems: '#list li',

        // override this function to return the server url to talk back to
        getCallbackUrl: function(previewItem) { },

        // override this function to return appropriate parameters for the callback
        getCallbackParams: function(previewItem) { }
    },

    /*========================================================================
    ** Private variables
    **========================================================================*/
    box: null,
    visible: false,
    elementId: "BauerPreviewBox",
    previewItem: null,
    previewTimer: null,
    previewDelay: 0.5,
    fullOpacity: 0.9,

    /*========================================================================
    ** Constructor function
    **========================================================================*/
    initialize: function(options) {

        // store options for later reference
        this.options = options;

        // create the preview box element in the DOM
        this.createPreviewBox();

        $$(this.options.previewItems).each(function(item) {

            // hook up mouse events
            item.observe('mouseover', this.handleMouseOver.bindAsEventListener(this));
            item.observe('mouseout', this.handleMouseOut.bindAsEventListener(this));

            // strip out attributes that would cause a browser tooltip to render
            if (item.parentNode.nodeName == 'A') {
                item.parentNode.removeAttribute('title');
            }

            item.removeAttribute('alt');

        } .bind(this));
    },

    /*========================================================================
    * Creates the preview box in the DOM
    /*========================================================================*/
    createPreviewBox: function() {

        this.box = $(this.elementId);

        if (!this.box) {

            // create the preview container
            this.box = document.createElement('div');
            Element.extend(this.box);
            this.box.setAttribute('id', this.elementId);

            this.box.setStyle({
                position: 'absolute',
                zIndex: '1000'
            });

            // default to invisible
            this.box.setOpacity(0);

            // append to the DOM
            document.body.appendChild(this.box);
        }
    },

    /*========================================================================
    * Starts the preview timer
    /*========================================================================*/
    handleMouseOver: function(event, eventItem) {

        // store a reference to the item that the event fired on
        this.previewItem = Event.element(event);

        // kick off the preview timer
        clearTimeout(this.previewTimer);
        this.previewTimer = this.updatePreviewFromServer.bind(this).delay(this.previewDelay);
    },

    /*========================================================================
    * Hides the preview and clears any active timer
    /*========================================================================*/
    handleMouseOut: function(event) {
        this.hidePreview();
    },

    /*========================================================================
    * Updates the preview box by calling back to the server
    /*========================================================================*/
    updatePreviewFromServer: function() {

        // call the assigned callback function to get the parameters to use
        var params = this.options.getCallbackParams(this.previewItem);
        var url = this.options.getCallbackUrl(this.previewItem);

        new Ajax.Request(url, {
            method: 'get',
            parameters: params,
            onSuccess: (function(transport) {
                this.box.innerHTML = transport.responseText;
                this.showPreview();
            }).bind(this)
        });
    },

    /*========================================================================
    * Shows the preview box (with any transitions)
    /*========================================================================*/
    showPreview: function() {

        // set the preview box location
        this.setPreviewPosition();

        // fade in the preview box
        if (this.visible == false) {
            this.visible = true;

            new Fx.Style(this.box, 'opacity', {
                duration: 400,
                transition: Fx.Transitions.quintIn,
                wait: true
            }).custom(0, this.fullOpacity);
        }
    },

    /*=================================================================================
    * Sets the position of the preview box based on the location of the preview item
    /*=================================================================================*/
    setPreviewPosition: function() {

        var position = this.previewItem.cumulativeOffset();
        this.box.style.top = (position.top + 6) + "px";
        this.box.style.left = (position.left + this.previewItem.offsetWidth + 10) + "px";
    },

    /*========================================================================
    * Hides the preview box (with any transitions)
    /*========================================================================*/
    hidePreview: function() {

        clearTimeout(this.previewTimer);

        if (this.visible == true) {

            this.visible = false;

            new Fx.Style(this.box, 'opacity', {
                duration: 400,
                transition: Fx.Transitions.quintIn,
                wait: true
            }).custom(this.fullOpacity, 0);
        }
    }
};

