/*
  popupmenu.js - simple JavaScript popup menu library.

  Copyright (C) 2007 Jiro Nishiguchi <jiro@cpan.org> All rights reserved.
  This is free software with ABSOLUTELY NO WARRANTY.

  You can redistribute it and/or modify it under the modified BSD license.

  Usage:
    var popup = new PopupMenu();
    popup.add(menuText, function(target){ ... });
    popup.addSeparator();
    popup.bind('targetElement');
    popup.bind(); // target is document;
*/
var PopupMenu = function() {
    this.init();
}
PopupMenu.SEPARATOR = 'PopupMenu.SEPARATOR';
PopupMenu.current = null;
PopupMenu.addEventListener = function(element, name, observer, capture) {
    if (typeof element == 'string') {
        element = document.getElementById(element);
    }
    if (element.addEventListener) {
        element.addEventListener(name, observer, capture);
    } else if (element.attachEvent) {
        element.attachEvent('on' + name, observer);
    }
};
PopupMenu.prototype = {
    init: function() {
        this.items  = [];
        this.width  = 0;
        this.height = 0;
    },
    setSize: function(width, height) {
        this.width  = width;
        this.height = height;
    },
    bind: function(element, group) {
        var self = this;
        if (!element) {
            element = document;
        } else if (typeof element == 'string') {
            element = document.getElementById(element);
        }
        this.target = element;
        if (!group) {
            group = document;
        } else if (typeof group == 'string') {
            group = document.getElementById(group);
        }
        this.group = group;

		var mouseoverEvent = function(e) {
            self.show();

			return false;
        };
		PopupMenu.addEventListener(this.target, 'mouseover', mouseoverEvent, true);

		var mouseoutEvent = function(e) {
			x = e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
			y = e.pageY || (e.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
			
			if (!self.within(self.element, x, y))
			{
				self.hide();
			}
			
			return false;
        };
		PopupMenu.addEventListener(this.target, 'mouseout', mouseoutEvent, true);
		
		var clickEvent = function(e) { if (e.srcElement != self.target) self.hide() };
        PopupMenu.addEventListener(document, 'click', clickEvent, true);
    },
    add: function(text, url) {
        this.items.push({ text: text, callback: function(target) {document.location.href = url} });
    },
    addSeparator: function() {
        this.items.push(PopupMenu.SEPARATOR);
    },	
	cumulativeOffset: function(element) {
		var valueT = 0, valueL = 0;
		do {
			if (element.offsetTop)
				valueT += element.offsetTop  || 0;
			if (element.offsetLeft)
			valueL += element.offsetLeft || 0;
			element = element.offsetParent;
		} while (element);
		return [valueL, valueT];
	},
	realOffset: function(element) {
		var valueT = 0, valueL = 0;
		do {
			valueT += element.scrollTop  || 0;
			valueL += element.scrollLeft || 0;
			element = element.parentNode;
		} while (element);

		return [valueL, valueT];
	},	
	within: function(element, x, y) {
		this.xcomp = x;
		this.ycomp = y;
		this.offset = this.cumulativeOffset(element);
	
		return (this.ycomp >= this.offset[1] &&
				this.ycomp <  this.offset[1] + element.offsetHeight &&
				this.xcomp >= this.offset[0] &&
				this.xcomp <  this.offset[0] + element.offsetWidth);
	},
    setPos: function(e) {
        if (!this.element) return;
        if (!e) e = window.event;
		var pos = this.cumulativeOffset(this.target);
		var curX = pos[0];
		var curY = pos[1];
        var x, y;
        if (window.opera) {
            x = curX;
            y = curY;
        } else if (document.all) {
            x = document.body.scrollLeft + curX;
            y = document.body.scrollTop + curY;
        } else if (document.layers || document.getElementById) {
            x = curX;
            y = curY;
        }
		newX = x - this.element.offsetWidth / 2 + this.target.offsetWidth / 2;
		posGroup = this.cumulativeOffset(this.group);
		minX = posGroup[0];
		maxX = minX + this.group.offsetWidth;
		dxMin = newX - minX;
		if (dxMin < 0)
		{
			newX -= dxMin;
		}
		dxMax = (newX + this.element.offsetWidth) - maxX;
		if (dxMax > 0)
		{
			newX -= dxMax;
		}
		
        this.element.style.top = y + 22 + 'px';
        this.element.style.left = newX + 'px';
    },
    show: function(e) {
        if (PopupMenu.current && PopupMenu.current != this)
		{
			PopupMenu.current.hide();
		}
        PopupMenu.current = this;
		this.target.className = 'active';
		this.target.parentNode.className = 'menu_main_hover';
        if (this.element) {
            this.element.style.display = '';
            this.setPos(e);
        } else {
            this.element = this.createMenu(this.items);
            document.body.appendChild(this.element);
            this.setPos(e);
        }
    },
    hide: function() {
        PopupMenu.current = null;
        if (this.element) this.element.style.display = 'none';
		this.target.className = '';
		this.target.parentNode.className = '';
    },
    createMenu: function(items) {
        var self = this;
        var menu = document.createElement('div');
        with (menu.style) {
            if (self.width)  width  = self.width  + 'px';
            if (self.height) height = self.height + 'px';
        }
		menu.className = 'submenu_bg';
        for (var i = 0; i < items.length; i++) {
            var item;
            if (items[i] == PopupMenu.SEPARATOR) {
                item = this.createSeparator();
            } else {
                item = this.createItem(items[i]);
            }
            menu.appendChild(item);
        }
        return menu;
    },
    createItem: function(item) {
        var self = this;
        var elem = document.createElement('span');

		elem.className = 'submenu_item';
        var callback = item.callback;
        PopupMenu.addEventListener(elem, 'click', function(_callback) {
            return function() {
                self.hide();
                _callback(self.target);
            };
        }(callback), true);
        PopupMenu.addEventListener(elem, 'mouseover', function(e) {
			elem.className = 'submenu_item_over';
        }, true);
        PopupMenu.addEventListener(elem, 'mouseout', function(e) {
			elem.className = 'submenu_item';
        }, true);
        elem.appendChild(document.createTextNode(item.text));
        return elem;
    },
    createSeparator: function() {
        var sep = document.createElement('span');
		sep.className = 'submenu_item_separator';
		sep.innerHTML = '|';
		
        return sep;
    }
};


