Event listener hover changing other element - javascript

I made this script for showing/hiding other div that comes to place of the one with event (ricon1) on mouse in and out:
HTML:
<div class="rule-container">
<div class="rule" id="rule1">
<div class="rule-icon" id="ricon1">
</div>
<div class="rule-decription" id="rdescription1">
</div>
</div>
<div class="rule" id="rule2">
<div class="rule-icon" id="ricon2">
</div>
<div class="rule-decription" id="rdescription2">
</div>
</div>
<div class="rule" id="rule3">
<div class="rule-icon" id="ricon3">
</div>
<div class="rule-decription" id="rdescription3">
</div>
</div>
<div class="rule" id="rule4">
<div class="rule-icon" id="ricon4">
</div>
<div class="rule-decription" id="rdescription4">
</div>
</div>
</div>
CSS:
div.rule {
display: inline-block;
width:20%;
margin-left:2%;
margin-right:2%;
background-color: cadetblue;
}
div.rule:first-child {
margin-left:3.5%;
background-color:yellow;
}
div.rule > div {
width:100%;
}
div.rule-icon {
height:240px;
background-color:lightpink;
display:block;
}
div.rule-decription {
height: 240px;
background-color: springgreen;
display:none;
}
JS:
document.getElementById("ricon1").addEventListener("mouseenter",function (){
document.getElementById('ricon1').style.display = 'none';
document.getElementById('rdescription1').style.display = 'block';
});
document.getElementById("ricon1").addEventListener("mouseout",function (){
document.getElementById('ricon1').style.display = 'block';
document.getElementById('rdescription1').style.display = 'none';
});
But the problem is that it flashes (continuously switching between on and off state, what am i doing wrong ?
How may i change script so i dont have to do it for all pairs of divs (ricon1, rdescription1; ricon2, rdescription2... etc) because there is like 6 pairs?

Is there a specific reason you don't want to use jQuery for that?
Anyway, here's an example without jQuery:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div class = "switch">
<div class = "icon">A</div>
<div style = "display:none" class = "desc">Desc1</div>
</div>
<div class = "switch">
<div class = "icon">B</div>
<div style = "display:none" class = "desc">Desc2</div>
</div>
<div class = "switch">
<div class = "icon">C</div>
<div style = "display:none" class = "desc">Desc3</div>
</div>
<script>
var icons = document.querySelectorAll('.switch');
for (var i = 0; i < icons.length; i++) {
icons[i].addEventListener("mouseenter", function() {
(this.querySelectorAll(".icon")[0]).style.display = 'none';
(this.querySelectorAll(".desc")[0]).style.display = 'block';
});
icons[i].addEventListener("mouseleave", function() {
(this.querySelectorAll(".icon")[0]).style.display = 'block';
(this.querySelectorAll(".desc")[0]).style.display = 'none';
});
}
</script>
</body>
</html>

Related

How to change from document to "this" in javascript

I am trying to wrap my head around prototype in javascript as well as getting used to the value of this. Currently I have this set to .cf--modal but when I use this to set a variable it does not seem to work. As this is my first of many functions I really don't want to hit the document and would rather target "this" within the Modal Toggle function.
How can I change the modal_toggle function so that document.getElementById and document.getElementsByClassname can be replaced with this.find or something along those lines.
$(function(){
$('.cf--modal').each(function(){
let cf = new ContactForm($(this));
});
});
var ContactForm = function(this$obj){
this.$obj = this$obj;
this.init();
}
ContactForm.prototype.init = function init(){
this.modal_toggle();
};
ContactForm.prototype.modal_toggle = function modal_toggle(){
let cfCTA = document.getElementsByClassName("modal-trigger")[0];
let cfModal = document.getElementsByClassName("cf--modal")[0];
let cfModalClose = document.getElementsByClassName("close-cf-modal")[0];
cfCTA.onclick = function () {
cfModal.style.display = "block";
}
cfModalClose.onclick = function(){
cfModal.style.display = "none";
}
}
.cf{
width:1000px;
margin:40px auto;
}
.inner-container{
padding:12px 24px;
border:1px solid grey;
border-radius:5px;
display:flex;
align-items:center;
justify-content:center;
}
.cf-block{
flex:1
}
/* Modal Styling */
.cf--modal{
width:375px;
height:200px;
position:absolute;
right:36px;
bottom:0;
border:1px solid grey;
display:none;
}
.close-cf-modal{
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Contact Us
<section class="cf">
<div class="cf-container">
<form>
<div class="inner-container">
<div class="cf-block">
<div class="cf-label">First Name</div>
</div>
<div class="cf-block">
<div class="cf-label">Last Name</div>
</div>
<div class="cf-block">
<div class="cf-label">Email</div>
</div>
<div class="cf-block">
<div class="cf-label">Message</div>
</div>
<div class="cf-block">
<div class="cf-label">Submit</div>
</div>
</div>
</form>
</div>
</section>
<section class="cf--modal">
<span class="close-cf-modal">close</span>
</section>
You should use this.$obj to refer to the modal element for the current ContactForm
ContactForm.prototype.modal_toggle = function modal_toggle() {
let cfModal = this.$obj;
let cfCTA = $(".modal-trigger");
let cfModalClose = cfModal.find(".close-cf-modal");
cfCTA.on("click", function() {
cfModal.show();
})
cfModalClose.on("click", function() {
cfModal.hide();
});
}

Is there a shorter more concise way to hide & show div with Javascript?

I am creating a dashboard with approximately 20 divs starting with "display: none;".
When the .onClick() in the sidebar will be used, it will show a specific div and keep hidden all the others.
I have used the classic solution of creating a function for each div, however, is extremely lengthy and the code looks like a mess.
Is there a better cleaner way to achieve this with Javascript?
Here is my code:
function presale() {
var x = document.getElementById("presale");
var y = document.getElementById("claim");
var z = document.getElementById("stake");
if (x.style.display === "grid") {
x.style.display = "none";
} else {
x.style.display = "grid";
y.style.display = "none";
z.style.display = "none";
}
}
function claim() {
var x = document.getElementById("presale");
var y = document.getElementById("claim");
var z = document.getElementById("stake");
if (y.style.display === "grid") {
y.style.display = "none";
} else {
x.style.display = "none";
y.style.display = "grid";
z.style.display = "none";
}
}
function stake() {
var x = document.getElementById("presale");
var y = document.getElementById("claim");
var z = document.getElementById("stake");
if (z.style.display === "grid") {
z.style.display = "none";
} else {
x.style.display = "none";
y.style.display = "none";
z.style.display = "grid";
}
}
*,
html {
color: #fff;
background-color: black;
}
#presale,
#claim,
#stake
/* Here I have many other divs like below */
{
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<link rel="stylesheet" href="MOD.CSS">
<script src="main2.js"></script>
<title>Base Template</title>
</head>
<body>
<div>
<ul>
<!-- Here I have other 20 options like the above -->
<li onclick="presale()">Presale</li>
<li onclick="claim()">Claim</li>
<li onclick="stake()">Stake</li>
<!-- Here I have other 20 options like the above -->
</ul>
<div id="presale">
<h1>Presale</h1>
</div>
<div id="claim">
<h1>Claim</h1>
</div>
<div id="stake">
<h1>Stake</h1>
</div>
</div>
</body>
</html>
Is there a better way to do this without the need to create a function and repeat the same thing over and over for each div?
There is no need for JS at all. You can simply use an anchor and use #id as hyper reference. Then you can display the element through CSS by using the :target-selector:
*,
html {
color: #fff;
background-color: black;
}
.d-none
/* Here I have many other divs like below */
{
display: none;
}
div:target {
display: grid;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<link rel="stylesheet" href="MOD.CSS">
<script src="main2.js"></script>
<title>Base Template</title>
</head>
<body>
<div>
<ul>
<!-- Here I have other 20 options like the above -->
<li>Presale</li>
<li>Claim</li>
<li>Stake</li>
<!-- Here I have other 20 options like the above -->
</ul>
<div id="presale" class="d-none">
<h1>Presale</h1>
</div>
<div id="claim" class="d-none">
<h1>Claim</h1>
</div>
<div id="stake" class="d-none">
<h1>Stake</h1>
</div>
</div>
</body>
</html>
Here you see a vanilla Javascript solution.
content divs are by default hidden.
If you click an element, the corresponding data-id get the class show.
window.onload = function () {
document.querySelectorAll('#nav li').forEach((elements) => {
elements.addEventListener('click', (el) => {
document.querySelectorAll('.content').forEach((item) => {
// hide all
item.classList.remove('show');
});
// show one
document.getElementById(el.target.getAttribute('data-id')).classList.add('show');
});
});
};
.content {
display: none;
}
.show {
display: block;
}
<ul id="nav">
<li data-id="presale">Presale</li>
<li data-id="claim">Claim</li>
<li data-id="stake">Stake</li>
</ul>
<div id="presale" class="content">
<h1>Presale</h1>
</div>
<div id="claim" class="content">
<h1>Claim</h1>
</div>
<div id="stake" class="content">
<h1>Stake</h1>
</div>
Something like this using data attributes and classlist toggles should also work.
I would consider minimizing your code (and CSS) by using generic CSS selectors to hide/show the individual sections. This also makes scalability and maintainability easier for the next guy.
This has the added benefit of your styling being controlled 100% using CSS and not arbitrary inline styles set by the javascript.
Adding another section is also easy as can be:
Add a new section with some id (eg. awesome-section)
Add a nav entry with the attribute data-toggle-section with the id as the value <li data-toggle-section="awesome-section">Awesome Section</li>
Profit
You're also not restricted to using just the nav elements themselves as the event listener is bound using the [data-toggle-section] selector which means that basically anything can show or hide a section as long as it has that attribute with the correct value.
const buttons = Array.from(document.querySelectorAll("[data-toggle-section]"));
const sections = buttons.map(element => {
return document.getElementById(element.dataset.toggleSection)
});
buttons.forEach(element => {
element.addEventListener('click', event => {
const selected = element.dataset.toggleSection;
sections.forEach(section => {
if(section.id === selected) {
section.classList.toggle('shown');
} else {
section.classList.remove('shown');
}
})
});
});
*,
html {
color: #fff;
background-color: black;
}
.option-section {
display: none;
}
.option-section.shown {
display: grid;
}
<div>
<ul>
<!-- Here I have other 20 options like the above -->
<li data-toggle-section="presale">Presale</li>
<li data-toggle-section="claim">Claim</li>
<li data-toggle-section="stake">Stake</li>
<!-- Here I have other 20 options like the above -->
</ul>
<div id="presale" class="option-section">
<h1>Presale</h1>
</div>
<div id="claim" class="option-section">
<h1>Claim</h1>
</div>
<div id="stake" class="option-section">
<h1>Stake</h1>
</div>
</div>
You could simply assign the same class (e.g. my_div) to every showable div, then pass the id to your function (that will show that and hide all the others).
function show_hide(id) {
document.querySelectorAll('.my_div').forEach(my_div => {
my_div.style.display = my_div.getAttribute('id') == id ? 'block' : 'none';
});
}
.my_div {
display: none;
}
<div>
<ul>
<li onclick="show_hide('presale')">Presale</li>
<li onclick="show_hide('claim')">Claim</li>
<li onclick="show_hide('stake')">Stake</li>
</ul>
<div class="my_div" id="presale">
<h1>Presale</h1>
</div>
<div class="my_div" id="claim">
<h1>Claim</h1>
</div>
<div class="my_div" id="stake">
<h1>Stake</h1>
</div>
</div>
Here's my attempt. It's sensibly the same as #ztom's answer but I tryed avoiding a foreach.
document.querySelectorAll("li").forEach(e => e.addEventListener("click", () => {
let shown = document.querySelector(".action:not(.d-none)")
if(shown){
shown.classList.add("d-none")
if(e.dataset.id != shown.id){
document.getElementById(e.dataset.id).classList.remove("d-none")
}
}else{
document.getElementById(e.dataset.id).classList.remove("d-none")
}
}))
.action{
display:grid;
}
.d-none{
display:none;
}
<ul>
<li data-id="presale">Presale</li>
<li data-id="claim">Claim</li>
<li data-id="stake">Stake</li>
</ul>
<div class="action d-none" id="presale">Presale</div>
<div class="action d-none" id="claim">Claim</div>
<div class="action d-none" id="stake">Stake</div>
When it comes to use the same logic on multiple elements, use classes instead of id's and your solution is shortened by default.
With jQuery, it's basically a 2-liner:
in CSS, create a class .hidden with display:none;
Your div and li elements should be grouped, using a class too.
Then you can simply refer to this classes and add the show/hide logic by:
$('h1:contains('+$(this).text()+')').parent().toggleClass("hidden");
$('h1:not(:contains('+$(this).text()+'))').parent().addClass("hidden");
$('document').ready(function(){
$('.toggle').on('click',function(){
$('h1:contains('+$(this).text()+')').parent().toggleClass("hidden");
$('h1:not(:contains('+$(this).text()+'))').parent().addClass("hidden");
});
});
*,
html {
color: #fff;
background-color: black;
}
.hidden
{
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="MOD.CSS">
<script src="main2.js"></script>
<title>Base Template</title>
</head>
<body>
<div>
<ul>
<!-- Here I have other 20 options like the above -->
<li class="toggle">Presale</li>
<li class="toggle">Claim</li>
<li class="toggle">Stake</li>
<!-- Here I have other 20 options like the above -->
</ul>
<div class="hidden">
<h1>Presale</h1>
</div>
<div class="hidden">
<h1>Claim</h1>
</div>
<div class="hidden">
<h1>Stake</h1>
</div>
</div>
</body>
</html>
This is a question for Code Review section https://codereview.stackexchange.com/
However, you can try smth like this:
const elems = ["presale", "claim", "stake"];
function toggle(elem) {
elems.map(i => {
let el = document.getElementById(i);
el.style.display = "none";
});
let active_el = document.getElementById(elem);
active_el.style.display = "grid";
}
and in html add the elem name as a param, so, replace this
<li onclick="presale()">Presale</li>
<li onclick="claim()">Claim</li>
<li onclick="stake()">Stake</li>
with this
<li onclick="toggle('presale')">Presale</li>
<li onclick="toggle('claim')">Claim</li>
<li onclick="toggle('stake')">Stake</li>
If you attach data attributes to both the list items and the "panels" you can use one function to match them up, and use a CSS class to determine whether it should be active or not.
// Cache the elements, the panels container, and the list element
// separately adding one event listener to the list. We're using
// event delegation for this - one listener captures all
// the events from its child elements
const allElements = document.querySelectorAll('.list li, .panels .panel');
const panels = document.querySelector('.panels');
const list = document.querySelector('ul');
list.addEventListener('click', handlePanel);
// When the listener is triggered
function handlePanel(e) {
// Check if it's a list item
if (e.target.matches('li')) {
// Destructure its id from the dataset
const { id } = e.target.dataset;
// Remove all the active classes from the elements
allElements.forEach(el => el.classList.remove('active'));
// And then add an active class to the list item,
// and the panel where their ids match
const selector = `[data-id="${id}"]`;
const item = list.querySelector(`li${selector}`);
const panel = panels.querySelector(`.panel${selector}`);
item.classList.add('active');
panel.classList.add('active');
}
}
.panel { display: none; }
.panel h1 { font-size: 1.2em; color: darkblue; }
ul { list-style-type: none; margin-left: 0; padding: 0; }
li { padding: 0.3em; border: 1px solid white; }
li:hover { background-color: thistle; cursor: pointer; }
li.active { border: 1px solid #454545; background-color: lightyellow; }
.panel.active { display: block; }
<ul class="list">
<li data-id="presale">Presale</li>
<li data-id="claim">Claim</li>
<li data-id="stake">Stake</li>
</ul>
<div class="panels">
<div data-id="presale" class="panel">
<h1>Presale</h1>
</div>
<div data-id="claim" class="panel">
<h1>Claim</h1>
</div>
<div data-id="stake" class="panel">
<h1>Stake</h1>
</div>
</div>
Additional documentation
classList
Destructuring assignment
Event delegation
matches
querySelector / querySelectorAll
Template/string literals

move an element from a div to another div

Let's assume that I have this structure
<div class="firstDiv">
<div class="insideDiv"></div>
</div>
<div class="secondDiv"></div>
<div class="thirdDiv"></div>
How can I move the .insideDiv from the .firstDiv to the .thirdDiv but going through the .secondDiv ?
I need just a hint or an idea. Thank you!
In vanilla JS, it works like this:
var moveIt = function() {
var outerDiv = document.getElementsByClassName('insideDiv')[0].parentElement;
var innerDiv = document.getElementsByClassName('insideDiv')[0];
if (outerDiv.nextElementSibling != null) {
outerDiv.nextElementSibling.appendChild(outerDiv.removeChild(innerDiv));
}
}
.firstDiv {
background-color: yellow
}
.secondDiv {
background-color: lightblue
}
.thirdDiv {
background-color: lightpink
}
<div class="container">
<div class="firstDiv">first
<div class="insideDiv">inside div</div>
</div>
<div class="secondDiv">second</div>
<div class="thirdDiv">third</div>
</div>
<button type="button" onclick="moveIt()">Move it!</button>
OPTIONAL: wrap-around in else statement below, this needs a scope to operate in. (set by div-element of class 'container'), to be added to above if statement.
else { outerDiv.parentElement.firstElementChild.appendChild(outerDiv.removeChild(innerDiv));
}
You can see a working example here: codepen: move child-element to nextSibling
If you don't mind using jquery:
<div class="firstDiv">
<div class="insideDiv">InsideBaseball</div>
</div>
<div class="secondDiv">SecondBase</div>
<div class="thirdDiv">ThirdBase</div>
<button id="SwapButton"> Swap! </button>
<script>
document.getElementById("SwapButton").onclick = function () {
var content = $('.insideDiv').html();
var content2 = $('.thirdDiv').html();
$('.thirdDiv').replaceWith(content);
$('.insideDiv').replaceWith(content2);
};
</script>

Javascript using mouse hover class to effect child ids

I am trying to make the class navButtons effect all of the ids inside it using the mouse over effect. I read on here that you can do this with a for loop but that would require changing the names of the ids. is there a way to do this without changing the names?
document.getElementsByClassName("navButtons").addEventListener("mouseover", mouseOver);
document.getElementsByClassName("navButtons").addEventListener("mouseout", mouseOut);
function mouseOver() {
document.getElementsByClassName("navButtons").style.color = "red";
}
function mouseOut() {
document.getElementsByClassName("navButtons").style.color = "black";
}
<nav>
<div class="navButtons">
<div id="about">about</div>
<div id="portfolio">portfolio</div>
<div id="contact">contact</div>
</div>
</nav>
You can just use css to add hover effect to all div inside .navButtons div.
.navButtons div{
color: red;
}
.navButtons div:hover{
color: green;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Hover effect</title>
</head>
<body>
<nav>
<div class="navButtons">
<div id="about">about</div>
<div id="portfolio">portfolio</div>
<div id="contact">contact</div>
</div>
</nav>
</body>
</html>
If I'm understanding you correctly, you want to apply styles to all the elements inside navButtons when hovering navButtons. This can be done with CSS only.
.navButtons:hover > div {
color: red;
}
<nav>
<div class="navButtons">
<div id="about">about</div>
<div id="portfolio">portfolio</div>
<div id="contact">contact</div>
</div>
</nav>
If you however, for some reason, want to use Javascript instead (not recommended for this purpose) you can do the following:
var navButtons = document.getElementsByClassName('navButtons')[0];
var children = navButtons.getElementsByTagName('div');
navButtons.addEventListener('mouseenter', function() {
for (var i = 0; i < children.length; i++) {
children[i].style.color = 'red';
}
});
navButtons.addEventListener('mouseleave', function() {
for (var i = 0; i < children.length; i++) {
children[i].style.color = 'black';
}
});
<nav>
<div class="navButtons">
<div id="about">about</div>
<div id="portfolio">portfolio</div>
<div id="contact">contact</div>
</div>
</nav>
document.getElementsByClassName("navButtons").addEventListener("mouseover", mouseOver);
you are trying to add event listener to a node list, you will have to attach it each node inside the list using a loop. then you can access the current element inside the mouseOver() function using event.target.
var navButtons = document.getElementsByClassName("navButtons");
for (var i=0; i<navButtons.length; i++){
navButtons[i].addEventListener("mouseover", mouseOver);
navButtons[i].addEventListener("mouseout", mouseOut);
}
function mouseOver(event) {
event.target.parentNode.style.color = "red";
}
function mouseOut(event) {
event.target.parentNode.style.color = "black";
}
<nav>
<div class="navButtons">
<div id="about">about</div>
<div id="portfolio">portfolio</div>
<div id="contact">contact</div>
</div>
</nav>
You can get all the children of the class by this method
var c = document.getElementById("navButtons").children;
c is now an Array. So you can iterate over this array, thereby having contact with each child
i.e c[0] is the first element

Refactoring jQuery repeating pattern

I have painted my self into a corner in order to quickly prototype.
What's the best way to refactor the following jQuery code? Its functionality is to toggle between some sidebar navigation items. I need it to be more dynamic in order to be scalable.
Would you add the IDs inside the if statements, in an array and iterate through them? Use variables? Create a function and call it on the html side onClick? No matter what I think of, it stills leads to a bunch of repeating code.
Thank you!
// TOGGLING LEFT NAVIGATION
$('#settingsClick').click(function() {
if( $('#addContainer, #noteContainer, #logoContainer, #themeContainer').is(':visible') ) {
$('#addContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#settingsContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#settingsContainer').slideToggle(350);
}
});
$('#addClick').click(function() {
if( $('#settingsContainer, #noteContainer, #logoContainer, #themeContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#addContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#addContainer').slideToggle(350);
}
});
$('#noteClick').click(function() {
if( $('#settingsContainer, #addContainer, #logoContainer, #themeContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#addContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#noteContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#noteContainer').slideToggle(350);
}
});
$('#logoClick').click(function() {
if( $('#settingsContainer, #addContainer, #noteContainer, #themeContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#addContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#logoContainer').slideToggle(350);
}
});
$('#themeClick').click(function() {
if( $('#settingsContainer, #addContainer, #noteContainer, #logoContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#addContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#themeContainer').slideDown(350);
} else {
$('#themeContainer').slideToggle(350);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="settingsClick">Click Me</a><br>
<div id="settingsContainer">Content...</div>
<br><br>
<a id="addClick">Click Me</a><br>
<div id="addContainer">Content...</div>
<br><br>
<p> Etc... Etc....</p>
You should group using the common CSS class, i.e. header and content. Using the established relationship you can target the others content holder and content associated with the current clicked header element.
$('.container .header').on('click', function() {
//Get the current element
var $this = $(this);
//find the content
var $content = $this.closest('.container').find('.content'); //$this.next()
//get all contents
var content = $('.container .content');
//Slide up others
content.not($content).slideUp(350);
//Slide down
$content.slideToggle(350);
});
.content {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="header" id="settingsClick">Click Me</div>
<div class="content" id="settingsContainer">Content...</div>
</div>
<div class="container">
<div class="header" id="addClick">Click Me</div>
<div class="content" id="addContainer">Content...</div>
</div>
<div class="container">
<div class="header" id="noteClick">Click Me</div>
<div class="content" id="noteContainer">Content...</div>
</div>
the best bet would be to do it like so
$(document).on('click', ".trigger", function() {
var sibling_content = $(this).siblings(".content");
if (!sibling_content.hasClass('active')) {
$(".content").slideUp('slow').removeClass('active');
sibling_content.slideDown('slow').addClass('active');
} else {
sibling_content.slideUp('slow').removeClass('active');
}
})
.trigger {
background-color: red;
color: white;
font-size: 16px;
}
.content {
background-color: blue;
color: white;
font-size: 16px;
padding: 20px 0;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>

Categories

Resources