I have 3 divs with the same class (i can't use IDs on them). I find all of them by targeting their class and then - on click - i want to apply some stuff (e.g. change background-color). i only managed to change all of them, but not only the one i'm actually clicking. what am i missing?
var thisDiv = $('.thisDiv');
thisDiv.click(function() {
var i = thisDiv.index(this);
console.log(i);
console.log(thisDiv.css('background-color'));
// this changes all of the div, not only the clicked one
thisDiv.css('background-color', 'red');
// console msg for the code below: Uncaught TypeError: thisDiv[i].css is not a function
// thisDiv[i].css('background-color', 'red');
// i also tried these, which didn't work...
//console.log(thisDiv[i].css('background-color'));
//console.log(thisDiv.eq[i].css('background-color'));
});
.thisDiv{width:50px;height:50px;background-color:lightgrey;float:left;margin:15px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="thisDiv">div 0</div>
<div class="thisDiv">div 1</div>
<div class="thisDiv">div 2</div>
use $(this) will give you the div which you have clicked
$(this).css('background-color', 'red');
use .eq():
thisDiv.eq(i)
as thisDiv is a collection of objects, you can get the specific ones with $(this) or .eq(i).
var thisDiv = $('.thisDiv');
thisDiv.click(function() {
var i = thisDiv.index(this);
thisDiv.eq(i).css('background-color', 'red');
});
.thisDiv {
width: 50px;
height: 50px;
background-color: lightgrey;
float: left;
margin: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="thisDiv">div 0</div>
<div class="thisDiv">div 1</div>
<div class="thisDiv">div 2</div>
Related
I have a set of div elements inside a container, .div-to-hide is displayed by default whilst .div-to-show is hidden.
When I click in .set, .div-to-hide should hide and .div-to-show should be visible. Next click should return the previous clicked element to its default state.
I need to display to buttons on click inside on .div-to-show.
<div class="container">
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
</div>
So far I have this:
let lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$('.div-to-hide').show();
$(this).children('.div-to-hide').hide();
} else {
lastClicked = this;
$('.div-to-hide').hide();
$(this).children('.div-to-hide').show();
$(this).children('.div-to-show').hide();
}
});
Can't get it to work properly tho.. I don't know what I am missing...
Any help is deeply appreciated!
UPDATE: got it working! Thanks everyone!
First, you are not using delegation (second parameter on the $.on() function) to define the .set element as your this inside the function.
If I understood correctly, you want to show the elements on the last one clicked and hide the rest. You don't really need to know which one you last clicked to do that
$('.container').on('click', '.set', function (e) {
// Now "this" is the clicked .set element
var $this = $(this);
// We'll get the children of .set we want to manipulate
var $div_to_hide = $this.find(".div-to-hide");
var $div_to_show = $this.find(".div-to-show");
// If it's already visible, there's no need to do anything
if ($div_to_show.is(":visible")) {
$div_to_hide.show();
$div_to_show.hide();
}
// Now we get the other .sets
var $other_sets = $this.siblings(".set");
// This second way works for more complex hierarchies. Uncomment if you need it
// var $other_sets = $this.closest(".container").find(".set").not(this);
// We reset ALL af them
$other_sets.find(".div-to-show").hide();
$other_sets.find(".div-to-hide").show();
});
Consider using class toggling instead.
$('.set').on('click', function(e) {
$('.set').removeClass('hidden-child');
$(this).addClass('hidden-child');
});
css:
.hidden-child .div-to-hide, .div-to-show {
display: none;
}
.hidden-child .div-to-show, .div-to-hide {
display: block;
}
This will make your code easier to reason about, and lets css control the display (style) rules.
Edit: changed class name for clarity; expanded explanation; corrected answer to conform to question
Try to make use of siblings() jQuery to hide and show other divs and toggle() jQuery to show and hide itself and also you will need to set click() event on .set, not in .container
$(document).on('click', '.set', function(e) {
$(this).find('.hide').toggle();
$(this).find('.show').toggle();
$(this).siblings('.set').find('.hide').show();
$(this).siblings('.set').find('.show').hide();
});
.show {
display: none;
}
.set div {
padding: 10px;
font: 13px Verdana;
font-weight: bold;
background: red;
color: #ffffff;
margin-bottom: 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="set">
<div class="hide">1 Hide</div>
<div class="show">1 Show</div>
</div>
<div class="set">
<div class="hide">2 Hide</div>
<div class="show">2 Show</div>
</div>
<div class="set">
<div class="hide">3 Hide</div>
<div class="show">3 Show</div>
</div>
</div>
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
I have a list of DIVS that have buttons inside. By default, all buttons are hidden. When I click within a DIV area, the current button inside of this clicked DIV are should show (class='.db') AND all previously clicked/shown buttons should be hidden (class='.dn'). In other words, at any time there should be only one button (currently clicked) shown and all other should be hidden.
I want to use vanilla Javascript and tried this below, but it won't work. I feel there is some small error but don't know where.. Note - the DIVS and buttons don't have their own unique IDs (they only have the same CSS (.posted) classes.
PS - maybe it'd be better not to add this onClick="t();" to each DIV and use an 'addEventListener' function, but this is way too much for me ; )
CSS:
.dn {display:none}
.db {display:block}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
HTML:
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
JAVASCRIPT:
function t()
{
var x=document.getElementsByClassName("posted"),i,y=document.getElementsByTagName("button");
for(i=0;i<x.length;i++)
{
x[i].y[0].className="dn";
};
x.y[0].className='db';//make sure the currently clicked DIV shows this button (?)
}
You might want to read more about selector, how to select class, block level etc.
some link might be helpful:
CSS selector:
https://www.w3schools.com/cssref/css_selectors.asp
jQuery selector:
https://api.jquery.com/category/selectors/
Solution - Using jQuery:
$('.posted').on('click', function() {
//find all class called posted with child called dn, then hide them all
$('.posted .dn').hide();
//find this clicked div, find a child called dn and show it
$(this).find('.dn').show();
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
Solution - Pure js version:
//get list of div block with class="posted"
var divlist = Array.prototype.slice.call(document.getElementsByClassName('posted'));
//for each div
divlist.forEach(function(item) {
//add click event for this div
item.addEventListener("click", function() {
//hide all button first
divlist.forEach(function(el) {
el.getElementsByTagName('button')[0].classList.add('dn');
});
//show button of the div clicked
this.getElementsByTagName('button')[0].classList.remove('dn');
}, false);
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
You can do this with with plain JavaScript using Event Bubbling, querySelector and the element classList attribute like this.
Change your HTML to look like this:
<div class="posts">
<div class="posted">
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
</div>
Then use JavaScript like this:
var posts = document.querySelector('.posts');
var allPosted = document.querySelectorAll('.posted');
//clicks bubble up into the posts DIV
posts.addEventListener('click', function(evt){
var divClickedIn = evt.target;
//hide all the buttons
allPosted.forEach(function(posted){
var postedBtn = posted.querySelector('button');
postedBtn.classList.remove('db');
});
// show the button in the clicked DIV
divClickedIn.querySelector('button').classList.add('db')
});
You can find a working example here: http://output.jsbin.com/saroyit
Here is very simple example using jQuery .siblings method:
$(function () {
$('.posted').click(function () {
$('button', this).show();
$(this).siblings().find('button').hide();
});
});
https://jsfiddle.net/3tg6o1q7/
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');
}
}
Say I have 5 divs, all having the same styling:
Fiddle
HTML
<div id="box"> </div>
<div id="box"> </div>
<div id="box"> </div>
<div id="box"> </div>
<div id="box"> </div>
CSS
#box {
background-color:blue;
width:200px;
height:50px;
display:block;
margin-top:10px;
}
I want to execute some jQuery in order to change the colour of every specific div on .mouseover(), and change it back to the original on .mouseout():
jQuery
$(document).ready(function() {
$('#box').mouseover(function() {
$('#box').css('background-color', 'red');
});
$('#box').mouseout(function() {
$('#box').css('background-color', 'blue');
});
});
This only works for the first instance of the div, how would I go about making this work for every individual one? I want each div to work as it's own but I have no idea how to do that.
I researched and found out about .each() but I'm clueless as to how to incorporate that into my function. Can someone please help me out? Thank you in advance.
ID must be Unique.
You can use the same class to all the elements. There is no need of using Javascript when you can use :hover in CSS to change the style of element on hover.
Updated Fiddle
.box {
background-color: blue;
width: 200px;
height: 50px;
display: block;
margin-top: 10px;
}
.box:hover {
background: red;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
As people said ID must be always unique and along with that if you want to achieve it jquery way, then you can do it as below:
$(document).ready(function() {
//bind class element with '.' prefixed
$('.box').mouseover(function() {
$(this).css('background-color', 'red');
//$(this) refers to current element here
});
$('.box').mouseout(function() {
$(this).css('background-color', 'blue');
});
});
.box {
background-color: blue;
width: 200px;
height: 50px;
display: block;
margin-top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
UPDATE
Using hover and with some performance improving aspect you can try to achieve it as below:
$(document).ready(function() {
$('.box').hover(function() {
$(this).css('background-color', 'red');
},function(){
$(this).css('background-color', 'blue');
});
});
You can't look for objects with same id, instead, you can use .each jquery function to look out for each div with id #box.
It looks like in this fiddle.
Fiddle
$(document).ready(function() {
$( "div#box" ).each(function() {
$( this ).mouseover(function(index) {
console.log( index + ": " + $( this ).text() );
$(this).css('background-color', 'red');
});
$( this ).mouseout(function(index) {
console.log( index + ": " + $( this ).text() );
$(this).css('background-color', 'blue');
});
});
});