changing clicked element's style in array through javascript - javascript

my html code:
<div class="mydiv" onclick="clickonelement()">div1</div>
<div class="mydiv" onclick="clickonelement()">div2</div>
<div class="mydiv" onclick="clickonelement()">div3</div>
<div class="mydiv" onclick="clickonelement()">div4</div>
<div class="mydiv" onclick="clickonelement()">div5</div>
<div class="mydiv" onclick="clickonelement()">div6</div>
<!-- javascript code -->
function clickonelement(){
mydiv = document.getElementsByClassName("mydiv");
for(i=0; i<mydiv.length; i++){
mydiv.item(i).style.backgroundColor = "red";
mydiv[this].style.backgroundColor = "#fff";
}
}
css code
.mydiv{width:300px; height:30px;}
I want on onClick event to change clicked element's background to white and other elements background remain red in color but my code
mydiv[this].style.backgroundColor = "#fff";
is not working. please solve this problem in JavaScript only. I am in basic stage of JavaScript.

You need to pass a reference to the element that you want to refer to with this, e.g. onclick="clickonelement(this)":
function clickonelement(elem) {
mydiv = document.getElementsByClassName("mydiv");
for (i = 0; i < mydiv.length; i++) {
mydiv.item(i).style.backgroundColor = "red";
elem.style.backgroundColor = "#fff";
}
}
<div class="mydiv" onclick="clickonelement(this)">div1</div>
<div class="mydiv" onclick="clickonelement(this)">div2</div>
<div class="mydiv" onclick="clickonelement(this)">div3</div>
<div class="mydiv" onclick="clickonelement(this)">div4</div>
<div class="mydiv" onclick="clickonelement(this)">div5</div>
<div class="mydiv" onclick="clickonelement(this)">div6</div>

This is JS code for your HTML code, you need add addEventListener.
function clickonelement() {
mydiv = document.getElementsByClassName("mydiv");
for (var i = 0; i < mydiv.length; i++) {
mydiv[i].addEventListener('click', function() {
this.style.backgroundColor = "red";
this.style.backgroundColor = "#fff";
});
}
}

Here is just another way of achieving the same functionality.
Objective
To remove inline event handler
Use loop only once instead of looping over all the matched class name (mydiv) on every click.
Used javascript functions & concepts
querySelectorAll : - Used to select all matched elements with same class that is mydiv. It will return an nodelist containing all matched elements
forEach:- is an array method which used to loop over list.It accepts three arguments. For this case two will be enough.
addEventListener:- Is use to attach event to an element
Closures:These functions 'remember' the environment in which they were created.
Hope this snippet will be useful
//Get all the matched Elements
var matches = document.querySelectorAll("div.mydiv");
//Use an variable to rememeber previous clicked element
var prevIndex = -1; //
// Loop over the list
matches.forEach(function(item,index){
(function(i){ // A closure is created
item.addEventListener('click',function(){
// if any previous element was clicked then rest it's background
if(prevIndex !== -1){
matches[prevIndex].style.background="red";
}
// change background of current element
item.style.background="#fff";
// update prevIndex
prevIndex = i;
})
}(index))
})
Check this DEMO

Related

Javascript - get class of another element with onclick

