jQuery keep parent highlight on submenu hidden navigation arrows - javascript

I need some help in jQuery and I really hope that I could find some help here. I would like when I use my navigation arrows (next/previous) when I am on a hidden item that the parent item stays highlight. For the first item home, it works but for the rest not. Does anybody can help me please?
here my fiddle
<div id="cssmenu">
<ul id="list">
<li>Home</li>
<ul class="hide"><li></li></ul>
<li>Newsletter</li>
... </div>
I tried to fiddle something :
$(document).ready(function(){
$('#cssmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents('li').addClass('active');
});
I manage my next and previous button like that :
$( "#next, #prev" ).click( function ( event ) {
var
positionActiveClass = menu.find( "> li.active" ).index(),
menuLength = menu.find( "> li" ).length - 1,
buttonId = $( this ).attr( "id" );
if ( buttonId === "next" ) {
if ( positionActiveClass === ( menuLength ) ) {
newElementActiveClass = menu.find( "li" ).eq( 0 );
newPositionActiveClass = newElementActiveClass.find( "> a" ).attr( "href" );
animation( newPositionActiveClass );
} else {
newElementActiveClass = menu.find( "li" ).eq( positionActiveClass + 1 );
newPositionActiveClass = newElementActiveClass.find( "> a" ).attr( "href" );
animation( newPositionActiveClass );
}
} else {
if ( positionActiveClass === 0 ) {
newElementActiveClass = menu.find( "li" ).eq( menuLength );
newPositionActiveClass = newElementActiveClass.find( "> a" ).attr( "href" );
animation( newPositionActiveClass );
} else {
newElementActiveClass = menu.find( "li" ).eq( positionActiveClass - 1 );
newPositionActiveClass = newElementActiveClass.find( "> a" ).attr( "href" );
animation( newPositionActiveClass );
}
}
event.preventDefault();
} );

There is an extra ul after the first li which has a class hide. What is that for? Just remove that ul and everything works fine.

Related

How to convert jQuery code that manages the expanded/collapsed state of items in a navigation menu to pure JS

I'm trying to convert some old jQuery code that manages the expanded/collapsed state of items in a navigation menu to pure JS and I've hit a roadblock.
HTML menu code:
<nav class="main-navigation">
<ul class="menu">
<li class="menu-item">
Item 1
<button class="dropdown-toggle" aria-expanded="false">
<svg class="svg-icon"></svg>
<span class="screen-reader-text">Expand submenu</span>
</button>
<ul class="sub-menu">
<li class="menu-item">
Item a
</li>
<li class="menu-item">
Item b
</li>
<li class="menu-item">
Item c
</li>
...
jQuery code:
var container = $( '.main-navigation' );
container.find( '.dropdown-toggle' ).on( 'click', function( e ) {
var _this = $( this );
e.preventDefault();
// Remove toggle classes and attributes from all menu items except the active one and its parents.
container.find( '.dropdown-toggle.toggle-on' )
.not( _this )
.not( _this.parents( '.children, .sub-menu' )
.prev( '.dropdown-toggle' )
)
.removeClass( 'toggle-on' )
.attr( 'aria-expanded', false );
...
} );
My attempts at pure JS code:
var container = document.querySelector( '.main-navigation' );
container.querySelectorAll( '.dropdown-toggle' ).forEach( item => {
item.addEventListener( 'click', function( e ) {
var _this = e.target;
e.preventDefault();
// Remove toggle classes and attributes from all menu items except the active one and its parents.
container.querySelector( '.dropdown-toggle.toggle-on' );
// How to convert the rest of the chained methods to pure JS?
???.classList.remove( 'toggle-on' ));
???.setAttribute( 'aria-expanded', false );
...
} );
} );
Basically, I don't know how to convert the not() methods to pure JS. I've seen some people resort to the :not CSS selector but I don't know if it's possible in this case.
Any help would be appreciated.
var container = document.querySelector( '.main-navigation' );
container.querySelectorAll( '.dropdown-toggle' ).forEach( item => {
item.addEventListener( 'click', function( e ) {
var _this = e.target;
e.preventDefault();
// Remove toggle classes and attributes from all menu items except the active one.
container.querySelectorAll( '.dropdown-toggle.toggle-on' ).forEach(el => {
el.classList.remove('toogle-on');
el.setAttribute( 'aria-expanded', false );
}
// add class, change attribute to clicked el
e.target.classList.add('toogle-on');
e.target.setAttribute( 'aria-expanded', true );
});
} );

Limit the items shown in a ul element

Here's my code to limit the number of visible list items in a ul:
$wnd.$(el)
.find('li:gt(9)')
.hide()
.end()
.append(
$wnd.$('<li>+More</li>').click( function(){
$wnd.$(this).siblings(':hidden').show().end().remove();
})
);
When +More is clicked it will show all the items immediately.
What should be added in the code such when +More is clicked it will not show everything yet, just the next 10 items? Then, when all items are shown, a +Less option should be shown to just show the first 10 items, as it was before.
That's a strange syntax, but something like this maybe
$wnd.$(el)
.find('li:gt(9)')
.hide()
.end()
.append(
$wnd.$('<li>+More</li>').click(function () {
$wnd.$(this).remove().siblings(':hidden').slice(0, 10).show();
if ($wnd.$(el).find('li:hidden').length === 0) {
$wnd.$(el).append(
$wnd.$('<li>+Less</li>').click(function () {
$wnd.$(el).find('li:gt(9)').hide();
})
)
}
})
);
This is one way:
$( 'li:gt(9)' )
.hide()
.parent()
.append(
$( '<li>more</li>' ).on( 'click', function() {
var el = $( this ).siblings( ':hidden' );
if ( el.length ) el.slice( 0, 10 ).show();
else $( 'li:gt(9)' ).not( this ).hide();
$( this ).text( $( this ).siblings( ':hidden' ).length ? 'more' : 'less' );
})
);
FIDDLE
How about this? https://jsfiddle.net/0hyL9ngr/
HTML
<ul id='some-list'>
<li class='list-item'>1</li>
<li class='list-item'>2</li>
<li class='list-item'>3</li>
...
<li class='list-item'>39</li>
<li class='list-item'>40</li>
<li class='list-item'>41</li>
<li id='show-more'>More</li>
<li id='show-first-ten'>Less</li>
</ul>
JavaScript
$('#show-more').on('click', function () {
$('.list-item:hidden:lt(10)').show();
if ($('.list-item:hidden').length == 0) {
$(this).hide();
$('#show-first-ten').show();
}
});
$('#show-first-ten').on('click', function () {
$('.list-item:gt(9)').hide();
$(this).hide();
$('#show-more').show();
});
CSS
#show-more {
cursor: pointer;
}
#show-first-ten {
display: none;
cursor: pointer;
}
.list-item:nth-child(n+11) {
display: none;
}

