active class does not show - javascript

I have this menu:
<nav class="show-for-large-up main-navigation default-navigation align_right" role="navigation">
<ul class="menu-main-navigation active">
<li id="menu-item-393" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home">
Home
</li>
<li id="menu-item-415" class="menu-item menu-item-type-post_type menu-item-object-page>
Shop
</li>
<li id="menu-item-491" class="menu-item menu-item-type-post_type menu-item-object-page">
About
</li>
<li id="menu-item-1086" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-1049 current_page_item active">
Services
</li>
<li id="menu-item-403" class="menu-item menu-item-type-post_type menu-item-object-page">
Portfolio
</li>
<li id="menu-item-1010" class="menu-item menu-item-type-post_type menu-item-object-page">
Contact Us
</li>
<li id="menu-item-503" class="menu-item menu-item-type-post_type menu-item-object-page">
Login / Register
</li>
</ul>
</nav>
myscript.js:
jQuery(document).ready(function($) {
var activeurl = window.location;
$('a[href="'+activeurl+'"]').parent('li').addClass('active');
$(function () {
var url = window.location.pathname,
urlRegExp = new RegExp(url.replace(/\/$/, '') + "$");
$('a').each(function () {
if (urlRegExp.test(this.href.replace(/\/$/, ''))) {
$(this).addClass('active');
$(this).parent().addClass("active");
}
});
});
var aurl = window.location.href; // Get the absolute url
var parts = aurl.split('/');
var lastSegment = parts.pop() || parts.pop(); // handle potential trailing slash
$(".main-navigation > ul > li > a").each(function(){
if($(this).attr("href") == aurl || $(this).attr("href") == '' ) {
$(this).addClass('active');
$(this).parent().addClass("active");
}
});
});
I am loading Js script:
function load_my_script(){
wp_register_script(
'my_script',
get_template_directory_uri() . '/js/myscript.js',
array( 'jquery' )
);
wp_enqueue_script( 'my_script' );
}
add_action('wp_enqueue_scripts', 'load_my_script');
Loading Css script:
function enqueue_custom_stylesheets() {
if ( ! is_admin() ) {
wp_enqueue_style( 'custom_css', get_template_directory_uri() . '/css/customCss.css' );
}
}
add_action( 'wp_enqueue_scripts', 'enqueue_custom_stylesheets', PHP_INT_MAX );
customCss.css:
.main-navigation > ul > li > a:active {
text-decoration: underline !important;
}
.main-navigation ul li:active {
text-decoration: underline !important;
}
Everything seems in place (loaded),but :active state only shows if I use developer console to trigger active state and only on href.
So to say $(this).parent().addClass("active"); does not any effect although most answers here do refer to parent()
How can I activate active state on href?
Thanx

Try this below code.
JQUERY
<script>
$(document).ready(function(){
$(window).load(function(){
var x = window.location.href;
$('.main-navigation ul a[href="'+x+'"]').each(function() {
if(x == window.location.href){
$('.main-navigation ul li').removeClass('active');
$(this).parent('li').addClass('active');
}
});
});
});
</script>
In your CSS
.main-navigation ul li.active a, .main-navigation > ul > li.active > a{
text-decoration: underline !important;
}
I'ved tried above jquery code and it works! :)

Working JQuery:
jQuery(document).ready(function($) {
var aurl = window.location.href; // Get the absolute url
var parts = aurl.split('/');
var lastSegment = parts.pop() || parts.pop(); // handle potential trailing slash
console.log(lastSegment);
$(".main-navigation > ul > li > a").each(function(){
if($(this).attr("href") == aurl || $(this).attr("href") == '' ) {
$(this).addClass('active');
}
});
});
Working Css:
.main-navigation > ul > li > a.active {
text-decoration: underline !important;
}
Credit to #Rahul.
Thanx everyone

Related

How to know the logic of multilevel menu event bubbling

