/*
  popupmenu.js - simple JavaScript popup menu library.

  Copyright (C) 2009 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;
		this.over	= null;
    },
	
    setSize: function(width, height) {
        this.width  = width;
        this.height = height;
        if (this.element) {
            var self = this;
            with (this.element.style) {
                if (self.width)  width  = self.width  + 'px';
                if (self.height) height = self.height + 'px';
            }
        }
    },
	
    bind: function(element) {
        var self = this;
        if (!element) {
            element = document;
        } else if (typeof element == 'string') {
            element = document.getElementById(element);
        }
        this.target = element;
		
        this.target.oncontextmenu = function(e) {
            self.show.call(self, e);
            return false;
        };
		
        var listener = function() {
			self.hide.call(self);
			if (self.currentSubmenu)
				self.currentSubmenu.hide();
		};
        PopupMenu.addEventListener(document, 'click', listener, true);
    },
	
    add: function(text, callback) {
        this.items.push({ text: text, callback: callback });
		
		return this.items.length - 1;
    },
	
    addSeparator: function() {
        this.items.push(PopupMenu.SEPARATOR);
		
		return this.items.length - 1;
    },
	
    setPos: function(e, parent) {
        if (!this.element) return;
        if (!e) e = window.event;
        var x, y;
		
		if (parent)
		{
			var bounds = getBounds(parent);
			x = bounds.left - 2 + bounds.width;
			y = bounds.top;
		}
		else
		{
			if (window.opera) {
				x = e.clientX;
				y = e.clientY;
			} else if (document.all) {
				x = document.body.scrollLeft + event.clientX;
				y = document.body.scrollTop + event.clientY;
			} else if (document.layers || document.getElementById) {
				x = e.pageX;
				y = e.pageY;
			}
			x += 2;
			y += 2;
		}
		
        this.element.style.top  = y + 'px';
        this.element.style.left = x + 'px';
    },
	
	onDisplay: function(){},
    onClose: function() {},
	
	show: function(e, parent) {
        /*if (PopupMenu.current && PopupMenu.current != this) return;
		
        PopupMenu.current = this;*/
		
		if (!this.element)
		{
			this.element = this.createMenu(this.items);
			this.element.style.display = 'none';
            document.body.appendChild(this.element);
		}
		
		this.clickedItem = this.overItem;
		
		this.setPos(e, parent);
        this.element.style.display = '';
		
		this.onDisplay();
    },
    
	hide: function()
	{
        PopupMenu.current = null;
        if (this.element) this.element.style.display = 'none';
		
		if (this.currentSubmenu)
			this.currentSubmenu.hide();
		
		this.onClose();
    },
	
	showItem: function(index)
	{
		this.items[index].style.display = 'block';
	},
	
	hideItem: function(index)
	{
		this.items[index].style.display = 'none';
	},
	
	getItem: function(index)
	{
		return this.items[index];
	},
	
	showAll: function ()
	{
		for (var i = 0; i < this.items.length; i++)
			this.showItem(i);
	},
	
	
	hideAll: function ()
	{
		for (var i = 0; i < this.items.length; i++)
			this.hideItem(i);
	},
	
    createMenu: function(items) {
        var self = this;
		this.items = new Array();
		
		var menu = document.createElement('div');
			menu.className = 'contextmenu';
		
        var content = document.createElement('div');
			content.className = 'content';
			
        for (var i = 0; i < items.length; i++) {
            var item;
            item = this.createItem(items[i]);
            content.appendChild(item);
			
			this.items[this.items.length] = item;
        }
		
		menu.appendChild(content);
        return menu;
    },
	
    createItem: function(item) {
        var self = this;
		
		var icon = document.createElement('DIV');
			icon.className = 'icon';
			
		var column = document.createElement('DIV');
			column.className = 'column';
		
		if (item == PopupMenu.SEPARATOR)
		{
			var line = document.createElement('DIV');
				line.className = 'element';
				line.style.height = '4px';
				
			var content = document.createElement('div');
				content.className = 'separator';
		
		}
		else
		{
			var line = document.createElement('A');			
				line.className = 'element';
			
			var callback = item.callback;
				
				line.menu = this;
				
				line.onmouseover = function (e)
				{
					if (this.menu.currentSubmenu)
						this.menu.currentSubmenu.hide();
				};
					
				if (typeof(callback) == 'object')
				{
					line.submenu = callback;
					addElementClass(line, 'parent');
					
					line.onmouseover = function (e)
					{
						if (this.menu.currentSubmenu)
							this.menu.currentSubmenu.hide();
						
						this.menu.currentSubmenu = this.submenu;
						this.submenu.show(e, this);
					}
				}
				else
				{
					PopupMenu.addEventListener(line, 'click', function(callback)
					{
						return function() {
							self.hide();
							callback(self.clickedItem);
						};
					}(callback), true);
					
				}
			
			var content = document.createElement('P');
				content.appendChild(document.createTextNode(item.text));	
		}
		
		line.appendChild(icon);
		line.appendChild(column);
		line.appendChild(content);
		
		line.getBounds = function()
		{
			return getBounds(this);
		}
		
        return line;
    },
	
    createSeparator: function() {
        var sep = document.createElement('div');
		sep.className = 'separator';
		
        return sep;
    }
};

