JavaScript Event Firing Twice - javascript

I have a short piece of JS which is supposed to show and hide the secondary navigation of a site. If a user clicks Menu Item A it shall show, they click it again and it hides and if Menu Item A is open and they click Menu Item B then it closes A and opens B in its place.
The first part of this works, I can click a single menu item and it will open and close, if however I click a different menu item whilst one is open then it shall close (as expected), open (as expected) and then close again. It's as if the event is being fired twice.
Here is my JS snippet.
$(document).ready(function() {
$('.NavButton').click(function(event) {
handleSecondaryNavigation(event.target.alt);
});
});
function handleSecondaryNavigation(MenuItem) {
if ($('#ul' + MenuItem).is(':visible')) {
// Menu item visible, hide it
$('#SecondaryNavigation').animate({
width: 'toggle'
}, 350, function() {
$('#ul' + MenuItem).hide();
});
} else if ($('#SecondaryNavigation').is(':visible')) {
// Clicked different menu item, hide then show (swap)
$('#SecondaryNavigation').animate({
width: 'toggle'
}, 350, function() {
$('#SecondaryNavigation ul').hide(function() {
handleSecondaryNavigation(MenuItem);
});
});
} else {
// Menu not visible, show it
$('#ul' + MenuItem).show(function() {
$('#SecondaryNavigation').animate({
width: 'toggle'
}, 350);
});
}
}
#MainNavigation {
background: #F1F1F1;
position: fixed;
top: 0px;
left: 0px;
bottom: 0px;
}
#MainNavigation .NavButton {
width: 20px;
display: block;
padding: 15px 20px;
cursor: pointer;
}
#SecondaryNavigation {
position: fixed;
top: 0px;
left: 60px;
bottom: 0px;
background: #DADADA;
width: 200px;
display: none;
box-shadow: 2px 0px 5px #686868;
}
#SecondaryNavigation ul {
display: none;
margin: 0px 10px;
}
#SecondaryNavigation ul li {
display: block;
padding: 10px;
border-bottom: 1px solid #CBCBCB;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav id="MainNavigation">
<img class="NavButton" alt="A" />
<img class="NavButton" alt="B" />
</nav>
<nav id="SecondaryNavigation">
<ul id="ulA">
<li>Lorem</li>
<li>Ipsum</li>
</ul>
<ul id="ulB">
<li>Lorem</li>
<li>Ipsum</li>
</ul>
</nav>
Swapping out the handleSecondaryNavigation(MenuItem) bit and hard coding the action installed of recursively also does not work.
Any ideas? I'm sure it's probably something silly...
Thanks

I have solved your issue and please find the working fiddle
This event listener is triggered twice each time for each ul element
$('#SecondaryNavigation ul').hide(function() {
console.log("hide trug");
handleSecondaryNavigation(MenuItem);
});
change this to
$('#SecondaryNavigation ul').hide(function() {
});
handleSecondaryNavigation(MenuItem);
I have updated the fiddle as well
Hope this helps

Related

jQuery: getPos for my drop-down menu

