I checked out some other posts on here but still couldn't get this issue to work.
I have several elements in my html with the class cardContainer:
<div class="cardContainer">
<div id="card2" class="block" onclick="changeClass()">
</div>
</div>
<div class="cardContainer">
<div id="card3" class="block" onclick="changeClass()">
</div>
</div>
For each onClick event I would like to call this JS function:
<script type="text/javascript">
function changeClass(){
if(document.getElementById("card2").className == "block")
document.getElementById("card2").className += " rotated";
else
document.getElementById("card2").className = "block";
}
</script>
What I would like to do is include the card3 id, so it fires the same function on click. How would I be able to combine the ids "card2" and "card3" in the javascript so the function works?
I get that if I use getElementById, I can only get one and not multiple ids/classes, but I tried using getElementsByClassName for example without success. Also looked at other posts but couldn't get this to work based on the suggestions... I am new to Javascript and not quite sure on how to approach this.
Thanks for your help!
Try this:
HTML
<div class="cardContainer">
<div class="card block">Click Here</div>
<div class="card block">Click Here</div>
<div class="card block">Click Here</div>
</div>
JavaScript
var cards = document.querySelectorAll(".card");
for (var i = 0; i < cards.length; i++) {
var card = cards[i];
card.onclick = function () {
if (this.classList.contains("block")) {
this.classList.add("rotated");
this.classList.remove("block");
}
else {
this.classList.add("block");
this.classList.remove("rotated");
}
};
}
Here is the Demo
Compatibility table for support of querySelector/querySelectorAll: Can I Use
You can pass the id of the div being clicked on your changeClass function:
<div id="card3" class="block" onclick="changeClass(this.id)">
This way, it will be easier to handle your class switching process:
function changeClass(id) {
var div = document.getElementById(id);
switch (id) {
case "card2": {
if (div.className == "className") {
div.className = "anotherClassName";
}
break;
}
case "card3": {
if (div.className == "block") {
div.className = "rotated";
}
break;
}
default: {
// any other case
}
}
}
use document.getElementsByClassName( doesn't work on ie<9 or FF<3) if you don't care about older browsers and if you do then i suggest you to use jquery, or just sizzle.js to use css selectors
I think you're looking for something like this?. (assuming you're ok with using jQuery)
http://jsfiddle.net/LqpKt/
<div class="cardContainer">
<div id="card1" class="block"></div>
</div>
<div class="cardContainer">
<div id="card2" class="block"></div>
</div>
<div class="cardContainer">
<div id="card3" class="block"></div>
</div>
<div id="output"></div>
$('.cardContainer').click(function(e){
var name = $(this).find('.block').attr('id');
$('#output').append($('<div>').html('clicked ' + name));
})
Related
I try to appendChild several element (for loop) with javascript but it doesn't work
see: https://jsfiddle.net/9tsop7zw/3/
Or:
window.onload = function() {
var profile = document.getElementById("profileJS");
console.log(profile)
for(let i=0; i<5; i++) {
document.getElementById("appendchild").appendChild(profile);
}
}
<script type="text/template" id="profileJS">
<div class="content">
<div class="logo"></div>
<div class="name">Profile Name</div>
<div class="follower">119k</div>
</div>
</script>
<div id="appendchild"></div>
It's only work with
document.getElementById("something").innerHTML = document.getElementById("profileJS").innerHTML;
but I really need to appendChild for make this very clean
(cause with .innerHTML solutions I need to create childs before set them to the "profileJS".innerHTML)
tell me if you know some solution ty
Hi im working on animating an arrow in an accordion but it only animates the first row no matter which one i pick. I know its a target issue but can make this work. some help would be great!!
code pen here https://codepen.io/al-web-dev/pen/bGRXdyL
<div class="myDiv">
<div class="row">
<div class="col-4">Test</div>
<div class="col-4 cheese">test 1</div>
<div class="col-4">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</div>
</div>
<div class="row">
<div class="col-4">Test</div>
<div class="col-4 cheese">test 2</div>
<div class="col-4">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</div>
</div>
</div>
var myDiv = document.getElementsByClassName("row");
for (var i = 0; i < myDiv.length; i++) {
myDiv[i].addEventListener("click", function (event) {
let toggleAble = document.querySelector(".fa-arrow-up");
let cheese = document.querySelector(".cheese");
event.target.classList.toggle("yello");
event.target.classList.toggle("arrow-down");
});
}
The code in your codepen and your example given here is different. I suggest settling on one version of the code if you're gonna ask for help.
The problem you were facing in your codepen example had to do with var toggleAble. You were query-selecting by a classname. .querySelector will only pick the first element from a list of elements it finds. That is why you've had only the first arrow react. Change document before your query selector method to myDiv[i] - the element you're looking for the arrow in. Like so:
for (let i = 0; i < myDiv.length; i++) {
myDiv[i].addEventListener("click", function (event) {
var toggleAble = myDiv[i].querySelector(".fa-arrow-up");
toggleAble.classList.toggle("arrow-down");
});
}
Oh and for some reason you've renamed the function parameter to myDiv, an already declared array of elements. I've changed it back to event for you.
just wondering what went wrong.. i have two div named click_1 and click_2.. and i want to toggle the div named hide corresponding with their numbers.. lets say click_1 with hide_1 and click_2 with hide_2.. but when i ran the code only click_1 is functioning .. what seems to be wrong... newbie here.. recently learned jquery
<div id='click_1'>
<div id='hide_1'></div>
</div>
<div id='click_2'>
<div id='hide_2'></div>
</div>
<script>
function toggle_div(id_A,id_B){
for(var i=0; i<3; i++){
var new_A = id_A + i;
var new_B = id_B + i;
$(new_A).click(function(){
$(new_B).toggle();
});
}
}
toggle_div('click_','hide_');
</script>
The issue is because your id selectors are missing the # prefix:
toggle_div('#click_', '#hide_');
However you should note that you will also need to use a closure for this pattern to work otherwise the new_B element will always be the last one referenced in the for loop.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='click_1'>
click 1
<div id='hide_1'>hide 1</div>
</div>
<div id='click_2'>
click 2
<div id='hide_2'>hide 2</div>
</div>
<script>
function toggle_div(id_A, id_B) {
for (var i = 1; i < 3; i++) {
var new_A = id_A + i;
var new_B = id_B + i;
(function(a, b) {
$(a).click(function() {
$(b).toggle();
})
})(new_A, new_B);
}
}
toggle_div('#click_', '#hide_');
</script>
As you can see this is very verbose, rather complicated and hardly extensible. A much better approach is to use generic classes and DOM traversal to repeat the same logic on common HTML structures.
To achieve this put common classes on the elements to be clicked and the elements to toggle. Then in the single click event handler you can use the this keyword to reference the element which was clicked, then find() the element to toggle within that. Something like this:
$(function() {
$('.click').click(function() {
$(this).find('.hide').toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click">
click 1
<div class="hide">hide 1</div>
</div>
<div class="click">
click 2
<div class="hide">hide 2</div>
</div>
<div class="click">
click 3
<div class="hide">hide 3</div>
</div>
Also note that this pattern means that you can have an infinite number of .click elements with matching .hide content without ever needing to update your JS code.
It is better not to use for loop for click event ! If you have id like that your can handle by that clicked id split ....
$("[id^='click_']").on("click",function () {
$('#hide_'+this.id.split('_')[1]).toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='click_1'>
Click1
<div id='hide_1'>hide1</div>
</div>
<div id='click_2'>
Click2
<div id='hide_2'>hide2</div>
</div>
I need to display different output according to each different icon clicked without defining separate functions;
HTML:
<p onclick="expand()" id="i1">icon1</p>
<p onclick="expand()" id="i2">icon2</p>
<p onclick="expand()" id="i3">icon3</p>
<div id="blocki1"></div>
<div id="blocki2"></div>
<div id="blocki3"></div>
Can I do something like this with JS?
function expand() {
document.getElementById("block" + this.id).style.display = "block";
}
I've tried the method above which apparently didn't work, I need to a)store icon's id and b) combine the id with string. Don't sure if that's possible.
<p onclick="expand(this.id) id="i1">icon1</p>
<p onclick="expand(this.id) id="i2">icon2</p>
<p onclick="expand(this.id) id="i3">icon3</p>
<div id="blocki1"></div>
<div id="blocki2"></div>
<div id="blocki3"></div>
<script>
function expand(e) {
document.getElementById("block" + e).style.display = "block";
}}
</script>
First.. You have 4 typos. First 3 are that you don't have closing " after onclick="expand()
<p onclick="expand() id="i1">icon1</p>
<!-- There needs to be " after expand() -->
Last typo is you have extra closing } after expand function.
Now, since you're not using addEventListener API, the value of this will not be set on your expand function.
So you need to pass your current element as a parameter to the function.
<p onclick="expand(this)" id="i1">icon1</p>
<p onclick="expand(this)" id="i2">icon2</p>
<p onclick="expand(this)" id="i3">icon3</p>
<div id="blocki1">blocki1</div>
<div id="blocki2">blocki2</div>
<div id="blocki3">blocki3</div>
(Added some place holder text to divs to see if this works)
Lastly, access the current element in your function as a first parameter.
function expand(el) {
document.getElementById("block" + el.id).style.display = "block";
}
Pass parameters to the function
You need to pass some data (e.g. the reference to the object, its name, or whatever else you need) to the function you're calling.
For example, look at the sample code from https://www.w3schools.com/jsref/event_onclick.asp
<p onclick="myFunction(this, 'red')">Click me to change my text color.</p>
<script>
function myFunction(elmnt,clr) {
elmnt.style.color = clr;
}
</script>
I might approach it slightly differently by removing the inline JS, and using classes and data attributes. Here I have classes and data attributes on all the elements. I attach click event listeners to the "buttons" which call the handleClick function. This function checks the data id attribute of the button and grabs the corresponding slide, adding a "show" class to its class list.
const buttons = document.querySelectorAll('.button');
buttons.forEach(button => {
button.addEventListener('click', handleClick, false);
});
function handleClick(e) {
const id = e.target.dataset.id;
const slide = document.querySelector(`.slide[data-id="${id}"]`);
slide.classList.add('show');
}
.slide {
display: none;
}
.show {
display: block;
}
<p class="button" data-id="1">icon1</p>
<p class="button" data-id="2">icon2</p>
<p class="button" data-id="3">icon3</p>
<div class="slide" data-id="1">blocki1</div>
<div class="slide" data-id="2">blocki2</div>
<div class="slide" data-id="3">blocki3</div>
Your code should like this
<p onclick="expand(this) id="i1">icon1</p>
<p onclick="expand(this) id="i2">icon2</p>
<p onclick="expand(this) id="i3">icon3</p>
<div id="blocki1"></div>
<div id="blocki2"></div>
<div id="blocki3"></div>
<script>
function expand(elm) {
document.getElementById("block" + elm.id).style.display = "block";
}
</script>
If you are a beginner, I would suggest you to avoid practice of adding handlers in HTML, before it becomes your coding attitude.
Instead, add eventlisteners for them in js. Separation of concerns is really big theory.
And it's relativelyeasy to deal with this in event handlers
You can read more about it here
var ps = Array.from(document.querySelectorAll("p"));
for(var i=0; i< ps.length; i++){
ps[i].addEventListener(("click"), function(){
document.getElementById("block" + this.id).style.display = "block";
})
}
div{
display: none;
}
<p id="i1">icon1</p>
<p id="i2">icon2</p>
<p id="i3">icon3</p>
<div id="blocki1">This is 1</div>
<div id="blocki2">This is 2</div>
<div id="blocki3">This is 3</div>
I'm trying to show appropriate content using this method: determine id of the clicked div, than open div content with determined id + '-box'. But it doesn't work.
JQuery that doesn't work:
$(".portfolio-apps section").click(function() {
var currentID = '#' + $(this).attr('id');
console&&console.log(currentID);
var currentIDBox = currentID + "-box";
console&&console.log(currentIDBox);
$(currentID).click(function() {
$('.portfolio-entry-text').hide('fast');
var bcn = $(currentIDBox);
if ($('.box-content').is(':visible')) {
$('.box-content').hide();
bcn.show();
}
else {
$('.box-content').hide();
bcn.slideToggle(200);
}
});
});
Similar JQuery that is working:
$("#gterminal").click(function() {
$('.portfolio-entry-text').hide('fast');
var bcn = $('#gterminal-box');
if ($('.box-content').is(':visible')) {
$('.box-content').hide();
bcn.show();
}
else {
$('.box-content').hide();
bcn.slideToggle(200);
}
});
HTML
<div class="portfolio-apps clearfix">
<section class="button" id="gterminal">
<span>Google in Terminal</span>
</section>
<section class="button" id="MySQLToJSON">
<span>MySQL to JSON</span>
</section>
</div>
<div id="wrapper" >
<div class="box-content" id="gterminal-box">
<p>BOX 1</p>
</div>
<div class="box-content" id="MySQLToJSON-box">
<p>BOX 2</p>
</div>
</div>
You're binding a .click event internally, which means that the -box showing/hiding won't be triggered until a second click. This doesn't make sense to me. If you just remove the internal .click binding, it seems to work quite nicely:
http://jsfiddle.net/Th3wT/