jQuery multiple toggle hide all / show only one

Hello Dear Programmers,
I have a header menu, with "Search", "Language", "Time" toggle functions.
Regarding display onClick it works correctly, but I need If I Click on "Search" show only "Search" and hide all "Language", "Time".
My code
.js
$( '.search-toggle' ).on( 'click.twentyfourteen', function( event ) {
var that = $( this ),
wrapper = $( '.search-box-wrapper' );
that.toggleClass( 'active' );
wrapper.toggleClass( 'hide' );
if ( that.is( '.active' ) || $( '.search-toggle .screen-reader-text' )[0] === event.target ) {
wrapper.find( '.search-field' ).focus();
}
} );
$( '.language-toggle' ).on( 'click.twentyfourteenn', function( event ) {
var that = $( this ),
wrapper = $( '.language-box-wrapper' );
that.toggleClass( 'active' );
wrapper.toggleClass( 'hide' );
} );
$( '.time-toggle' ).on( 'click.twentyfourteennn', function( event ) {
var that = $( this ),
wrapper = $( '.time-box-wrapper' );
that.toggleClass( 'active' );
wrapper.toggleClass( 'hide' );
} );
and html
<div class="search-toggle">
<?php _e( 'Search', 'twentyfourteen' ); ?>
</div>
<div class="language-toggle">
<?php _e( 'Search', 'twentyfourteenn' ); ?>
</div>
<div class="time-toggle">
<?php _e( 'Search', 'twentyfourteennn' ); ?>
</div>
<div id="search-container" class="search-box-wrapper hide">
<div class="search-box">
<?php get_search_form(); ?>
</div>
</div>
<div id="language-container" class="language-box-wrapper hide">
<div class="language-box">
language
</div>
</div>
<div id="time-container" class="time-box-wrapper hide">
<div class="time-box">
time
</div>
</div>
If I understand what you mean you want to hide two different elements when clicking search you want the others to hide?
By using add you can group elements together then add classes to show or hide:
$('#element1_id').add('#element2_id').removeClass('show');
$('#element1_id').add('#element2_id').addClass('hide');
or just straight up hide them with jQuery.
$('#element1_id').add('#element2_id').hide();
You could also give the element you want to hide together a common class name:
ie: toggle
then you can simply use the class toggle to hide them:
$('.toggle').removeClass('show');
$('.toggle').addClass('hide');
or
$('.toggle').hide();
i think this will hide other parts, i have not tried this but hope will work for u
$( '.search-toggle' ).on( 'click.twentyfourteen', function( event ) {
var that = $( this ),
wrapper = $( '.search-box-wrapper' );
that.toggleClass( 'active' );
$( '.search-box-wrapper' ).hide();
$( '.time-box-wrapper' ).hide();
$( '.language-box-wrapper' ).hide();
if ( that.is( '.active' ) || $( '.search-toggle .screen-reader-text' )[0] === event.target ) {
wrapper.find( '.search-field' ).focus();
}
} );
$( '.language-toggle' ).on( 'click.twentyfourteenn', function( event ) {
var that = $( this ),
wrapper = $( '.language-box-wrapper' );
$( '.search-box-wrapper' ).hide();
$( '.time-box-wrapper' ).hide();
$( '.language-box-wrapper' ).hide();
that.toggleClass( 'active' );
} );
$( '.time-toggle' ).on( 'click.twentyfourteennn', function( event ) {
var that = $( this ),
wrapper = $( '.time-box-wrapper' );
$( '.search-box-wrapper' ).hide();
$( '.time-box-wrapper' ).hide();
$( '.language-box-wrapper' ).hide();
that.toggleClass( 'active' );
} );
This should solve the problem. You can view working demo with this link Working Demo
Summary of what I did.
I added some text as link in the html (just for testing)
I added .hide() Jquery class to hide the three wrapper classes before the click events
I added a little bit of animation to wrapper.toggle('slow')
I changed wrapper.toggleClass('slow') to wrapper.toggle('slow')
$('.search-box-wrapper').hide();
$('.language-box-wrapper').hide();
$('.time-box-wrapper').hide();
$('.search-toggle').on('click.SearchLink', function (event) {
var that = $(this),
wrapper = $('.search-box-wrapper');
that.toggleClass('active');
wrapper.toggle('slow');
if (that.is('.active') || $('.search-toggle .screen-reader-text')[0] === event.target) {
wrapper.find('.search-field').focus();
}
});
$('.language-toggle').on('click.LangLink', function (event) {
var that = $(this),
wrapper = $('.language-box-wrapper');
that.toggleClass('active');
wrapper.toggle('slow');
});
$('.time-toggle').on('click.TimeLink', function (event) {
var that = $(this),
wrapper = $('.time-box-wrapper');
that.toggleClass('active');
wrapper.toggle('hide');
});

