var CONTEXT_MENU_OPTIONS = 
{
    iconSize        : {width: 16,height:16},
    item            : {height: 20, className: 'ctx-menu-item'},
    menu            : {className: 'ctx-menu'},
    alpha           : 100,
    rightArrow      : './images/ctx.menu.right.arrow.png',
    hideDelay       : 200,
    CB              : {}
};

function ContextMenu(obj)
{
    this.id             = '__CTXMENU_'+Math.ceil(Math.random()*10000);
    this.container      = new Array();
    this.itemList       = new Array();
    this.itemCount      = 0;
    this.validType      = ["chkbox", "radio", "html", "separator", "default"];
    this.noCloseT       = ["chkbox", "radio"];
    this.overMenu       = 0
    this.openedLevels   = new Array();
    this.levelStorage   = new Array();  
    this.opener         = null; 
    this.onShow         = null;    
    
    this.assign(obj);
}
/**
 * Új elemet ad hozzá a menühöz
 * 
 * @param Object param  - name: Ezen a néven lehet hivatkozni majd az elemre, ha nincs megadva akkor az "item_elemSorszáma" lesz
 *                      - type: Elem típus lehet chkbox, radio, html, default, ha nincs megadva a deafult lesz az értéke
 *                      - onClickClose: Ha az elemre kattintanak bezárja-e a menut
 *                      - content: ez fog a menuitemben szerepelni
 *                      - cb: onclick eseményre lefutot callback függvény
 *                      - className: ha egyéni class-t akarunk adni egy elemnek
 *                      - img: ha egy képet szeretnék a bal oldalán az elemnek
 *                      - sub: ha rendelkezik submenuvel akkor a level számát megadva azt a menut jeleníti meg
 *                      - level: melyik szinten helyezkedjen el az adott menu
 *                      - radioGroup: ha radiobutton típusú itemekte csoportosítani kell akkor azok lesznek egy csoportba ahol ez az érték ugyanaz lehetőleg string legyen és egyedi
 *                      - selected: ha chkbox vagy radio akkor lehet ezt megadni és értelem szerűen true/false 
 *                      - disable: ha true akkor a menu nem kattintható
 *
 * @return Object Az aktuális elem objektuma
 */
ContextMenu.prototype.addItem = function(param)
{
    var name        = (isUndefined(param.name)          ? 'item_'+this.itemCount    : param.name);
    var type        = (isUndefined(param.type)          ? 'default'                 : (this.validType.exists(param.type.toLowerCase()) ? param.type : 'default'));
    var close       = (isUndefined(param.onClickClose)  ? (this.noCloseT.exists(type.toLowerCase()) ? false : true) : param.onClickClose);
    var content     = (isUndefined(param.content)       ? name+': Undefined Content' : param.content);
    var cb          = (param.cb instanceof CallBack     ? param.cb                  : null);
    var className   = (isUndefined(param.className)     ? ''                        : param.className);
    var img         = (isUndefined(param.img)           ? null                      : param.img);
    var sub         = (isUndefined(param.sub)           ? false                     : param.sub);
    var level       = (isUndefined(param.level)         ? 0                         : param.level);
    var radioGroup  = (isUndefined(param.radioGroup)    ? null                      : param.radioGroup);
    var selected    = (isUndefined(param.selected)      ? false                     : param.selected);
    var disable     = (isUndefined(param.disable)       ? false                     : param.disable);
    
    if(!isObject(this.itemList[level])) this.itemList[level] = {};
    
    this.level(level).addLevel(sub);
    
    this.itemList[level][name] = this.createItem({
        name        : name,
        type        : type,
        close       : close,
        content     : content,
        cb          : cb,
        classN      : className,
        img         : img,
        sub         : sub,
        level       : level,
        radioGroup  : radioGroup,
        selected    : selected,
        disabled    : disable
    });
    
    this.itemCount++;
    return this.itemList[level][name];   
}

