I would like to simplify the code by not typing each div (#TopicA, #TopicB, #main, etc.) ID that is to be collapsed when an option is selected.
I would like all the divs besides the ones that trigger the button to automatically collapse. How can I make this happen?
Example: When I click TopicA1, I want to collapse all other divs, but I dont want to put all div IDs in JS code.
Demo: JSFiddle
<div id="main" class="QA">
<h2>Title</h2>
<h3>Subtitle</h3>
<button class="ClassButtonA">Topic A</button>
<button class="ClassButtonB">Topic B</button>
<button class="ClassButtonC">Topic C</button>
</div>
<div id="TopicA" class="QA">
<h2>XX</h2>
<button class="ClassButtonA1">Topic A1</button>
</div>
$(".ClassButtonA").click(function() {
$("#TopicA").toggle("slow").trigger('reset');
});
$(".ClassButtonA").click(function() {
$("#TopicB, #TopicC, #main").slideUp("slow").trigger("reset");
A single function handles the toggle, and hides all siblings to the currently displayed div. Note that I did modify your structure some -- the content pane div now contains all the divs I wish to show/hide, thus leaving the button pane displaying. Hope it helps!
// Event handler for click on any button el
$(".QA button").click(function() {
// The text of the button matches the id
// of the div els, if I strip spaces.
var toggleThis = "#" + $(this).text().replace(/\s/g, '')
// Using the given string above, toggle that
// div el, and hide all siblings to that.
$(toggleThis).show("slow").trigger('reset').siblings().hide("slow").trigger('reset');
});
.QA {
font: normal normal 14px/1 Helvetica;
margin: 1px;
border-radius: 10px;
text-align: center;
}
#TopicA,
#TopicB,
#TopicC,
#TopicA1 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main" class="QA">
<h2>Title</h2>
<h3>Subtitle</h3>
<button class="ClassButtonA">Topic A</button>
<button class="ClassButtonB">Topic B</button>
<button class="ClassButtonC">Topic C</button>
</div>
<div class="content-pane">
<div id="TopicA" class="QA">
<h2>XX</h2>
<button class="ClassButtonA1">Topic A1</button>
</div>
<div id="TopicA1" class="QA">
<h2>123</h2>
</div>
<div id="TopicB" class="QA">
<h2>YY</h2>
</div>
<div id="TopicC" class="QA">
<h2>ZZ</h2>
</div>
</div>
Related
I had the idea to make an "edit" button for each card of my list which transformed the reading areas into a text area.
In the idea, nothing complicated because I did it on a profile page. But in this example I only had one button with my area already defined
Today I have several rows that are all going to have an "edit" button. Not having the number of buttons that will be generated, I cannot create a function for each one.
Do you have an idea ?
Regarding my code, here is a card example of what it looks like
On my profile page, I had put "input text" in display none and I put my span in display inherit (and I think to do the same here)
<div class="card-body ">
<div class="row">
<div class="col">
<button>Click to update </button>
</div>
</div>
<div class="row">
<div class="col">
<span style="display:inherit">read area</span>
<input type="text" style="display:none">write area</input>
</div>
<div class="col">
<span style="display:inherit">read area 2</span>
<input type="text" style="display:none">write area 2</input>
</div>
</div>
</div>
Yes you can have a single function added as event listener for several html elements. The key is fetching the element that triggered the event so that it becomes a parameter for the function to work according to the exact button clicked.
That's made having the argument event in your event handler and accessing to the event.target to retrieve the object triggering the event.
Here's a demo showing that concept. There's a collection of rows each one having an edit button. The edit buttons are initialized at the begginning so that each one will be added an event listener pointing to the single function editClickHandler
//when document is ready
document.addEventListener('DOMContentLoaded', ()=>{
//initialize buttons
initEditButtons();
});
function initEditButtons(){
//retrieves all the button contained in .container .row collection
editButtons = document.querySelectorAll('.container > .row > button.edit');
//for each one of them
editButtons.forEach((editButton, i)=>{
//adds a click event handler
editButton.addEventListener('click', editClickHandler);
});
}
function editClickHandler(event){
//find the currently selected row
document.querySelector('.container > .row.rowSelected')
//remove its selected class
?.classList.remove('rowSelected');
//clicked edit button
const clickedButton = event.target;
//row corresponding to the clicked button
const selectedRow = clickedButton.closest('div.row');
//adds the class rowSelected to the clicked row
selectedRow.classList.add('rowSelected');
}
*{
box-sizing: border-box;
}
.container{
width: fit-content;
}
.row{
margin-bottom: 2px;
padding: 3px 6px;
}
.rowSelected{
border: dashed 2px gray;
}
button.edit{
cursor: pointer;
}
<div class="container">
<div class="row">
<span>01</span>
<span>Field1</span>
<span>Field2</span>
<button class="edit">Edit</button>
</div>
<div class="row">
<span>02</span>
<span>Field1</span>
<span>Field2</span>
<button class="edit">Edit</button>
</div>
<div class="row">
<span>03</span>
<span>Field1</span>
<span>Field2</span>
<button class="edit">Edit</button>
</div>
<div class="row">
<span>04</span>
<span>Field1</span>
<span>Field2</span>
<button class="edit">Edit</button>
</div>
</div>
I'm making a website that requires me to have 18 icons of which, each icon has its own assign div that is hidden, and once pressed the hidden Div slides down and shows below the icon. These icons have to be in a different Div from the content I want to hide/show.
I'm using Elementor on wordpress since I'm really ignorant when it comes to webdesign and programing,
I've found this jquery that I'm using to show and hide Div when I click on icons.
I've assign the icons as .showBlock1 .ShowBlock2 .ShowBlock3 etc and the Divs as .hiddenBlock1 .hiddenBlock2 .hiddenBlock3 etc... and it works how I want except that I only want 1 active at a time, so that if I press icon1, it shows Div1 and then if I press icon2, it hides Div1 and shows Div2 and so on.
jQuery(document).ready(function( $ ){
var hbtn = $(".showBlock");
var hcon = $(".hiddenBlock");
hcon.hide();
hbtn.click(function(e) {
var index = hbtn.index(this)
$(hcon).eq(index).slideToggle("slow");
e.preventDefault();
});
});
jQuery(document).ready(function( $ ){
var hbtn = $(".showBlock2");
var hcon = $(".hiddenBlock2");
hcon.hide();
hbtn.click(function(e) {
var index = hbtn.index(this)
$(hcon).eq(index).slideToggle("slow");
e.preventDefault();
});
});
Since I'm really ignorant to coding I've been just repeating the script and changing the numbers on the class .showBlock and .hiddenBlock.
Maybe the following is helpful to you?
$(function(){
var hbtn = $(".showBlock");
var hcon = $(".hiddenBlock");
hcon.hide();
hbtn.click(function(e) {
var curr=hcon.eq(hbtn.index(this));
hcon.not(curr).hide();
curr.slideToggle("slow");
e.preventDefault();
});
});
.cont1 {height:50px}
.hiddenBlock {display: inline-block; width:60px; height: 40px; background-color:#ccc}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cont1">
<div class="hiddenBlock">1</div>
<div class="hiddenBlock">2</div>
<div class="hiddenBlock">3</div>
<div class="hiddenBlock">4</div>
<div class="hiddenBlock">5</div>
<div class="hiddenBlock">6</div>
</div>
<div>
<button class="showBlock">show 1</button>
<button class="showBlock">show 2</button>
<button class="showBlock">show 3</button>
<button class="showBlock">show 4</button>
<button class="showBlock">show 5</button>
<button class="showBlock">show 6</button>
</div>
A button click will at first hide all visile .hcon elements and will then .slideToggle the one corresponding to the button position.
Edit
After having had a look at your web page I can simplify your structure as shown below:
jQuery(function($){
const btns=$("div.showBlock");
const scts=$("section.hiddenBlock");
$("section").on("click","div.showBlock",function(){
let curr=scts.eq(btns.index(this));
scts.not(curr).hide();
curr.toggle();
});
})
.showBlock {display: inline-block; background-color:#ccc;
width:50px; margin:2px;padding:6px}
.hiddenBlock {background-color:#eea; width:192px; padding:6px; margin-top:8px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
...
<section
class="... elementor-element-51eaf85 ..." data-id="51eaf85" data-element_type="section">
<div class="elementor-container elementor-column-gap-no">
<div class="elementor-column ... elementor-element-1a773d0 showBlock" ...>
one
</div>
<div class="elementor-column ... elementor-element-6b9441a showBlock" ...>
two
</div>
<div class="elementor-column ... elementor-element-ce4f2d4 showBlock" ...>
three
</div>
</div>
</section>
<section class="... elementor-element-fc98ed1 hiddenBlock ..." data-id="fc98ed1" style="">first section</section>
<section class="... elementor-element-cf64eb5 hiddenBlock ..." data-id="cf64eb5" style="display: none;">second section</section>
<section class="... elementor-element-f16da07 hiddenBlock ..." data-id="f16da07" style="display: none;">third section</section>
...
The HTML structure there is an excerpt from the page. I removed a few class attributes to improve the readability and added a little makeshift CSS to make it "presentable".
On top of that I unified your classes "showBlock1", "showBlock2", "showBlock3" to "showBlock" and "hiddenBlock", "hiddenBlock2", "hiddenBlock3" to "hiddenBlock".
Have a look at it and play around with it ...
I just want to add class for the button after another class but it's inside of another div. Take a look at this example.
<div class="wrap">
<button class="one">Click</button>
<button class="two">Click</button>
</div>
<div class="bottom"></div>
.add-me{
color:red;
}
In here, I want to add to class button one. But it needs to be applied when bottom class appears.(This is a validation message. So I can't style directly to button one.)
I tried with this way. But it only apply for wrapper div.
$('.bottom').prev('div').first().addClass('add-me');
Here is the fiddle: https://jsfiddle.net/eqhj0vm9/2/
You have to use $('.bottom').prev().find(':first-child').addClass('add-me'); to select the prev element's first child.
$(function() {
$(".activate").click(function(){
$('.bottom').show();
$('.bottom').prev().find(':first-child').addClass('add-me');
});
});
.add-me {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button class="one">Click</button>
<button class="two">Click</button>
</div>
<div class="bottom" style="display:none"> BOTTOM CLASS </div>
<br />
<button class="activate">Activate bottom class</button>
I have a three button navigation panel, comprising of three divs and an anchor. On mouse over, myFunction() assigns a class to the three divs and anchor tag, for styling purposes.
<nav>
<div id="btn1" class="button" onMouseOver="myFunction();">
<div id="btn_bdr1">
<div id="btn_bdr2">
</div>
</div>
</div>
<div id="btn3" class="button" onMouseOver="myFunction();">
<div id="btn_bdr1">
<div id="btn_bdr2">
</div>
</div>
</div>
<div id="btn2" class="button" onMouseOver="myFunction();">
<div id="btn_bdr1">
<div id="btn_bdr2">
</div>
</div>
</div>
</nav>
What I need to do is find the ID of the div which called myFunction(), so I can make a change within the function to only the calling div, not all three.
Using JavaScript only, how can I go about doing this.
Thanks in advance.
There is two ways you can do is
1) Send an argument to the method with the div's name
Example
<div id="btn1" class="button" onMouseOver="myFunction('btn1')">
2) Send the element this
Example
<div id="btn1" class="button" onMouseOver="myFunction(this)">
In the javascript you can then do
myFunction(element) {
//element is now the element you clicked on
}
You can use the event object and look at the target (e.target). This is a reference to the element itself so to get the ID you would simply access the element's id property. (e.target.id)
document.querySelectorAll('.a').forEach(function(ele, ind) {
ele.addEventListener("mouseover", function(e) {
console.log(e.target, e.target.id);
})
});
.a {
height: 40px;
width: 40px;
border: solid black 3px;
margin-top: 5px;
}
<div class="a" id="one"></div>
<div class="a" id="two"></div>
<div class="a" id="three"></div>
You can call this.event.target from myFunction() to determine which element generated the event.
For example:
myFunction() {
console.log("I was called by: ", this.event.target);
}
UPDATED
I think I may have inadvertently made the question confusing. This is an update that is more specific with updated code based on comments and answer I have been given so far. Thank you to everyone that has taken the time to comment and answer.
How can I get the ID of a <div> with the class of .button when I have a click listener for .button. If .button or any of its children are clicked, it should return the ID for that particular div with the class of .button.
This is what I have so far: New JSFiddle
HTML
<div class="row">
<div id="b1" class="button">
<h2>Button 1</h2>
</div>
<div id="b2" class="button">
<h2>Button 2</h2>
</div>
<div id="b3" class="button">
<h2>Button 3</h2>
</div>
</div>
jQuery
var selected = "";
$('.button').on('click', function(e) {
selected = e.target.id;
$('.button').css('backgroundColor', '#becde5');
$('#' + selected).css('backgroundColor', '#3b71c6');
$('#selected').html(selected);
});
This is almost correct but does not propagate, if I click on a <h2> the function does not work. However if I click on the .button div itself it works.
Initial Question
I am trying to create a general function that can identify what child was selected from its parents click listener. The child may have its own children that would all be considered part of the same element so that if any of these children where selected they should also elicit the same response from the click listener.
This is an example of what I have working so far: JSFiddle
HTML consisting of three buttons that all have one child <h2> tag and share the <div class="row"> as their parent.
<div class="row">
<div class="b1 button">
<h2 class="b1">Button 1</h2>
</div>
<div class="b2 button">
<h2 class="b2">Button 2</h2>
</div>
<div class="b3 button">
<h2 class="b3">Button 3</h2>
</div>
</div>
jQuery that listens for a click on <div class="row">. It retrieves the first class name of the clicked element and stores it in a variable. The elicited response in this case is a change of the CSS style background-color though this is arbitrary and would change depending on the use of the function.
var selected = "";
$('.row').on('click', function(e) {
selected = e.target.className.split(" ")[0];
$('.b1, .b2, .b3').css('backgroundColor', '#becde5');
$("." + selected).css('backgroundColor', '#3b71c6');
$('#selected').html(selected);
});
The fact that I am adding a lot of classes to elements purely to identify them on a click seems like it would not scale very well and is generally a bad approach. This method also means that I would always have to put the class name that identifies what element was selected at the beginning of its HTML class attribute. This could potentially clash with other functions using the same method.
Is there a better way to identify what child element was selected from its parents click listener, where a child may have other children that also require the same response from the listener?
EDIT based on the edited question:
I think that what you really want is the id of the element that triggered the event.
But by using e.target you have the target element... which is not necessarily the element that triggered the event.
See in this updated Fiddle.
So simply use $(this) as the selector to retrieve the id... Using .attr("id").
;)
Answer to the initial question:
To determine what can be "selected", I used a "clickable" class.
To avoid using id or class as an identifier to determine what has been clicked,
a data attribute can be usefull.
I used data-id... But you can use whatever you want, like: data-selected or data-target, and assign whatever value to it.
In the below code, I made two exactly identical rows, except their data-id value.
var selected = "";
$('.clickable').on('click', function(e) {
e.stopPropagation(); // To prevent bubbling.
// Reset all bg colors
$('.button').css('backgroundColor', 'initial');
$('.row').css('backgroundColor', 'initial');
// Find exactly what was clicked
if ($(this).hasClass("row")) {
var row = $(this).data("id");
selected = row + " (whole)";
}
if ($(this).hasClass("button")) {
// Find in which row
var row = $(this).closest(".row").data("id");
var btn = $(this).data("id");
selected = btn + " in " + row;
}
// Pale all buttons
$('.button').css('backgroundColor', '#becde5');
// Change bg color of the selected element
$(this).css('backgroundColor', '#3b71c6');
$('#selected').html(selected);
});
.row {
display: table;
width: 100%;
color: white;
border-spacing: 20px;
}
.button {
display: table-cell;
border-radius: 12px;
background-color: #6fa1f2;
text-align: center;
}
#selected {
font-size: 30px;
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span>Selected : <span id="selected">no selection</span></span><br>
<div class="row clickable" data-id="row1">
<div class="button clickable" data-id="btn1">
<h2>Button 1</h2>
</div>
<div class="button clickable" data-id="btn2">
<h2>Button 2</h2>
</div>
<div class="button clickable" data-id="btn3">
<h2>Button 3</h2>
</div>
</div>
<br>
<div class="row clickable" data-id="row2">
<div class="button clickable" data-id="btn1">
<h2>Button 1</h2>
</div>
<div class="button clickable" data-id="btn2">
<h2>Button 2</h2>
</div>
<div class="button clickable" data-id="btn3">
<h2>Button 3</h2>
</div>
</div>
no need to id the subject, since it was the one clicked, i.e. e.target which with jQuery you cant select like $(e.target) without any trouble
then you need .closest('.button') to search up to the parent .button (if any)
$('.row').on('click', function(e) {
$('.row > .button').css('backgroundColor', '#becde5');
$(e.target).closest('.button').css('backgroundColor', '#3b71c6');
console.log($(e.target).html());
});
.button {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="row">
<div class="button">
<h2>Button 1</h2>
</div>
<div class="button">
<h2>Button 2</h2>
</div>
<div class="button">
<h2>Button 3</h2>
</div>
</div>
If you avoid giving an identifier (classes, IDs, etc) you'd need to do some manual checking for tag type to see what you clicked on (so basically, an identifier as well)
Here's an example, and not very memory efficient method
jsfiddle example
$('.row, .row *').on('click', function(e) {
e.stopPropagation()
$('.button').removeClass('active')
$('.button').css('backgroundColor', '#becde5');
$(this).toggleClass('active')
$('#selected').html(e.target.tagName + ': ' + e.target.className);
});
If you bind a click to div.row and clicked the h2 tag inside the button, and want to manipulate the h2 tag, you could check its tagName- but that less scalable than your OP.