/**
* Don't change or remove the head comments!
* 
* DHTML hierarchical, object oriented menu: VB MENU 1.4
* Copyright (C) 2003-2004  Vladimir Bodurov
*                               
*   Version  1.4  2004-02-20  
*                               
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*                                                                 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
                                               
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*                                                                        
* Copy of GNU Lesser General Public License at: http://www.gnu.org/copyleft/lesser.txt
*                                                    
* Source code home page: http://www.bodurov.com/menu.html
*/

with (document) {
    // this we need for IE for MAC
    if(typeof Array.prototype.push=="undefined"){
        Array.prototype.push=function(){ 
            var i=0; b=this.length,a=arguments; 
            for(i;i<a.length;i++)
                this[b+i]=a[i];
            return this.length 
        };
        Array.prototype.pop=function(){
            var len = this.length;
            var lastVal = "";
            if(len>0){
                len--;
                lastVal = this[len];
                this.length = len;
            }
            return lastVal; 
        };
    } 
}


// ----------------------------- Square object starts here ---
function S_IsIn(x,y){
    if((x>=this.sqStartX && x<=this.sqEndX) && (y>=this.sqStartY && y<=this.sqEndY)){
        return true;
    }else{
        return false;
    }
}
// to be used for debuging (if you need less file size you can remove it)
function S_ToString(){
    return "[ id:"+this.id +"|StartX:"+this.sqStartX+"|StartY:"+this.sqStartY+"|EndX:"+this.sqEndX+"|EndY"+this.sqEndY+" ]";
}
// to get a copy of this square object
function S_GetCopy(){
    return new Square(this.id,this.sqStartX,this.sqStartY,(this.sqEndX-this.sqStartX),(this.sqEndY-this.sqStartY));
}
// constructor of object Square
function Square(id,sqX,sqY,sqWidth,sqHeight){
    // properties 
    this.id = id;
    this.sqStartX = sqX;
    this.sqStartY = sqY;
    this.sqEndX = sqWidth+sqX;
    this.sqEndY = sqHeight+sqY;
    
    // methods
    this.IsIn = S_IsIn;
    this.ToString = S_ToString;
    this.GetCopy = S_GetCopy;
}
// ----------------------------- Square object ends here ---
// ----------------------------- Polygon object starts here ---
// to be used for debuging (if you need less file size you can remove it)
function P_ToString(){
    var result = "";
    var len = this.squares.length;
    for(var i=0;i<len;i++){
        result += this.squares[i].ToString();
    }
    return "Length:"+len+"; "+result;
}
// check if this square is already in polygon
function P_IsInPolygon(id){
    var len = this.squares.length;
    if(len>1){
        for(var i=0;i<len;i++){
            var currId = this.squares[i].id;
            if(id==currId){
                return true;
            }
        }
    }
    return false;
}
// set the polygon (consists of two squares)
function P_Set(square_1,square_2){
    if(!this.IsInPolygon(square_1.id)){
        this.id = square_1.id;
        this.squares[0] = square_1;
        this.squares[1] = square_2;
    }
}
// check if x and y is withinn this polygon
function P_IsIn(x,y){
    for(var i=0;i<this.squares.length;i++){
        if(this.squares[i].IsIn(x,y)) return true;
    }
    return false
}
// to get a copy of the object Polygon
function P_GetCopy(){
    var polygon = new Polygon();
    polygon.Set(this.squares[0].GetCopy(),this.squares[1].GetCopy());
    return polygon;
}
// constructor of object Polygon
function Polygon(){
    // properties
    this.squares = new Array(new Square(0,0,0,0,0),new Square(0,0,0,0,0)); // array of squares
    this.id;
    
    // methods
    this.Set = P_Set;
    this.IsInPolygon = P_IsInPolygon;
    this.IsIn = P_IsIn;
    this.ToString = P_ToString;
    this.GetCopy = P_GetCopy;
}
// ----------------------------- Polygon object ends here ---
// ----------------------------- Link object starts here ---
// constructor of object Link
function Link(text,url,target,id,parent){
    // properties
    this.text = text;
    this.url = url;
    this.target = target;
    this.id = id;
    this.parent = parent;
}
// ----------------------------- Link object ends here ---