/**
 * Létrehozza az elemet, felépítése:
 *   <div class="elem-típusa elem-className elem-neve enable/disable CONTEXT_MENU_OPTIONS.items.className ">
 *      <div class="left">
 *          <img /> v. <input />
 *          <div class="tdiv"></div> ha a menu disableden van akkor ez megjelenik (display: block;)
 *      </div>
 *      <div class="right">
 *          <span>Ide kerül a szöveges tartalom ha nem HTML típúsú</span> ha HTML akkor ide
 *      </div>
 *   </div>
 * 
 * @param Object p Bővebb info az addItem függvénynél
 * @return az elkészített elem objektuma 
 */
ContextMenu.prototype.createItem = function(p)
{
    var classN      = new Array(CONTEXT_MENU_OPTIONS.item.className, p.classN, 'enable', p.name);
    var left_c      = null;
    var right_c     = null;
    var row         = document.createElement('div');    
    row.left        = document.createElement('div');
    row.right       = document.createElement('div');
    row.level       = p.level;
    row.ContextMenu = this;
    
    row.left.className  = 'left';
    row.right.className = 'right';    
    
    var _style = {
        height      : CONTEXT_MENU_OPTIONS.item.height + 'px',
        position    : 'absolute',
        left        : '0px'           
    };
    
    if(p.sub)
    {
        row.right.arrow = this.createImg(CONTEXT_MENU_OPTIONS.rightArrow);
        if(isElement(row.right.arrow))
        setStyle(row.right.arrow, {
            position    : 'absolute',
            right       : '5px'            
        });
        classN.push('sub');
    }
    
    switch(p.type.toUpperCase())
    {
        case 'CHKBOX':
            left_c = this.createChkBox(p);            
            right_c = this.createText(p.content);
            p.chkID = left_c.id;
            classN.push('chkbox'); 
        break;
        
        case 'RADIO':
            left_c  = this.createRadio(p);
            right_c = this.createText(p.content);
            p.radioID = left_c.id;
            classN.push('radio');
        break;
        
        case 'HTML':
            left_c = this.createImg(p.img);
            right_c = p.content
        break;
        
        case 'SEPARATOR':
            setStyle(row.right,{
                position    : 'absolute',
                left        : CONTEXT_MENU_OPTIONS.item.height - 3 + 'px',
                right       : '5px'
            });
            _style.height = '1px';
            classN.push('separator');
        break;
        
        default:
        case 'DEFAULT':
            left_c = this.createImg(p.img);
            right_c = this.createText(p.content);            
            classN.push('default');
        break;
    }
    
    
    disableSelection(row);
    disableSelection(row.left);
    disableSelection(row.right);
    if(isElement(left_c))disableSelection(left_c);
    if(isElement(right_c))disableSelection(right_c);
    
    
    row.className = classN.join(' ');
    row.setAttribute('sub', p.sub);
    row.setAttribute('name', p.name);
    
    setStyle(row, _style);
    setStyle(row.left, {
        width       : CONTEXT_MENU_OPTIONS.item.height + 'px',        
        position    : 'absolute',
        left        : '0px',
        top         : '0px'        
    });
    
    setStyle(row.right, {
        height      : parseInt(row.style.height) + 'px',
        marginLeft  : parseInt(row.left.style.width) + 'px'              
    }),
    
    row.appendChild(row.left);
    row.appendChild(row.right);    
    
    row.leftDisable = document.createElement('div');
    row.leftDisable.className = 'tdiv';
    setStyle(row.leftDisable, {
        position    : 'absolute',
        left        : '0px',
        top         : '0px',
        width       : parseInt(row.left.style.width) + 'px',
        height      : parseInt(row.left.style.width) + 'px'
    });
    
    if(isElement(row.right.arrow))  row.right.appendChild(row.right.arrow);    
    if(isElement(left_c))           row.left.appendChild(left_c);
    if(isElement(right_c))          row.right.appendChild(right_c);
    row.left.content = left_c;
    row.right.content = right_c;
    row.left.appendChild(row.leftDisable);    
    
    for(var key in p) if(!isFunction(p[key])) row[key] = p[key];
    
    row.disable = function()
    {
        this.ContextMenu.disable(this);
    }
    row.enable = function()
    {
        this.ContextMenu.enable(this);
    }
    row.isChecked = function()
    {
        return this.left.content.checked;
    }
    row.setChecked = function(state)
    {
        this.left.content.setChecked(state);
    }
    if(p.disabled) row.disable();
    this.addEventsToRow(row);
    
    return row;
}