I'm trying to understand the logic happening in my basic multilevel menu click event. I understood what happening on clicking on "About" menu in the navigation. And it works as per my expecation of code. But when i click on "Profile" menu (Submenu of "About" menu), JS makes it's sublevel menu "display:none". I tried to think in the aspect of even bubbling. But eventhough the bubbling happens here, it should not be working like this. Actually for me, its really complicated to understand how JS works here. It would be a Great Help if anyone can explain with a simple and understandable way. Thank You Very Much in Advance!!!
let menus = document.querySelectorAll(".main-navigation ul li a");
menus.forEach((item) => {
if (item.parentElement.querySelector("ul")) {
item.parentElement.classList.add("has-submenu");
}
});
let submenu = document.querySelectorAll(".has-submenu");
submenu.forEach((item) => {
item.addEventListener("click", (e) => {
e.preventDefault();
let ul = e.target.parentElement.querySelector("ul");
let cs = window.getComputedStyle(ul).display;
if (cs === "none") {
ul.style.cssText = "display:block";
}
else {
ul.style.cssText = "display:none";
}
});
});
.main-navigation ul {list-style:none;margin:0;padding:0;font-family:arial;}
.main-navigation ul li {padding:.35rem;background:#f9f9f9;}
.main-navigation ul li ul {padding-left:1rem;display:none;}
.main-navigation ul li a {display:block;text-decoration:none;}
<div class="main-navigation">
<ul>
<li>Home</li>
<li>About +
<ul>
<li>Profile +
<ul>
<li>History</li>
<li>Management</li>
</ul>
</li>
<li>Vision</li>
<li>Mission</li>
</ul>
</li>
<li>Services +
<ul>
<li>Web Design</li>
<li>Web Development</li>
</ul>
</li>
<li>Contact</li>
</ul>
</div>
Solution
If you add a console.log inside your click handler you will notice that the event for the nested item is called twice.
You probably knew that it could happen and you used preventDefault.
However, preventDefault is for the browser's default effects (for example, it prevents your page to refresh as you put an href attribute) but in your case the double behaviour is from your own custom listener.
This means, you need to add stopPropagation that prevents further propagation of the current event in the capturing and bubbling phases.
Working Demo
let menus = document.querySelectorAll(".main-navigation ul li a");
menus.forEach((item) => {
if (item.parentElement.querySelector("ul")) {
item.parentElement.classList.add("has-submenu");
}
});
let submenu = document.querySelectorAll(".has-submenu");
submenu.forEach((item) => {
item.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
let ul = e.target.parentElement.querySelector("ul");
let cs = window.getComputedStyle(ul).display;
if (cs === "none") {
ul.style.cssText = "display:block";
} else {
ul.style.cssText = "display:none";
}
});
});
.main-navigation ul {
list-style: none;
margin: 0;
padding: 0;
font-family: arial;
}
.main-navigation ul li {
padding: .35rem;
background: #f9f9f9;
}
.main-navigation ul li ul {
padding-left: 1rem;
display: none;
}
.main-navigation ul li a {
display: block;
text-decoration: none;
}
<div class="main-navigation">
<ul>
<li>Home</li>
<li>About +
<ul>
<li>Profile +
<ul>
<li>History</li>
<li>Management</li>
</ul>
</li>
<li>Vision</li>
<li>Mission</li>
</ul>
</li>
<li>Services +
<ul>
<li>Web Design</li>
<li>Web Development</li>
</ul>
</li>
<li>Contact</li>
</ul>
</div>

Setting threshold on max number of classes selected/activated on click on multiple divs/id's

