Javascript get "this" class with onClick function - javascript

I want to create a function which manipulates an element with a specific class.
So far I have this:
function myFunc() {
var ball = document.getElementsByClassName('ball');
var myBall = 0;
myBall = ball[0].innerHTML; // HERE I NEED TO GET THE CURRENT BALL CLICKED
myBall[0].innerHTML = ++nr; // THE SAME HERE
}
The problem is that I don't know how to get the exactly div with the class:ball which was clicked. I know that myBall[0] is wrong. I need to set somehow the number representing the element clicked.
My HTML:
<div id="container">
<div class="ball" onclick="myFunc()">1</div>
<div class="ball" onclick="myFunc()">1</div>
<div class="ball" onclick="myFunc()">1</div>
</div>

Something like this
var elems = document.querySelectorAll('#container .ball');
for (var i=elems.length; i--;) {
elems[i].addEventListener('click', myFunc, false);
}
function myFunc() {
this.innerHTML = parseInt(this.innerHTML, 10) + 1;
}
<div id="container">
<div class="ball">1</div>
<div class="ball">2</div>
<div class="ball">3</div>
</div>

Related

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>

Get Position of a Child Element After a Click Event

I wanted to write a program that would return a child elements position inside the parent element, but I am having problems. I tried writing the following code but it did not work as expected; Instead of returning the position value it returned the click event. Here is what I tried doing:
(P.S I wanted to solve this problem in raw JS)
(function () {
// body...
var x = document.getElementsByClassName("bubble");
for(var i=0; i<x.length; i++) {
x[i].addEventListener('click', function(i){
console.log(i);
});
}
})();
HTML:
<div id=holder>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
</div>
If you are wanting to find the position as in the x and y coordinates, you can do the following:
make sure the parent div (#holder) is positioned
Make use of offsetLeft and offsetTop
If you are wanting to find position as in array position, you can use
Array.prototype.indexOf.call(collection, element)
(function() {
// body...
var x = document.getElementsByClassName("bubble");
for (var i = 0; i < x.length; i++) {
x[i].addEventListener('click', function(a) { // change the variable name here otherwise you have a local var i conflicting with the loop var i
console.log(this.offsetLeft, this.offsetTop); // this is the element clicked
console.log(Array.prototype.indexOf.call(x, this) + 1); // this is the position as an index (plus 1)
});
}
})();
#holder {
position:relative; /* position the parent */
}
<div id="holder">
<div class="bubble">1</div>
<div class="bubble">2</div>
<div class="bubble">3</div>
<div class="bubble">4</div>
</div>
i in your listener's function stands for the whole element and his events, not for the index from your for loop. Logging it may crash/lag your browser.
I would suggest you to use ES6 treasures with Array#forEach.
const elems = document.querySelectorAll('#holder .bubble');
Array.from(elems).forEach((v, i) => v.addEventListener('click', () => {
console.log(`Child position: ${i}`);
}));
<div id="holder">
<div class="bubble">a</div>
<div class="bubble">b</div>
<div class="bubble">c</div>
<div class="bubble">d</div>
</div>
However, if you really want to use for loop, do not pass any arguments into your listener's function and change var i inside your loop into let i.
const x = document.getElementsByClassName("bubble");
for (let i = 0; i < x.length; i++) {
x[i].addEventListener('click', function() {
console.log(i);
});
}
<div id="holder">
<div class="bubble">a</div>
<div class="bubble">b</div>
<div class="bubble">c</div>
<div class="bubble">d</div>
</div>
You can use this funcion: https://developer.mozilla.org/en-US/docs/DOM/element.getBoundingClientRect
https://jsfiddle.net/dt1224Ld/
(function () {
// body...
var x = document.getElementsByClassName("bubble");
for(var i=0; i<x.length; i++) {
x[i].addEventListener('click', function(i){
var element = this.getBoundingClientRect();
console.log(element.top, element.right, element.bottom, element.left);
});
}
})();