/**
 * Megjeleníti a menüt és definiál az elemekhez két eventHandlert a leaveMouse és az enterMouse eventeket
 * és a ContextMenu objektumhoz egy onshow eventet ami akkor fut le mielőtt kirajzolja a menüt,
 * plusz beállítja hogy mikor tűnjön el a menü
 *
 * @param Integer level Amelyik szintet meg kell jeleníteni default: 0
 * @param Integer x A menü bal oldali pozíciója az egész dokumentumot véve alapul default: az egér x pozíciója - 4
 * @param Integer y A menu felső oldali pozíciója az egész dokumentumot véve alapul default: az egér y pozíciója - 4
 * @param Object event A amikor megnyitásra kerül annak az eventje
 */
ContextMenu.prototype.show = function(event, level, x, y)
{
    var level   = (isUndefined(level) ? 0 : level);
    var id      = this.id+'-level-'+level;
    var br      = document.createElement('br'); 
    if(event)   this.opener = (window.event) ? event.srcElement : event.target;
    if(event)   var e = event || window.event;    
    this.openedLevels[level] = true;    
    
    if(e)
    {
        if(window.event)
        {
            if(isUndefined(x)) var x  = e.clientX + document.body.scrollLeft - 4;
         	if(isUndefined(y)) var y  = e.clientY + document.body.scrollTop - 4;         	
        }
        else
        {
            if(isUndefined(x)) var x  = e.pageX - 4;
        	if(isUndefined(y)) var y  = e.pageY - 4;
        }
    } 
    
    if(!isElement(this.container[level]))
    {
        this.container[level] = document.createElement('div');
    }
    
    this.container[level].id = id;
    setStyle(this.container[level],{
        position        : 'absolute',
        left            : x + 'px',
        top             : y + 'px',
        display         : 'none',
        opacity         : ''+CONTEXT_MENU_OPTIONS.alpha / 100+'',
        filter          : 'alpha(opacity='+CONTEXT_MENU_OPTIONS.alpha+')'
    });
    
    if(this.onShow instanceof CallBack)
    {
        this.onShow.execute(this);
    }
    
    if($(id))
    {
        $(id).style.display = 'block';
        setStyle($(id+'iframe'),{
            left        : x + 'px',
            top         : y + 'px',
            display     : 'block',
            width       : parseInt(this.container[level].offsetWidth) + 'px',
            height      : parseInt(this.container[level].offsetHeight) + 'px'
        });
        
        if(this.container[level].hideTimeout) clearTimeout(this.container[level].hideTimeout);
        
        document.getElementsByTagName('body').item(0).appendChild($(id+'iframe'));
        document.getElementsByTagName('body').item(0).appendChild($(id));
        return true;
    }
    
    var iframe  = this.createIframe(x,y);
    iframe.id   = id+'iframe';    
    
    if(!isUndefined(this.itemList[level]))
    {
        if(isObject(this.itemList[level]))
        {
            this.container[level].row = new Array();
            for(var i in this.itemList[level])
            {
                var act = this.itemList[level][i];
                if(isFunction(act)) continue;
                
                this.container[level].appendChild(act);
                this.container[level].row.push(act);
                if(['radio','chkbox'].exists(act.type.toLowerCase()))
                { 
                    act.left.content.setChecked(act.selected);
                    if(act.type.toLowerCase() == 'radio' && act.radioGroup) 
                            act.left.content.setName(act.radioGroup);
                    else    act.left.content.setName(act.name);
                }      
            }
        }
    }
    
    this.container[level].className = CONTEXT_MENU_OPTIONS.menu.className + ' level-' + level;
    
    document.getElementsByTagName('body').item(0).appendChild(iframe);
    document.getElementsByTagName('body').item(0).appendChild(this.container[level]);
    
    setStyle(this.container[level],{display: 'block', width: 2000 + 'px'}); 
    
    var maxWidth = 0;
    for(var i=0 ; i<this.container[level].row.length ; i++)
    {
        var act = this.container[level].row[i];
        if(parseInt(act.offsetWidth) > maxWidth) maxWidth = parseInt(act.offsetWidth);        
    }
    
    var top = 0;
    for(var i=0 ; i<this.container[level].row.length ; i++)
    {
        var act = this.container[level].row[i];
        act.style.width = maxWidth + 'px';
        act.style.top   = top + 'px';
        top += parseInt(act.offsetHeight) + (act.type.toLowerCase() == 'separator' ? 7 : 0);
    }
    this.container[level].style.width = maxWidth + 2 + 'px';
    this.container[level].style.height = top + 'px';
    
    setStyle(iframe, {
        width       : parseInt(this.container[level].offsetWidth) + 'px',
        height      : parseInt(this.container[level].offsetHeight) + 'px',
        display     : 'block'
    });
    
    this.container[level].level         = level;
    this.container[level].parent        = this;
    this.container[level].oncontextmenu = function(){return false;}
    this.container[level].onmousemove   = function(e)
    {
        var e   = (window.event) ? window.event : e;
        var tg  = (window.event) ? e.srcElement : e.target;
        var x   = 0;
        var y   = 0;
        var cx  = 0;
        var cy  = 0;
        
        if(window.event)
        {
            x   = e.offsetX;
            y   = e.offsetY;
            cx  = e.clientX + document.body.scrollLeft;
         	cy  = e.clientY + document.body.scrollTop;         	
        }
        else
        {
            x   = e.layerX;
            y   = e.layerX;
            cx  = e.pageX;
        	cy  = e.pageY;
        }
        
        if(this.parent.overMenu != this.level)
        {
            this.parent.container[this.parent.overMenu].over = false;
            if(this.parent.overMenu != this.parent.level(this.level).getParent())
            this.parent.container[this.parent.overMenu].hide();
        }                
        
        if( cx >= parseInt(this.offsetLeft) &&
            cx <= parseInt(this.offsetLeft) + parseInt(this.offsetWidth) &&
            cy >= parseInt(this.offsetTop) &&
            cy <= parseInt(this.offsetTop) + parseInt(this.offsetHeight))
        {
            this.over               = true;
            this.parent.overMenu    = this.level;                        
        }       
        
        if(this.actRow)
        {
            if(this.actRow != this.parent.getRowElement(tg))
            {
                var func = this.parent.itemList[this.level][this.actRow.getAttribute('name')].leaveMouse;
                if(isFunction(func)) func(this.actRow);
                this.actRow = null;                
            }
        }
        else
        {
            this.actRow = this.parent.getRowElement(tg);
            if(isElement(this.actRow))
            {
                var func = this.parent.itemList[this.level][this.actRow.getAttribute('name')].enterMouse;
                if(isFunction(func)) func(this.actRow);
            }
            else
            {
                this.actRow = null;
            }
        }
        
        if(this.hideTimeout) clearTimeout(this.hideTimeout);
    }
    
    this.container[level].onmouseout = function()
    {
        
        var opened = this.parent.openedLevels.filter(function(v){return v}, true);
        if( (opened.length == 0 || (opened.existsKey(this.level) && opened.maxKey() == this.level)) && !this.hideTimeout )
        {
            if(isFunction(this.hide)) this.hide();
        }
        else
        {
            if(this.hideTimeout){clearTimeout(this.hideTimeout); this.hideTimeout = null;}
        }
    }
    
    this.container[level].hide = function()
    {
        CONTEXT_MENU_OPTIONS.CB[this.id] = new CallBack(this.parent.hide, this.parent);
        var delay = (this.level === 0 ? CONTEXT_MENU_OPTIONS.hideDelay * 2 : CONTEXT_MENU_OPTIONS.hideDelay );
        this.hideTimeout = setTimeout('CONTEXT_MENU_OPTIONS.CB["'+this.id+'"].execute('+this.level+')', delay);
    }
    
    if(this.onAfterShow instanceof CallBack)
    {
        this.onAfterShow.execute(this);
    }
}