// ----------------------------- LinkBox object starts here ---
// pushes a link into LinkBox object
function LB_PushLink(level,linkObj){
    this.links.push(linkObj);
    this.id = linkObj.parent;
    this.level = level;
}

// constructor of object LinkBox
function LinkBox(){
    // properties
    this.links = new Array(); // array of Link objects
    this.id = 0;
    this.level = 0;
    
    // methods
    this.PushLink = LB_PushLink;
}
// ----------------------------- LinkBox object ends here ---
// ----------------------------- MenuCreator object starts here ---
function MC_DocMoveHandler(e) {
    var x = (mc.isNS || mc.isMO) ? e.pageX:event.clientX + self.document.body.scrollLeft;
    var y = (mc.isNS || mc.isMO) ? e.pageY:event.clientY + self.document.body.scrollTop;
    if(mc.is_shown){
        if( !mc.polygon.IsIn(x,y) ){
            mc.Hide();
        }
    }
}

function MC_InitMouseHandlers() {
    document.onmousemove = this.DocMoveHandler;
    if (this.isNS || this.isMO){
        document.captureEvents(Event.MOUSEMOVE);
    }
}

// draw invisible boxes
function MC_Draw(){
    if(this.ok){
        
        var all = "";
        var text;
        var url;
        var target;
        var id;
        // var parent;
        var len = this.boxes.length;
        var level = 0;
        var start;
        // if this.write_first_level == false then the first level will be enetered manually
        if(this.write_first_level) start = 0;
        else start = 1;
        
        for(var i=start;i<len;i++){
        var css = "";
            level = this.boxes[i].level;

            for(var j=0;j<this.boxes[i].links.length;j++){
                text = this.boxes[i].links[j].text;
                url = this.boxes[i].links[j].url;
                target = this.boxes[i].links[j].target;
                id = this.boxes[i].links[j].id;
                if(target!="") target = " TARGET="+target;
                var linkTagStart = "";
                var linkTagEnd = "";
                if(url!=""){
                    var link_style = (level == 1) ? 'FirstMenuLink' : 'MenuLink';
                    linkTagStart = "<a href='"+url+"'"+target+" class='"+link_style+"'>";
                    linkTagEnd = "</a>";
                }
                if(level==1) { 
                    css = " class='FirstMenuElement'";
                } else {
                    if(j==0)
                        css = " class='MenuElementFirst'";
                    else 
                        css = " class='MenuElement'";
                }
                all += "<div id='link_"+id+"' onmouseover='mc.Show(this);mc.OverStyle(this)' onmouseout='mc.NormalStyle(this)'"+css+">"+
                       linkTagStart+text+linkTagEnd+"</div>\n<img id='img_"+id+"' name='img_"+id+"' src='"+this.image+"' style='position:absolute;display:none'>";
            }
    
        }
    
        document.write(all);
        // make first level visible and place it in proper place    
        this.ShowFirstLevel();
        // initialise mousemove event
        this.InitMouseHandlers();
    }
}
// places the first level boxes on the screen at the tags <div id="MenuLine" style="position:relative"></div>
function MC_ShowFirstLevel(){
    if(this.write_first_level){
        var links = this.boxes[0].links;
        var len = links.length;
        var leftShift = 0;
        var topShift = 0;
        var posObj = document.getElementById("MenuLine");
        if(this.isIE || this.isMO){
            
            var posObjIe = document.getElementById("MenuLineIE");
            
            if(posObjIe!=null) posObj = posObjIe;
            
        }
        
        
        for(var i=0;i<len;i++){
            var id = links[i].id;
            var linkObj = document.getElementById("link_"+id);
            linkObj.style.display="block";

            
            var posX = parseInt(posObj.offsetLeft)+parseInt(this.posBodyLeft);
            var posY = parseInt(posObj.offsetTop)+parseInt(this.posBodyTop);
            linkObj.style.left = posX+leftShift;
            linkObj.style.top = posY+topShift;
            if(this.is_vertical) topShift += linkObj.offsetHeight;
            else leftShift += linkObj.offsetWidth;
        }
    }else{
        var links = this.boxes[0].links;
        var len = links.length;
        var idArray = new Array(len);
        for(var i=0;i<len;i++){
            idArray[i] = links[i].id;
        }
        var br_type  = (this.isIE || this.isMO) ? "IE" : "";
        var elements = document.getElementsByName("MenuBox"+br_type);
        // in case MenuBoxIE is not defined
        if (elements==null){
            elements = document.getElementsByName("MenuBox");
        }
       
        for(var j=0;j<elements.length;j++){
            elements[j].id = "link_"+idArray[j];
        }
    }
}
// removes all boxes from the screen
function MC_HideAll(){
    var len1 = this.boxes.length;
    for(var i=0;i<len1;i++){
        var box = this.boxes[i];
        if(box.level>1){
            var len2 = box.links.length;
            for(var j=0;j<len2;j++){
                var id = box.links[j].id;
                var div = document.getElementById("link_"+id);
                if(div!=null) div.style.display="none";
                var img = document.getElementById("img_"+id);
                if(img!=null) img.style.display="none";
            }
        }
    }
    this.polygonsLine = new Array(this.polygon);
}
// shows box
function MC_Show(obj){

    if(this.ok){
        var box = this.GetBoxById(this.IsolateId(obj.id));
      
        if(box!=null){
            if(this.currentBox.level!=0 && this.currentBox.level!=(box.level-1) && this.currentBox.id!=box.id){
                if(box.level==2) this.HideAll();
                else this.Hide();
            }
    
            this.is_shown = true;
            this.currentBox = box;
            var len = box.links.length;
            var vertShift = 0;
            var initX = 0;
            var initY = 0;
            for(var i=0;i<len;i++){
                
                var id = box.links[i].id;
                var subObj = document.getElementById("link_"+id);
                var coordY = this.CalculateY(obj,box.level,vertShift);
                var coordX = this.CalculateX(obj,box.level);

                if(this.isNS){
                    coordX = coordX + this.posBodyLeft;
                    coordY = coordY + this.posBodyTop;
                }
                
                var winWidth = document.getElementsByTagName("body")[0].offsetWidth;
                subObj.style.display="block";
                
                subObj.style.top = coordY;
                //  subObj.style.top = (box.level > 2) ? coordY + 5 : coordY;
                
                var correction = this.CenterCorrection(subObj.offsetWidth,obj.offsetWidth,box.level);

                if((coordX + obj.offsetWidth) > winWidth && box.level>2){
                    coordX -= obj.offsetWidth*2 - this.pad;
                }
                
                // Stoyan HACK 
                if (obj.id=='link_' + this.align_right) {
                    coordX -= subObj.offsetWidth - obj.offsetWidth
                }
                
                subObj.style.left = coordX + correction;
                
                vertShift += subObj.offsetHeight;
                if(this.HasChildren(id)) this.AddImage(coordX+correction,coordY,subObj.offsetWidth,id);
                if(i==0){
                    initX = coordX;
                    initY = coordY;
                }
                
            }
            
            this.polygon = new Polygon();
            this.polygon.Set(new Square(box.id,initX-this.pad,initY-this.pad,subObj.offsetWidth+this.pad,vertShift+this.pad),
                             new Square(box.id,obj.offsetLeft,obj.offsetTop,obj.offsetWidth,obj.offsetHeight+this.pad));
    
            if(!this.IsInPolygonsLine(this.polygon.id)) 
                this.polygonsLine.push(this.polygon.GetCopy());     
    
        }
    } 
}
// to center the box
function MC_CenterCorrection(boxWidth,trigetWidth,level){
    if(!this.is_vertical && level==2 && this.is_centered){
        return (trigetWidth/2)-(boxWidth/2);
    }
    return 0;
}
// check if box has children
function MC_HasChildren(id){
    for(var i=0;i<this.boxes.length;i++){
        if(this.boxes[i].id==id) return true;
    }
    return false
}
// add an arrow image
function MC_AddImage(coordX,coordY,width,id){
    var imgObj = document.getElementById("img_"+id);
    imgObj.style.display="block";
    imgObj.style.top = coordY+5;
    imgObj.style.left = coordX+(width-12);
}
// calculates Y coordinate
function MC_CalculateY(obj,level,vertShift){
    var i;
    if(!this.is_vertical && level==2) i = obj.offsetTop + obj.offsetHeight + vertShift;
    else i = obj.offsetTop + vertShift;
    return i;
}
// calculates X coordinate
function MC_CalculateX(obj,level){
    var i;
    if(!this.is_vertical && level==2) i = obj.offsetLeft;
    else  i = obj.offsetLeft + obj.offsetWidth-10;
    return i;
}
// hides box when the mouse is out of it
function MC_Hide(){
    if(this.ok){
        var box = this.GetBoxById(this.currentBox.id);
        if(box!=null){
            this.is_shown = false;
            var len = box.links.length;
            for(var i=0;i<len;i++){
                var id = box.links[i].id;
                var subObj = document.getElementById("link_"+id);
                if(subObj!=null) subObj.style.display="none";
                var imgObj = document.getElementById("img_"+id);
                if(imgObj!=null) imgObj.style.display="none";
            }
            len = this.polygonsLine.length;
            if(len>1){
                this.polygon = this.polygonsLine[len-2];
                this.currentBox = this.GetBoxById(this.polygon.id);
                this.is_shown = true;
                this.polygonsLine.pop();
            }
        }

    }

}
// changes the style when mouseover
function MC_OverStyle(obj){
    if(obj.className=="MenuElement") obj.className = "MenuElementOver";
    else if(obj.className=="FirstMenuElement") obj.className = "FirstMenuElementOver";
    else if(obj.className=="MenuElementFirst") obj.className = "MenuElementFirstOver";
}
// changes the style back when mouseout
function MC_NormalStyle(obj){
    if(obj.className=="MenuElementOver") obj.className = "MenuElement";
    else if(obj.className=="FirstMenuElementOver") obj.className = "FirstMenuElement";
    else if(obj.className=="MenuElementFirstOver") obj.className = "MenuElementFirst";
}
// to be used for debugging (if you need less file size you can remove it)
function MC_ToString(){
    var boxesInfo = "";
    for(var i=0;i<this.boxes.length;i++){
        boxesInfo += " [ ";
        for(var j=0;j<this.boxes[i].links.length;j++){
            boxesInfo += " (text:"+this.boxes[i].links[j].text+
                         ", url:"+this.boxes[i].links[j].url+
                         ", target:"+this.boxes[i].links[j].target+
                         ", id:"+this.boxes[i].links[j].id+
                         ", parent:"+this.boxes[i].links[j].parent+") \n";
        }
        boxesInfo += " ] id:"+this.boxes[i].id+" level:"+this.boxes[i].level+"\n";
    }
    return  "boxes:{"+boxesInfo+"}";
}
// give integer only
function MC_IsolateId(id){
    if(id.indexOf("link_")==0) id=id.substr(5);
    return id;
}
// get box object by its id
function MC_GetBoxById(id){
    var len = this.boxes.length;
    for(var i=0;i<len;i++){
       if(this.boxes[i].id==id){
            return this.boxes[i];
            
        }
    }
    return null;
}
// add a link to the menu
function MC_Add(text,url,target){
    if(target=="undefined") target = "";
    if(url=="undefined") url = "";
    var level = 0;
    this.id++;
    
    this.boxes[this.currBoxCount].PushLink(this.level,new Link(text,url,target,this.id,this.parent));
}
// start adding box
function MC_Start(){
    this.level++;
    this.boxCount++;
    this.parent = this.id;
    this.boxes[this.boxCount] = new LinkBox();
    this.parentsLine.push(this.parent);
    this.boxesLine.push(this.boxCount);
    this.currBoxCount = this.boxCount;

}
// end adding box
function MC_End(){
    this.level--;
    this.parentsLine.pop();
    var len = this.parentsLine.length;
    if(len>0) this.parent = this.parentsLine[len-1];
    else this.parent = 0;
    if(this.parent=="undefined") this.parent = 0;
    this.boxesLine.pop();
    var i = this.boxesLine.length-1;
    this.currBoxCount = this.boxesLine[i];
}
// check if this polygon is already in the array of current polygons
function MC_IsInPolygonsLine(id){
    var len = this.polygonsLine.length;
    for(var i=0;i<len;i++){
        var curr = this.polygonsLine[i]
        if(curr.id==id) return true;
    }
    return false;
}
// make it vertical
function MC_Vertical(){
    this.is_vertical = true;
}
// center the box
function MC_Center(){
    this.is_centered = true;
}
// do not write first level links
function MC_DoNotWriteFirstLevel(){
    this.write_first_level = false;
}
function MC_SetBodyMargins(){
    var posBody = document.getElementsByTagName("BODY");
    var posBodyTop = 0;
    var posBodyLeft = 0;
    if(this.isNS || this.isMO){
        this.posBodyTop = posBody[0].offsetTop;
        this.posBodyLeft = posBody[0].offsetLeft;
    }else{
        this.posBodyTop = posBody[0].topMargin;
        this.posBodyLeft = posBody[0].leftMargin;
    }
    
}
function MC_DetectBrowser(){
    // browser detection
    
    var appVer = parseInt(navigator.appVersion);
    
    if(navigator.userAgent.indexOf("Netscape")>=0){
        this.isNS = true; // is Netscape 6+
        this.isIE = false;
        if(navigator.userAgent.indexOf("Netscape/6")<0){ // if is NS7+ is like Mozilla
            this.isNS = false;
            this.isMO = true;
        }
    }else{
        if(navigator.userAgent.indexOf("Opera")>=0){
            this.isOP = true; // is Opera
            this.isIE = false;
        }else{
            if(navigator.appName.indexOf("Netscape")>=0){
                this.isMO = true; // is Mozilla
                this.isIE = false;
            }
        }
    }
    
    if(((this.isNS || this.isMO) && appVer<5) || ((this.isOP || this.isIE) && appVer<4)) this.ok=false;
    
    //this.isIE = false;
    //this.isNS = true;
    
    
}
// constructor
function MenuCreator(){
    
    // properties
    this.img   = new Image();
    this.img.src   = this.image;
    this.boxes = new Array(); // array of Box objects
    this.is_vertical = false; // is the first level vertical, if false it is horisontal
    this.is_centered = false; // is the first level centered
    this.currentBox = new LinkBox(); // currently shown box 
    this.is_shown = false; // is there shown box
    this.write_first_level = true; // to write or not wirst level

    this.isNS = false;
    this.isOP = false;
    this.isMO = false;
    this.isIE = true;
    this.ok = true;
    
    this.id = 0;
    this.parent = 0;
    this.boxCount = -1;
    this.level = 0;
    this.currBoxCount = 0;
    this.boxesLine =  new Array(); // array of box numbers
    this.parentsLine = new Array(); // array of parents
    this.polygon = new Polygon(); // empty Polygon object
    this.polygonsLine = new Array(); // array of Polygons used
    this.pad = 10; // pad arrownd the polygon
    
    // Stoyan HACK
    this.align_right = -1;

    // methods
    this.Add = MC_Add;
    this.Start = MC_Start;
    this.End = MC_End;
    this.IsolateId = MC_IsolateId;
    this.ToString = MC_ToString;
    this.Draw = MC_Draw;
    this.Show = MC_Show;
    this.Hide = MC_Hide;
    this.InitMouseHandlers = MC_InitMouseHandlers;
    this.GetBoxById = MC_GetBoxById;
    this.ShowFirstLevel = MC_ShowFirstLevel;
    this.CalculateX = MC_CalculateX;
    this.CalculateY = MC_CalculateY;
    this.IsInPolygonsLine = MC_IsInPolygonsLine;
    this.InitMouseHandlers = MC_InitMouseHandlers;
    this.DocMoveHandler = MC_DocMoveHandler;
    this.AddImage = MC_AddImage;
    this.HasChildren = MC_HasChildren;
    this.HideAll = MC_HideAll;
    this.CenterCorrection = MC_CenterCorrection;
    this.OverStyle = MC_OverStyle;
    this.NormalStyle = MC_NormalStyle;
    this.Vertical = MC_Vertical;
    this.Center = MC_Center;
    this.DoNotWriteFirstLevel = MC_DoNotWriteFirstLevel;
    this.DetectBrowser = MC_DetectBrowser;
    this.SetBodyMargins = MC_SetBodyMargins;
    
    this.DetectBrowser();
    this.SetBodyMargins();
    
    
    
    
}
// ----------------------------- MenuCreator Object ends here ---
