jQuery .append is occurring multiple times. How do I prevent this? - javascript

I looked at some similar posts, but haven't found the solution I'm looking for. I am attempting to append div#dropdownmenu only once. However, it continues to occur as I hover over the div. Any help would be greatly appreciated.
$(function () {
if ($('div#dropmenu').length == 0) {
$('#site_nav > ul > a').live('mouseenter', function () {
$(this).append("<div></div>");
$('#site_nav > ul > li a div').attr('id', 'dropmenu');
$('div#dropmenu').html("<ul></ul>");
$('div#dropmenu ul').html("<li><a>Mission</a></li><li><a>Story</a></li><li><a>Quality</a></li><li><a>Pledge</a></li><li><a>Bio</a></li>");
});
} else {
$('#site_nav > ul > li > a').append("");
}
});

You can remove the function handler after it's been executed. I gave the anonymous function a name for easier reference.
$(function () {
if ($('div#dropmenu').length == 0) {
$('#site_nav > ul > a').live('mouseenter', function f() {
$(this).append("<div></div>");
$('#site_nav > ul > li a div').attr('id', 'dropmenu');
$('div#dropmenu').html("<ul></ul>");
$('div#dropmenu ul').html("<li><a>Mission</a></li><li><a>Story</a></li><li><a>Quality</a></li><li><a>Pledge</a></li><li><a>Bio</a></li>");
$(this).die('mouseenter', f);
});
} else {
$('#site_nav > ul > li > a').append("");
}
});
http://api.jquery.com/die/

You are checking $('div#dropmenu').length == 0) before you attach the event listener, after that, the listener is attached and will always execute. You can move the check inside the event listener.
$(function () {
$('#site_nav > ul > a').live('mouseenter', function () {
if ($('div#dropmenu').length == 0) {
$(this).append("<div></div>");
$('#site_nav > ul > li a div').attr('id', 'dropmenu');
$('div#dropmenu').html("<ul></ul>");
$('div#dropmenu ul').html("<li><a>Mission</a></li><li><a>Story</a></li><li><a>Quality</a></li><li><a>Pledge</a></li><li><a>Bio</a></li>");
} else {
$('#site_nav > ul > li > a').append("");
}
});
});

You can also use the .one() jQuery method to ensure that the event handler is executed only once.
$(function () {
if ($('div#dropmenu').length == 0) {
$('#site_nav > ul > a').one('mouseenter', function () {
$(this).append("<div></div>");
$('#site_nav > ul > li a div').attr('id', 'dropmenu');
$('div#dropmenu').html("<ul></ul>");
$('div#dropmenu ul').html("<li><a>Mission</a></li><li><a>Story</a></li><li><a>Quality</a></li><li><a>Pledge</a></li><li><a>Bio</a></li>");
});
} else {
$('#site_nav > ul > li > a').append("");
}
});
http://api.jquery.com/one/

Related

Wordpress Menu - Show Sub-menu on Click