jQuery: select elements with slice

in a page i've got different divs elements with the same class
<div id="masterdiv">
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div>
with a setTimeout i want to take three elements for time do some action with them.
i tried with the slice function:
var elements = $("#masterdiv").find('.a');
var t = setInterval(function () {
var currentElements = elements.slice(points.f, points.l);
/* where points.f = 0 and points.l = 3 */
/* do something with currentElements then increment points.f and points.l +1 */
}, xinterval );
But there's a problem, at a certain time my code will reach a .slice(8,10) / .slice(9,11) and a in a selection of 11 divs.
So in these cases (point.l > elements.length()) i want select the first divs instead of the exceeded ones:
In the case of .slice(8,10) i want to select instead of the
inexistent div '10' the div 0 with the 8,9 divs .
In the case of .slice(9,11) i want to select instead of the
inexistent divs '10','11' the div 0,1 with the 9 div.
How can i accomplish this? Can i do it with slice or should i use another function?
Thanks in advance for all the help.
An alternative, would be to use the pop() and push() array functions like this:
var $elements = $("#masterdiv").find('.a');
// Convert to native Array
var elements = Array.prototype.slice.apply($elements);
var t = setInterval(function () {
elements.slice(points.f,points.l).forEach(function(el){
// do something on the element...
$(el).addClass('debug');
});
elements.push(elements.shift()); // Re-arrange elements array for loop
}, xinterval );
Here's the codepen demo: http://codepen.io/kostasx/pen/mRVzqQ?editors=0010
you can increment your variable like this,
var elements = $("#masterdiv").find('.a');
/* where points.f = 0 and points.l = 3 */
var t = setInterval(function () {
var currentElements;
if(points.l > elements.length && points.f<=elements.length){
tempArr1 = elements.slice(points.f);
tempVar = points.l % elements.length;
tempArr2 = elements.slice(0,tempVar);
currentElements = [...tempArr1,...tempArr2];
}
else{
currentElements = elements.slice(points.f, points.l);
}
/* do something with currentElements then increment points.f and points.l +1 */
}, xinterval );
I have not covered edge cases,please find yourself ;)

changing clicked element's style in array through 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

finding index of parent of a certain class

I have the following HTML:
<div class="Wrapper">
<div class="SomeOtherClass"></div>
<div class="SomeOtherClass"></div>
<div class="MyClass">
<div class="SomeElement" id="test"></div>
<div class="SomeElement"></div>
</div>
<div class="MyClass">
<div class="SomeElement" id="test2"></div>
<div class="SomeElement"></div>
</div>
</div>
And I have the following javascript:
$('.Wrapper').find('.SomeElement').each(function () {
if (SomeCondition) {
var TheElement = $(this);
var TheIndexOfParentClass = TheElement... //HERE
return;
}
});
As you can see, I loop through all the SomeElements and I pick one. Now I want to know the index of the parent's class (here "MyClass"). For instance, if I pick out "test" then the TheIndexOfParentClass should be 0 and if I pick out test2 then TheIndexOfParentClass should be 1. Note that the number of elements of SomeOtherClass can vary; I don't want the actual index of the parent, I want the index of the parent's class relative to all children of the Wrapper element. How do I do this?
Thanks.
I think you want this :
$('.Wrapper').find('.MyClass').each(function(TheIndexOfParentClass) {
$('.SomeElement', this).each(function(){
if (SomeCondition) {
var TheElement = $(this);
each pass to the callback the iteration index and so by decomposing the iteration you can ask jQuery to count for you.
If you want to stick with your flow, You could do this also by passing class to index method,
$('.Wrapper').find('.SomeElement').each(function () {
if (SomeCondition) {
var TheElement = $(this);
var TheIndexOfParentClass = TheElement.parent().index('.MyClass'); //HERE
return;
}
});
What we are avoiding here is double each loop.

Categories

Resources