I'm trying to make a jQuery drop-down menu, but usable anywhere on my page. I would like it to be dynamic (as each element that contains the trigger class and that it is positioned perfectly). To do this, I need to have a jQuery code that replace my drop-down with the element clicked like this example (at the center of the clicked text): http://prntscr.com/7hw91t on this site: https://www.invisionpower.com/
My HTML code:
<ul>
<li class="more">
More
</li>
<li class="more">
Second Menu
</li>
</ul>
This code is referred to the elements that, when clicked, will open the drop-down: http://prntscr.com/7hwa7m The "drop-down-menu-trigger" is the class that will trigger the opening of the drop-down menu.
This is the drop-down-menu code that is placed at the bottom of my index.php:
<div id="more-drop-down-menu" class="drop-down-menu">
<ul>
<li>
<a class="modal-window-trigger" name="modal-window-faq" id="faq" href="faq.php">Frequently Asked Questions</a>
</li>
<li>
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
</ul>
</div>
</div>
And my JS code:
(function($)
{
$(".drop-down-menu-trigger").click(function(e)
{
e.preventDefault();
$(".drop-down-menu").css({"visibility": "visible"});
});
})(jQuery);
my CSS:
.drop-down-menu
{
background-color: #FFFFFF;
position: absolute;
top: 188px;
right: 0;
box-shadow: 0 15px 110px rgba(0, 0, 0, 0.2);
border-radius: 3px;
visibility: hidden;
}
.drop-down-menu:before
{
right: 10px;
bottom: 100%;
margin-left: -15px;
border: 15px solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-bottom-color: #FFFFFF;
}
.drop-down-menu a
{
display: block;
color: #000000;
padding: 10px;
}
.drop-down-menu a:hover
{
background-color: #F5F5F5;
}
I would like to have help for this, so thanks to those who will try to help me.
Possibly something like this but not tested, you should put or render what you have in jsfiddler so we can see what your after.
(function($)
{
$(".drop-down-menu-trigger").click(function(e)
{
e.preventDefault();
//get location offset css
var leftPos = $(this).offset().left,
topPos = $(this).offset().top;
$(".drop-down-menu").css({
"visibility": "visible",
"left": leftPos,
"top": topPos
});
});
})(jQuery);
Updated Answer :
There was several changes which included CSS and some offset in jquery for getting the carret to the middle off the menu, here is the updated version on fiddler
http://jsfiddle.net/screepts/rh2w16of/2/
here is the screenshot of updated code working with your menu

Keep Div visible after mouse moves from trigger (jQuery)

I am currently building a layout where I have several 'triggers' inside a <nav><ul><li><a> element - each display a <div> which effectively sits 'behind' (z-index).
I need the divs (#showme and #showmetoo) to stay visible even if the user moves the mouse from the respective trigger (.thetrigger, .thenextrigger) - as the divs will contain content/links.
Additionally, when the user moves from one trigger to the next the displayed div should change.
<header>
<nav>
<ul>
<li><a class="thetrigger">Show Me That Thing</a></li>
<li><a class="thenexttrigger">Show Me That Thing</a></li>
</ul>
</nav>
<div id="showme">Yay, this thing</div>
<div id="showmetoo">and this thing</div>
</header>
CSS
header {
width: 100%;
height: 300px;
position: relative;
background: red;
z-index: 1;
}
nav {
position: absolute;
top: 10px;
left: 30px;
z-index: 3;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
}
nav ul li {
float: left;
padding: 30px;
}
.thetrigger, .thenexttrigger {
color: white;
}
#showme {
display: none;
background: blue;
color: white;
position: absolute;
top: 0;
left: 0;
height: 300px;
width: 100%;
z-index: 2;
}
#showmetoo {
display: none;
background: green;
color: white;
position: absolute;
top: 0;
left: 0;
height: 300px;
width: 100%;
z-index: 2;
}
jQuery
$(document).ready(function() {
$('.thetrigger').hover(function() {
$('#showme').fadeIn();
}, function() {
$('#showme').fadeOut();
});
$('.thenexttrigger').hover(function() {
$('#showmetoo').fadeIn();
}, function() {
$('#showmetoo').fadeOut();
});
});
http://jsfiddle.net/richardblyth/24bcs/
Demo
It sounds like you want the div to remain until the next trigger is hovered over.
You can use a lot less jQuery if you use a class for the triggers, and find their respective divs using data. With this you can add as many triggers + corresponding divs as you like without having to write more jQuery.
HTML
<header>
<nav>
<ul>
<li><a class="trigger" data-show="pane1">Show Me That Thing</a></li>
<li><a class="trigger" data-show="pane2">Show Me That Thing</a></li>
</ul>
</nav>
<div class="pane" data-show="pane1" id="showme">Yay, this thing</div>
<div class="pane" data-show="pane2" id="showmetoo">and this thing</div>
</header>
jQuery
$(function(){
$('.trigger').on('mouseover', function(){
// show the desired pane and hide its siblings
$('.pane[data-show="' + $(this).data('show') + '"]').fadeIn().siblings('.pane').fadeOut();
});
});
I think what you actually want, if I understand you question, is to hide the other #showme element when you hover into the trigger element associated with the #showmetoo element.
Like this:
$(document).ready(function() {
$('.thetrigger').hover(function() {
$('#showme').fadeIn();
$('#showmetoo').fadeOut();
});
$('.thenexttrigger').hover(function() {
$('#showmetoo').fadeIn();
$('#showme').fadeOut();
});
});
http://jsfiddle.net/4N26S/