dotimeout not working properly

I am trying to use the dotimeout plugin to create a delay for the effect of showing a sub-nav when hovering over the top nav. The plug in seems to work well when the active class is added to the first li but when added to subsequent li's, it stops showing the hidden ul for this above the active li.
Here's my script:
$(function(){
$('ul.main-nav').each(function(){
var nav = $(this);
nav
.mouseover(function(e){
nav.doTimeout( 'main-nav', 500, over, e.target );
}).mouseout(function(){
nav.doTimeout( 'main-nav', 500, out );
});
function over( elem ) {
var parent = $(elem).closest( 'li.main-nav' );
out( parent );
parent.children( 'a' ).addClass( 'hover' );
parent.children( 'ul:hidden' ).slideDown( 'fast' );
};
function out( elem ) {
var parents = elem
? $(elem).closest( 'li.main-nav' ).siblings()
: nav.children();
if ( nav.is( '.main-nav-horizontal' ) ) {
parents = parents.not( '.active' );
}
parents.children( 'a' ).removeClass( 'hover' );
parents.children( 'ul' ).hide();
};
});
});
Here's my jsfiddle
I can see people are using this plugin so this issue seems like it should be easily solved but everything as far as I can see should work properly.
Change your out function to this.
function out( elem ) {
var parents;
if (elem) {
parents = $(elem).closest( 'li.main-nav' ).siblings();
}
else {
parents = nav.children();
showthisone = parents.filter( '.active' );
parents = parents.not( '.active' );
}
parents.children( 'a' ).removeClass( 'hover' );
parents.children( 'ul' ).hide();
if (!elem) {
showthisone.children( 'a' ).addClass('hover');
showthisone.children( 'ul' ).show();
}
};

