I have 5 divs that contain copy.
I have a back and next button, to display each div.
Back | Next
<div class="vote-result first">
this is example copy
</div>
<div class="vote-result">
this is some more copy
</div>
<div class="vote-result">
some more copy
</div>
<div class="vote-result">
this is the last div
</div>
// hide the divs, except the first one.
.vote-result { display: none; }
.vote-result.first { display: block; }
The first time the next button link is clicked, I want to remove the off class, to show it as clickable, I probably should disable the link initially too and re-enable it too.
$(".back-btn").removeClass("off");
Once I display the last div, I need to add the off class to the next-btn and disable it.
I thought about using a carousel js plugin to accomplish this, but it is overkill for now.
I know of a way to do this, but it would involve assigning subclasses to the links based on what next or back button was clicked, so it will know what div to show next, as well as removing or adding the off class to the links.
I am hoping to find a solution that allows me to add more div's to display without modifying the code. Any help is appreciated, thank you.
Here is solution for you. I have created Fiddle for your requirement.
HTML code:
<a class="back-btn off">Back</a> | <a class="next-btn">Next</a>
<div class="vote-result first selectedDiv">
this is example copy
</div>
<div class="vote-result">
this is some more copy
</div>
<div class="vote-result">
some more copy
</div>
<div class="vote-result last">
this is the last div
</div>
JS/JQuery Code:
$(".back-btn").click(function(){debugger;
var prevElement=$('.selectedDiv').prev();
prevElement.show();
$(".selectedDiv").hide();
$(".selectedDiv").removeClass("selectedDiv");
prevElement.addClass("selectedDiv");
if($('.first').css('display')=="block"){
$(".back-btn").addClass("off");
}
else{
$(".next-btn").removeClass("off");
}
});
$(".next-btn").click(function(){debugger;
var nextElement= $('.selectedDiv').next();
nextElement.show();
$(".selectedDiv").hide();
$(".selectedDiv").removeClass("selectedDiv");
nextElement.addClass("selectedDiv");
if($('.last').css('display')=="block"){
$(".next-btn").addClass("off");
}
else{
$(".back-btn").removeClass("off");
}
});
CSS code:
.vote-result { display: none; }
.vote-result.first { display: block; }
.off{display:none;}
Your HTML file:
<html>
<head>
<style>
.vote-result { display: none; }
.vote-result.first { display: block; }
.off {
color: Red;
}
a {
color: blue;
}
</style>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="code.js"></script>
</head>
<body>
Back | Next
<div class="vote-result first">
this is example copy
</div>
<div class="vote-result">
this is some more copy
</div>
<div class="vote-result">
some more copy
</div>
<div class="vote-result">
this is the last div
</div>
</body>
</html>
Your new "code.js" file in the same directory:
/**
* The zero-based index of the <div class="vote-result"> element that is currently being shown
* #var {Number}
*/
var activeIndex = 0;
function getNumberOfItems() {
return $('.vote-result').length;
}
function synchronizeInterface() {
var numberOfItems = getNumberOfItems(),
lastIndex = numberOfItems - 1;
$('.vote-result').removeClass('first');
$('.vote-result').each(function(index) {
if (index == activeIndex) {
$(this).addClass('first');
}
})
$('.back-btn').toggleClass('off', activeIndex == 0);
$('.next-btn').toggleClass('off', activeIndex == lastIndex);
}
$(function() {
$('.back-btn,.next-btn').on('click', function() {
// If the button clicked is not deactivated
if (!$(this).hasClass('off')) {
// Determine whether the "Next" button was clicked (otherwise "Back" was clicked)
var clickedNext = $(this).hasClass('next-btn');
// Move the active index in the appropriate direction while not allowing it to fall outside the boundaries of appropriate indices
activeIndex = clickedNext
? Math.min(activeIndex + 1, getNumberOfItems() - 1)
: activeIndex = Math.max(0, activeIndex - 1);
// Make sure the interface now reflects the updated JavaScript variables
synchronizeInterface();
}
return false;
});
});
Some notes: You had an unclosed double-quote for one of your class attributes in your provided HTML. Also, I added some additional styling -- you may want to rename the ".first" CSS class to ".active" instead.
take a look at jquerys .next() function for navigating - jQuery - Next(). you can also check for the last item like this.
if($(this).is(':last-child'))
{
$('.next-btn').removeClass('off');
}else{
$('.next-btn').addClass('off');
}
check everytime a navigation button is clicked and do the same for the first button
Related
(I will link a code sandbox with all my code (at its latest) to be viewed if you want to)
https://codesandbox.io/s/distracted-hellman-pyej06?file=/index.html
I have two issues that I was hoping to address
Problem-1: I have a website called dirieahmed. ml (the same as the code sandbox) I have a night mode / light mode toggle, however when I click on night mode my logo (the image which is called hello.jpg and is above the face picture) will stay the same which makes sense but looks terrible because it looks like an imperfect white square. As a result, I wanted to change this. Therefore when I click on night mode I want the image to change into the night mode version of the logo I have made (it will be called hello-dark.jpg) Is there a way i can do that? I will link the appropriate code down below but if you would like to see the CSS you can view the sandbox
<div class="image1">
<img src="img/hello.jpg" alt="something" width="400" height="300">
</div>
<script async>
<--!This is my dark theme toggle-->
document.querySelector('.theme-toggle-button').addEventListener('click', () => {
document.body.classList.toggle('dark')
})
Problem-2: On my sandbox, you can view an About me, Education and Achievements and Other content elements, these elements are buttons when clicked they will drop down a content, if I click on about me then Education about me will open then close and allow Education to open. Pretty Normal and similarly for the button called "Other" but when i click on Other again to reset all the views and make it clean like when it was originally where no dropdowns exsisted that wont happen. Is there a way for me to make a javascript that will close all content from that div when clicked on it twice. (the code of CSS is in the sandbox but Html and JS will be here)
<div class="container">
<button id="one" class="click one" title="click me">About Me</button>
<div class="list-1 sec">
<h1 class="content-header-one content">Dummy text header</h1>
<p class="content-paragraph-one">Dummy text</p>
</div>
<button class="click two" title="click me">Education and Achivements</button>
<div class="list-2 sec">
<p class="content-paragraph2 content">Dummy text</p>
<ul class="content-list content">
<li>- Achivement #1</li>
<li>- Achivement #2</li>
<li>- Achivement #3</li>
</ul>
</div>
<button class="click three" title="click me" >Other</button>
<div class="list-3 sec">
<h1 class="content-header-two content">Dummy text header</h1>
<p class="content-paragraph3 content">Dummy text</p>
</div>
<script async>
// Instanciate List div's
let list1 = document.querySelector(".list-1");
let list2 = document.querySelector(".list-2");
let list3 = document.querySelector(".list-3");
// Reset's all views to the default without .newlist
const resetAllViews = () => {
list1.classList.remove("newlist");
list2.classList.remove("newlist");
list3.classList.remove("newlist");
};
// Checks to see what button is clicked and shows correct list based on input
document.addEventListener(
"click",
function (e) {
e = e || window.event;
var target = e.target;
if (target.classList.contains("one")) {
resetAllViews();
list1.classList.add("newlist");
}
if (target.classList.contains("two")) {
resetAllViews();
list2.classList.add("newlist");
}
if (target.classList.contains("three")) {
resetAllViews();
list3.classList.add("newlist");
}
}, false);
</script>
</div>
Again you can view the result I have in the sandbox (latest) and on the most recent website dirieahmed.ml for real life view
Sorry if I repeated myself a lot and any help would be appreciated though I prefer if you can show me the code as a runner snippet as I am fairly new so its a bit difficult for me to understand all vocabulary but again any help is appreciated
As for the 1st point, i think you have 2 possibilities:
Add the image as a background image with css, so you can easily toggle. Normally you show the "light" image, and if the body has the dark class then you can show the "dark" image.
The second idea is to add two <img> elements to the page and hide / show accordingly, something like:
.image-light {
display: block;
}
body.dark .image-light {
display: none;
}
.image-dark {
display: none;
}
body.dark .image-dark {
display: block;
}
As to the 2nd point i think you should to it like this:
you have a variable to hold the current open element
when you click a button you get the "value" vor that button
If the value if the same as the current open variable, then you reset the variable (maybe to null), otherwise you set the current open variable to the value of that button
Then you can have an update function. On this function you go through all the of "target" elements. If the element corresponds to the currently open variable, you open it, otherwise you close it.
Something like:
let currentlyOpen = null;
let buttons = document.querySelectorAll(".your-buttons");
let targets = document.querySelectorAll('.your-targets');
button.forEach((button) => {
button.addEventListener('click', (event) => {
const newTarget = event.target.getAttribute('your-identifier-attribute');
currentlyOpen = currentlyOpen === newTarget ? null : newTarget;
updateUI();
});
})
function updateUI() {
targets.forEach((target) => {
targetIdentifier = target.getAttribute('the-identifier-attribute');
targetIdentifier === currentlyOpen
? target.classList.add('your-class-for-open-list')
: target.classList.remove('your-class-for-open-list');
})
}
I have created an example for you:
let openContent = null;
const buttons = document.querySelectorAll('button');
const contents = document.querySelectorAll('.content');
buttons.forEach((button) => {
button.addEventListener('click', (event) => {
const newTargetId = event.target.getAttribute('target-id');
openContent = newTargetId === openContent ? null : newTargetId;
updateUI();
});
});
function updateUI() {
contents.forEach((content) => {
const contentId = content.getAttribute('id');
contentId === openContent
? content.classList.add('visible')
: content.classList.remove('visible');
});
}
.content {
display: none;
}
.content.visible {
display: block;
}
<p> click one of the buttons to show more content</p>
<button target-id="one">One</button>
<button target-id="two">Two</button>
<button target-id="three">three</button>
<p class="content" id="one">Content one</p>
<p class="content" id="two">Content two</p>
<p class="content" id="three">Content three</p>
Here is an example of doing this using two elements where one is hidden based on theme. You could make it a photo that you want to change. This way both images are loaded and you don't have to have the client wait for an image to load when themes change.
The way I accomplished this was mainly in css. The only javascript is to toggle the dark class on the page. The dark page has css variables which represent whether or not elements on the page have a display of none or block. On the actual elements which toggle, I feed those css variables into them. It is also possible to add animations or transitions to make it feel fancy, but hopefully this small demonstration satisfies your need for modifications to your own project.
const $ = str => document.querySelector(str);
const page = $(".page");
$(".theme-toggle").addEventListener("click", () => {
page.classList.toggle("dark");
});
body {
display: grid;
place-items: center;
}
.page {
--light-logo: block;
--dark-logo: none;
display: flex;
flex-direction: column;
text-align: center;
}
.page.dark {
--light-logo: none;
--dark-logo: block;
background-color: black;
color: white;
}
.logo-container {
font-size: 5rem;
}
.logo-container .dark {
display: var(--dark-logo);
}
.logo-container .light {
display: var(--light-logo);
}
<div class="page">
Hello World
<div class="logo-container">
<div class="light">🌞</div>
<div class="dark">🌑</div>
</div>
<button class="theme-toggle">🌞 / 🌑</button>
</div>
Answer 1: It is possible to simple solve by CSS, but this is not good idea for the SEO optimization. Better and most simple solution is to use 2 images and add class "hidden", where you will set for this class {display:none} in css file. Next you must modify your script to set/remove "hidden" class by the selected light/dark mode.
<div class="image1">
<img src="img/hello.jpg" alt="something" width="400" height="300">
</div>
Another better solution is modify the DOM, replace img element when mode is changed, or change the src attribute, e.g.:
document.getElementById("myImageId").src="img/hello-dark.jpg";
This is hard to explain precisely. But here we go:
I have a button that calls a function
<button onclick="myFunction_gsm()">Men</button>
When the button is pressed, it triggers a script. This script grabs a hidden section and displays it. The script goes like this:
<script>
//Gender Selection Script Men//
function myFunction_gsm() {
var x = document.getElementById("men-sizing");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
</script>
On the screen this plays out so that you click the button, a section appears, if I click the same button again the section hides again. However, I have another 2 sections. 3 Sections in total. For this example, the above script works for 1 section, the A section. There is also B and C. I would like to include the behavior that when A has been pressed, therefore displaying section A, if I then press the button for B the B section appears but the A section disappears without having to press the A button again. A Dynamic change of sorts.
I am a complete starter for coding but I assume it's something you add into the if statement. Any help would be greatly appreciated.
I would prefer solutions that incorporate the code I have now, since I won't have much use recreating it from scratch. It would solve this, but cause many new problems.
Define a class for all sections, for example sec. On click event pass the selected id, hide all of them and just toggle the selected one.
function myFunction_gsm(sectionId) {
let sec = document.querySelectorAll('.sec');
sec.forEach(itm => {
if(itm.id !== sectionId) itm.style.display = 'none'
})
var x = document.getElementById(sectionId);
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
let sec = document.querySelectorAll('.sec');
sec.forEach(itm => {
itm.style.display = 'none'
})
<button onclick="myFunction_gsm('sec1')">Sec1</button>
<button onclick="myFunction_gsm('sec2')">Sec2</button>
<button onclick="myFunction_gsm('sec3')">Sec3</button>
<div class="sec" id="sec1"> some text 1 here</div>
<div class="sec" id="sec2"> some text 2 here</div>
<div class="sec" id="sec3"> some text 3 here</div>
You might use class names for the sections. Then at the start of the function have all elements with that class name be hidden and afterwards display the currently clicked one.
If you want to preserve the toggle functionality for the section (so clicking A twice displays and hides it again), you want to check the display state of the currently clicked one first before hiding all. And then only display the clicked one if it was hidden before.
The modern approach is to avoid using .style within JS. This add the stylign as inline-style which ahs the highest specificty weight with exeption of important. The modern solution is to use classList to apply, remove or toggle a CSS-Class.
You add a class to CSS to hide element such as: .display-none { display: none; }`
Then you add a function to your button to hide all sections with a certain class by adding the class mentioned at step 1: function hideAll() { document.querySelectorAll('.class-name').forEach(el => el.classList.add('display-none')); }
You add a second function to the onclick trigger of a button thow a certain element by removing the class: element.classList.remove('display-none');
function hideAll() {
document.querySelectorAll('.section').forEach(el => el.classList.add('display-none'));
}
function showA() {
document.querySelector('#section-a').classList.remove('display-none');
}
function showB() {
document.querySelector('#section-b').classList.remove('display-none');
}
function showC() {
document.querySelector('#section-c').classList.remove('display-none');
}
.display-none {
display: none;
}
<button onclick="hideAll(); showA()">Show A</button>
<button onclick="hideAll(); showB()">Show B</button>
<button onclick="hideAll(); showC()">Show C</button>
<section id="section-a" class="section display-none">Section A</section>
<section id="section-b" class="section display-none">Section B</section>
<section id="section-c" class="section display-none">Section C</section>
CSS-only Solution
If you dont want to sue scripts, you could use a pure CSS-Method that works through the :target selector. This allows you to use anchor as "trigger".
Hide the scetiond with display: none; either by selecting them directly or adding a class to them.
use an anchor with an href="#id" instead of a link. This will move the page to that element but also manipulate the websites adress.
Use *:target { display: block; } to show targeted elements:
.display-none {
display: none;
}
*:target {
display: block;
}
/* for styling purpose only */
a {
margin-right: 15px;
}
Show A
Show B
Show C
<section id="section-a" class="display-none">Section A</section>
<section id="section-b" class="display-none">Section B</section>
<section id="section-c" class="display-none">Section C</section>
I want buttons in a slider to get underlined when a slide is visible.
I think I need to check if a data attribute is true, and then add class.
When inspecting my webpage, I find this in properties > dataset: DOMStringMap > isactiveslide: "true"
I need to check if a slide has isactiveslide: "true" (or even data-isactiveslide: "true") and then add class.
I think I am close and have tried these two codes:
jQuery(function () {
if (jQuery('menu1').attr('isactiveslide') === true) {
jQuery(this).find("#test1").addClass("underline");
}
})
and
jQuery('menu1').each(function(){
if(jQuery(this).attr('isactiveslide')==true())
jQuery('#test1').addClass('underline');
})
EDIT (added after some great answers and questions)
And here is the section, where the data attribute "isactiveslide" occurs, copied from the page:
<rs-slide data-key="rs-1898" data-title="WORKS" data-in="o:0;" data-out="a:false;" class="menus works1" id="works1" data-originalindex="2" data-origindex="1" data-description="" data-sba="" data-scroll-based="false" style="overflow: hidden; height: 100%; width: 100%; z-index: 20; opacity: 1; visibility: inherit;" data-owidth="300" data-oheight="200" data-rspausetimeronce="0" data-isactiveslide="true"><
So, the next slide which is not yet shown has data-isactiveslide="false". I reckon, identifying "true" is how I can add class.
EDIT May 4th - I think I am close now, but it still does not work.
jQuery('#slide1[data-isactiveslide="true"]')("#slide1-btn").addClass('.underline');
any help is very appreciated!
Can be easily done by css:
You need to find the class applied on the active slide and button
rs-slide.menus[data-isactiveslide="true"] .button-class-name-here{
text-decoration:underline!important;
}
or
Find which slider you are using and on the slide change event of that slider apply the class on the button for styling.
Try this code:
var $ = document.querySelectorAll.bind(document) //No need for jquery - simply import the function
$(".menu1[data-is-active-slide]").forEach((el, index) => {
$("#test1")[index].classList.add('underline');
$("#test1")[index].innerText = "Selected!";
console.log(1);
})
<div class="menu1" data-is-active-slide='true'>1</div>
<div id="test1"></div>
<div class="menu1" data-is-active-slide='false'>2</div>
<div id="test1"></div>
<div class="menu1">3</div>
<div class="menu2" data-is-active-slide='false'>4</div>
<div class="menu2">5</div>
<div class="menu1" data-is-active-slide>6</div>
<div id="test1"></div>
<div class="menu2">7</div>
<div class="menu1 menu2" data-is-active-slide="true">8</div>
<div id="test1"></div>
<div class="menu1 menu2">9</div>
The beginning declaration of $ is simply defining it since I did not import jQuery.
The next part is where the 'fun' begins. I used $(".menu1[data-is-active-slide]") to select all elements with class menu1 and with the property that data-is-active-slide is present. Then, I simply defined an action inside the function, for the sake of demonstrating that it works.
I am trying to create the following.
I have a button and on click of that button i need to add some active class to a div, but i have 4 divs with same class. What am trying to create is like a Choose Bet system like when you click first time on button you choose the first bet, when second time the second, i have 4 bets.
My html structure is the below
<div class="game_paytable_bluebet_column game_paytable_column"></div>
<div class="three_bet_wrappaer">
<div class="game_paytable_greenbet_column game_paytable_column"></div>
<div class="game_paytable_orangebet_column game_paytable_column"></div>
<div class="game_paytable_redbet_column game_paytable_column"></div>
</div>
What i did so far with jquery see below
jQuery('.choose_bet_button').click(function(){
if(!jQuery('.game_paytable_column:first').hasClass('active_blue_bet')){
jQuery('.game_paytable_column:first').addClass('active_blue_bet');
}else{
jQuery('.game_paytable_column:first').removeClass('active_blue_bet');
jQuery('.game_paytable_column').next().addClass('active_blue_bet');
}
});
With this code it is getting 2 elements.
Any idea how to get a solution to this?
Thanks in advance.
Here is an interpretation, please see the comments for a breakdown.
jQuery('.choose_bet_button').click(function(){
// get all the elements that match your selector
var $columns = $('.game_paytable_column')
// get the currently active element
var $active = $columns.filter('.active_blue_bet')
// get the index of the active element relative to your columns
var index = $active.length ? $columns.index($active) : -1
// increment the index if there is a next element or reset to 0
var newIndex = ($columns.length > index + 1)
? index + 1
: 0
// remove the active class from all elements
$columns.removeClass('active_blue_bet')
// set the new active column
$columns.eq(newIndex).addClass('active_blue_bet')
});
.game_paytable_column {
width: 100%;
height: 40px;
margin: 4px;
background: #eee;
}
.active_blue_bet {
background: #bada55;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game_paytable_bluebet_column game_paytable_column active_blue_bet"></div>
<div class="three_bet_wrappaer">
<div class="game_paytable_greenbet_column game_paytable_column"></div>
<div class="game_paytable_orangebet_column game_paytable_column"></div>
<div class="game_paytable_redbet_column game_paytable_column"></div>
</div>
<button class="choose_bet_button">choose</button>
Using :eq() you can achieve your requirement.
And initialize a counter and based on the counter add class in div.
And every four click make the counter 0.
Please check this snippet.
var _click = 0;
$('.choose_bet_button').click(function(){
if((_click % $(".game_paytable_column").length)==0){_click=0;}
$('.game_paytable_column').removeClass('active_blue_bet');
$('.game_paytable_column:eq('+_click+')').addClass('active_blue_bet');
_click++;
if($.trim($(".in_sight_area").html())==""){
$(".in_sight_area").html('<div class="top_bet_column_two top_bet_column game_paytable_column">New One</div>');
}
});
.active_blue_bet{
color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="in_sight_area"></div>
<div class="game_paytable_bluebet_column game_paytable_column">1</div>
<div class="three_bet_wrappaer">
<div class="game_paytable_greenbet_column game_paytable_column">2</div>
<div class="game_paytable_orangebet_column game_paytable_column">3</div>
<div class="game_paytable_redbet_column game_paytable_column">4</div>
</div>
<br/>
<button class="choose_bet_button">Choose Bet</button>
<div class="game_paytable_redbet_column game_paytable_column">5</div>
If you have a button... i.e.:
<button onclick="next()" >NEXT</button>
Seems quite simple:
// get all elements with class game_paytable_column
var columns = document.getElementsByClassName("game_paytable_column");
// counter to control the actual index
var counter = 0;
function next() {
// this selects the actual element and shows content
alert(columns[counter].innerHTML);
//and passes to next element
if (counter == columns.length - 1)
counter = 0;
// first if necessary
else
counter ++;
}
WORKING DEMO
That's all :)
I have written this function as a click event callback on a button, which when clicked toggles the class to provide a dropdown. This works if the dropdown element is next, but not if the element is outside of the clicked element's parent. The problem is is that I have multiple buttons on the same page that have the same functionality, and they all fire when one is clicked:
https://jsfiddle.net/21xj96up/7/
$('.direction-button').on('click', function() {
$(this).next('.direction-dropdown').toggleClass('active');
});
.fade-in {
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity .3s ease-in-out, all .3s ease-in-out;
}
.active {
visibility: visible;
opacity: 1;
transform: translate(0, 0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script>
<div class="contact-card">
<div class="contact-directions">
Directions
</div>
<!-- end .contact-directions -->
<div class="contact-info"></div>
<!-- .contact-info -->
<div class="contact-partner"></div>
<!-- end .contact-info -->
</div>
<!-- end .contact-card -->
<div class="direction-dropdown fade-in">
<p>Display #1</p>
</div>
<div class="contact-card">
<div class="contact-directions">
Directions
</div>
<!-- end .contact-directions -->
<div class="contact-info"></div>
<!-- .contact-info -->
<div class="contact-partner"></div>
<!-- end .contact-info -->
</div>
<!-- end .contact-card -->
<div class="direction-dropdown fade-in">
<p>Display #1</p>
</div>
Any and all help greatly appreciated :)
Check if it has a "parent-container" named contact-card if so take next from that one else do what you did already:
https://jsfiddle.net/21xj96up/12/
$('.direction-button').on('click', function(){
if( 1 === $(this).closest('.contact-card').next('.direction-dropdown').length) {
$(this).closest('.contact-card').next('.direction-dropdown').toggleClass('active');
} else {
$(this).next('.direction-dropdown').toggleClass('active');
}
});
Update with "shorter" version https://jsfiddle.net/21xj96up/21/
Now this is even a bit better cause we use the same
$(this).closest('.contact-card').next('.direction-dropdown')
twice. So we can save it to a variable and then use the variable.
$('.direction-button').on('click', function(){
var parentElement = $(this).closest('.contact-card').next('.direction-dropdown');
if( 1 === parentElement.length) {
parentElement.toggleClass('active');
} else {
$(this).next('.direction-dropdown').toggleClass('active');
}
});
I wold suggest this code, since selection conditions are not the same :
$('.direction-button').on('click', function(){
var b = $(this);
if(b.parents('div').length>0) {
b.parents('div').next('.direction-dropdown').toggleClass('active');
} else {
b.next('.direction-dropdown').toggleClass('active');
}
});
In cases like those, when there is an inconsistent element-hierarchy, you can work with data-attributes and IDs, which makes toggler and content hierarchy-independent.
Attribute for the Toggler:
data-toggle-target="display1"
ID for the target
`id="display1"`
The jQuery-Code
$( '#' + $(this).attr('data-toggle-target')).toggleClass('active');
https://jsfiddle.net/s57zk5hb/
On your code, since $(this) is inside the context of $('.direction-button'), this really means the "direction-button". There is no next "direction-dropdown" present for "direction-button" in the same level of "direction-button".
div
div
direction button
<it looks for the item here>
/div
/div
<item is actually here>
you can try,
$(this).parent().parent().next().toggleClass('active');
to achieve the functionality in the second case.
It would obviously be better if the structure were consistent. Assuming that you have little control over that, though, would mean you also have little control over additional classes or ids that would provide a better solution. In light of this, you can find the index of the current button in a collection of all the buttons and dropdowns and find the next dropdown in that list.
var idx = $(this).index('.direction-button, .direction-dropdown');
$('.direction-button, .direction-dropdown')
.slice(idx)
.filter('.direction-dropdown')
.first()
.toggleClass('active');
Like so: https://jsfiddle.net/j7h32w90/1/
This will work in nearly any DOM structure.