How to get index position of clicked element in javascript - 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/

Related

How can I append a button to all my class

I'm trying to give a button inside all my class .why-text. I selected them by document.querySelectorAll('.why-text'); And use the loop "for" to append button to all the class. But it doesn't working. This is my code:
var btnAddCart = document.createElement("button");
btnAddCart.innerHTML = "Add";
var WhyTxt = document.querySelectorAll('.why-text');
for (let i = 0; i < WhyTxt.length; i++) {
WhyTxt[i].appendChild(btnAddCart);
}
You create only one button, then keep appending that very same button to n locations, so it ends up in the last of those. Appending an element that is already in the DOM effectively moves that element.
You need to create the button in the loop to have individual buttons:
const WhyTxt = document.querySelectorAll('.why-text');
for (let i = 0; i < WhyTxt.length; i++) {
const btnAddCart = document.createElement("button");
btnAddCart.textContent = "Add";
WhyTxt[i].appendChild(btnAddCart);
}
That being said, your code can also be simplified by alot:
for (let el of document.querySelectorAll(".why-text")) {
el.append(Object.assign(document.createElement("button"),{textContent:"Add"}));
}
You have to create the element each time, within the loop. It could be made outside the looped and cloned within it but you are only making one element in the current structure so it can only be added once.
This working snippet uses the simple approach of making a new button element inside each loop of the parent collection.
var WhyTxt = document.querySelectorAll('.why-text');
console.log(WhyTxt.length);
for (let i = 0; i < WhyTxt.length; i++) {
var btnAddCart = document.createElement("button");
btnAddCart.innerHTML = "Add";
WhyTxt[i].appendChild(btnAddCart);
}
div {
height: 2em;
background: yellow;
}
<div class="why-text"></div><br>
<div class="why-text"></div><br>
<div class="why-text"></div><br>
<div class="why-text"></div><br>
<div class="why-text"></div><br>

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

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/

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/

Categories

Resources