How to detect the ordered position of a class element - javascript

Detecting the name of a class is straightforward.
event.target.className
However detecting if a given element is the 3rd, 5th or 11th that uses a particular class is tough, at least for me. I used the console (F12) to find a property I could use but no luck.
In the following simplified example what property or other feature can determine if the user clicked ("box-a")[0] ("box-a")[1] ("box-a")[2] or ("box-a")[3]? I know that I can use individual IDs for each element but I'd rather keep this simple if it is technically possible.
var count;
for (count = 0; count < 4; count++) {
document.getElementsByClassName("box-a")[count].addEventListener("click", checker);
}
function checker() {
document.getElementsByClassName("box-b")[0].innerHTML = event.target.className;
}
// event.target.className targets the classes name, but what property targets the [0], [1], [2] or [3]?
.box-a {
background-color: green;
border: 0.6rem solid black;
padding: 10px;
font-family: arial;
font-size: 4rem;
}
.box-b {
display: block;
background-color: blue;
border: .25rem solid red;
padding: 10px;
font-family: arial;
font-size: 4rem;
}
<div class="box-a">Box 1</div>
<div class="box-a">Box 2</div>
<div class="box-a">Box 3</div>
<div class="box-a">Box 4</div>
<div class="box-b"></div>

When looping over the elements, add an event listener to each box that passes the index of the clicked box to your checker function.
function checker(index) {
// Do whatever you want with the index here
console.log(index)
}
// Add the same event listener to each element, but passing the index of
// the element to the checker function
[].slice.call(document.getElementsByClassName('box-a'))
.forEach(function(element, index) {
element.addEventListener('click', function() { checker(index) })
})
<div class="box-a">Box 1</div>
<div class="box-a">Box 2</div>
<div class="box-a">Box 3</div>
<div class="box-a">Box 4</div>
<div class="box-a">Box 5</div>

This may be not the best solution but it works.
// Click on any div element and see the output
document.querySelectorAll('.box-a').forEach((e) => { // Add the event listener to all the elements with class .box-a
e.addEventListener('click', (event) => {
var element = event.target;
var index = Array.from(element
.parentNode // Get the parent node of the clicked element
.querySelectorAll('.' + element.className)) // Select all the elements inside the parent node (siblings) with the same class name of the clicked element
.indexOf(element) + 1; // Look for the index of the clicked element, + 1
console.log(index);
});
});
Here's a working bin:
JSBin

Related

Add a style to a class onclick a button

I have these 3 Boxes with the same classes and a button:
function turnRedAndAddPadding() {
/* ??? */
}
.box {
border: 1px solid;
display: inline;
}
<button onclick="turnRedAndAddPadding();">Press</button>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
I want to add styles to the class .box when clicking on the button without adding a new class to the boxes. Basically, if you press the button, the class .box should get a red background color and a padding and all the elements that have this class should have the same. Is there an easy way in JavaScript to solve this problem?
Thanks in advance.
You don't really want to add properties to the existing class. What you should do is add a new class that contains those red/padding properties to each element's class list.
Toolkit
You need some way to "pick up" the elements for processing. Since you have more than one querySelectorAll is probably the go-to choice which will give you a static nodelist (rather than a live HTML collection that methods like getElementsByClassName give you which have some side-effects if you don't use them correctly.)
You'll want a way to iterate over the elements to the processing. There are a number of possibilities provided in that link but forEach is a good choice here.
You'll want a way to update the class list of each element in the iteration. The unsuprisingly-named classList has, among its methods, add which accepts a string of the CSS class you want to add.
Define a new class ("redpad" in this example) that can be used.
Finally, because you want to avoid inline JS in 2023, you should be using addEventListener which accepts a) an event type and b) the name of the function you want to call when that event is fired.
const button = document.querySelector('button');
const boxes = document.querySelectorAll('.box');
button.addEventListener('click', turnRedAndAddPadding);
function turnRedAndAddPadding() {
boxes.forEach(box => {
box.classList.add('redpad');
});
}
.box {
border: 1px solid;
display: inline;
}
.redpad {
background-color: red;
padding: 0.5em;
}
<button type="button">Press</button>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
Based on that post you could try something like this:
function turnRedAndAddPadding() {
stylesheet = document.styleSheets[0]
stylesheet.insertRule(".box { background-color: red; padding: 10px;}", 0);
}
.box {
border: 1px solid;
display: inline;
}
<button onclick="turnRedAndAddPadding();">Press</button>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
Hope it helps.
Some really useful documentation by W3 Schools talks about how to use getElementsByClassName which you can find here You can find about editing the padding as well from here via the padding property of each element.
Below I am finding all div's that have the class box. Then iterating over each of them and assigning the colour and padding. You can change this to your liking.
There are also many other properties that you can edit for each DOM element like divs!
function turnRedAndAddPadding() {
const collection = document.getElementsByClassName('box');
for (let i = 0; i < collection.length; i++) {
collection[i].style.backgroundColor = 'red';
collection[i].style.padding = '5px';
}
}
Just adding some javascript you can achieve your goal.
document.querySelectorAll with this you can collect all elements with class box and then loop with a foreach function
function turnRedAndAddPadding() {
let box = document.querySelectorAll('.box');
box.forEach(el => {
el.style.background = 'red';
el.style.padding = '20px'
})
}
.box {
border: 1px solid;
display: inline;
}
<button onclick="turnRedAndAddPadding()">Press</button>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>