/**
 * Elrejti a menüt
 *
 * @param Integer level melyik szintet kell elrejteni
 * @param Object self Saját objektum 
 * @param Boolean onlyChild ha true akkor csak az almenüket fogje eltűntetni ha false akkor a level szintűt és az almenőket is
 */
ContextMenu.prototype.hide = function(level, self, onlyChild)
{
    self        = isObject(self) ? self : this;
    level       = (isUndefined(level) ? 0 : level);
    var child   = self.level(level).getChildList();    
    
    if(isArray(child))
    {
        for(var i=0 ; i<child.length ; i++)
        {
            self.hide(child[i], self);
        }
    }
    
    if(isElement(self.container[level]) && !onlyChild)
    {
        self.openedLevels[level] = false;
        
        self.container[level].style.display = 'none';
        var ifr = $(self.container[level].id+'iframe');
        if(isElement(ifr))
            ifr.style.display = 'none';
    }    
}

/**
 * Ez a függvény hozzálétre a checkboxokat, 
 * felüldefiniálható az elején és akkor saját módon lehet elkészíteni a checkboxokat
 *
 * @param Object p Több infó az addItem függvénynél
 * @return checkbox objektum
 */
ContextMenu.prototype.createChkBox = function(p)
{
    var e   = document.createElement('input');
    e.type  = 'checkbox';
    e.id    = this.id+'_'+Math.ceil(Math.random() * 10000);  
    
    setStyle(e,{
        margin: (getBrowser().ie ? -4 : 0)+'px'
    });  
    
    e.setDisable = function(){this.disabled = true;}
    e.setEnable  = function(){this.disabled = false;} 
    e.setChecked = function(mode){this.setAttribute('checked', (mode ? 'checked' : '')); this.checked = mode;}
    e.setName    = function(name){this.setAttribute('name', name); this.name = name;}
    e.onclick    = function(){this.setChecked(!this.checked);}       
    return e;
}