I want to individually toggle to different divs using the same function. Each of these divs has a common class and a different id. The function toggle is called using an onclick parameter on two separate <a> elements:
<a class="btn" id="btnOne" onclick="toggler();">Show/hide divOne</a>
<div class="box" id="divOne">
<a class="btn" id="btnTwo" onclick="toggler();">Show/hide divTwo</a>
<div class="box" id="divTwo">
I first tried to get these divs with getElementsByClassName but, as it returns an HTMLCollection, the script can't target each div individually.
So I tried to select the <a> tags ids (btnOne and btnTwo), but couldn't figure out how to retrieve the divs class using these ids (as we're talking about two different elements here).
In the end, I came back to the getElementById method, as I couldn't figure out how to select them based on their class:
function toggler() {
var id = document.getElementById("divId");
if (id.style.display === "none") {
id.style.display = "block";
} else {
id.style.display = "none";
}
};
This leaves me with two functions instead of just one. Any suggestion on how to target the two divs individually?
You can access the next sibling using nextElementSibling presuming the box will always be right after the hyperlink.
// Put the buttons into an array
const buttons = [...document.getElementsByClassName("btn")];
// Assing an event listener for every button
buttons.map(button => button.addEventListener("click", function(e) {
// Find the next sibling
const box = e.target.nextElementSibling;
// Toggle the display value
if (box.style.display === "none") {
box.style.display = "block";
} else {
box.style.display = "none";
}
}));
a {
display: block;
}
.box {
width: 5rem;
height: 2rem;
background-color: blue;
}
<a class="btn">Show/hide divOne</a>
<div class="box"></div>
<a class="btn">Show/hide divTwo</a>
<div class="box"></div>
There is a simple way to select the divs with their class name and you already used it.
The answer is getElementsByClassName. But in vanilla JS things are a little bit (over)complicated.
It will not target both divs individually. Instead, if you want to select the first div with this class you would do it like this:
getElementsByClassName('classname')[0]
If you want to select the second div you would use:
getElementsByClassName('classname')[1]
and so on. But there is a way of course.
You want to use loops:
var x = document.getElementsByClassName("classname");
for (var i = 0; i < x.length; i++) {
if (x[i].style.display === "none") {
x[i].style.display = "block";
} else {
x[i].style.display = "none";
}
}
In this way, you will target ALL divs with this class.
I'd dynamically add the events on the switches, using their classes. I added the class showHideDivBtn to them. To make sure you know which div you have to toggle, I used a data-id.
With addEventListener, I can use the event variable I named e. With this one, I have access to properties, such as the data-id I wrote.
let buttons = document.getElementsByClassName("showHideDivBtn");
for (let i = 0; i < buttons.length; ++i)
{
buttons[i].addEventListener('click', function(e)
{
let divToToggle = document.getElementById(e.srcElement.dataset.id);
if (divToToggle.style.display === "none")
divToToggle.style.display = "block";
else
divToToggle.style.display = "none";
});
}
<a class="btn showHideDivBtn" data-id="divOne" id="btnOne">Show/hide divOne</a>
<div class="box" id="divOne">One</div>
<br />
<a class="btn showHideDivBtn" data-id="divTwo" id="btnTwo">Show/hide divTwo</a>
<div class="box" id="divTwo">Two</div>
Use substr to get the word after extracting 'btn' from anchor id which will result in One or Two then while defining the if use "div"+word this will get the div by it is related a tag
function toggler() {
var word=this.id.substr(3);
var id = document.getElementById("div"+word);
if (id.style.display === "none") {
id.style.display = "block";
} else {
id.style.display = "none";
}
};

Binding an event listener to multiple elements with the same class

I'm trying to apply the onclick event with JavaScript to the following elements:
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
If I click on the first element (with index [0]) then this works, but I
need this event applicable for all classes:
document.getElementsByClassName('abc')[0].onclick="function(){fun1();}";
function fun1(){
document.getElementsByClassName('abc').style.color="red";
}
.onclick does not expect to receive a string, and in fact you don't need an extra function at all.
However, to assign it to each element, use a loop, like I'm sure you must have learned about in a beginner tutorial.
var els = document.getElementsByClassName('abc');
for (var i = 0; i < els.length; i++) {
els[i].onclick = fun1;
}
function fun1() {
this.style.color = "red";
}
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
To expand on the solution provided by #rock star I added two small additions to the function. First it is better to add / reemove a class (with an associated style rule) to an element than directly applying the stylerule to the element.
Secondly - on the click event - this will now remove the red class (and therefore style) from the previously selected element and add it to the new element. This will allow only one element to be red at a time (in the original solution any element that was clicked would become red).
var els = document.getElementsByClassName('abc');
for (var i = 0; i < els.length; i++) {
els[i].onclick = fun1;
}
function fun1() {
var oldLink = document.getElementsByClassName('red')[0];
if(oldLink) {oldLink.classList.remove('red')};
this.classList.add('red');
}
.red {
color:red;
}
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
This works:
<body>
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
<script>
var elements = document.getElementsByClassName('abc');
for(var i = 0, max = elements.length; i < max; i += 1) {
var clickedElement = elements[i];
clickedElement.onclick=function (){
fun1(this);
};
}
function fun1(element){
element.style.color="red";
}
</script>
</body>

Why wont my onclick not remove any of my classes?

