So I have a nested bootstrap dropdown in my navbar. Here is the code that prevents the dropdown on click of a nested drop to execute its normal task. This works well.
(function($) {
$(document).ready(function() {
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(event) {
event.preventDefault();
event.stopPropagation();
$(this).parent().siblings().removeClass('open');
$(this).parent().toggleClass('open');
});
});
})(jQuery);
In this code, onclick of the dropdown's <li> does something. When the click is on a normal li of the dropdown it works fine but when it is in a nested dropdown's li the function is executed but when it ends it is executed again (the onClick). The way I've found to avoid that its complete seconde execution is I check in my if statement if $(this) (the clicked li) is null, which it is when it's executed the second time out of nowhere. This way is pretty gross but it works, but does anyone see why the method is called a second time and how to stop it from getting called twice?
$("#dropdownViewModeSelect").on('click', 'li', function() {
selectedViewMode = $(this).attr("viewmode");
if (selectedViewMode != "undefined" && selectedViewMode != null)
{
if (selectedViewMode != previouslySelectedViewMode || currentTimelineMode != previouslySelectedTimelineMode)
{
//Remove glyphicons to all i
var touslesideslis = $("#dropdownViewModeSelect li").find("i").removeClass('glyphicon glyphicon-ok');
//Add glyphicons to clicked i
$(this).find("i").addClass('glyphicon glyphicon-ok');
//Add text to button
currentViewModeSecondary = $(this).attr("viewmodesecondary");
var textBtn;
if (currentViewModeSecondary != "classic")
textBtn = "Ligne du temps - " + $(this).text();
else
textBtn = $(this).text();
$("#dropdownMenuViewMode").text(textBtn);
$("#dropdownMenuViewMode").append('<span class="glyphicon glyphicon-eye-open pull-left"></span>');
$("#dropdownMenuViewMode").append('<span class="caret caret-filter"></span>');
if ($(window).width() >= 768)
Global.Responsiveness();
}
}
});
Here's my HTML for the dropdown.
<li class="dropdown"> <a class="dropdown-toggle" id="dropdownMenuViewMode" data-toggle="dropdown" role="button" aria-expanded="false"><span class="glyphicon glyphicon-eye-open pull-left"></span>Jour<span class="caret"></span></a>
<ul class="dropdown-menu" id="dropdownViewModeSelect" role="menu">
<li viewmode="jour" viewmodesecondary="classic"><a id="linkJour">Jour<i class='dropdownFiltreImage glyphicon glyphicon-ok'></i></a>
</li>
<li viewmode="ressource" viewmodesecondary="classic"><a id="linkRessource">Ressources/Jour<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="week" viewmodesecondary="classic"><a id="linkSemaine">Semaine<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="month" viewmodesecondary="classic"><a id="linkMois">Mois<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="year" viewmodesecondary="classic"><a id="linkAnnee">Année<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="agenda" viewmodesecondary="classic"><a id="linkAgenda">Agenda<i class='dropdownFiltreImage'></i></a>
</li>
<li class="dropdown dropdown-submenu">Ligne du temps
<ul class="dropdown-menu">
<li viewmode="timeline" viewmodesecondary="timeline"><a id="linkTimelineDay">Jour<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="timeline" viewmodesecondary="timeline"><a id="linkTimelineWeek">Semaine<i class='dropdownFiltreImage'></i></a>
</li>
<li viewmode="timeline" viewmodesecondary="timeline"><a id="linkTimelineMonth">Mois<i class='dropdownFiltreImage'></i></a>
</li>
</ul>
</li>
</ul>
If your click handler is being called twice it is probably being set twice. Try changing your selector. This may not be the ultimate class structure you want but I'll bet if you add the same class to each of your list elements and then use that class in the selector for the click handler your problem goes away.
Related
I have three same items in the DOM. Exactly what I mean is a wobbling line <span class="caret"></span>
<ul>
<li class="nav-item-1">
ITEM 1
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-2">
ITEM 2
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-3">
ITEM 3
<span class="caret"></span>
</li>
</ul>
Scenario:
I click on the first <span class="caret"></span> gets the class "open", and the rest still has only "caret". I click on the second <span class="caret"></span> gets the class "open", and in the first the class "open" is removed. Is it possible? I wrote something like this:
$(".caret").click(function () {
$(this).data('clicked', true);
if ($('.caret').data('clicked')) {
$(".caret").toggleClass('opened');
}
});
It works, but all "caret" classes get toggleClass('opened') and I just want it to get the one you click on...
You were on the right track by using $(this) but then reverted back to using $('.caret'). Do this:
$(".caret").click(function () {
$(this).toggleClass('opened');
});
Askers request to close all other .caret classes:
$(".caret").click(function () {
$(".caret").removeClass('opened');
$(this).addClass('opened');
});
Your HTML is invalid so it is going to produce wrong HTML Markup in the browser. Not knowing how you actually want it to look, I can not offer a solution on fixing it. Once you get it fixed, The basic code should be
$('.caret').on('click', function () {
$('.caret.opened') // all the open carets
.not(this) // removed the one that was clicked
.removeClass('opened'); // remove the class
$(this)
.toggleClass('opened'); // toggle the one that was clicked
//.addClass('opened'); // if you want it always open
});
if one always has to be opened
$('.caret').on('click', function () {
$('.caret.opened') // all the open carets
.removeClass('opened'); // remove the class
$(this)
.addClass('opened'); // set clicked to open
});
I have a feeling you might have meant this
having a span in a UL is invalid HTML
$(".nav-item a").on("click",function(e) {
e.preventDefault();
$(".caret").removeClass('opened');
$(this).next(".caret").addClass('opened'); // could toggle if needed
});
.caret::after { content: "🡁" }
.opened::after { content: "🠿" }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="nav-item" id="nav-1">ITEM<span class="caret"></span></li>
</ul>
<ul>
<li class="nav-item" id="nav-2">ITEM<span class="caret"></span></li>
</ul>
<ul>
<li class="nav-item" id="nav-3">ITEM<span class="caret"></span></li>
</ul>
jQuery is not needed for this unless you're already using it in other places in your project.
const navItems = [...document.querySelectorAll("[class^=nav-item-")];
navItems.forEach(item => {
item.addEventListener("click", () => {
const opened = document.querySelector(".opened");
if (opened) {
opened.classList.remove("opened");
}
item.parentElement.querySelector(".caret").classList.add("opened");
});
});
/* demo only */
.caret.opened:after {
content: "opened";
}
<ul>
<li class="nav-item-1">
ITEM
</li>
<span class="caret"></span>
</ul>
<ul>
<li class="nav-item-2">
ITEM
</li>
<span class="caret"></span>
</ul>
<ul>
<li class="nav-item-3">
ITEM
</li>
<span class="caret"></span>
</ul>
The HTML needs correction. Something like below is syntactically more correct.
Let's add up CSS to show what caret looks like.
And then, in JavaScript, handle the toggle.
$("ul").click(function (e) {
var caret = $(this).find('.caret');
$('.caret').data('clicked', false);
$('.caret').removeClass('opened');
caret.data('clicked', true);
caret.toggleClass('opened');
});
.caret {
background-color: red;
border: 1px solid blue;
width: 10px;
height: 10px;
display: none;
}
.opened {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="nav-item-1">
ITEM
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-2">
ITEM
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-3">
ITEM
<span class="caret"></span>
</li>
</ul>
Please correct your HTML tag
missed anchor closing tag
add .nav class on each li
$(".nav").on('click', function() {
if ($(this).next('.caret').hasClass('clicked opened')) {
$('.caret').removeClass('clicked opened');
} else {
$('.caret').removeClass('clicked opened');
$(this).next('.caret').addClass('clicked opened');
}
});
https://jsfiddle.net/n56b84t9/1/
I want to hide my menu by clicking on any part of the web, rather than the menu button here is de js:
mobile_nav.click(function(){
if (desktop_nav.hasClass("js-opened")) {
desktop_nav.slideUp("slow", "easeOutExpo").removeClass("js-opened");
$(this).removeClass("active");
}
else {
desktop_nav.slideDown("slow", "easeOutQuart").addClass("js-opened");
$(this).addClass("active");
// Fix for responsive menu
if ($(".main-nav").hasClass("not-top")){
$(window).scrollTo(".main-nav", "slow");
}
}
});
and the HTML
<div class="inner-nav desktop-nav">
<ul class="clearlist scroll-nav local-scroll">
<li class="active">Home</li>
<li>Who we help</li>
<li>
Services <i class="fa fa-angle-down"></i>
<!-- Sub -->
<ul class="mn-sub to-left" style="background: white !important;">
<li>
Recovery Coaching
</li>
<li>
Coaching and Support for Loved Ones
</li>
<li>
Family and Couples Coaching
</li>
<li>
Interventions
</li>
<li>
LIFE COACHING IN RECOVERY
</li>
<li>
Separation and Divorce Coaching
</li>
<li>
Therapy
</li>
</ul>
<!-- End Sub -->
</li>
<li>About us</li>
<li>WORK WITH US</li>
<li>FAQ</li>
<li>Blog</li>
</ul>
</div>
I wanted a simple code that I can put in that js, because I tried to put in the head tag in the index but its not working, any ideas? I have the CSS too but I think its not relevant at this point, the site is:
http://www.familyaddictionspecialist.com/test/
Is this what you want?
var thatMenu = $('.thatMenu');
$(document).mouseup(function (e) {
if (!thatMenu.is(e.target) && thatMenu.has(e.target).length === 0) {
thatMenu.hide();
}
});
untested but looking at your code, this could work.
the idea is that there is an event handler on the body of the page that when it fires, it checks to make sure you haven't clicked on any child of js-opened, and closes the element with class js-opened.
$(document).ready(function(){
$("body").click(function(event) {
if ($(event.target).parents('div').hasClass("js-opened") === false){
console.log('closed menu');
$('.js-opened').slideUp("slow", "easeOutExpo").removeClass("js-opened");
}
});
});
var $menu = $('.main-nav');
$('mobile_nav').click(function () {
$menu.toggle();
});
$(document).mouseup(function (e) {
if (!$menu.is(e.target) // if the target of the click isn't the container...
&& $menu.has(e.target).length === 0) // ... nor a descendant of the container
{
desktop_nav.slideUp("slow", "easeOutExpo").removeClass("js-opened");
$(this).removeClass("active");
}
});
I want to set a child element to aria-expanded="true" when its parent contains a class active:
<li class="dropdown active">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
Section 4
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li class="">Section 4-1</li>
<li class="">Section 4-2</li>
</ul>
</li>
This code comes from a example here
When in that example, I scroll down to section 4-1 and 4-2 I would like the dropdown to open up. I have tried several things, but I have not found a working solution.
What you actually want is to add the class open to the active drop down, the effect you want has nothing to do with aria-expanded=true:
Use this code:
$(window).scroll(function(){
if ( $( ".dropdown" ).is( ".active" ) ) {
$( ".dropdown.active" ).addClass("open");
}
else
{
$( ".dropdown" ).removeClass("open");
}
});
If it on a click event, use something similar to this.
$('body').on('click', 'li.dropdown', function(){
if($(this).hasClass('active')){
$(this).children().attr('aria-expanded', true);
}
});
or
$('body').on('click', 'li.dropdown', function(){
if($(this).hasClass('active')){
$(this).find('a.dropdown-toggle').attr('aria-expanded', true);
}
});
This is something like my code:
<li class="dropdown" id="dropdown1">Dropdown<b class="caret"></b>
<ul class="dropdown-menu">
<li id="li-1">List1</li>
<li id="li-2">List</li>
</ul>
</li>
but when middle click is pressed I want to stop execution of my onclick event.
Something like this disables the onclick whenever the middle button is clicked
$(document).mousedown(function(e) {
if (e.which == 2) {
e.preventDefault();
alert("middle button");
$('a').prop("onclick", null); // disable onclick
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class="dropdown" id="dropdown1">Dropdown<b class="caret"></b>
<ul class="dropdown-menu">
<li id="li-1"><a href="#" onclick='alert("li-1")'>List1</a>
</li>
<li id="li-2"><a href="#" onclick='alert("li-2")'>List</a>
</li>
</ul>
</li>
event.button can have a value of 0,1,2 representing left, middle, and right mouse button respectively. Knowing that, you can take advantage of short circuit evaluation to get the job done.
(event.button !=1 ) && !alert('li-1') Is basically the same as
if(event.button != 1){
return !alert('li-i') // true (just to make sure the event it sent)
return false;
The first li in the snippet will alert() if it wasn't clicked by the middle mouse button, the second li will alert() if it wasn't clicked by the left mouse button.
<li class="dropdown" id="dropdown1">Dropdown<b class="caret"></b>
<ul class="dropdown-menu">
<li id="li-1">List1
</li>
<li id="li-2">List2
</li>
</ul>
</li>
My HTML code looks like this:
<div id="sidebar-menu" class="main_menu_side hidden-print main_menu">
<div class="menu_section">
<ul class="nav side-menu">
<li>
<a>
<i class="fa fa-home"></i>home
<span class="fa fa-chevron-down"></span>
</a>
<ul class="nav child_menu" style="display: none">
<li>
Dashboard
</li>
<li>
dashbord2
</li>
</ul>
</li>
<li>
<a>
<i class="fa fa-edit"></i>form
<span class="fa fa-chevron-down"></span>
</a>
<ul class="nav child_menu" style="display: none">
<li>
general form
</li>
<li>
form validation
</li>
</ul>
</li>
</ul>
</div>
</div>
to add/remove class based on current url, i am using this:
$(function () {
var url = window.location.href;
$('#sidebar-menu a[href="' + url + '"]').parent('li').addClass('current-page');
$('#sidebar-menu a').filter(function () {
return this.href == url;
}).parent('li').addClass('current-page').parent('ul').slideDown().parent().addClass('active');
});
It works, but when i click this link
dashbord2
the class="current-page" doesn't change to current path url
How i fix this?
Your issue arises from the page not being reloaded when you click on the link with hash in it, while your code only executes on page load, or dom ready to be exact. The solution is to whether use window's hashchange event (not supported in < IE8) or, like #sirrocco mentioned, use click event with setTimeout to detect the change of hash:
function setCurrentMenuPage() {
var url = window.location.href;
var anchors = $('#sidebar-menu a');
anchors.parent('li').removeClass('current-page');
anchors.filter(function () {
return this.href == url;
}).parent('li').addClass('current-page').parent('ul').slideDown().parent().addClass('active');
}
$(function () {
setCurrentMenuPage();
$('#sidebar-menu a').on('click', function (e) {
if ($(this).attr('href').indexOf("#") >= 0) {
setTimeout(function () {
setCurrentMenuPage();
}, 100);
}
});
});
Hope that helps.