2016-07-25 48 views
0

所以,这是事情。网站侧面有一个菜单栏。当你点击它时,菜单保持器从侧面翻入(菜单打开),当你再次单击该条时,菜单保持器回滚并隐藏菜单。到目前为止很简单。在吧台上,有一个带有“菜单”文字的图标。当您打开菜单时,图标会更改,文字将更改为“CLOSE”。当您关闭菜单时,它将恢复正常。仍然没什么大不了的。如何确保事件不会再次触发,如果它尚未停止?

这是它的样子:

closed menu

opened menu(以下简称 'ZATVORIŤ' 标题的意思是 'CLOSE' 不担心)

现在让我们看中。我们需要一个的效果,文字转换,使它看起来很酷和平滑。所以当菜单关闭时,没有标题。只有菜单图标。当用户将鼠标悬停在栏上时,文字将显示。只要用户将鼠标悬停在栏上,“MENU”标题就会逐字出现。这意味着,将出现的第一个字母将是'M',第二个'E'...'N'...'U'。整个标题将出现在几百毫秒,也许半秒。当用户悬停时,标题将由后者消失。所以'男人'...'我'...'M'...''。你明白了。 'CLOSE'字幕的工作方式相同。当用户点击该栏时(当然他需要首先将鼠标悬停在栏上,因此已有'MENU'字幕),'MENU'字幕逐字消失,'CLOSE'字幕将逐字出现。当用户关闭菜单时,'CLOSE'字幕以同样的方式消失。漂亮的东西。

现在到了整个问题的根源。只要用户正常工作,此功能就可以工作。只要用户一直在栏杆上快速移动,它会在事件已经运行时触发事件(我最好猜测问题是什么)。如果他不断点击栏,也会发生同样的情况 - “CLOSE”标题会混乱而不是“MENU”标题。然后,而不是这些字幕的字母将出现“未定义”的情侣。所以标题看起来像'MEundefinedundefinedundefined ....'或'MMMMENundefinedundefined ...'或类似的东西。所以我最初的想法是,它是一个错误的错误,因为我把字幕保存在字母数组中,它显示'未定义',对吧?我迅速修补它以确保不会出现“未定义” - 如果用户试图将其制动,则事件仅停止触发。他可以在酒吧上空盘旋,什么都不会发生。当他打开菜单(并关闭它)时,它会变得正常。但这不是它应该如何工作,我需要修复它。

所以我需要做的(我认为)是确保事件不会触发,如果一个已经在进行(以某种方式)。我尝试了一些javascript函数,比如delay()或者setTimeout()...我试图让函数脱离效果 - 失败。我花了太多时间在这方面,而且我缺乏使这个工作正常工作所需的想法和技能。任何人都可以检查我的代码,并给出一些建议,或者修补它?

下面的代码:

HTML:

<div id="navigation_bar"> <!-- THE NAVIGATION BAR WITH ICON AND CAPTION HOLDER FOR THE TEXT --> 
    <img id="menu_icon" src="<?= $base_url ?>public/web/images/menu.png"> 
    <p class="zatvorit">ZATVORIŤ</p> 
    <p class="menu">MENU</p> 
    <p class="caption_holder"><!-- HERE WILL THE MAGIC HAPPEN --></p> 

</div> 
<div id="navigation_holder"> <!-- NOT IMPORTANT PART, ONLY THE MENU HOLDER AND MENU --> 

    <p class="close_nav_mobile"> 
     <img src="<?= base_url() ?>public/web/images/close_menu.png"> 
    </p> 

    <ul id="menu_item_list" class=""> 
     <li role="presentation"><a class="menu_1" href="<?= $base_url ?>nasa-ponuka">NAŠA PONUKA</a></li> 
     <li role="presentation"><a class="menu_2" href="<?= $base_url ?>referencie">REFERENCIE</a></li> 
     <li role="presentation"><a class="menu_3" href="<?= $base_url ?>kontakt">KONTAKT</a></li> 
     <li id="order_link" class="menu_order_link order_form_open" role="presentation"><a href="#"><b>OBJEDNÁVKA</b></a></li> 
     <li id="registration_link" class="menu_reg_form_link reg_form_open" role="presentation"><a href="#">REGISTRÁCIA</a></li> 
    </ul> 
     <a href="#"><img id="fb_icon" src="<?= $base_url ?>public/web/images/fb_icon.png"></a> 
</div> 

的JavaScript & jQuery的(神奇的东西)