I have a huge problem here.
I can't get my onclick to work as I want .. So I hope someone here can help me.
#NiceToKnow
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="video"></div>
I want it to display: none; every of my class="nice", so you only can see class="video", but nothing happens at all.
You are selecting the elements of the class not the class itself. So you will have to loop through the elements as javascript can only edit what is in the DOM not the CSS classes that effect your elements. So getElementsByClassName returns an array of nodes in which we must loop through and hide each one. Click runsnippet below to see this work
function changeNice(){
//ASSIGN ELEMENTS TO ARRAY
elementsofClass=document.getElementsByClassName('nice');
for(i=0; i<elementsofClass.length; i++){
//HIDE SELECTED ELEMENT
elementsofClass[i].style.display='none';
}}
#NiceToKnow
<div id="cards1" class="nice">TEST 1</div>
<div id="cards2" class="nice">TEST 2</div>
<div id="cards3" class="nice">TEST 3</div>
<div id="cards4" class="video">I don't HIDE</div>
Also don't use duplicate ID. This will cause errors later when trying to select your elements.
The getElementsByClassName will return an array, so we need to iterate through the array and hide one by one.
So it is better to declare a function and define the logic inside that. Please see the example below.
window.hideAllniceClass = function () {
var elems = document.getElementsByClassName('nice');
for (var i = 0; i != elems.length; ++i) {
elems[i].style.display = "none"; // hidden has to be a string
}
}
#NiceToKnow
<div id="cards1" class="nice">Test Content</div>
<div id="cards2" class="nice">Test Content</div>
<div id="cards3" class="nice">Test Content</div>
<div id="cards4" class="video">Test Video Content</div>
DEMO
Change your code to something like that:
var elems = document.getElementsByClassName('nice');
for(var i = 0; i < elems.length; i++) {
elems[i].style.display = 'none'
}
You have to iterate on the results returned by getElementsByClassName.
jsfiddle
You can create a loop that will loop through all the nice elements and then display none like this: https://jsfiddle.net/7vf9pz8u/
<script>
function hide(){
for(ct=0; ct < 3; ct++){
document.getElementsByClassName('nice')[ct].style.display='none'
}
}
</script>
getElementsByClassName returns array of all the match elements so you will have to provide index or loop through all of them to change their property.
Change your code to this
document.getElementsByClassName('nice')[0].style.display='none'
//For every element
var e = document.getElementsByClassName('nice');
for (i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
As your divs do not have unique names they are in an array cards[].
So to access a particular div you need to reference the the array to that particular div. The quoted solution should work.

Use function to remove divs after a sepecified div

HTML:
<div class="page">111111</div>
<div class="page">222222</div>
<div class="page">333333</div>
<div class="page">444444</div>
<div class="page">555555</div>
JavaScript:
var div = document.getElementsByClassName("page");
for (i = 0; i < div.length; i++) {
bt = document.createElement("button");
bt.innerHTML = "kill my followings";
div[i].appendChild(bt);
bt.onclick = function (i) {
return function () {
kill(div[i]);
}
}(i);
}
function kill(obj) {
// ...
}
See FIDDLE here.
I constructed some divs which class="page". I used JavaScript to add buttons to each div, and add onClick event to each of them.
I need to remove the divs after my current operating div. e.g, If user click button in No.3 div, No.4 and 5 should be removed.
How to realized it?
(if not necessary, the structure of original html is not allowed to change)
Thanks a lot!
This should be the simplest way to go:
function kill(obj) {
while (obj.nextSibling) {
obj.parentNode.removeChild(obj.nextSibling);
}
}
DEMO: http://jsfiddle.net/BtSKJ/3/

target selected members of an array

I have a series of divs of the same class; some with title attributes set - some without:
<div class="component_wrapper cw1" title="thisTitle1">... </div>
<div class="component_wrapper cw2" title="thisTitle2">... </div>
<div class="component_wrapper cw3" title="thisTitle3">... </div>
<div class="component_wrapper cw4" title="">... </div>
<div class="component_wrapper cw5" title="">... </div>
I've constructed a javascript function that loops through these divs and displays the ones with the title attribute set by setting their css display attribute to "inline":
function checkComponent(e){
var hdrSet = document.getElementsByClassName("component_wrapper");
var titles = {};
for (var i=0; i<hdrSet.length; i++){
if ( !titles[ hdrSet[i].title ] ) {
titles[ hdrSet[i].title ] = true;
hdrSet[i].style.display = "inline";
}
}
}
checkComponent();
the problem is, when I load the page the divs that I'm trying to target display (good), but also 1 of the divs not targeted displays. In the example above, the first four divs display, when all I want is the first three. What's wrong with my code... and is there an better way to construct the function?
Your code checks for duplicate titles, not missing ones. Here's how you could fix that:
function checkComponent(){
var hdrSet = document.getElementsByClassName("component_wrapper");
for (var i = 0; i < hdrSet.length; i++){
if(hdrSet[i].title) {
hdrSet[i].style.display = "inline";
}
}
}
checkComponent();
Also, if you're open to using jQuery, it's much neater and more compatible:
function checkComponent() {
$('.component_wrapper[title]:not([title=""])').css('display', 'inline');
}
checkComponent();

Categories

Resources