Get Position of a Child Element After a Click Event - javascript

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);
});
}
})();

Related

Access sibling of an attribute within an object, onclick javascript

I'm creating 5 objects, each one with a div attached as source attribute, at which onclick should open the relative html page in an iframe.
Need to access the simple value of i==[i].num for each element on onclick function, so to select actor[i].num from within actor[i].source, thought it should be simple.
// html
<div id="op0" class="op"><img src="gfx/0.svg"></div>
<div id="op1" class="op"><img src="gfx/1.svg"></div>
<div id="op2" class="op"><img src="gfx/2.svg"></div>
<div id="op3" class="op"><img src="gfx/3.svg"></div>
<div id="op4" class="op"><img src="gfx/4.svg"></div>
// js
var i=0;
let actor = {};
for (i = 0; i < 5; i++) {
actor[i] = {
num: i,
source: document.getElementById('op'+[i]),
clicked: 0
}
actor[i].source.addEventListener( 'click', function() {
console.log(this) // the source attribute <div>
console.log(this.num) // undefined
console.log(parent.num) // undefined
console.log(actor[i].num) // TypeError
clickActor(i) // returns 5 at the time of click
});
}
function clickActor(num){
if (actor[num].open == 0){
actor[num].source.classList.add("scaleUp");
document.getElementById("iFrame").src = "op"+num+".html";
actor[num].open = 1;
// div to move and scale
} else {
actor[num].source.classList.remove("scaleUp");
document.getElementById("iFrame").src = "";
document.getElementById("iFrame").style.pointerEvents = "none";
actor[num].open = 0;
// div to move and scale back
}
}
var variables are function scopes, so your i variable is being reused over and over again in your loop, so that when you actually click the button, i will be the last number of the loop. You can bypass this by simply creating a new function scope by inserting a self-executing function in place of your callback function.
actor[i].source.addEventListener( 'click', (function(i) {
return (function() {
console.log(actor[i].num) // this is should print out the object assign above it
clickActor(i) // i is now the index of the actor
});
})(i));

How to get index position of clicked element in javascript

I am trying to get the index value of a particular element that is clicked on from a for loop array. What i would like to do is then use this index value and pass it to a variable called indexValue which will then determine a specific div to show. The div it will show will be the one with the same index value that was passed to the variable. I hope this makes sense, I am just not to sure how to achieve this?
The markup would be something like this
HTML
<div class="button"></div>
<div class="button"></div>
<div class="button"></div>
<div class="button"></div>
CSS
.test {
display: none;
}
.show {
display: block;
}
JS
var button = document.querySelectorAll('.button');
for (var i = 0; i < button.length; i++) {
button[i].addEventListener('click', function () {
var indexValue: //Get index value from clicked element
var test = document.querySelectorAll('.test');
test[indexValue].classlist.add('show');
}
}
You can put your eventListener in a closure that takes a parameter from your loop. The alert is only so that when you click it in the fiddle you can see the result of the index
var button = document.querySelectorAll('.button');
for (var i = 0; i < button.length; i++) {
button[i].addEventListener('click', ((j) => {
return function() {
alert(j)
}
})(i))
}
http://jsfiddle.net/cbpw61ur/20/

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>

Javascript get "this" class with onClick function

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>

How to display items of a particular div on mouseover

I have the div structure
<div id="navigate">
<div class="menu">
<div class="group">Mail</div>
<div class="item">Folders</div>
<div class="item">Messages</div>
</div>
<div class="menu">
<div class="group">Contacts</div>
<div class="item">Friends</div>
<div class="item">Work</div>
</div>
<div class="menu">
<div class="group">Setting</div>
<div class="item">General</div>
<div class="item">Account</div>
</div>
</div>
Right now all items are hidden, and only divs with class 'group' is shown. What I would like to do is if I mouse over a specific menu div, only items of that menu would appear.
Right now I have this code:
function initialise()
{
hideAllItems();
setMouseOvers();
}
function hideAllItems()
{
var nav = document.getElementById("navigate");
var items = nav.getElementsByClassName("item");
for(var i = 0; i < items.length; i++)
{
items[i].style.visibility = "hidden";
items[i].style.display = "none";
}
}
function setMouseOvers()
{
var nav = document.getElementById("navigate");
var menuArr = nav.getElementsByClassName("menu");
for(var x = 0; x < menuArr.length; x++)
{
var itemArrs = menuArr[x].getElementsByClassName("item");
/*var show = function(){ show(itemArrs); };
var hide = function(){ hide(itemArrs); };*/
menuArr[x].onmouseover=function(){ show(itemArrs); };
menuArr[x].onmouseout=function(){ hide(itemArrs); };
}
}
function show(itemArr)
{
for(var i = 0; i < itemArr.length; i++)
{
alert(itemArr[i].innerHTML);
itemArr[i].style.visibility = "visible";
itemArr[i].style.display = "block";
}
}
function hide(itemArr)
{
for(var i = 0; i < itemArr.length; i++)
{
itemArr[i].style.visibility = "hidden";
itemArr[i].style.display = "none";
}
}
And this works, thought it only displays General and Account no matter which menu I hover over. I vaguely understand whats going wrong, but I can't see anyway to fix it. Any ideas? I do not want to change the html structure (e.g. add ids, or create specific classes) if i can help it!
I know that you most probably are looking for a javascript solution, but you could use a simple CSS solution:
.group:hover ~ .item {
display: block;
}
Working Fiddle
But be aware that it is not supported by older IE (< 8) browsers SUPPORT. It depends on your target group if you want to use it.
Why not simply using CSS: DEMO
.menu .item{
display:none;
}
.menu:hover .item{
display:block;
}
As you ask for an JavaScript Only solution (no change in HTML/css) i suggest the following:
The problem is using "itemArrs" in an anonymous function, as only the latest written "itemArrs" is used for all of them, use "this" instead.
for example:
...
groups[x].onmouseover=function(){ show(this); };
...
and
function show(item) {
var items = item.parentNode.getElementsByClassName("item");
...
A complete JS-only solution that works can be found here:
http://jsfiddle.net/Wn4d4/3/

Categories

Resources