This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
Closed 3 years ago.
How to change + to - when menu parent menu item is clicked. i was looking to target ::after element using jquery but i cant find way to target pseudo element using jquery
I want to change below css to when perent menu is clicked
.ir-nav-w > ul li::after {
/* padding-left: 10px; */
text-transform: uppercase;
content: "-";
position: absolute;
left: 15px;
top: 4px;
line-height: 30px;
font-size: 20px;
z-index: 0;
}
Fiddle code
$(".nav-w > ul > li > a").click(function() {
$(this).next().slideToggle();
});
//open active list
$('.nav-w ul li').children().has('.active-menu').css('display', 'block');
// compare url with nav url to show active url
$(function() {
//var url = window.location.href;
var url = window.location.pathname;
var pgurl = window.location.href.substr(
window.location.href.lastIndexOf("/") + 1
);
$(".nav-w ul li a").each(function() {
if ($(this).attr("href") == url || $(this).attr("href") == "") {
$(this).addClass("active-menu");
}
});
console.log("url : " + window.location.pathname);
});
.nav-w a {
color: black;
padding: 10px 15px;
padding-left: 35px;
text-decoration: none;
display: block;
border-bottom: 1px solid #f1f1f1;
font-size: 12px;
font-weight: 600;
/* color: #178B43 !important; */
color: #757575;
}
/* ul inside content area*/
.nav-w ul {
margin-left: 0px;
list-style-type: none;
margin-bottom: 0px;
}
.nav-w ul li {
/*padding-left: 10px;*/
text-transform: uppercase;
position: relative;
width: 100%;
}
/* ol inside content area*/
.nav-w>ul {
padding-left: 0px;
padding-right: 0px;
}
.nav-w ul>li ul {
padding-left: 0px;
padding-right: 0px;
display: none;
}
.active-menu {
color: red !important;
}
.nav-w>ul li::after {
text-transform: uppercase;
content: "+";
position: absolute;
left: 15px;
top: 4px;
line-height: 30px;
font-size: 20px;
z-index: 0;
}
.nav-w>ul li ul li::after {
text-transform: uppercase;
content: "";
position: absolute;
left: 0px;
top: 5px;
line-height: 32px;
font-size: 20px;
z-index: 0;
}
.nav-w ul li ul li a {
padding-left: 45px;
}
.nav-w a:hover {
background: #f5f5f5;
border-left: 2px solid #178B43;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav-w">
<ul class="">
<li>Share Information
<ul class="" style="display: none;">
<li>Share Overview</li>
<li>Share Graph </li>
<li>Investement Calculator</li>
<li>Historical Share Prices</li>
</ul>
</li>
<li>Financial Information
<ul class="" style="display: none;">
<li>Earning Releases</li>
<li>Financial Statements</li>
<li><a href="/investor-relations/financial-information/presentation">Presentation
</a></li>
<li><a href="/investor-relations/financial-information/quarterly-key-figures">Quarterly Key Figures
</a></li>
<li><a href="/investor-relations/financial-information/annual-key-figures">Annual Key Figures
</a></li>
</ul>
</li>
</ul>
</div>
The way I would do it is to add a class to the parent menu after it is clicked, such as open.
And then in your css you could add a special modifier:
.nav-w > ul li.open::after {
content: "-"
}
And when it is click again, remove the class open.
You can't manipulate :after, because it's not technically part of the DOM and therefore is inaccessible by any JavaScript. But you can add a new class with a new ::after specified.
Add this to your code:
// JS
const $listItems = $('.ir-nav-w > ul li');
$listItems.onClick(
$listItems.removeClass('closed');
this.addClass('closed')
);
// CSS
.ir-nav-w > ul li.closed::after {
content: "+";
}
Trick is to add css:
.nav-w > ul li.selected::after {
content: "-";
}
and toggle selected class on click:
$(".nav-w > ul > li > a").click(function () {
$(this).parent().toggleClass("selected");
$(this).next().slideToggle();
});
$(".nav-w > ul > li > a").click(function () {
$(this).parent().toggleClass("selected");
$(this).next().slideToggle();
});
//open active list
$('.nav-w ul li').children().has('.active-menu').css('display', 'block');
.nav-w a {
color: black;
padding: 10px 15px;
padding-left: 35px;
text-decoration: none;
display: block;
border-bottom: 1px solid #f1f1f1;
font-size: 12px;
font-weight: 600;
/* color: #178B43 !important; */
color: #757575;
}
/* ul inside content area*/
.nav-w ul{
margin-left: 0px;
list-style-type:none;
margin-bottom:0px;
}
.nav-w ul li{
/*padding-left: 10px;*/
text-transform:uppercase;
position:relative;
width:100%;
}
/* ol inside content area*/
.nav-w > ul {
padding-left: 0px;
padding-right: 0px;
}
.nav-w ul > li ul {
padding-left: 0px;
padding-right: 0px;
display:none;
}
.active-menu {
color: red !important;
}
.nav-w > ul li::after {
text-transform: uppercase;
content: "+";
position: absolute;
left: 15px;
top: 4px;
line-height: 30px;
font-size: 20px;
z-index: 0;
}
.nav-w > ul li.selected::after {
content: "-";
}
.nav-w > ul li ul li::after {
text-transform: uppercase;
content: "";
position: absolute;
left: 0px;
top: 5px;
line-height: 32px;
font-size: 20px;
z-index: 0;
}
.nav-w ul li ul li a {
padding-left:45px;
}
.nav-w a:hover {
background: #f5f5f5;
border-left: 2px solid #178B43;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav-w">
<ul class="">
<li>Share Information
<ul class="" style="display: none;">
<li>Share Overview</li>
<li>Share Graph </li>
<li><a href="/investor-relations/share-nformations/investor-calculator/" >Investement Calculator</a></li>
<li>Historical Share Prices</li>
</ul>
</li>
<li>Financial Information
<ul class="" style="display: none;">
<li>Earning Releases</li>
<li>Financial Statements</li>
<li><a href="/investor-relations/financial-information/presentation">Presentation
</a></li>
<li><a href="/investor-relations/financial-information/quarterly-key-figures">Quarterly Key Figures
</a></li>
<li><a href="/investor-relations/financial-information/annual-key-figures">Annual Key Figures
</a></li>
</ul>
</li>
</ul>
</div>
It's not actually possible to target :after, because it isn't part of the DOM and can't be accessed through JavaScript code. This isn't a jQuery limitation.
You could just set a class on the element itself, and change the :after rule when the class is set, i.e.:
.nav-w > ul li.active::after
{
content: "-"
}
Add active class to the anchors' parent:
$(".nav-w > ul > li a").click(function () {
$(this).next().slideToggle();
$(this).parent().toggleClass('active');
});
And replace ::after on the active class:
.nav-w > ul li.active::after {
content: '-'
}
You can do with :after prop.
You can do something like this
.li-item::after{
content: "+";
}
.li-item-minus::after{
content: "-" !important;
}
While in jQuery - you can toggle class .li-item-minus on click of each list item
jQuery(".naw-v ul li").on("click", function(){
jQuery(this).toggleClass("li-item-minus");
});
Which means - on click of this li element, you toggleClass li-item-minus which has different content form main one.
Related
I have a horizontal responsive menu that works great, here is link to the page with it
I tried to make a new one with dropdown menus but can't get it to work. Instead of having a dropdown appear on hover, it shows the menus automatically in the line below. Here is link to codepen showing the errors http://codepen.io/mlegg10/pen/akLaVA
$(document).ready(function() {
$('nav').prepend('<div id="responsive-nav" style="display:none">Menu</div>');
$('#responsive-nav').on('click', function() {
$('nav ul').slideToggle()
});
$(window).resize(function() {
if ($(window).innerWidth() < 768) {
$('nav ul li').css('display', 'block');
$('nav ul').hide()
$('#responsive-nav').show()
} else {
$('nav ul li').css('display', 'inline-block');
$('nav ul').show()
$('#responsive-nav').hide()
}
});
$(window).resize();
});
$(document).on('scroll', function() {
if ($(document).scrollTop() > 100) {
$('#nav').addClass('fixed')
} else {
$('#nav').removeClass('fixed')
}
});
body {
margin: 0;
font-family: Georgia;
}
#menu-bar {
width: 100%;
height: auto;
margin: 50px auto 0;
background-color: #ff4500;
text-align: center;
}
#header h1 {
padding: 15px 0;
margin: 0;
}
#nav {
background-color: #036;
text-align: center;
}
#nav ul {
list-style: none;
padding: 0;
margin: 0
}
#nav ul li {
display: inline-block;
padding: 5px 0;
margin: 0;
}
#nav.fixed {
width: 100%;
position: fixed;
top: 0;
left: 0;
}
nav ul li a {
padding: 0 5px;
text-decoration: none;
color: #fff;
}
nav ul li:hover {
background-color: #ff0000;
}
#responsive-nav {
cursor: pointer;
color: #fff;
font-family: Georgia;
font-weight: bold;
padding: 5px 0;
}
#content {
width: 90%;
margin: 0 auto 20px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid #ddd;
padding: 5px;
}
#drop-nav li ul li {
border-top: 0px;
#drop-nav li ul li {
border-top: 0px;
}
ul li a {
display: block;
background: #036;
padding: 5px 10px 5px 10px;
text-decoration: none;
white-space: nowrap;
color: #fff;
}
ul li a:hover {
background: #f00;
}
**this part is in the head tags:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://responsive-nav.com/demo/responsive-nav.js"></script>**
<header id="menu-bar">
<nav id="nav">
<ul>
<li>Home
</li>
<li>Accomodations
</li>
<li>Amenities
</li>
<li>Rates
</li>
<li>Links
<ul>
<li>Dropwdown 1
</li>
<li>Dropdown 2
</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</nav>
</header>
Your javascript code has lots of unclosed line endings - you are missing the semicolons quiet often.
Additionally, jQuery will apply nav ul to all elements it finds. Meaning if there is a second occurrence, which is the case in your case, it will be applied to that too.
Instead: you should give your level 0 menu a clean, identifiable class, which you can preciesly target:
<!-- Your new HTML Markup -->
<nav class="mother-of-all-dropdown-lists">
and then in your jQuery:
$('.mother-of-all-dropdown-lists').slideToggle();
Sorry, that I keep writing, there are jQuery selectors wrong as well:
The id / hashtag is missing, so..:
$('nav ul li').css('display','inline-block');
$('nav ul').show()
should be:
$('#nav ul li').css('display','inline-block');
$('#nav ul').show();
I am writing a jquery dropdown script for my navigation submenus. I have return false on the top level anchors but the problem is that this is also applying to the anchors in the submenus. My script also adds chevrons to the top level links that have submenus but those are also being added to the submenu links. What am I doing wrong? Here is a jsFiddle. Thanks for your time.
<div class="nav-outter">
<nav>
<ul>
<li>Home</li>
<li class="has-submenu">Services
<ul>
<li>Web Development</li>
<li>Photography</li>
<li>Multimedia</li>
</ul>
</li>
</ul>
</nav>
</div>
$(document).ready(function() {
$('nav > ul > li.has-submenu').each(function() {
$(this).find('a:first-child').each(function() {
$(this).append('<i class="fa fa-chevron-down"></i>');
$(this).on('click', function(e) {
e.preventDefault();
$(this).parent().find('ul').each(function() {
if ($(this).hasClass('active')) {
$(this).removeClass('active')
.slideUp(300);
} else {
$(this).addClass('active')
.slideDown(300);
}
});
});
});
});
});
.nav-outter {
position: relative;
z-index: 1;
}
nav > ul {
list-style: none;
}
nav > ul > li {
display: inline-block;
}
nav > ul > li > a {
padding: 3px 15px;
font-size: 1.2em;
color: #2c3e50;
text-decoration: none;
}
nav > ul > li > ul {
display: none;
position: absolute;
z-index: 5;
list-style: none;
border: 1px solid #FC4349;
border-bottom: 0px;
margin-left: 0px;
padding-left: 0px;
margin-top: 3%;
}
nav > ul > li > ul > li {
border-bottom: 1px solid #FC4349;
}
nav > ul > li > ul > li > a {
display: block;
padding: 15px 25px 15px 10px;
text-align: left;
background: #fff;
color: #FC4349;
text-decoration: none;
}
The find('a:first-child') is going to include every first child which is all of the links since each one is a first-child
A simpler approach would be just target the children of has-submenu and remove one each
$('nav > ul > li.has-submenu').children('a').each(function() {
$(this).append('<i class="fa fa-chevron-down"></i>');
$(this).on('click', function(e) {
.....
Or using your code if you had used find('a:first') it would have worked since you would be targeting only the first <a> in each of those class
I've created myself a accordion menu, but I've got a problem. When I click for the first time on 'li' element slideUp doesn't work.
$(document).ready(function() {
$('#menu ul li a').click(function(e) {
e.preventDefault();
if ($(this).parent().hasClass('active')) {
if ($(this).next().is(':visible')) {
$(this).next().slideUp();
$(this).parent().removeClass('active');
} else {
$(this).next().slideDown();
}
} else {
$('#menu ul li').each(function() {
$(this).removeClass('active');
});
$('#menu ul li ul').slideUp();
$(this).next().slideDown();
$(this).parent().addClass('active');
}
});
});
#menu,
#menu ul,
#menu li,
#menu a {
margin: 0;
padding: 0;
border: 0;
list-style: none;
font-weight: normal;
text-decoration: none;
line-height: 1;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
position: relative;
}
#menu a {
line-height: 1.3;
}
#menu > ul > li {
margin: 0;
}
#menu > ul > li:last-child {
margin: 0;
}
#menu > ul > li > a {
font-size: 15px;
display: block;
color: #ffffff;
text-shadow: 0 1px 1px #000;
padding: 5px;
}
#menu > ul > li > a > span {
display: block;
padding: 6px 10px;
font-weight: bold;
}
#menu > ul > li > a:hover {
text-decoration: none;
background: #0074a2 url('../img/icons/menuActive.png') no-repeat 101%;
}
#menu > ul > li.active {
border-bottom: none;
}
#menu > ul > li.active > a {
background: #0074a2 url('../img/icons/menuActive.png') no-repeat 101%;
color: #fff;
text-shadow: 0 1px 1px #000;
}
/* Sub menu */
#menu ul ul {
padding: 5px 12px;
display: none;
background: #333333;
}
#menu ul ul li {
padding: 3px 0;
}
#menu ul ul a {
display: block;
color: #fff;
font-size: 13px;
font-weight: bold;
padding: 10px 0;
}
#menu ul ul a:hover {
color: #0074a2;
}
#menu ul li.active ul {
display: block;
}
#menu ul li img {
float: left;
margin: -2px 4px 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu">
<ul>
<li class='has-sub active'><a href='#'><span>AAA</span></a>
<ul>
<li><a href='#'><span>AAA_1</span></a></li>
<li><a href='#'><span>AAA_2</span></a></li>
<li><a href='#'><span>AAA_3</span></a></li>
</ul>
</li>
<li class='has-sub'><a href='#'><span>BBB</span></a>
<ul>
<li><a href='#'><span>BBB_1</span></a></li>
<li><a href='#'><span>BBB_2</span></a></li>
</ul>
</li>
<li class='has-sub last'><a href='#'><span>CCC</span></a>
<ul>
<li><a href='#'><span>CCC_1</span></a></li>
<li><a href='#'><span>CCC_2</span></a></li>
<li><a href='#'><span>CCC_3</span></a></li>
<li><a href='#'><span>CCC_4</span></a></li>
</ul>
</li>
</ul>
</div>
Here is my simple code typed in jsfiddle.
jsfiddle
Could anyone tell me where is an error and how to solve it ?
Thanks !
The state of the html goes like this:
1. From start: <ul>
2. After you click once: <ul style="display: none;">
3. After you click it again: <ul style="display: block;">
Now I'm not that great when it comes to css, but if you keep track of the dynamic css which goes on when you press it, then you'll know what attributes you are missing on your styling.
The problem is active class has been removed before finishing slideUp animation. Use setTimeout function like following.
setTimeout(function(){
$(this).parent().removeClass('active')
}, 0);
You can increase time if you need.
Update:
I think your selector should be.
$('#menu > ul > li > a')
instead of
$('#menu ul li a')
I don't want to include bootstrap in my project, but I want to use the dropdown plugin separately. The reason I chose Bootstrap's one because it's a robust and relatively non-complicated one (I just need the basic functionality – to work flawlessly, not any extra features)
I tried to make the dropdown css as close to bootstrap's css as possible, but the menu refuses to hide when I click outside the dropdown.
HTML:
<div id="top_links">
<ul>
<li class="dropdown"> Menu
<ul class="dropdown-menu">
<li> Submenu 1
</li>
<li> Submenu 1
</li>
<li> Submenu 1
</li>
</ul>
</li>
</ul>
</div>
JS (tried both including full bootstrap.js and just bootstrap-dropdown.js plugin):
$('#top_links').find("li.dropdown > a").dropdown()
CSS:
#top_links > ul {
list-style-type: none;
}
#top_links > ul > li {
position: relative;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
*vertical-align: auto;
margin-left: 28px;
}
#top_links > ul > li:first-child {
margin-left: 0;
}
#top_links > ul > li > a {
display: block;
text-decoration: none;
position: relative;
padding-top: 28px;
}
#top_links > ul > li > a:before {
content:"";
width: 30px;
height: 20px;
position: absolute;
top: 0;
left: 50%;
margin-left: -15px;
}
#top_links > ul > li.dropdown > a {
margin-right: 13px;
}
#top_links > ul > li.dropdown:after {
content:"";
position: absolute;
right: 0;
bottom: 6px;
width: 8px;
height: 6px;
}
#top_links > ul > li > ul {
display: none;
list-style-type: none;
position: absolute;
z-index: 10;
width: auto;
border: 1px solid #edeae6;
background-color: #f6f3ef;
padding: 5px;
margin: 0 -6px 0px -6px;
}
#top_links > ul > li > ul li {
padding: 5px 0;
}
#top_links > ul > li > ul li a {
display: block;
}
#top_links > ul > li > ul li > .icon {
top: 6px !important;
}
#top_links > ul > li.open > ul {
display: block;
}
On JSFiddle: Live DEMO
This seems to work when I don't use the manual trigger, so I removed this line:
$('#top_links').find("li.dropdown > a").dropdown()
And added data-toggle attribute to the links:
Menu
Works now: DEMO
However, do you think this is a bug in Bootstrap? Is it intended to work as I tried it?
Try this
<script>
$(document).ready(function () {
$(".dropdown").on('click', function () {
$(".dropdown-menu").toggle("slow");
});
});
$(".dropdown").on("click", function (event) {
event.stopPropagation();
});
$(document).on("click", function () {
$(".dropdown-menu").toggle("slow");
});
</script>
Demo
http://jsfiddle.net/hg2T6/2/
I am working on a website for a client. For the menu/navigation bar, I created one for them (they were very specific) with dropdowns, but there is one problem--when you mouse over one of the items on the dropdown, it dissappears--check it out here http://www.brandonsdesigngroup.com/menu-expamle.html.
for the code, I call jquery from google API's, then there is the javascript, the CSS, and the actual content (in an unordered list).
Javascript:
<script type="text/javascript">
$(document).ready(function(){
$("#nav-one li").hover(
function(){ $("ul", this).fadeIn("fast"); },
function() { }
);
if (document.all) {
$("#nav-one li").hoverClass ("sfHover");
}
});
$.fn.hoverClass = function(c) {
return this.each(function(){
$(this).hover(
function() { $(this).addClass(c); },
function() { $(this).removeClass(c); }
);
});
};
</script>
CSS:
<style type="text/css">
.nav, .nav ul {
list-style: none;
margin: 0;
padding: 0;
height:20px
}
.nav {
z-index: 100;
position: relative;
}
.nav li {
border-left: 0px solid #000;
float: left;
margin: 0;
padding: 0;
position: relative;
font-family: Arial, Helvetica, sans-serif;
font-style:normal;
font-size:12px;
}
.nav li a, .nav li a:link, .nav li a:active, .nav li a:visited {
font:1.22em/25px "Arial Narrow", Arial, sans-serif letter-spacing:5px;
color: #FFFFFF;
display: block;
padding: 0 10px;
text-decoration: none;
text-style: narrow;
margin-right:26px;
}
.nav li a:hover {
margin-right:26px;
color: #FFFFFF;
}
#nav-one li:hover a,
#nav-one li.sfHover a {
color: #FFFFFF;
}
#nav-one li:hover ul a,
#nav-one li.sfHover ul a {
color: #FFFFFF;
height:20px;
background-image: url(menubar/transparent.png);
}
#nav-one li:hover ul a:hover,
#nav-one li.sfHover ul a:hover {
color:#FFFFFF;
background-image:url(menubar/transparent.png);
}
.nav ul {
border-bottom: 0px solid #FFFFFF;
list-style: none;
margin: 0;
width: 100px;
position: absolute;
top: -99999px;
left: 0px;
}
.nav li:hover ul,
.nav li.sfHover ul {
top: 22px;
}
.nav ul li {
border: 0;
float: none;
font-family: Arial, Helvetica, sans-serif;
font-style:normal;
font-size:10px;
}
.nav ul a {
border: 0px solid #000;
border-bottom: 0;
padding-right: 50px;
margin-bottom: 0px;
width: 130px;
white-space: nowrap;
}
.nav ul a:hover {
color: #FFFFFF;
}
</style>
<style type="text/css">
body {
width: auto;
height: auto;
background-color: #3A2C21;
}
</style>
HTML:
<td background="images/menu_bg.gif" height="25"><ul id="nav-one" class="nav">
<li>
HOME
</li>
<li>
PROFILE
<ul>
<li>ABOUT</li>
<li>PEOPLE</li>
<li>SERVICES</li>
<li>TRADE SHOWS</li>
</ul>
</li>
<li>
PORTFOLIO
<ul>
<li>ARTISTIC TILE</li>
<li>ATLANTIS</li>
<li>BLANCO</li>
<li>BUTLER"S OF FAR HILLS</li>
<li>HAMPTON FORGE</li>
<li>HILAND H. TURNER</li>
<li>MIELE</li>
<li>POGGENPOHL</li>
<li>THG FAUCETS</li>
<li>TOP KNOBS</li>
<li>VIXEN HILL</li>
</ul>
</li>
<li>
PUBLIC RELATIONS
<ul>
<li>PRESS ATTENTION</li>
<li>FRANK PR</li>
<li>HITS</li>
<li>MORE HITS</li>
<li>LEVERAGING PR</li>
</ul>
</li>
<li>
CONTACT
</li>
</ul>
Problem #1: Menu disappears before cursor can reach submenu.
Usually this is due to a gap between the <li> tag and the subnavigation <ul>. A gap of even one pixel will cause the navigation to disappear before the cursor can reach the submenu.
For instance, add a padding: 0 0 10px; to .nav li in your CSS, and the problem goes away.
You could also set a specific height for the <li> to cover the problem, too.
Problem #2: Menu disappears when cursor runs over the image slideshow.
As to the problem of your menu disappearing when you reach the point where your image slideshow and menu collide, that's due to a z-index problem.
You should set the .nav to have a z-index: 200 (or anything greater than 100, according to your slideshow -- I try to go overboard). This will make sure it sits above the gallery.
Javascript
<script>
sfHover = function() {
var sfEls = document.getElementById("navbar").getElementsByTagName("li");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" hover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" hover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
</script>
html
Already a Member? Login
Become a Member?
Signup
Army
Navy
Airforce
I would use the Hover Intent plug-in. It is designed for exactly this kind of usage and helps provide a more robust dropdown.