<script type="text/javascript"> 
    menuOn = false; //is true when menu is opened 

    //this makes the array of letters for 'MENU' caption 
    captionMenu = $("p.menu").text(); 
    var lettersMenu = []; 
    lengthMenu = captionMenu.length; 
    for (var i = 0; i <= lengthMenu - 1; i++) { 
     lettersMenu[i] = captionMenu.charAt(i); 
    }; 

    //this makes the array of letters for 'CLOSE' (acutally 'ZATVORIŤ') caption 
    captionClose = $("p.zatvorit").text(); 
    var lettersClose = []; 
    lengthClose = captionClose.length; 
    for (var i = 0; i <= lengthClose - 1; i++) { 
     lettersClose[i] = captionClose.charAt(i); 
    }; 

    //some variables to be able to check what's going on 
    length = 0; //length of the caption we're working with 
    captionMenuOn = false; //true when the 'MENU' caption is visible 
    captionCloseOn = false; //true when the 'ZATBORIŤ' caption is visible 
    j = 0; // how many letters have appeared already 
    k = lengthMenu-1; //example of "how not to name your variables" but It should solve the off-by-one error 

    //now the 'MENU' caption will appear letter by letter 
    $(document).on("mouseenter", "#navigation_bar", function(){ 
     if(!menuOn && j==0) { //of course it won't be possible if the menu is opened and there are any letters left 
      j = 0; 
      length = lengthMenu; //we're working with 'MENU' now 
      interval = 150/length; //counts the interval depending on caption lenght 
      for (var i = 0; i <= length - 1; i++) { //looping the letters 
       $('p.caption_holder').delay(interval).queue(function (next) { 
        $(this).append('<span class="caption_parcial_' + j + '">' + lettersMenu[j] + '</span>'); 
        j++; //a letter has appeared 
        if (j == length-1) { //if all the letters have appeared 
         captionMenuOn = true; //now you see me 
        } 
        next(); 
       }); 
      } 
      k = lengthMenu - 1; //we should have 4 letters there somewhere 
     } 
    }); 

    //now the 'MENU' caption will disappear letter by letter an inverse event to that above 
    $(document).on("mouseleave", "#navigation_bar", function(){ 
     if(!menuOn && k==lengthMenu-1) { //so the menu needs to be closed and the 'MENU' caption should be visible 
      length = lengthMenu; //we're working with 'MENU' again 
      interval = 150/length; 
      k = length; 
      for (var i = 0; i <= length - 1; i++) { 
       $('.caption_holder').delay(interval/2).queue(function (next) { 
        k--; //a letter has disappeared 
        $('.caption_parcial_' + k).remove(); 
        if (k == 0) { //if we have no letters left 
         captionMenuOn = false; //now you don't (see me) 
        } 
        next(); 
       }); 
      } 
      j = 0; //we have 0 letters visible now 
     } 
    }); 

    //--------------------------------------THIS PART OPENS AND CLOSES THE MENU and resets the 'j' variable in case someone messed up the captions 
    $(document).on("click", "#navigation_bar, .close_nav_mobile", function(){ 
     if(menuOn) 
      $(".caption_holder").show(); 
     smallMenu(); 
    }); 

    $(document).on("click", ".menu_order_link", function(){ 
     smallMenu(); 
     j=0; 
    }); 
    $(document).on("click", ".menu_reg_form_link", function(){ 
     smallMenu(); 
     j=0; 
    }); 

     //function that opens or closes the menu 
    function smallMenu() { 

     if(!menuOn) { //if the menu is closed 

     $("#menu_icon").attr("src", base_url + "public/web/images/close_menu.png").addClass("menu_close"); //icon changes 
     //$("nav > ul").show(); 
      //the 'MENU' caption dissapears, we've seen this code before 
      length = lengthMenu; 
      interval = 150/length; 
      j = length; 
      for (var i = 0; i <= length - 1; i++) { 
       $('.caption_holder').delay(interval/2).queue(function (next) { 
        j--; 
        $('.caption_parcial_' + j).remove(); 
        //and the 'CLOSE' caption will appear right away 
        if (j == 0) { 
         captionMenuOn = false; 
         length = lengthClose; //now we're working with 'CLOSE' caption 
         interval = 150/length; 
         j = 0; 
         for (var i = 0; i <= length - 1; i++) { 
          $('p.caption_holder').delay(interval).queue(function (next) { 
           $(this).append('<span class="caption_parcial_' + j + '">' + lettersClose[j] + '</span>'); 
           j++; 
           if (j == length-1) { 
            captionCloseOn = true; 
           } 
           next(); 
          }); 
         } 
        } 
        next(); 
       }); 
      } 



      /* 
     $("#navigation_holder").animate(
      { 
       'left' : '0%' 
      }, 1250, 'easeOutExpo');*/ 

     $("#navigation_holder").css("left", "0%"); //and the menu shows 

     menuOn = true; //the menu is opened 

     } 
     else { //if the menu is opened 

     $("#menu_icon").attr("src", base_url + "public/web/images/menu.png").removeClass("menu_close"); //changing icon 
      //we need to hide the 'CLOSE' caption 
      length = lengthClose; 
      interval = 150/length; 
      j = length; 
      for (var i = 0; i <= length - 1; i++) { 
       $('.caption_holder').delay(interval/2).queue(function (next) { 
        j--; 
        $('.caption_parcial_' + j).remove(); 
        if (j == 0) { 
         captionCloseOn = false; 
        } 
        next(); 
       }); 
      } 

     /* 
     $("#navigation_holder").animate(
      { 
       'left' : '-50%' 
      }, 1250, 'easeOutExpo');*/ 

      //and hide the menu 
     if($(".mobile_nav").is(":visible")) { 
      $("#navigation_holder").css("left", "-100%"); 
     } else { 
      $("#navigation_holder").css("left", "-50%"); 
     } 



     menuOn = false; //now the menu is closed 

     } 


    } 


    //NOT IMPORTANT 
    $(window).resize(function() { 

     if(!menuOn) { 

      if($(".mobile_nav").is(":visible")) { 
       $("#navigation_holder").css("left", "-100%"); 
      } else { 
       $("#navigation_holder").css("left", "-50%"); 
      } 

     } 

    }); 