jquery, hover over parent, slideToggle child, not work quite well

So when user hover over div(#cart-quick-view) child(.cart_details_box) needs to slideDown, and to slideUp when mouse gets out of parent(#cart-quick-view). Problem with this code is that sometimes I get 2-3 extra bouncing when mouse is in area of child(.cart_details_box).
Fiddle: http://jsfiddle.net/Y9QLC/
HTML:
<div id="cart-quick-view">
<ul class="nav navbar-nav navbar-right">
<li>...</li>
</ul>
<div class="cart_details_box"></div>
</div>
CSS:
#cart-quick-view {
float: right;
position: relative;
border: 1px solid black;
}
.cart_details_box {
display: none;
position: absolute;
height: 200px;
width: 205px;
background-color: #F8F8F8;
border-radius: 5px;
border:1px solid #E7E7E7;
padding: 0px 3px 3px 3px;
top: 55px;
right: 0;
}
JS:
$(function() {
$('#cart-quick-view').hover(function() {
$('.cart_details_box').slideToggle('slow');
});
});
It is because of the queuing of animations when the mouse enter and leave the parent element quickly. You can use .stop(true, true) to clear the existing animations to fix it
$(function () {
$('#cart-quick-view').hover(function () {
$('.cart_details_box').stop(true, true).slideToggle('slow');
});
});
Demo: Fiddle
The stop() method is an option, but there is also a jQuery plugin available called hoverFlow that can fix the problem with a better looking transition.

changing element id with jQuery not work for my function