/**
 * Ez a függvény hozzálétre a radiobuttont, 
 * felüldefiniálható az elején és akkor saját módon lehet elkészíteni a radiobuttont
 *
 * @param Object p Több infó az addItem függvénynél
 * @return radio objektum
 */
ContextMenu.prototype.createRadio = function(p)
{
    var e   = document.createElement('input');
    e.type  = 'radio';
    e.id    = this.id+'_'+Math.ceil(Math.random() * 10000);  
    
    setStyle(e,{
        margin: (getBrowser().ie ? -4 : 0)+'px'
    });
    
    e.setDisable = function(){this.disabled = true;}
    e.setEnable  = function(){this.disabled = false;}
    e.setChecked = function(mode){this.setAttribute('checked', (mode ? 'checked' : '')); this.checked = mode;}
    e.setName    = function(name){this.setAttribute('name', name); dump('RADIO_NAME: '+name); this.name = name;}
    //e.onclick    = function(){this.setChecked(!this.checked);}       
    return e;
}

/**
 * Ez a függvény hozzálétre a szöveges tartalmat, 
 * felüldefiniálható az elején és akkor saját módon lehet elkészíteni a szöveges tartalmat
 *
 * @param Object txt Szöveges tartalom
 * @return span objektum
 */
ContextMenu.prototype.createText = function(txt)
{
    var e           = document.createElement('span');
    e.innerHTML     = txt;
    setStyle(e,{
        margin      : '0px',
        whiteSpace  : 'nowrap'
    });
    return e;
}