jQuery: change css of the page number when scrolling

I'm trying to figure how to change the css class of #pg2 to 'active' when the user scrolls to #bx2 and change #pg3 to 'active' when the user scrolls to #bx3 and so on...
<ul id="navi" style="position:fixed;top:0">
<li>1</li>
<li>2</li>
<li>3</li>
...
<li>100</li>
</ul>
<div class="tallbigblock" id="bx1">...</div>
<div class="tallbigblock" id="bx2">...</div>
<div class="tallbigblock" id="bx3">...</div>
...
<div class="tallbigblock" id="bx100">...</div>
Here is my jquery:
$( window ).scroll( function() {
var t = $( "#bx1" ).offset().top;
if( $(this).scrollTop() > t )
{
$( "#navi li a" ).removeClass( "active" ).hasClass( "active" );
$( "#pg1" ).addClass( "active" );
}
var t = $( "#bx2" ).offset().top;
if( $(this).scrollTop() > t )
{
$( "#navi li a" ).removeClass( "active" ).hasClass( "active" );
$( "#pg2" ).addClass( "active" );
}
var t = $( "#bx3" ).offset().top;
if( $(this).scrollTop() > t )
{
$( "#navi li a" ).removeClass( "active" ).hasClass( "active" );
$( "#pg3" ).addClass( "active" );
}
});
The thing is, if I have a 50 ".tallbigblock" divs... or dynamically generated ".tallbigblock" divs...
I've been trying to figure out how to make the jquery work for n number of ".tallbigblock" divs without coding the jquery for each div manually...
hope you guys can help me out...
Thanks a bunch!!
This is untested but the only difference from the original code is that it's not hard-coded and only allows one box to be active at a time.
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
$('#navi li a').removeClass('active');
$('.tallbigblock').each(function()
{
if(scrollTop > $(this).offset().top)
{
$('#pg'+this.id.split('x')[1]).addClass('active');
return false; // this breaks the each loop
}
});
});
Based on the code #summoner posted, I've modified and tested the following code:
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
$(".tallbigblock").each(function() {
if(scrollTop > $(this).offset().top)
{
var i = $(this).attr('id');
var nid = "#pg" + i.replace("bx", "");
$("#navi li a").removeClass("active").hasClass("active");
$(nid).addClass("active");
}
});
});

Categories