﻿/*____________________________________________
|     _     _ ___      __ _                   |
|    (_)___(_) __|___ / _| |_ __ _ _ _ ___    |
|    | |_ /| \__ | _ \  _|  _/ _` | '_/ -_)   |
|    |_/__||_|___|___/_|  \__\__,_|_| \___|   |
|                                             |
|       ©2010 iziSoftware - Version 1.0       |
|_____________________________________________|


WEMENU : Gestion des menu d'une page

*/


//Démarrage
$(document).ready(function() {
    WEMenuCoreJs.Initialize()
});

//Demande de rechargement de l'éditeur
$(document).bind("OEReload", function(e) { 
    for (ElemID in OEConfWEMenu) {
        
        var ConfWEMenu = OEConfWEMenu[Elem]; 
        
        //Rechargement de l'element menu
        if (ElemID == e.ID) {WEMenuCoreJs.IniMenu(ElemID)}
        
        //Rechargement du hook
        var $Hook = WEMenuCoreJs.IniHook(Elem);
        if (ConfWEMenu.Hook == e.ID) {WEMenuCoreJs.IniHook(ElemID)}  
  
    }
});


var WEMenuCoreJs = {

    //Propriétés
    $CurentElem: null,      //Menu courant -> gestion des masquages
    $CurentGroup: null,     //Group actif
    HideTimer: null,        //Timer de fermeture global
    ShowAnimTimer: null,    //Timer ouverture sous menu
    HideAnimTimer: null,    //Timer fermeture sous menu
    ShowTimer: null,        //Timer d'affichage
    zindex: 100000,         //Z-index des menus


    //Initialisation des menus
    Initialize: function() {
        for (Elem in OEConfWEMenu) {
            WEMenuCoreJs.IniMenu(Elem)
        }
    },

    
    //Initialisation du hook (accrocheur)
    IniHook: function(Elem) {
    
        var ConfWEMenu = OEConfWEMenu[Elem];    

        var $Hook = $("#" + ConfWEMenu.Hook)
        if ($Hook.size() < 1) { return false }

        var StartX = ConfWEMenu.StartX;
        if (StartX == null) { StartX=0 }
        
        var StartY = ConfWEMenu.StartY;
        if (StartY == null) { StartY=0 }
        
        var WEDataStartXY = { "X": StartX, "Y": StartY };
        
        $Hook.data("WEDataStartXY", WEDataStartXY)
        $Hook.data("WEDataStartPosition", ConfWEMenu.StartPosition)
    
        return $Hook
    
    },

    IniTrigger: function(Elem, $Hook) {
     
        var $Elem = $("#" + Elem); 
        var ConfWEMenu = OEConfWEMenu[Elem];
         
         //Initialisation des triggers -> Tous les trigger entraineront les même actions
        var SelectorAllID = "";
        for (TriggerID in ConfWEMenu.Trigger) {SelectorAllID += "#" + ConfWEMenu.Trigger[TriggerID] + ", "}
        var $Trigger = $(SelectorAllID);
        if ($Trigger.size() < 1) { return }        

        
        switch (ConfWEMenu.EventType) {
            case 0: //Click
                $Trigger.click(function(e) {WEMenuCoreJs.ShowMenuBase($Hook, $Elem); return false});
                break;
            case 1: //Over et Click
                $Trigger.mouseenter(function(e) {WEMenuCoreJs.ShowMenuBase($Hook, $Elem); return false});
                $Trigger.unbind('click').attr('onclick','').click(function(e) {WEMenuCoreJs.ShowMenuBase($Hook, $Elem); return false});
                break;
            case 2:  //DblClick
                $Trigger.dblclick(function(e) {WEMenuCoreJs.ShowMenuBase($Hook, $Elem); return false});
                break;
            case 3:  //Over
                $Trigger.mouseenter(function(e) {WEMenuCoreJs.ShowMenuBase($Hook, $Elem); return false});
                break;
        }


        //Mise à jour du MenuBase actif
        $Trigger.mouseenter(function(e) {
            WEMenuCoreJs.$CurentElem = $Elem;
        });

        //Demande la fermeture décalée en cas de sortie du MenuBase
        $Trigger.mouseleave(function(e) {
            WEMenuCoreJs.$CurentElem = null;
            WEMenuCoreJs.SetAutoHide($Elem);
        });
        
        return $Trigger
        
    },

    //Initialisation d'un menu
    IniMenu: function(Elem) {

        var $Elem = $("#" + Elem)

        //Chargement des données de conf
        var ConfWEMenu = OEConfWEMenu[Elem];
        $Elem.data("ConfWEMenu", ConfWEMenu);

        //Quitte si pas de données
        if (ConfWEMenu.MenuGroup == null) { return };

        //Premier group
        var $StartMenuGroup = $Elem.find("#" + ConfWEMenu.MenuGroup.ID + ":first");

        //Quitte si aucun group
        if ($StartMenuGroup.size() < 1) { return }
        

        //Création des événements sur les triggers
        if (WEInfoPage.RenderMode == "Editor") {

            $Elem.bind('WEEdSelectHiddenElement', function() {
                var $Hook = WEMenuCoreJs.IniHook(Elem);
                if ($Hook == false) { return }
                WEMenuCoreJs.ShowMenuBase($Hook, $Elem);
            });
            
            $Elem.bind('WEEdUnSelectHiddenElement', function() {
                $(this).hide();
            });

        } else {
         
            var $Hook = WEMenuCoreJs.IniHook(Elem);
            if ($Hook == false) { return }
            WEMenuCoreJs.IniTrigger(Elem, $Hook);
              
        }

        //Mise à jour du MenuBase actif
        $Elem.mouseenter(function(e) {
            WEMenuCoreJs.$CurentElem = $(this);
        });

        //Demande la fermeture décalée en cas de sortie du MenuBase
        $Elem.mouseleave(function(e) {
            WEMenuCoreJs.$CurentElem = null;
            WEMenuCoreJs.SetAutoHide($(this));
        });


        //Création des événements sur les menus
        this.CreateMenuItemEvent($Elem, $StartMenuGroup);

    },

    //Création des événements sur les WEMenuItem d'un groupe (WEMenuGroup)
    CreateMenuItemEvent: function($Elem, $StartMenuGroup) {

        //Recupération rapide du focus
        $StartMenuGroup.mouseover(function(e) {
            if ($(this).queue("fx").length > 0) {
                $(this).stop(true, true)
                $(this).show()
            }
        });

        //Boucle sur les Items enfants
        $StartMenuGroup.children(".OESZ_WEMenuItem, .OESZ_WEMenuTop, .OESZ_WEMenuBottom, .WEMenuSeparator").each(function() {

            //Annule les evènements du même type sur tous les Items parents sauf $Elem
            $(this).mouseenter(function(e) {
                e.stopPropagation();
                $Elem.trigger('mouseenter');
            });

            //Group enfant
            var $ChildGroup = $(this).children(".OESZ_WEMenuGroup:first");

            //Fermeture des autre sousmenu de meme niveau
            $(this).mouseenter(function(e) {
                WEMenuCoreJs.CloseAllMenuThisLevel($(this), $Elem);
            });
            $(this).click(function(e) {WEMenuCoreJs.CloseAllMenuThisLevel($(this), $Elem)});

            //Quit si aucun group enfant
            if ($ChildGroup.size() == 0) { return true }

            //Creation de l'evenement d'ouverture du sous menu            
            $(this).mouseenter(function(e) {WEMenuCoreJs.ShowMenu($Elem, $(this));return false});
            $(this).click(function(e) {WEMenuCoreJs.ShowMenu($Elem, $(this));return false});

            //Récursivité
            WEMenuCoreJs.CreateMenuItemEvent($Elem, $ChildGroup)

        });
    },
    
    //Fermeture des autre sousmenu de meme niveau
    CloseAllMenuThisLevel: function($StartMenuGroup, $Elem) {
        var $ChildGroup = $StartMenuGroup.children(".OESZ_WEMenuGroup:first");
        var $HideGroup = $StartMenuGroup.parent().find(".OESZ_WEMenuGroup");
        if ($ChildGroup.size() > 0) { $HideGroup = $HideGroup.not($ChildGroup) }
        WEMenuCoreJs.HideAnim($Elem, $HideGroup)    
    },

    //Affichage du menu de base
    ShowMenuBase: function($Hook, $Elem) {

        //Premier group du menu
        var $StartGroup = $Elem.find(".OESZ_WEMenuGroup:first");

        //Quit si il est déjà visible
        if ($StartGroup.is(':visible')) { return }

        //force la fermeture rapide de tous les menu avant d'ourir celui ci
        $(".OESZ_WEMenuGroup").hide()

        //Force l'affichage menu base
        $Elem.css("display", "block");

        //Position du premier group
        var StartPosition = WEMenuCoreJs.StartPosition($Elem, $Hook, $StartGroup);
        $StartGroup.css("top", StartPosition.Y).css("left", StartPosition.X);

        //gestion du zindex
        this.zindex = 100000;
        $Elem.css("z-index", this.zindex);

        //Memo du dernier group ouvert
        $CurentGroup = $StartGroup;

        //Ouvre le premier group
        WEMenuCoreJs.ShowAnim($Elem, $StartGroup);

    },



    //Affichage d'un menu
    ShowMenu: function($Elem, $MenuItem) {

        var $ChildGroup = $MenuItem.children(".OESZ_WEMenuGroup:first");

        //Calcul de la position du menu a afficher (affichage dans la fenetre visible)
        var Position = this.ChildStartPosition($Elem, $MenuItem);
        $ChildGroup.css("top", Position.Y).css("left", Position.X);

        //Gesion du zindex des groups
        this.zindex += 1;
        $ChildGroup.css("z-index", this.zindex);

        //Memo du dernier group ouvert
        $CurentGroup = $ChildGroup;

        //Affichage
        WEMenuCoreJs.ShowAnim($Elem, $ChildGroup)

    },

    //Fermeture des menus décalé
    SetAutoHide: function($Elem) {

        if (WEInfoPage.RenderMode == "Editor") { return }

        clearTimeout(this.HideTimer)
        this.HideTimer = setTimeout(function() {

            if (WEMenuCoreJs.$CurentElem == null) {
                WEMenuCoreJs.HideAnim($Elem, $Elem.find(".OESZ_WEMenuGroup"))
            }

        }, $Elem.data("ConfWEMenu").AutoHidePeriod);

    },

    //Gestion des positions des menus
    StartPosition: function($Elem, $Hook, $StartGroup) {

        //initialisation des variables
        var Position = { "X": 0, "Y": 0 };
        var StartPosition = $Hook.data("WEDataStartPosition");
        var StartX = $Hook.data("WEDataStartXY").X;
        var StartY = $Hook.data("WEDataStartXY").Y;

        if (StartPosition == null) { return Position }

        var HookLeft = $Hook.offset().left - $Elem.offset().left;
        var HookTop = $Hook.offset().top - $Elem.offset().top;

        switch (StartPosition) {
            case 0: //RightTop
                Position.X = HookLeft + $Hook.outerWidth(true);
                Position.Y = HookTop;
                break;
            case 1: //RightBottom
                Position.X = HookLeft + $Hook.outerWidth(true);
                Position.Y = HookTop + $Hook.outerHeight(true);
                break;
            case 2: //LeftBottom
                Position.X = HookLeft;
                Position.Y = HookTop + $Hook.outerHeight(true);
                break;
            case 3: //LeftTop
                Position.X = HookLeft;
                Position.Y = HookTop;
                break;

        }


        //Gestion de l'affichage dans l'espace visible de l'ecran
        //la taille maximal en X necessaire à l'affichage (15Px = largeur de la scrollbar)
        var MaxX = Position.X + $StartGroup.outerWidth() - $(document).scrollLeft() + 15
        if (MaxX > $(window).width()) {
            // repositionnement si on n'a pas la place de l'afficher normalement
            Position.X -= MaxX - $(window).width()
        } else {
            //decalage donné par l'utilisateur 
            Position.X += StartX
        }

        //la taille maximale en Y necessaire à l'affichage
        var MaxY = Position.Y + $StartGroup.outerHeight() - $(document).scrollTop() + 15
        if (MaxY > $(window).height()) {
            // repositionnement si on n'a pas la place de l'afficher normalement
            Position.Y -= MaxY - $(window).height() 
            Position.Y -= StartY
        } else {
            //decalage donné par l'utilisateur 
            Position.Y += StartY
        }

        return Position

    },


    //verifie si le menu suivant s'affiche dans la fentre visible et corrige les position si ce n'est pas le cas
    ChildStartPosition: function($Elem, $MenuItem) {

        var Position = { "X": 0, "Y": 0 };
        var $ChildGroup = $MenuItem.children(".OESZ_WEMenuGroup:first");
        var ParentMenuTopHeight = $MenuItem.parent().find(".OESZ_WEMenuTop:first").outerHeight(true)
        var MenuItemMarginTop = parseInt($MenuItem.css("margin-top"))

        var Conf = $Elem.data("ConfWEMenu")

        //positionement initiale
        if (MenuItemMarginTop != NaN) { Position.Y = (MenuItemMarginTop * -1) }
        Position.X = $MenuItem.outerWidth() + Conf.SubMenuStartX

        //la taille maximal en X necessaire à l'affichage
        var MaxX = $MenuItem.offset().left + Position.X + $ChildGroup.outerWidth() - $(document).scrollLeft()
        if (MaxX > $(window).width()) {
            //Repositionnement si on n'a pas la place de l'afficher normalement
            Position.X = ($ChildGroup.outerWidth() + Conf.SubMenuStartX) * -1;
        }

        // la taille maximal en Y necessaire à l'affichage
        var MaxY = ($MenuItem.offset().top + $ChildGroup.outerHeight()) - $(document).scrollTop()
        if (MaxY > $(window).height()) {
            //Repositionnement si on n'a pas la place de l'afficher normalement
            Position.Y = $(window).height() - ($MenuItem.offset().top + Position.Y + $ChildGroup.outerHeight()) + $(document).scrollTop();
        } else {
            //Position de départ
            Position.Y -= ParentMenuTopHeight
        }

        return Position;
    },

    //Affichage d'un group avec effet
    ShowAnim: function($Elem, $MenuGroup) {

        clearTimeout(this.ShowAnimTimer)
        this.ShowAnimTimer = setTimeout(function() {
            $MenuGroup.stop(true, true);
            $MenuGroup.fadeIn(WEMenuCoreJs.SpeedEffectConvertor($Elem.data("ConfWEMenu").OpenSpeedEffect), function() { })
        }, 100);
    },

    //Ferture d'un group avec effet
    HideAnim: function($Elem, $MenuGroup) {

        clearTimeout(this.HideAnimTimer)
        this.HideAnimTimer = setTimeout(function() {
            $MenuGroup.stop(true, true);
            $MenuGroup.fadeOut(WEMenuCoreJs.SpeedEffectConvertor($Elem.data("ConfWEMenu").HideSpeedEffect), function() { })
        }, 100);
    },



    //Convertion des enum d'effets 
    SpeedEffectConvertor: function(OpenSpeedEffect) {

        switch (OpenSpeedEffect) {
            case 0:
                SpeedEffect = "'fast'";
                break;
            case 1:
                SpeedEffect = "'slow'";
                break;
        }
        return SpeedEffect;
    }




}