</script> 

CSS(如果你想在你的本地主机正常运行):

@import url(https://fonts.googleapis.com/css?family=Biryani:400,700,300,600); 


* { 
    font-family: 'Biryani', sans-serif !important; 
    margin: 0px; 
    padding: 0px; 
} 

body, html { 
    margin:0; 
    padding:0; 
    height:100%; 
} 

body { 
    overflow-x:hidden; 
} 


/*---------------------------NAVIGATION------------------------*/ 


#navigation_bar { 
    width: 55px; 
    height: 100%; 
    background-color: #000; 
    display: block; 
    position: fixed; 
    margin: 0; 
    text-align: center; 
    cursor: pointer; 
    z-index: 1500; 
} 

#menu_icon { 
    margin: auto; 
    max-width: 22px; 
    text-align: center; 
    position: relative; 
    top: 49%; 
} 

.zatvorit { 
    display: none; 
    font-size: 16px; 
    color: white; 
    font-family: "BauerBodoniDOT-Regular", serif !important; 
    -ms-transform: rotate(-90deg); 
    -webkit-transform: rotate(-90deg); 
    transform: rotate(-90deg); 
    position: absolute; 
top: 50%; 
left: -11px; 
margin-top: -74px; 
} 

.menu { 
    display: none; 
    font-size: 16px; 
    color: white; 
    font-family: "BauerBodoniDOT-Regular", serif !important; 
    -ms-transform: rotate(-90deg); 
    -webkit-transform: rotate(-90deg); 
    transform: rotate(-90deg); 
    position: absolute; 
    top: 42%; 
    left: 6px; 
    margin-top: 5px; 
} 

.menu_close { 
    max-width: 18px !important; 
} 

.caption_holder { 
    font-size: 16px; 
    color: white; 
    font-family: "BauerBodoniDOT-Regular", serif !important; 
    -ms-transform: rotate(-90deg); 
    -webkit-transform: rotate(-90deg); 
    transform: rotate(-90deg); 
    position: absolute; 
    top: 50%; 
    left: 3px; 
    margin-top: -59px; 
    width: 50px; 
    text-align: left; 
} 

.right_buttons { 
    position: absolute; 
    top: 48px; 
    right: 55px; 
} 

.caption_holder span { 
    font-family: "BauerBodoniDOT-Regular", serif !important; 
    letter-spacing: 3px; 
} 

#navigation_holder { 
    width: 50%; 
    max-width: 50%; 
    height: 100%; 
    background-color: #000; 
    display: block; 
    position: fixed; 
    padding: 50px; 
    margin: 0; 
    text-align: right; 
    z-index: 1000; 
    left: -50%; 
     transition:all ease 0.5s; 
    -webkit-transition:all ease 0.5s; 
    -moz-transition:all ease 0.5s; 
    -o-transition:all ease 0.5s; 
} 

感谢您的帮助和建议! :)

+3

TL; DR - 阅读[问]! – Amit

+0

使用由第一个事件设置的标志,并检查每个事件。 – dandavis

+1

值得阅读[*我如何问一个好问题?](/帮助/如何问)和* [mcve] * –

回答

1

使用SEMAPHOR模式,与名为locked变量,如果事件的动作停止这是false(完):

var locked_mouseenter=false; //initialize "UNLOCK" 
$(document).on("mouseenter", "#navigation_bar", function(){ 
    if(!locked_mouseenter){ 
     locked_mouseenter = true; //lock 

     // you code here of event's action 

     // code stop here, so the next instruction is : 
     locked_mouseenter = false; //unlock 
    } 
}); 
相关问题