I've been working on a skill tree 'persay' and I ran into an interesting problem.
I have my code setup to allow a user to click a talent to show that particular talent has been selected up to a max number of 4 talents total. Once you have selected 4 talents you have to deselect a talent to select a different one.
My problem comes when I duplicate the talent tree for a second talent tree on the same page(for a second hero/class essentially or a second party member out of your party). I can't figure out how to make the same 'threshold of a max of 4 talents' on other skill trees standalone. What happens is that they all share the same threshold across all trees. I have tried making separate id's each and even changing the variable names within each function.
var skillTotal = 0;
var skillSelected = 0;
$( "#selectable01>li.skill-slot" ).bind( "click", function ( e ) {
var threshold = 4;
var price = 1;
if ($(this).hasClass('selected')) {
skillTotal = skillTotal - 1;
skillSelected--;
$(this).toggleClass('selected');
}
else if (price + skillTotal <= threshold) {
skillTotal = skillTotal + price;
skillSelected++;
$(this).toggleClass('selected');
}
});
$( "#selectable02>li.skill-slot" ).bind( "click", function ( e ) {
var threshold = 4;
var price = 1;
if ($(this).hasClass('selected')) {
skillTotal = skillTotal - 1;
skillSelected--;
$(this).toggleClass('selected');
}
else if (price + skillTotal <= threshold) {
skillTotal = skillTotal + price;
skillSelected++;
$(this).toggleClass('selected');
}
});
/* NOT USING THIS CURRENTLY
$( "#campSelectable>li.camp-slot" ).bind( "click", function ( e ) {
var campThreshold = 3;
var campPrice = 1;
if ($(this).hasClass('selected')) {
campTotal = campTotal - campPrice;
selectedCamp--;
$(this).toggleClass('selected');
}
else if (campPrice + campTotal <= campThreshold) {
campTotal = campTotal + campPrice;
selectedCamp++;
$(this).toggleClass('selected');
}
}); */
.skill-slot, .camp-slot{
border:2px solid black;
width:100px;
margin: 5px;
opacity: .4;
}
.skill-slot:hover, .camp-slot:hover {
opacity: 1;
}
.raffle-slot.taken{
background:red;
}
.selected{
background: rgb(255, 128, 128);
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calc">
<ol class="roster" id="selectable01">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>
<ol class="roster" id="selectable02">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>
</div>
Here are the things I have tried:
Initially my identifier was : $( "#calc>ol>li.skill-slot" ).on so I began adding additional id's to drill down further and make sure that my functions were targeting specific div's, so I moved to this: $( "#calc>#selectable01>li.skill-slot" ).on and $( "#calc>#selectable02>li.skill-slot" ).on
The reason I didn't want to target a second ID is because I'll be using templates that are appended to the #calc div effectively replacing the current roster with a new one. I also did this for testing to see if I could resolve the issue by making them their own individual id's, which didn't work.
A way simpler approach using Event delegation. Toggle .selected to either deactivate the current .skill-slot, or to activate it if there are less than 4 .selected.skill-slots in this group.
$('#selectable01, #selectable02').on('click', '.skill-slot', function(e){
if($(this).hasClass('selected') || $('.selected.skill-slot', e.delegateTarget).length < 4){
$(this).toggleClass('selected');
}
});
.skill-slot, .camp-slot{
border:2px solid black;
width:100px;
margin: 5px;
opacity: .4;
}
.skill-slot:hover, .camp-slot:hover {
opacity: 1;
}
.raffle-slot.taken{
background:red;
}
.selected{
background: rgb(255, 128, 128);
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calc">
<ol class="roster" id="selectable01">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>
<ol class="roster" id="selectable02">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>
</div>
As you are using global variables for the count and total, this obviously leads to a global limit. To make the limit local to each of the groups, you could use data attributes of these ol elements, so they work independently from each other. With some other little improvements, your code could look like this:
$("#selectable01, #selectable02").data("skillTotal", 0).data("skillSelected", 0);
$("#selectable01>li.skill-slot,#selectable02>li.skill-slot").on("click", function () {
var threshold = 4,
price = 1,
sign = $(this).hasClass('selected') ? -1: 1,
$p = $(this).parent(),
newPrice = $p.data("skillTotal") + sign*price;
if (newPrice > threshold) return;
$p.data("skillTotal", newPrice)
.data("skillSelected", $p.data("skillSelected") + sign);
$(this).toggleClass('selected');
});
.skill-slot, .camp-slot{
border:2px solid black;
width:100px;
margin: 5px;
opacity: .4;
}
.skill-slot:hover, .camp-slot:hover {
opacity: 1;
}
.raffle-slot.taken{
background:red;
}
.selected{
background: rgb(255, 128, 128);
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calc">
<ol class="roster" id="selectable01">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>
<ol class="roster" id="selectable02">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>
</div>
You're storing skillSelected outside of the event handlers so each event handler is reading that variable. You might need to get a running total of how many are selected each time the event handler is triggered.

Dropdown Menu Closes On Hover (Error)

Whhenever I hover over the menu it works fine. But, when I try to get to the submenu links and children, the menu closes
/*----------------------------------------------------
/* Dropdown menu
/* ------------------------------------------------- */
jQuery(document).ready(function($) {
function mtsDropdownMenu() {
var wWidth = $(window).width();
if (wWidth > 865) {
$('#navigation ul.sub-menu, #navigation ul.children').hide();
var timer;
var delay = 100;
$('#navigation li').hover(
function() {
var $this = $(this);
timer = setTimeout(function() {
$this.children('ul.sub-menu, ul.children').slideDown('fast');
}, delay);
},
function() {
$(this).children('ul.sub-menu, ul.children').hide();
clearTimeout(timer);
}
);
} else {
$('#navigation li').unbind('hover');
$('#navigation li.active > ul.sub-menu, #navigation li.active > ul.children').show();
}
}
mtsDropdownMenu();
$(window).resize(function() {
mtsDropdownMenu();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li id="menu-item-513" class="menu-item "><i class="fa fa-calculator"></i> OFFERTE AANVRAGEN
<ul class="sub-menu">
<li id="menu-item-1146" class="menu-item">Zonnepanelen installatie (Belgiƫ)
</li>
<li id="menu-item-1144" class="menu-item">Zonnepanelen reinigen (Belgiƫ)
</li>
<li id="menu-item-1145" class="menu-item">Zonnepanelen installatie (Nederland)
</li>
</ul>
</li>
The code you posted works just fine; here's a plnkr to prove it: https://plnkr.co/edit/IFaueUhKE3J1K9vY1NkQ?p=preview
(simply wrapped a <div id='navigation'><ul> round the top li).
If you still loose the hover over the child-elements, it's caused by something you're not showing in the original question. E.g. adding this css:
li.menu-item {
position: relative;
top: 50px;
left: 300px;
}
would make it difficult to reach the child items because you, briefly, lose the parent-hover while moving to the child.

jquery dynamic filter list

I'm trying to make a filter list on keypress. For example if I write in input "It", the elements that doesn't match this input value are hidden. I'm not sure if the idea I have with code below does the job. Any tips will be highly appreciated!
$('ul li ul li').addClass('displayNone');
var geInputValue = $('input').val();
var getInputLength = $('input').length;
function sortDynamically(){
$('input').on('keypress', function(){
for(var i=0; i < getInputLength; i++){
if(getInputValue === $('li').text){
// remove everything that doesnt match input value
$('li').siblings().addClass('displayNone');
}
else{
$('li').siblings().removeClass('displayNone');
});
}
sortDynamically();
ul, li{
list-style-type: none;
margin: 0;
padding: 0;
}
.displayNone{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<ul class="list">
<li>Item</li>
<li>Product
<ul>
<li>Bike</li>
</ul>
</li>
<li>About</li>
</ul>
This code filters based on what you type. If there is nothing in the text input then everything is shown.
$('input').on('keypress keyup', function(){
var value = $(this).val().toLowerCase();
if (value != '') {
$('.list > li').each(function () {
if ($(this).text().toLowerCase().indexOf(value) > -1) {
$(this).removeClass('displayNone');
} else {
$(this).addClass('displayNone');
}
});
} else {
$('.list > li').removeClass('displayNone');
}
});
ul, li{
list-style-type: none;
margin: 0;
padding: 0;
}
.displayNone{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<ul class="list">
<li>Item</li>
<li>Product
<ul>
<li>Bike</li>
</ul>
</li>
<li>About</li>
</ul>
jQuery provides filters and javascript implements toLowerCase() and includes() methods that you can use to improve your code
<body>
<style>
.displayNone
{
display: none;
}
</style>
<input type="text" id="input-filter"/>
<ul class="list">
<li>Item</li>
<li>Product
<ul>
<li>Bike</li>
</ul>
</li>
<li>About</li>
</ul>
<script>
var items = $('ul.list li');
$('#input-filter').on('input', function ($event)
{
items.addClass('displayNone').filter(function (item)
{
return $(this).text().toLowerCase().includes($($event.target).val().toLowerCase());
}).removeClass('displayNone');
});
</script>
</body>

CSS Flyout Menu in conjunction with scrolling menu

I am new to javascript and am having trouble with menus. I can get a flyout menu to work, and I can get a scrolling menu to work (demo of scrolling menu http://css-tricks.com/examples/LongDropdowns/).
However, I cannot figure out how to merge the effects. Can someone please help me with the flyout code for below?
//HTML
<ul class="dropdown">
<li>CITIES BY STATE
<ul>
for (var p = 0; p < state.length; p++) {
<li> + states[p][0] + "");
<ul id="city\" class="city">
<li>CITY 1</li>
<li>CITY 2</li>
<li>CITY 3</li>
</ul>");
</li>");
}
</ul>
</ul>
</li>
//SCRIPT TO ALLOW SCROLL THROUGH LIST
<script>
var maxHeight = 600;
$(function(){
$(".dropdown > li").hover(function() {
var $container = $(this),
$list = $container.find("ul"),
$anchor = $container.find("a"),
height = $list.height() * 1.1, // make sure there is enough room at the bottom
multiplier = height / maxHeight; // needs to move faster if list is taller
// need to save height here so it can revert on mouseout
$container.data("origHeight", $container.height());
// so it can retain it's rollover color all the while the dropdown is open
$anchor.addClass("hover");
// don't do any animation if list shorter than max
if (multiplier > 1) {
$container
.css({
height: maxHeight,
overflow: "hidden"
})
.mousemove(function(e) {
var offset = $container.offset();
var relativeY = ((e.pageY - offset.top) * multiplier) - ($container.data("origHeight") * multiplier);
if (relativeY > $container.data("origHeight")) {
$list.css("top", -relativeY + $container.data("origHeight"));
};
});
}
}, function() {
var $el = $(this);
// put things back to normal
$el
.height($(this).data("origHeight"))
.find("ul")
.css({ top: 0 })
.show()
.find("a")
.removeClass("hover");
});
});
</script>
This is what I have tried, but I am off. I want a list of cities to display to the right of the state list when I hover on a state.
/*code to show/hide city menu*/
#city li:hover ul ul, #city li:hover ul ul ul, #city li:hover ul ul ul ul{
display:none;
}
#city li:hover ul, #city li li:hover ul, #city li li li:hover ul, #city li li li li:hover ul{
display:block;
}
Chrisoph is right. This is just jibberish:
<ul class="dropdown">
<li>CITIES BY STATE
<ul>
for (var p = 0; p < state.length; p++) {
<li> + states[p][0] + "");
<ul id="city\" class="city">
<li>CITY 1</li>
<li>CITY 2</li>
<li>CITY 3</li>
</ul>");
</li>");
}
</ul>
</ul>
</li>
This is syntactially correct HTML/Javascript. Screw it... I decided to just code it for you because I'm bored, but you really need to go back to basics in HTML/JavaScript.
<html>
<head>
<title>test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function()
{
var map = [
{state: "NSW", cities: ["Sydney", "Newcastle", "Orange"]},
{state: "QLD", cities: ["Brisbane", "Cairns", "Townsville"]},
{state: "VIC", cities: ["Melbourne", "Geelong", "Ballarat"]},
{state: "SA", cities: ["Radelaide", "Mount Gambier"]},
{state: "TAS", cities: ["Hobart", "Devonport", "Launceston"]}
];
for (var i = 0; i < map.length; i++)
{
var a = $('<a href="#">').html(map[i].state);
var li = $('<li>').append(a);
var cities = $('<ul>').attr('id', map[i].state).addClass('cityList');
for(var j = 0; j < map[i].cities.length; j++)
{
cities.append($('<li>').html(map[i].cities[j]));
}
li.append(cities);
$('#citiesByState').append(li);
}
});
</script>
</head>
<body>
<ul class="dropdown">
<li>
CITIES BY STATE
<ul id="citiesByState"></ul>
</li>
</ul>
</body>
</html>
Now go back and fix your question and test it then we'll look at any new problems.

Categories