Jquery: Give styling (padding) of the parent class based on the condition that the first child matches with the class I want

Parent Class: cmp-container
There are two child classes -
productmodelfootnotes
footnotes
According to the sequence of the child I want to give padding as follows -
If "productmodelfootnotes" child class comes first -> Apply padding=40px to the parent class (cmp-container)
If "footnotes" child class comes first -> Apply padding=64px to the parent class (cmp-container)
First of all, initialize your parent element
let parent = document.querySelector('.cmp-container')
Then add style, based on condition
let firstChild = parent.children[0];
if(firstChild.classlist.contains('productmodelfootnotes'){
parent.style.padding = "40px";
} else if(firstChild.classlist.contains('footnotes')) {
parent.style.padding = "64px";
}
Consider the following.
$(function() {
$(".cmp-container").each(function(i, el) {
if ($("div:eq(0)", el).hasClass("productmodelfootnotes")) {
$(el).addClass("shortpad");
} else if ($("div:eq(0)", el).hasClass("footnotes")) {
$(el).addClass("longpad");
}
});
});
.cmp-container {
border: 1px solid blue;
margin-bottom: -1px;
}
.cmp-container .footnotes {
border: 1px solid red;
}
.cmp-container .productmodelfootnotes {
border: 1px solid green;
}
.shortpad {
padding: 40px;
}
.longpad {
padding: 64px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cmp-container">
<div class="productmodelfootnotes">
Product Note 1
</div>
<div class="footnotes">
Foot Note 1
</div>
</div>
<div class="cmp-container">
<div class="footnotes">
Foot Note 2
</div>
</div>
<div class="cmp-container">
<div class="productmodelfootnotes">
Product Note 3
</div>
<div class="footnotes">
Foot Note 3
</div>
</div>
<div class="cmp-container">
<div class="footnotes">
Foot Note 4
</div>
<div class="productmodelfootnotes">
Product Note 4
</div>
</div>
Using .each(), we can iterate over the DIV elements and check the order of the children. If they meet the specific condition, we can add a Class or apply a Style to that element.
See More: https://api.jquery.com/each/
I assign i as the Index and el as the Element. I then use a Find selector, $("div:eq(0)", el) which is the same as $(el).find("div").eq(0) where 0 represents the first item in the list or elements that is Found.
Using .hasClass() we can check if it is true or false, and perform a specific action based on the condition.
See More: https://api.jquery.com/hasClass/
I used an if / else if statement to check two conditions. This is in case another element may appear first that should not have any padding.

Jquery selector - how can I ensure this works?

I have some buttons, labelled logo1 - logo15 respectively.
There is another button called 'lets-go' that fires a function based on these buttons being selected - when you click a logo the class 'active'.
When there is no logo selected, I would like this button to not be in the DOM - and be hidden. At the moment, the 'active' class for the button brings it's opacity to 1.
I have this jquery statement at the moment.
if (!$('.logo1, .logo2, .logo3, .logo4, .logo5, .logo6, .logo7, .logo8, .logo9, .logo10, .logo11, .logo12, .logo13, .logo14, .logo15').hasClass("active")) {
$('#lets-go').removeClass('active')};
But it's not working.
This is an example of one of my logoX buttons:
$('.logo15').on('click', function(e) {
$('.logo15').toggleClass("active");
$('#b15').toggleClass('alive');
$('#b15').toggleClass('zoomTarget');
$('#b15').toggleClass('dead');
$('#lets-go').addClass('active');
$('#popoutLetsGo').addClass('expand');
$('.instructions-arrow-2').addClass('hide')
});
On click, they apply the class of 'active' to let's go. But it doesn't remove it, ever. Just if you click any of the 15 buttons a new button appears, but if you deselect the button it's still there - and then the next screen is blank.
Can you see why it's not?
I am basically looking for: If none of these classes have the class of active, then make sure this id doesn't have the class of active either.
Consider the following:
if (!$("[class*='logo']").hasClass("active")) {
$('#lets-go').removeClass('active')};
}
This looks at the Class attribute for a item starting with "logo", so .logo3 would be one of those elements. But you may want to test each one.
$("[class*='logo']").each(function(i, el){
if(!$(el).hasClass("active")){
$('#lets-go').removeClass('active')};
}
});
See More:
https://api.jquery.com/attribute-contains-selector/
https://api.jquery.com/each/#each-function
You can also use simplified classes to help group selectors. Consider the following.
$(function() {
$(".logo").click(function() {
$(".logo.active").removeClass("active");
$(this).addClass("active");
$("#letsgo").prop("disabled", false);
});
$("#letsgo").prop("disabled", true);
})
.logo {
padding: .4em;
border: 1px solid black;
border-radius: 3px;
margin: 3px;
background: #eee;
color: #999;
}
.active {
background: white;
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Make a Selection</p>
<div class="logo item-1">Logo 1</div>
<div class="logo item-2">Logo 2</div>
<div class="logo item-3">Logo 3</div>
<div class="logo item-4">Logo 4</div>
<div class="logo item-5">Logo 5</div>
<button id="letsgo">Let's Go!</button>

Check to see of current clicked element equals to previous clicked element-Javascript

I have a list of items displayed in a container with a dropdown associated with every container.A snippet of how the container list looks:
http://jsfiddle.net/jHpKB/2/
When I click on the button , the dropdown menu shows up, however, when I try to click on any other button button, the dd stays and does not hide. the list is dynamically created. What I was trying to do is if the current clicked element is same as that of the previous clicked elemnt, then hide the first dd menu
Is there way to check if a clicked element is equal to the previous clicked element in javascript(no jquery)
code:
afterRender: function() {
this.el.on('click', function(e) {
//here i want to check (if e.getTarget() === secondClickedEment) { //do something}
},this);
}
is this possible?
Thanks
You can test object equality with jQuery using the is function. Requires 1.6 or higher.
var stuff = $('#stuff');
var thing = stuff;
if (stuff.is(thing)) {
// the same
}
So for your situation this should work:
afterRender: function() {
this.el.on('click', function(e) {
var clickedElm = $(e.getTarget());
var secondElm = $(secondClickedElm);
if (clickedElm.is(secondElm)){
// same elements
}
},this);
}
jQuery example:
use var lastClicked; to hold the last clicked element, then each click check if the same one clicked then reset the lastclicked, otherwise update the lastclicked.
var lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$(this).children('.menu').hide();
} else {
lastClicked = this;
$('.menu').hide();
$(this).children('.menu').show();
}
});
.container {
border: 1px solid #333;
height: 300px;
width: 200px;
float: right;
margin-right: 20px;
}
.menu {
display: none;
}
.button {
border: 1px solid #333;
background: #333;
float: right;
height: 20px;
width: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="button">
</div>
<div class="menu">
<div class="option1 option">option1</div>
<div class="option2 option">option2</div>
</div>
</div>
<div class="container">
<div class="button">
</div>
<div class="menu">
<div class="option1 option">option1</div>
<div class="option2 option">option2</div>
</div>
</div>
<div class="container">
<div class="button">
</div>
<div class="menu">
<div class="option1 option">option1</div>
<div class="option2 option">option2</div>
</div>
</div>
One way to do this would be to dynamically add/remove a class to the div, indicating if it's open or not. Then on click, you could just toggle that class.
Example:
let containers = document.getElementsByClassName('container');
for (let i=0; i<containers.length; i++) {
let button = containers.item(i).getElementsByClassName('button')[0];
let menu = containers.item(i).getElementsByClassName('menu' )[0];
button.addEventListener('click', function() {
menu.classList.toggle('open');
});
}
Then in your CSS:
.open {
display: block;
}

HTML and Javascript - Detecting which div box was clicked?

If I have multiple div boxes lined up (not overlapping), how can I detect which box is clicked?
For example, here is pseudocode:
HTML:
<div id="box1" onClick="clicked()">Box 1</div>
<div id="box2" onClick="clicked()">Box 2</div>
<div id="box3" onclick="clicked()">Box 3</div>
JS:
function clicked(){
var first="box1";
var second="box2";
var third="box3";
if (the div id of what you clicked is equal to first)
/*do something here*/
if (the div id of what you clicked is equal to second)
/*do something here*/
etc
etc
}
My main problem is that I don't know how to properly write the if statement. I'm not sure how to get the div's id that you clicked in JavaScript. I'm thinking of something like this:
if (document.getElementById() = first)
/*do stuff*/
I'm aware that I can solve this problem by having three different functions such as clicked1(), clicked2(), and clicked3(), but I would prefer not to have so many functions.
Any help is appreciated, thank you.
Pure Javascript has a built in target in the event object. This is basically the opposite of getElementById, its basically getIdByElement(though this method doesn't exist). To access it all you need to do is edit your HTML from onClick="clicked()" to onClick="clicked(event)" and change your clicked function into code similar to this:
function clicked(event) {
var id = event.target.id,
first = 'box1',
second = 'box2',
third = 'box3';
if(id === first) {
...
} else if(id === second) {
...
} else if(id === third) {
...
}
}
To explain why this works, when a JavaScript event is fired you get an object about it, it looks like this:
This is so that you can get certain details about what happened. In this case, you wanted the target id. This works by selecting all divs on the page. Also to shorten the code if you want, you can pass in this instead and do this.id. Such as:
function clicked(reference) { //pass in this instead of event
let id = reference.id;
...
}
Here is an example of it in work:
function clicked(event) {
let p = document.getElementById('clicked-item')
p.textContent = event.target.id + ' clicked';
}
<div id="box1" onClick="clicked(event)">Box 1</div>
<div id="box2" onClick="clicked(event)">Box 2</div>
<div id="box3" onclick="clicked(event)">Box 3</div>
<p id="clicked-item">none clicked</p>
It is a good idea to separate HTML and JS(though not 100% necessary). So to remove the onClick attribute on each element do something like this:
let selector = document.getElementsByTagName('div')
for(let element of selector) {
element.addEventListener('click', function(event) {
clicked(event);
});
}
The code starts by getting all elements that are a div with getElementsByTagName, though you can use other selectors too. Then using a for loop we loop through all the divs and add an onClick event running clicked.
You could make this work using inline event handlers but it'd be better to move your binding code to your actual scripts. You can still use one function, just apply it to each element.
The click handler will receive an event object which gives information about the click. Part of that is the .target property which will give you the source of the click event i.e, the element you clicked on.
function clicked(e) {
var target = e.target;
console.log(target.id);
}
document.querySelector('#box1').addEventListener('click', clicked);
document.querySelector('#box2').addEventListener('click', clicked);
document.querySelector('#box3').addEventListener('click', clicked);
.box {
float: left;
width: 100px;
height: 100px;
margin-right: 2px;
background-color: #000;
color: #EEE;
}
<div id="box1" class="box">Box 1</div>
<div id="box2" class="box">Box 2</div>
<div id="box3" class="box">Box 3</div>
If you're hellbent on using inline bindings, the simplest way to do this would be to pass this into your function call. That will pass the element directly.
function clicked(target) {
console.log(target.id);
}
.box {
float: left;
width: 100px;
height: 100px;
margin-right: 2px;
background-color: #000;
color: #EEE;
}
<div id="box1" class="box" onclick="clicked(this)">Box 1</div>
<div id="box2" class="box" onclick="clicked(this)">Box 2</div>
<div id="box3" class="box" onclick="clicked(this)">Box 3</div>
By adding clicked(this) it selects the div you click on and returns that specific div's data.
<div id="box1" onClick="clicked(this)">Box 1</div>
<div id="box2" onClick="clicked(this)">Box 2</div>
<div id="box3" onclick="clicked(this)">Box 3</div>
By adding the div as a parameter it specifies the div you clicked on's internal data, and adding a switch statement to trigger a specific response to each div.
function clicked(div) {
if(div.id = 'box1') {
console.log('1');
} else if(div.id = 'box2') {
console.log('2');
} else if(div.id = 'box3') {
console.log('3');
}
}

Categories

Resources