/*
Script: Tips.js
Class for creating nice tips that follow the mouse cursor when hovering an element.

License:
MIT-style license.

Authors:
Valerio Proietti
Christoph Pojer
*/

var Tips = new Class({

    Implements: [Events, Options],

    options: {/*
		onAttach: $empty(tip, element),*/
        onShow: function(tip) {
            tip.setStyle('visibility', 'visible');
        },
        onHide: function(tip) {
            tip.setStyle('visibility', 'hidden');
        },
        title: 'title',
        text: function(el) {
            return el.get('rel') || el.get('href');
        },
        showDelay: 100,
        hideDelay: 100,
        className: 'tip-wrap',
        offset: { x: 16, y: 16 },
        fixed: false
    },

    initialize: function() {
        var params = Array.link(arguments, { options: Object.type, elements: $defined });
        if (params.options && params.options.offsets) params.options.offset = params.options.offsets;
        this.setOptions(params.options);
        this.container = new Element('div', { 'class': 'tip' });
        this.tip = this.getTip();

        if (params.elements) this.attach(params.elements);
    },

    getTip: function() {
        return new Element('div', {
            'class': this.options.className,
            styles: {
                visibility: 'hidden',
                display: 'none',
                position: 'absolute',
                top: 0,
                left: 0
            }
        }).adopt(
			new Element('div', { 'class': 'tip-top' }),
			this.container,
			new Element('div', { 'class': 'tip-bottom' })
		).inject(document.body);
    },

    attach: function(elements) {
        var read = function(option, element) {
            if (option == null) return '';
            return $type(option) == 'function' ? option(element) : element.get(option);
        };

        $$(elements).each(function(element) {
            var title = read(this.options.title, element), text = read(this.options.text, element);

            //split title to get text
            var dual = title.split('::');
            if (dual.length > 1) {
                title = dual[0].trim();
                text = dual[1].trim();
            } else {
                text = el.title;
            }                


            element.erase('title').store('tip:native', title).retrieve('tip:title', title);
            element.retrieve('tip:text', text);
            this.fireEvent('attach', [this.tip, element]);

            var events = ['enter', 'leave'];
            if (!this.options.fixed) events.push('move');

            events.each(function(value) {
                element.addEvent('mouse' + value, element.retrieve('tip:' + value, this['element' + value.capitalize()].bindWithEvent(this, element)));
            }, this);
        }, this);

        return this;
    },

    detach: function(elements) {
        $$(elements).each(function(element) {
            ['enter', 'leave', 'move'].each(function(value) {
                element.removeEvent('mouse' + value, element.retrieve('tip:' + value) || $empty);
            });

            element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');

            if ($type(this.options.title) == 'string' && this.options.title == 'title') {
                var original = element.retrieve('tip:native');
                if (original) element.set('title', original);
            }
        }, this);

        return this;
    },

    elementEnter: function(event, element) {
        $A(this.container.childNodes).each(Element.dispose);

        ['title', 'text'].each(function(value) {
            var content = element.retrieve('tip:' + value);
            if (!content) return;

            this[value + 'Element'] = new Element('div', { 'class': 'tip-' + value }).inject(this.container);
            this.fill(this[value + 'Element'], content);
        }, this);

        this.timer = $clear(this.timer);
        this.timer = this.show.delay(this.options.showDelay, this, element);
        this.tip.setStyle('display', 'block');
        this.position((!this.options.fixed) ? event : { page: element.getPosition() });
    },

    elementLeave: function(event, element) {
        $clear(this.timer);
        this.timer = this.hide.delay(this.options.hideDelay, this, element);
    },

    elementMove: function(event) {
        this.position(event);
    },

    position: function(event) {
        var size = window.getSize(), scroll = window.getScroll(),
			tip = { x: this.tip.offsetWidth, y: this.tip.offsetHeight },
			props = { x: 'left', y: 'top' },
			obj = {};

        for (var z in props) {
            obj[props[z]] = event.page[z] + this.options.offset[z];
            if ((obj[props[z]] + tip[z] - scroll[z]) > size[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
        }

        this.tip.setStyles(obj);
    },

    fill: function(element, contents) {
        if (typeof contents == 'string') element.set('html', contents);
        else element.adopt(contents);
    },

    show: function(el) {
        this.fireEvent('show', [this.tip, el]);
    },

    hide: function(el) {
        this.fireEvent('hide', [this.tip, el]);
    }

});


window.addEvent('load', function() {
    /* Tips  */
    var x = 0;
    var y = 20;
    var isfixed = false;
    if (/MSIE (5.5|6.)/.test(navigator.userAgent)) {
        x = -140;
        y = -70;
        isfixed = true;
    }
    var ToopTips = new Tips($$('a.ToolTips'), {
        showDelay: 400,
        hideDelay: 400,
        offsets: { 'x': x, 'y': y },
        fixed: isfixed
    });

});
