How to add class to only one of multiple same elements - javascript

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/

Related

how to get a specific string in an href in javascript

I am trying to create an onload event where a function compares the current URL to an href and displays content according to the href that is shown. I want to accomplish this by selecting a child from a parent, though I am unsure as to how to get the contents within the href specifically. Here is a bit of the code I have written:
html
<ul id="main-nav">
<li class="nav active">Shipping</li>
<li class="nav">returns</li>
<li class="nav">Custom Orders</li>
<li class="nav">Replacements/ Warranty</li>
<li class="nav">Most Frequently Asked Questions</li>
<li class="nav">RAD Principles</li>
<li class="nav">Environmental Stewardship</li>
<li class="nav">MADE in the USA</li>
</ul>
js
var href = $("#main-nav").children('a');
$("div.faq-container").hide();
if (window.location.href.includes(href)) {
$("div.faq-container").eq("0").show();
} else (window.location.href.includes(href)) {
$("div.faq-container").eq("1").show();
}
the main issue I have is that I want to write the line that has
var href = $("#main-nav").children('a');
so that it grabs the contents within the href alone, and nothing else outside of that, so that it would have either "#shipping", "#returns", etc. as its value.
You took the problem by the wrong end. What you need to know is the location.hash to target the right div to display.
This should be closer:
var hash = window.location.hash
// Hide all .faq-container
$("div.faq-container").hide()
// If there is a hash
if(hash){
$("#"+hash).show()
}
Here's a vanilla JavaScript example which will make the selected section visible.
It uses the hashchange event to detect when the hash has changed.
const sections = [...document.querySelectorAll('.section')];
function showSelected () {
sections.forEach(section => section.classList.remove('show'));
if(location.hash.length) {
const section = document.querySelector(location.hash);
if (section) {
section.classList.add('show');
}
}
}
window.addEventListener('hashchange', showSelected);
.section {
margin: 0.5rem;
padding: 0.5rem;
background-color: #e0e0e0;
width: 10rem;
display: none;
}
.show {
display: block;
}
<ul id="main-nav">
<li class="nav active">Shipping</li>
<li class="nav">returns</li>
<li class="nav">Custom Orders</li>
<li class="nav">Replacements/ Warranty</li>
<li class="nav">Most Frequently Asked Questions</li>
<li class="nav">RAD Principles</li>
<li class="nav">Environmental Stewardship</li>
<li class="nav">MADE in the USA</li>
</ul>
<div id="shipping" class="section">#shipping</div>
<div id="returns" class="section">#returns</div>
<div id="custom" class="section">#custom</div>
<div id="replacements" class="section">#replacements</div>
<div id="mostFAQs" class="section">#mostFAQs</div>
<div id="RAD" class="section">#RAD</div>
<div id="environmental" class="section">#environmental</div>
<div id="USA" class="section">#USA</div>

Want to hide menu by clicking outside the menu element

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");
}
});

avoid closing the menu if submenu items is clicked

This is a multilevel menu. When i click the link "About" it opens the submenu which contains 3 links Johnny, Julie & Jamie.
When i click "About" again, it closes the menu. Clicking the submenu also closes the menu, and that i want to avoid.
How do i avoid closing the opened submenu, if i click the submenu (Johnny, Julie & Jamie) ?
$('li.parent').click(function() {
$(this).find('.sub-nav').toggleClass('visible');
});
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<li class="parent">About
<ul class="sub-nav">
<li>Johnny
</li>
<li>Julie
</li>
<li>Jamie
</li>
</ul>
</li>
<li class="parent">AnotherLink
<ul class="sub-nav">
<li>Martin
</li>
<li>Rasmus
</li>
<li>Morten
</li>
</ul>
</li>
</ul>
Alternative to stopPropagation approach for child elements would be adding a small check if the clicked element is the current one (and not it's descendants):
$('li.parent').click(function(e) {
if (this === e.target)
$(this).find('.sub-nav').toggleClass('visible');
});
$('li.parent').click(function(e) {
if (this === e.target)
$(this).find('.sub-nav').toggleClass('visible');
});
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<li class="parent">About
<ul class="sub-nav">
<li>Johnny
</li>
<li>Julie
</li>
<li>Jamie
</li>
</ul>
</li>
<li class="parent">AnotherLink
<ul class="sub-nav">
<li>Martin
</li>
<li>Rasmus
</li>
<li>Morten
</li>
</ul>
</li>
</ul>
You need to stopPropagation of event on child anchor elements:
$("li.parent a").click(function(e) {
e.stopPropagation();
});
You need to prevent the click on the .sub-nav element to be transmitted to your event handler: https://api.jquery.com/event.stoppropagation/

jQuery method called twice?

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.

click blank area go back to selected section

<li class="list ">A
<ul class="names">
<li class="list">1
</li>
<li class="list">2
</li>
</ul>
</li>
<li class="list ">B
<ul class="names selected">
<li class="list selected">1
</li>
<li class="list">2
</li>
<li class="list">3
</li>
<li class="list">4
</li>
</ul>
</li>
<li class="list ">C
<ul class="names">
<li class="list">1
</li>
<li class="list">2
</li>
<li class="list">3
</li>
<li class="list">4
</li>
</ul>
</li>
$('.list').click(function () {
var that = this;
$('.list').each(function () {
if (that == this) return true; //continue
$('.names:not(:hidden)', this).slideToggle();
});
$('ul.names', this).slideToggle();
})
ul.names{display: none;}
li.list{
width:150px;
background:#A9FF7A;
}
ul.names {
width:150px;
background:#A9FF7A;
}
ul.selected{
display: block;
}
li.selected{
background:red;
}
online Sample: http://jsfiddle.net/gyYyd/
B's submenu 1 is highlighted. If I click on menu A or C, then A or C section will be opened, but how do I click PAGE BLANK area (outside of the background color) to go back to B section (to open B section)
Thanks in advance
You can capture clicks on the document object and trigger a click on the required list item.
$(document).click(function() {
var selected = $('.selected:first');
if(!selected.closest('ul.names').is(':visible')) {
selected.closest('.list').trigger('click');
}
});
Also, make sure to return false from your current list item click handler - so that normal clicks on list items don't propagate to the above handler.
DEMO: http://jsfiddle.net/gyYyd/2/

Categories

Resources