I've created a jQuery dropdown menu that shows div dropdowns on hover.
It's for a website's navigation menu, but the problem is that some menu items don't need a dropdown and I can't hide the menu for these items.
Here's the JSFiddle. What I need is for the menu item titled "No Hover" to not show the dropdown div.
This is the JavaScript that I'm using:
$(function () {
var $oe_menu = $('#oe_menu');
var $oe_menu_items = $oe_menu.children('li');
var $oe_overlay = $('#oe_overlay');
$oe_menu_items.bind('mouseenter', function () {
var $this = $(this);
$this.addClass('slided selected');
$this.children('.hover-div').css('z-index', '9999').stop(true, true).slideDown(200, function () {
$oe_menu_items.not('.slided').children('.hover-div').hide();
$this.removeClass('slided');
});
}).bind('mouseleave', function () {
var $this = $(this);
$this.removeClass('selected').children('.hover-div').css('z-index', '1');
});
$oe_menu.bind('mouseenter', function () {
var $this = $(this);
$oe_overlay.stop(true, true).fadeTo(200, 0.6);
$this.addClass('hovered');
}).bind('mouseleave', function () {
var $this = $(this);
$this.removeClass('hovered');
$oe_overlay.stop(true, true).fadeTo(200, 0);
$oe_menu_items.children('.hover-div').hide();
})
});
And the HTML structure:
<div class="oe_wrapper">
<div id="oe_overlay" class="oe_overlay"></div>
<ul id="oe_menu" class="oe_menu">
<li>Home
<div class="hover-div">Content 1</div>
</li>
<li>Projects
<div class="hover-div">Content 2</div>
</li>
<li>No Hover
<div class="hover-div">This should not appear and no other menu divs or the dark overlay should be shown.</div>
</li>
<li>Events
<div class="hover-div">Content 4</div>
</li>
<li>Stores
<div class="hover-div">Content 5</div>
</li>
</ul>
Thanks for your help! Once again, the JSFiddle is here.
use a specific id for that item and check if it is hovered, do nothing!
if($(this).attr('id', 'TheID'))
return false;
How about add one more class for the item you don't want to show and update a few script?
DEMO http://jsfiddle.net/L6BEE/12/
CSS
<div class="hover-div not-shown">
This should not appear and no other menu divs or the dark overlay should be shown.
</div>
JQUERY
// updated code starts
if($this.children('.hover-div').hasClass('not-shown')){
$oe_menu_items.not('.slided').children('.hover-div').hide();
$this.removeClass('slided');
}
else{
$this.children('.hover-div').css('z-index', '9999').stop(true, true).slideDown(200, function () {
$oe_menu_items.not('.slided').children('.hover-div').hide();
$this.removeClass('slided');
});
}
// updated code ends
If you add a class to the li tags and change the jquery selector, it should work :
<li class="sub-menu">
var $oe_menu_items = $oe_menu.children('li.sub-menu');
http://jsfiddle.net/L6BEE/8/
Related
I've created a simple ajax loading content which works but I'm trying to change the class 'active' (it adds a border-bottom to let the user know which menu they are looking at) depending on which target has been clicked. I've attempted using jquery but to no avail. If someone could help or point me in the right direction it would be greatly appreciated.
This is my attempt:
$(document).on('click', '.menu-tabs li a', function () {
$('.active').removeClass('active');
$(this).parent().addClass('active');
});
HTML:
<div class="menu-tabs" id="menu-tabs">
<ul>
<li class="active">FOOD</li>
<li class="">DESSERTS</li>
<li class="">DRINKS</li>
</ul>
</div>
<article class="menu-container" id="menu-container">
<?php include('food.php'); ?>
</article>
AJAX:
var trigger = $('#menu-tabs ul li a'),
container = `$('#menu-container');
trigger.on('click', function () {
var $this = $(this),
target = $this.data('target');
container.load(target + '.php');
return false;
});`
Please check the below code section. Taken mostly from your own code. Just added the CSS for checking and it seems to work for me. At-least the navigation is changing "active" class on click.
$(document).on('click', '.menu-tabs li a', function() {
$('.active').removeClass('active');
$(this).parent().addClass('active');
});
.active{
background:green;
}
.active a{
color:#fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="menu-tabs" id="menu-tabs">
<ul>
<li class="active">FOOD</li>
<li class="">DESSERTS</li>
<li class="">DRINKS</li>
</ul>
</div>
<article class="menu-container" id="menu-container">
<?php include('food.php'); ?>
</article>
I have jQuery tab menu call ajax.
Menu is working perfect, but now I want when page loaded it always show the first tab to be loaded (means active).
You can see the fiddle here: https://jsfiddle.net/waspinator/rw8ujfg3/
<ul class="nav nav-tabs tabs-up " id="friends">
<li active> Contacts </li>
<li> Friends list</li>
<li>Awaiting request</li>
<div class="tab-content">
<div class="tab-pane active" id="contacts">
</div>
<div class="tab-pane" id="friends_list">
</div>
<div class="tab-pane urlbox span8" id="awaiting_request">
</div>
</div>
JS
$('[data-toggle="tabajax"]').click(function(e) {
var $this = $(this),
loadurl = $this.attr('href'),
targ = $this.attr('data-target');
$.get(loadurl, function(data) {
$(targ).html(data);
});
$this.tab('show');
return false;
});
In this case, I want Contact content loaded on page loaded. How can set this?
$('#contacts_tab').trigger('click'); if you are allowed to use the id.
This should work. Just abstract the function, and bind it to the event, but also call it on load with the first tab selected to call it on. (EDIT: Sorry I got the spacing on your function wrong before because I mis-copied it. Also, tested it and changed a few things to work out a kink or two.)
function doAjaxStuff(event, tab) {
var $this = tab || $(this)
var $this = tab || $(this),
loadurl = $this.attr('href'),
targ = $this.attr('data-target');
$.get(loadurl, function(data) {
$(targ).html(data);
});
$this.tab('show');
return false;
}
doAjaxStuff(null, $('.nav-tabs li:first-child a'))
$('[data-toggle="tabajax"]').click(doAjaxStuff);
I have the following navigation, using the jquery accordion code below. Currently each of the #top-level nav items are set to toggle open and close the <div class="slide"> to reveal the children items. I'd like to modify code so that the <div class="slide"> stays open when user lands on any of its children.
Screenshot for your reference:
Any help is much appreciated. Thanks in advance.
<ul class="nav">
<li id="top-level" class="has-drop"><a class="opener" href="/index.php/visitor-information/"><em>Visitor Information</em></a>
<div class="slide">
<ul>
<li>Visitor Information</li>
<li>About our town</li>
<li>Gallery</li>
<li>I'm Hungry</li>
</ul>
</div>
</li>
<li id="top-level" class="has-drop"><a class="opener" href="/index.php/membership/"><em>Membership</em></a>
<div class="slide">
<ul>
<li>Membership</li>
<li>Advocacy</li>
<li>Ambassadors</li>
<li>Board Of Directors</li>
</ul>
</div>
</li>
<li id="top-level" class=""><a class="opener" href="/index.php/upcoming-events/"><em>Upcoming Events</em></a></li>
<li id="top-level" class="has-drop"><a class="opener" href="/index.php/online-store/"><em>Online Store</em></a>
<div class="slide">
<ul>
<li>Online Store</li>
<li>Business Compliance Materials</li>
<li>Events</li>
<li>Membership Products</li>
</ul>
</div>
</li>
<li id="top-level" class=""><a class="opener" href="/index.php/contact-us/"><em>Contact us</em></a></li>
</ul>
jQuery Accordian plugin code:
/*
* jQuery Accordion plugin
*/
;(function($){
$.fn.slideAccordion = function(opt){
// default options
var options = $.extend({
addClassBeforeAnimation: false,
allowClickWhenExpanded: false,
activeClass:'active',
opener:'.opener',
slider:'.slide',
animSpeed: 300,
collapsible:true,
event:'click'
},opt);
return this.each(function(){
// options
var accordion = $(this);
var items = accordion.find(':has('+options.slider+')');
items.each(function(){
var item = $(this);
var opener = item.find(options.opener);
var slider = item.find(options.slider);
opener.bind(options.event, function(e){
if(!slider.is(':animated')) {
if(item.hasClass(options.activeClass)) {
if(options.allowClickWhenExpanded) {
return;
} else if(options.collapsible) {
slider.slideUp(options.animSpeed, function(){
hideSlide(slider);
item.removeClass(options.activeClass);
});
}
} else {
// show active
var levelItems = item.siblings('.'+options.activeClass);
var sliderElements = levelItems.find(options.slider);
item.addClass(options.activeClass);
showSlide(slider).hide().slideDown(options.animSpeed);
// collapse others
sliderElements.slideUp(options.animSpeed, function(){
levelItems.removeClass(options.activeClass);
hideSlide(sliderElements);
});
}
}
e.preventDefault();
});
if(item.hasClass(options.activeClass)) showSlide(slider); else hideSlide(slider);
});
});
};
// accordion slide visibility
var showSlide = function(slide) {
return slide.css({position:'', top: '', left: '', width: '' });
};
var hideSlide = function(slide) {
return slide.show().css({position:'absolute', top: -9999, left: -9999, width: slide.width() });
};
}(jQuery));
Are the children being loaded via AJAX or is the menu simply revealing content? If so, it sounds like the anchor tags inside are hooked up to the click event of your accordion.
I noticed there's an option: "allowClickWhenExpanded" which appears to prevent the slide from hiding on click:
if(item.hasClass(options.activeClass)) {
if(options.allowClickWhenExpanded) {
return;
} else if(options.collapsible) {
slider.slideUp(options.animSpeed, function(){
hideSlide(slider);
item.removeClass(options.activeClass);
});
}
}
So try enabling that to "true" at the top of the function (or when you initialize the accordion).
If you're looking to auto-expand the navigation menu based on the "current page", you could use jQuery:
if ($('.nav').length > 0)
{
var currentUrl = window.location.pathname;
var navLink = $('.nav').find("a[href='/" + currentUrl + "']"); // find current page in navigation
// find parent
var parentLink = navLink.parentsUntil('.has-drop').find('.opener');
// trigger click on accordion, effectively expanding it (assuming menu always starts collapsed)
parentLink.trigger('click');
}
I am very close but just can't see what I am missing in the jQuery script to only display the correct block of content based upon the anchor clicked and want to display initially to a visitor the first block of content from the anchors. Any help is appreciated.
I have dynamically generated anchor links with a class of .link
The content is also dynamically generated and each anchor point (A, B, C...) has it's content contained in a ul class of .test-full-list. Any help is appreciated.
Generated content:
Anchor links:
<span class="link">A</span>
<span class="link">B</span>
Content:
<div class="test-listing-container">
<ul class="test-full-list">
<ul class="test-category-list">
<a name="A"></a>
<div class="anchor-header">- A -</div>
<li id=test-list>
Some Link 1
Some Link 1
</li>
</ul>
</ul>
</div>
Script:
jQuery(document).ready(function () {
jQuery('.test-listing-container').hide();
jQuery('.link a').click(function () {
var jQuerydiv = jQuery('.test-full-list').eq(jQuery(this).index('.link a'));
jQuerydiv.show('.test-full-list'); // show the relevant div
});
});
If you're bringing in content dynamically, your .click() will not work. This is because the element you are trying to attach the click to hasn't been generated.
You can replace this:
jQuery('.link a').click(function() {
With this:
jQuery('.test-listing-container').on('click', '.link a', function() {
If that doesn't work:
jQuery(document).on('click', '.link a', function() {
Edit: Adding a fiddle to demo the code: http://jsfiddle.net/Fm6bR/1/
Assuming you can't change the markup slightly, you may do the following
A
B
<div class="test-listing-container">
<ul class="test-full-list">
<ul class="test-category-list">
<a name="A"></a>
<div class="anchor-header">- A -</div>
<li id=test-list>
Some Link 1
Some Link 1
</li>
</ul>
</ul>
</div>
jQuery(document).ready(function(){
jQuery('ul.test-category-list').hide();
jQuery('ul.test-category-list').first().show(); //show the first one by default
jQuery(document).on('click', '.link a', function (evt) {
var $a = jQuery(evt.currentTarget),
name = $a.attr('href').substr(1),
$a2 = jQuery('.test-listing-container').find('a[name="' + name + '"]'),
$ul = $a2.parents('ul.test-category-list').first();
jQuery('ul.test-category-list').hide(); // hide all
$ul.show(); // show the relevant one
});
});
Generate the content with an id based on the anchor name or some other unique identifer of the content. set data-content on each link to the id of the contents id. then use jquery to get the content by using .data function on the link in the click function
HTML
<span class="link">A</span>
<span class="link">B</span>
<div class="test-listing-container">
<ul class="test-full-list" id="fulllistA">
<ul class="test-category-list">
<li id=test-list>
Some Link 1
Some Link 1
</li>
</ul>
</ul>
</div>
Javascript
jQuery(document).on("click",".link a",function(e){
e.preventDefault();
e.stopPropagation();
var content = jQuery("#"+jQuery(this).data("content"));
jQuery(".test-listing-container > ul").not(content).hide(); // hide the others.
content.show();
});
I wrote a dropdown menu with the following structure. It is supposed to drop down on click, and close on click.
Here's the HTML
<ul id="nav" class="nav">
<li>
<a id="menu1" class="menu">MENU 1</a> <!-- top menu -->
<div id="submenu1" class="submenu"> <!-- hidden by default -->
SUBMENU ITEM 1 <!-- submenu item -->
SUBMENU ITEM 2
</div>
</li>
<li>
<a id="menu2" class="menu">MENU 2</a>
<div id="submenu2" class="submenu">
SUBMENU ITEM 1
SUBMENU ITEM 2
SUBMENU ITEM 2
</div>
</li>
</ul>
And that's the JavaScript (using jQuery)
$("#menu1").click(function() {
$("div.submenu").hide(); // hide all menus
$("#submenu1").toggle(); // open this menu
});
$("#menu2").click(function() {
$("div.submenu").hide(); // hide all menus
$("#submenu2").toggle(); // open this menu
});
$("#menu3").click(function() {
$("div.submenu").hide(); // hide all menus
$("#submenu3").toggle(); // open this menu
});
$("#menu4").click(function() {
$("div.submenu").hide(); // hide all menus
$("#submenu4").toggle(); // open this menu
});
$(document).bind('click', function(e) {
var $clicked = $(e.target);
if (! $clicked.parents().hasClass("nav"))
$("div.submenu").hide();
});
There is a lot of repetition in the first part of the JS, is there a way to make this shorter, nicer, better?
You should be able to reduce the script to:
$(".nav .menu").click(function() {
$("div.submenu").hide(); // hide all menus
$(this).next().toggle(); // open this menu
});
$(document).click(function(e) {
if (! $(e.target).parents().hasClass("nav"))
$("div.submenu").hide();
});
Yes:
var $submenus = $('.submenu');
$(".menu").click(function(e){
var $menu = $(this).next('.submenu').toggle();
$submenus.not('#' + $menu[0].id).hide();
e.preventDefault();
});
$(document).click(function(e){
if( !$(e.target).closest('.nav').length ) $submenus.hide();
});