I would like to hide the submenus and show them after their parents get clicked. At the moment I'm using a snippet I found on here, which unfortunately doesn't hide the submenu when loading. So I'm basically looking for an inverted solution of this or something completely else :)
The site: https://webnew.dpg-gruppe.eu
The snippet:
$(document).ready(function () {
$('#navmenu > ul > li:has(ul)').addClass("has-sub");
$('#navmenu > ul > li > a').click(function () {
var checkElement = $(this).next();
$('#navmenu li').removeClass('active');
$(this).closest('li').addClass('active');
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
$(this).closest('li').removeClass('active');
checkElement.slideUp('normal');
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
$('#navmenu ul ul:visible').slideUp('normal');
checkElement.slideDown('normal');
}
if (checkElement.is('ul')) {
return false;
} else {
return true;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can try to add this line
$('#navmenu ul.sub-menu').hide();
after $(document).ready(function () {

Simple scroll javascript - Can I add a class to multiple other classes cleanly?

I'm just wondering if there is a way to condense this script? My JS is pretty rough, but it seems like I should be able to just insert an or operator to add the class of shrink to any class that passes, I can't seem to get the syntax correct though. It just seems like a lot of redundancy.
$(window).scroll(function() {
if ($(document).scrollTop() > 50) {
$('nav').addClass('shrink');
} else {
$('nav').removeClass('shrink');
}
if ($(document).scrollTop() > 50) {
$('.nav a').addClass('shrink');
} else {
$('.nav a').removeClass('shrink');
}
if ($(document).scrollTop() > 50) {
$('.navbar-brand').addClass('shrink');
} else {
$('.navbar-brand').removeClass('shrink');
}
});
Or is there a way to add a class to all children of a given element?
$(window).on('scroll', function() {
$('nav, nav a, .navbar-brand').toggleClass('shrink', $(this).scrollTop() > 50);
});
Using the multiple selector to target all matching elements, and toggleClass to toggle the class based on the second argument, being the "state".
this references the window inside the event handler, and $(window).scrollTop() should be the same as $(document).scrollTop() 99.99% of the time.
Probably something like this?
$(window).scroll(function() {
if ($(document).scrollTop() > 50) {
$('nav, .nav a, .navbar-brand').addClass('shrink');
}
else {
$('nav, .nav a, .navbar-brand').removeClass('shrink');
}
});
You could try:
$(window).scroll(function() {
if ($(document).scrollTop() > 50) {
$('nav, .nav a, .navbar-brand').addClass('shrink');
} else {
$('nav, .nav a, .navbar-brand').removeClass('shrink');
}
});
Have a look at:
https://api.jquery.com/multiple-selector/

.slideup() removing entire ul instead of just the nested li

Having a few issues with this badboy:
Basically need it so that when one of the hidden lists collapses the markup is checked to see if there are any other 'active' lists already open, and to close those before a new one is opened. It looks messy if more than one is open at the same time.
Link:
http://www.matchboxlondon.com/ten/menu3/index.html
Try:
1. Click Menu
2. Click Services
3. Click Pilates to expand
4. Click Fitness to expand
Problem: Heading is also removed when .slideup() is used.
What my code is doing at the moment is checking to see if anything is opened with a globally defined variable called 'somethingOpen' - this is set to null on page load. This is all well and good BUT I feel it may have something to do with the complete display:none of the collapsable lists:
Because it's listy and nesty, I'll only include the js in here and not the markup:
somethingOpen = null; // to set after close and open
$('#cssmenu > ul > li > a').click(function () {
if (somethingOpen === true) { // first check
$("#cssmenu > ul > li").each(function () {
$("#cssmenu > ul > li.active").removeClass('active').slideUp(); // <-- problem here
somethingOpen = false; // closing so set to false
return false; // exit function
});
} // End somethingOpen if
// Open
var checkElement = $(this).next(); // more checks
$(this).closest('li').addClass('active'); // add active class
somethingOpen = true; // redefine if anything is open
// Close
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
$(this).closest('li').removeClass('active');
checkElement.slideUp('normal');
somethingOpen = false;
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
$('#cssmenu ul ul:visible').slideUp('normal');
checkElement.slideDown('normal');
}
// Returns
if (checkElement.is('ul')) {
return false;
} else {
return true;
}
}); // End click
Try This:
//$("#cssmenu > ul > li.active").removeClass('active').slideUp(); // -- problem here
$("#cssmenu > ul > li.active").animate({height: "toggle", opacity: "toggle"}, 'fast');
For anyone that was interested, it needed a little tweaking, using children() and an after (>) to properly select the right element.
somethingOpen = null; // to set after close and open
$('#cssmenu > ul > li > a').click(function () {
if (somethingOpen === true) { // first check
$("#cssmenu > ul > li").each(function () {
$("#cssmenu").children('.active').removeClass('active');
$("#cssmenu > ul > li > ul").slideUp('normal');
somethingOpen = false; // closing so set to false
return false; // exit function
}); // end each
}
}); // End somethingOpen if

Change a icon, not all

I managed to do everything right, open each element. As you can see in the example below all the icons change together, but as it does to replace only what was clicked?
$('.list-prod > li > span').on('click', function() {
$(this).next().slideToggle('slow', function() {
if($(this).is(':visible')) {
$('.list-prod > li > span').addClass('collapse');
} else {
$('.list-prod > li > span').removeClass('collapse');
}
});
});
External link demo
JSFIDDLE DEMO
$('.list-prod > li > span').on('click', function () {
$(this).toggleClass('expand collapse');
$(this).next().slideToggle('slow');
});
Here what you should write
$('.list-prod > li > span').on('click', function () {
$(this).next().slideToggle('slow', function () {
$(this).prev().toggleClass('collapse');
});
});
since this within the callback function refer to the collapsed / visible div

Close Javascript menu by clicking outside of menu

I want to close my Javascript menu by clicking outside of the menu. I am using this menu. I'm not professional, please tell me how to change my code to do that:
$("#theme_select").click( function () {
if (theme_list_open == true) {
$(".center ul li ul").fadeOut();
theme_list_open = false;
} else {
$(".center ul li ul").show();
theme_list_open = true;
}
return false;
});
$("#theme_list ul li a").click(function () {
var theme_data = $(this).attr("rel").split(",");
$("li.purchase a").attr("href", theme_data[1]);
$("li.remove_frame a").attr("href", theme_data[0]);
$("#iframe").attr("src", theme_data[0]);
$("#theme_list a#theme_select").text($(this).text());
$(".center ul li ul").hide();
theme_list_open = false;
return false;
});
If you want to close that menu when the iframe area is clicked, you have to do that in the iframe. Try putting this in your iframe's document ready function:
$("html").click( function () {
$(".center ul li ul", window.parent.document).fadeOut();
window.parent.theme_list_open = false;
});
Seems you use $("#theme_select").click( function () { for both open and close the menu. and use $("#theme_list ul li a").click(function () { to handle click on menuitem, which will close the menu after.
In fact there is simple solution to your problem. Use $("#theme_select").click for only open the menu, and $("#theme_list ul li a") for handle the link, and introduce $(window).click to close the menu.
function checkAndCloseMenu(evt) {
var dropmaker = $('#theme_select')[0];
for (var node = evt.target; node != document.body; node = node.parentNode)
if (node == dropmaker) return false; // check if click in the dropmaker
$('.center ul li ul').fadeOut();
$(window).unbind('click', checkAndCloseMenu);
}
$("#theme_select").click(function() {
$(".center ul li ul").show();
$(window).click(checkAndCloseMenu);
});
$("#theme_list ul li a").click(function() {
var theme_data = $(this).attr("rel").split(",");
$("li.purchase a").attr("href", theme_data[1]);
$("li.remove_frame a").attr("href", theme_data[0]);
$("#iframe").attr("src", theme_data[0]);
$("#theme_list a#theme_select").text($(this).text());
return false;
});
PS: may be you should give the menu and menuitems some class names, your selector is painful to read.

Categories