/**
 * Ez a függvény hozzálétre a képeket, 
 * felüldefiniálható az elején és akkor saját módon lehet létrehozni a képeket
 *
 * @param String src A kép url-je
 * @return img objektum
 */
ContextMenu.prototype.createImg = function(src)
{
    if(!src)
    {
        return null;
    }
    var e       = document.createElement('img');
    e.width     = parseInt(CONTEXT_MENU_OPTIONS.iconSize.width);  
    e.height    = parseInt(CONTEXT_MENU_OPTIONS.iconSize.height);  
    e.src       = src;
    setStyle(e,{
        margin  : '-2px',
        display : 'block'        
    });
    return e;
}

/**
 * Ez hozza létre az iframet a menu mögé hogy kitakarjon bizonyos elemeket: pl flash, formelemek stb...
 */
ContextMenu.prototype.createIframe = function(x,y)
{
    var e = document.createElement('iframe');
    setStyle(e, {
        position    : 'absolute',
        left        : parseInt(x) + 'px',
        top         : parseInt(y) + 'px',
        opacity     : '0',
        filter      : 'alpha(opacity=0)',
        display     : 'none'
    });
    return e;
}

/**
 * A meüelemhez társít eventeket
 */
ContextMenu.prototype.addEventsToRow = function(row)
{
    if(row.disabled)
    {
        row.enterMouse = function(){}       
        row.leaveMouse = function(){}       
        row.onclick = function(){} 
        return false;      
    }
    
    if(row.sub)
    {
        row.close = false;
        row.enterMouse = function(row)
        {
            var menu    = row.ContextMenu;
            var x       = parseInt(menu.container[row.level].style.left) + parseInt(menu.container[row.level].offsetWidth) - 10;
            var y       = parseInt(menu.container[row.level].style.top) + parseInt(row.offsetTop) + parseInt(row.offsetHeight) / 2;
            menu.hide(row.level, '', true);
            menu.show(null, row.sub, x, y);             
            menu.openedLevels[row.sub] = true;                      
        }
        
        row.leaveMouse = function(row)
        {
            var menu = row.ContextMenu;
            if(menu.container[row.level].over)
            {
                if(row.sub > 0);
                menu.container[row.sub].hide();                
            }
            if(isElement(menu.container[row.level])) menu.container[row.level].onmouseout();
        }       
    }
    
    row.onclick = function()
    {
        if(this.close) this.ContextMenu.hide(0);
        if(this.type.toUpperCase() == 'CHKBOX') this.left.content.setChecked(!this.left.content.checked);
        if(this.type.toUpperCase() == 'RADIO')  this.left.content.setChecked(!this.left.content.checked);
        if(this.cb instanceof CallBack) this.cb.execute(this.ContextMenu);
        
    }
           
}

/**
 * Szintkezelést valósít meg
 */
ContextMenu.prototype.level = function(level)
{
    var level = level;
    var s = this;
    
    return {
        actLevel    : level,
        stack       : s.levelStorage,
        
        getParent: function()
        {
            if(this.actLevel == 0) return null;
            p = -1;
            for(var k in this.stack)
            {
                if(isArray(this.stack[k]))
                {
                    if(this.stack[k].exists(this.actLevel))
                    {
                        p = k;   
                    }                    
                }
            }
            return (p != -1 ? p : null);
        },              
        
        getChildList: function()
        {
            return this.stack[this.actLevel];
        },
        
        addLevel: function(level)
        {
            if(level)
            {
                if(!isArray(this.stack[this.actLevel]))         this.stack[this.actLevel] = new Array();                
                if(!this.stack[this.actLevel].exists(level))    this.stack[this.actLevel].push(level);
            }
        }    
    };
}

