javascript - How to make sure event won't trigger again if it hasn't stopped yet? -
so, here's thing. there's menu bar on side of website. when click on it, menu holder rolls in side (the menu opened), when click on bar again, menu holder rolls , hides menu. pretty simple far. on tat bar, there icon text 'menu'. when open menu, icon changes , text changes 'close'. when close menu, returns normal. still not big deal.
this how looks like:
opened menu (the 'zatvoriŤ' caption means 'close' don't worry that)
now let's fancy. need effect, text transition make cool , smooth. when menu closed, there's no caption. there's menu icon. text show when user hovers on bar. user hovers on bar, 'menu' caption appear letter letter. means, first letter appear 'm', second 'e'... 'n'... 'u'. whole caption appear in few hundred milliseconds, maybe half second. when user hovers away, caption disappear letter latter. 'men' ... 'me' ... 'm'... ' '. got point. 'close' caption works same way. when user clicks on bar (of course needs hover on bar first, there's 'menu' caption already) 'menu' caption disappears letter letter , 'close' caption appear letter letter. when user closes menu, 'close' caption disappears same way. pretty nice thing.
now root of whole problem. works user acts normally. user keep hovering on , away bar fast, it'll trigger event while event running (my best guess problem is). same goes if keeps clicking on bar - 'close' caption mess instead of 'menu' caption. then, instead of letters of captions couple of 'undefined' appear. caption 'meundefinedundefinedundefined....' or 'mmmmenundefinedundefined...' or similar. thought @ first was, off-by-one error, because got captions saved in arrays of letters , it's showing 'undefined', right? patched make sure no 'undefined' appear - if user tries brake it, events quit triggering. can hover on bar , nothing happen. it'll normal when opens menu (and closes it). that's not how should work , need fix it.
so need (i think) make sure event wont trigger if 1 in progress (somehow). tried javascript function delay() or settimeout()... tried make functions out of effects - unsuccessfully. spent time on , i'm out of ideas , skills needed make work properly. able check code me , give suggestion or maybe patch it?
here's code:
html:
<div id="navigation_bar"> <!-- navigation bar icon , caption holder 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 magic happen --></p> </div> <div id="navigation_holder"> <!-- not important part, menu holder , 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 (magic stuff)
<script type="text/javascript"> menuon = false; //is true when menu opened //this makes array of letters 'menu' caption captionmenu = $( "p.menu" ).text(); var lettersmenu = []; lengthmenu = captionmenu.length; (var = 0; <= lengthmenu - 1; i++) { lettersmenu[i] = captionmenu.charat(i); }; //this makes array of letters 'close' (acutally 'zatvoriŤ') caption captionclose = $( "p.zatvorit" ).text(); var lettersclose = []; lengthclose = captionclose.length; (var = 0; <= lengthclose - 1; i++) { lettersclose[i] = captionclose.charat(i); }; //some variables able check what's going on length = 0; //length of caption we're working captionmenuon = false; //true when 'menu' caption visible captioncloseon = false; //true when 'zatboriŤ' caption visible j = 0; // how many letters have appeared k = lengthmenu-1; //example of "how not name variables" should solve off-by-one error //now 'menu' caption appear letter letter $(document).on("mouseenter", "#navigation_bar", function(){ if(!menuon && j==0) { //of course won't possible if menu opened , there letters left j = 0; length = lengthmenu; //we're working 'menu' interval = 150 / length; //counts interval depending on caption lenght (var = 0; <= length - 1; i++) { //looping 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 letters have appeared captionmenuon = true; //now see me } next(); }); } k = lengthmenu - 1; //we should have 4 letters there somewhere } }); //now 'menu' caption disappear letter letter inverse event above $(document).on("mouseleave", "#navigation_bar", function(){ if(!menuon && k==lengthmenu-1) { //so menu needs closed , 'menu' caption should visible length = lengthmenu; //we're working 'menu' again interval = 150 / length; k = length; (var = 0; <= length - 1; i++) { $('.caption_holder').delay(interval / 2).queue(function (next) { k--; //a letter has disappeared $('.caption_parcial_' + k).remove(); if (k == 0) { //if have no letters left captionmenuon = false; //now don't (see me) } next(); }); } j = 0; //we have 0 letters visible } }); //--------------------------------------this part opens , closes menu , resets 'j' variable in case messed 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 opens or closes menu function smallmenu() { if(!menuon) { //if menu 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 code before length = lengthmenu; interval = 150 / length; j = length; (var = 0; <= length - 1; i++) { $('.caption_holder').delay(interval / 2).queue(function (next) { j--; $('.caption_parcial_' + j).remove(); //and 'close' caption appear right away if (j == 0) { captionmenuon = false; length = lengthclose; //now we're working 'close' caption interval = 150 / length; j = 0; (var = 0; <= 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 menu shows menuon = true; //the menu opened } else { //if menu opened $("#menu_icon").attr("src", base_url + "public/web/images/menu.png").removeclass("menu_close"); //changing icon //we need hide 'close' caption length = lengthclose; interval = 150 / length; j = length; (var = 0; <= 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 menu if($(".mobile_nav").is(":visible")) { $("#navigation_holder").css("left", "-100%"); } else { $("#navigation_holder").css("left", "-50%"); } menuon = false; //now menu 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 (in case want run on localhost properly):
@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; }
thanks , suggestions! :)
use semaphor pattern, variable named locked
false
if event's action stopped (finished):
var locked_mouseenter=false; //initialize "unlock" $(document).on("mouseenter", "#navigation_bar", function(){ if( !locked_mouseenter ){ locked_mouseenter = true; //lock // code here of event's action // code stop here, next instruction : locked_mouseenter = false; //unlock } });
Comments
Post a Comment