want to assign 2 functions to a button when using the click event of jQuery, it will work like this: I have a div that is hidden behind another div when click the button that slides up div with jQuery to animate ... this #show ID shows the div, and the ID #hide hides the div, how can I assign 2 different IDs for the same button? I have done this using the ID attribute and attr ... is changed to #hide, but the function linked to this ID is not performedry
http://jsfiddle.net/dca2b/1/
HTML:
<div class="content"></div>
<div class="footer"></div>
<div class="hiddendiv">
show
</div>
CSS:
.content {
height: 400px;
}
.footer {
display: inline-table;
background: #ff8;
width: 100%;
height: 80px;
position: relative;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
}
.hiddendiv {
width: 500px;
height: 300px;
background: #252525;
position: relative;
z-index: 1;
top: -120px;
margin: 0 auto;
}
.hiddendiv a {
color: #000;
font-size: 15px;
font-family: sans-serif;
text-decoration: none;
padding-top:5px;
padding-bottom:5px;
padding-left: 20px;
padding-right: 20px;
background: #eee;
border-radius: 10px;
box-shadow: inset 0px 1px 20px 0px #333;
}
.hiddendiv a:hover {
color: #f0f;
}
JQUERY:
$("#show").click(function () {
$(".hiddendiv").animate({
top: "-=250"
}, "slow");
$("#show").attr("id", "hide");
});
$("#hide").click(function () {
$(".hiddendiv").animate({
top: "+=250"
}, "slow");
$("#hide").attr("id", "show");
});
So there are a couple of parts to my answer, bear with me:
(1) The reason it isn't working right now is because when you run $("#hide").click(function() { ..., there aren't yet any elements on the page with the hide id, so the function doesn't get set to run anywhere. One method you can use to get around this is to do the following:
$(".hiddendiv").on('click', '#hide', function() {
...
});
By attaching the click event handler instead to the parent div, whenever the parent sees that the event occurred in a child div with the id of hide, it will run the function on that child div.
(2) You shouldn't be using IDs here. If at some point you have more than one button that needs this functionality on you're page, you'll be in trouble, since an ID should only be used once per page. A class would work much better in this scenario. Then you can do something like:
$(".hiddendiv").on('click','.show', function () {
$(".hiddendiv").animate({
top: "-=250"
}, "slow");
$(".show").addClass('hide').removeClass('show');
});
(3) Finally, it works! But, if we add another hiddendiv to the page, we find that when we click one, it updates all of them. We can fix that by using this. When the function is triggered, the this keyword will refer to the element that you clicked (either with the show or hide class. We can take advantage of that and do the following:
$(".hiddendiv").on('click','.show', function () {
$(this).parent().animate({
top: "-=250"
}, "slow");
$(this).addClass('hide').removeClass('show');
});
$(".hiddendiv").on('click','.hide', function () {
$(this).parent().animate({
top: "+=250"
}, "slow");
$(this).addClass('show').removeClass('hide');
});

Change 'Click' function to mouseover/mouseout

I am using the following sliding div script:
http://www.webdesignerwall.com/demo/jquery/simple-slide-panel.html
Currently, the slidetoggle function is activated when the .btn-slide button is clicked. This slides up the "panel" div.
Upon clicking the .btn-slide button a second time, the panel div is closed.
I am a complete newb at js, so any assistance would be appreciated. Here's what I am trying to do:
1) When the mouse moves over (as opposed to clicking) the .btn-slide class, i would like the panel to slide out.
2) Then, when the mouse moves out of either the .btn-slide or #panel, i would like the panel to close. (but if the mouse is over either one, the panel should stay open).
I was able to get it working to where the slidetoggle function would close either one, or the other, but not both.
Thank you in advance for the help.
Sincerely,
Mac
Here is the JS:
<script type="text/javascript">
jQuery(function($){
$(document).ready(function(){
$('.btn-slide').click(function() {
$("#panel").slideToggle("slow");
$(this).toggleClass("active"); return false;
});
});
});
</script>
here is the HTML currently being used:
<div id="prod_nav_tab">
<div id="panel">
This is where stuff goes!
</div>
<p class="slide"><a class="btn-slide">Table of Contents</a></p>
</div>
I have played with the CSS to fit my particular web site and is as follows (the original js, html, css can be obtained from the link above).
div#prod_nav_tab {
width: 200px;
height: 31px;
overflow: hidden;
background-color:#F00;
float: left;
margin: 0px 0px 0px 75px;
}
a:focus {
outline: none;
}
#panel {
background-color:#F00;
width: 200px;
height: 200px;
display: none;
position: absolute;
bottom: 0px;
}
.slide {
margin: 0;
padding: 0;
/* border-top: solid 4px #422410; **Adds a line at top of slide button to distibuish it */
background: url(images/btn-slide.gif) no-repeat center top;
}
.btn-slide {
background: #d8d8d8;
text-align: center;
width: 200px;
height: 31px;
padding: 0px 0px 0 0;
margin: 0 0 0 0;
display: block;
font: bold 12pt Arial, Helvetica, sans-serif;
color: #666;
text-decoration: none;
position: relative;
cursor: pointer;
/* background: url(images/white-arrow.gif) no-repeat right -50px; ** Controls Arrow up/down */
}
.active {
background-position: right 12px;
}
When you move away from the .btn-slide to the #panel it hides it now because it triggers the mouseleave event of the .btn-slide.
To prevent this you should do something like:
HTML:
<div id="trigger">
Slide down
<div id="panel">
Content of your panel
</div>
</div>
JQuery:
jQuery(function($) {
$(document).ready(function() {
$("#trigger").mouseenter(function() {
$("#panel").slideDown("slow");
$(this).addClass("active");
}).mouseleave(function() {
$("#panel").slideUp("slow");
$(this).removeClass("active");
});
});
});
Make sure in your CSS you then set the panel to be hidden from start...
div#panel {
display: none;
}

Categories

Resources