ContextMenu.prototype.getRowElement = function(obj)
{
    var CN = CONTEXT_MENU_OPTIONS.item.className;
    
    if(isElement(obj))
    {
        if(obj.className)
        {
            if(obj.className.indexOf(CN) != -1)
            {
                return obj;
            }            
        }
        return this.getRowElement(obj.parentNode);               
    }
}

ContextMenu.prototype.getItem = function(level, name)
{
    if(this.itemList.existsKey(level))
    {
        if(this.itemList[level].existsKey(name))
        {
            return this.itemList[level][name];
        }
    }
    return null;
}

ContextMenu.prototype.disable = function(obj)
{
    var menu = obj.ContextMenu;
    if(obj.className.indexOf('enable') != -1)
    {
        obj.className = obj.className.replace(/enable/g, "disable");        
    }
    else
    {
        if(obj.className.indexOf('disable') == -1) obj.className += ' disable';
    }
    obj.disabled = true;
    obj.leftDisable.style.display = (['radio','chkbox'].exists(obj.type.toLowerCase()) ? 'none' : 'block');
    if(['radio','chkbox'].exists(obj.type.toLowerCase())) obj.left.content.setDisable();
    menu.addEventsToRow(obj);    
}

ContextMenu.prototype.enable = function(obj)
{
    var menu = obj.ContextMenu;
    if(obj.className.indexOf('disable') != -1)
    {
        obj.className = obj.className.replace(/disable/g, "enable");
    }
    else
    {
        if(obj.className.indexOf('enable') == -1) obj.className += ' enable';
    }
    obj.disabled = false;
    obj.leftDisable.style.display = (['radio','chkbox'].exists(obj.type.toLowerCase()) ? 'none' : 'block');
    if(['radio','chkbox'].exists(obj.type.toLowerCase())) obj.left.content.setEnable();
    menu.addEventsToRow(obj);
}

ContextMenu.prototype.assign = function(obj)
{
    if(isElement(obj))
    {
        obj.ContextMenu     = this;
        obj.oncontextmenu   = this.oncontextmenu;
        addEvent(document, 'mousedown', this, 'onmousedown');        
    }
}

ContextMenu.prototype.onmousedown = function(e)
{
    var e       = e || window.event;
    var opened  = this.openedLevels.filter(function(v){return v}, true);
    var hide    = true;
    
    var cx  = 0;
    var cy  = 0;
    
    if(window.event)
    {
        cx  = e.clientX + document.body.scrollLeft;
     	cy  = e.clientY + document.body.scrollTop;         	
    }
    else
    {
        cx  = e.pageX;
    	cy  = e.pageY;
    }
    
    if(!isUndefined(this.container[0]))
    {
        for(var i in opened)
        {
            if(isFunction(opened[i])) continue; 
            var act = this.container[i];
            
            if( cx >= parseInt(act.offsetLeft) &&
                cx <= parseInt(act.offsetLeft) + parseInt(act.offsetWidth) &&
                cy >= parseInt(act.offsetTop) &&
                cy <= parseInt(act.offsetTop) + parseInt(act.offsetHeight))
            {
                hide = false;                        
            }       
        }
        if(hide) this.hide(0);
    }
}

ContextMenu.prototype.oncontextmenu = function(e)
{
    var e = e || window.event;
    
    this.ContextMenu.show(e);
    
    return false;
}

ContextMenu.prototype.destroy = function()
{
    for(var i=0 ; i<this.container.length; i++)
    {
        var c = $(this.container[i].id);
        var i = $(this.container[i].id+'iframe');
        if(isElement(c)) c.del();
        if(isElement(i)) i.del();        
    }
    removeEvent(document, 'mousedown', this, 'onmousedown');
    
}