Javascript get index of same class repeated multiple times in html page - javascript

I'm trying to get the index of same class repeated multiple times in different structure. For example single-row is my class name and
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="somediv4">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
And below is the javascript code that I tried to get the index of my class single-row by on-click function:
.on('click', "#product-name", function (e) {
var index = $(this).parents(".single-row").index();
//var index = $(".single-row").index(this);
alert(index);
})
But I'm not getting the proper index for each div.
Live example:
$(document).on('click', "#product-name", function(e) {
var index = $(this).parents(".single-row").index();
//var index = $(".single-row").index(this);
alert(index);
})
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="somediv4">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Use $(this).parent().index(".single-row");
$(document).on('click', "#product-name", function(e) {
var index = $(this).parent().index(".single-row");
//var index = $(".single-row").index(this);
alert(index);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="somediv4">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="single-row">
<p id="product-name">product name 1</p>
</div>
</div>
<div class="single-row">
<p id="product-name">product name 1</p>
</div>

Two issues:
Your main issue is that .index(), with no arguments, gets the index of the first element in the set you call it on relative to its siblings. You want the other form of index you had commented-out (index taking an argument), but you passed in the wrong element. The one you want to pass in can be found via $(this).closest(".single-parent"). (Or, as Sumodh Nair points out, you can use the form accepting a string.)
id values must be unique on the page. Change those id="product-name" to class="product-name". (You might be able to get away with not changing this, but it's still incorrect and needs changing.)
Updated example:
$(document).on('click', ".product-name", function(e) {
var index = $(".single-row").index($(this).closest(".single-row"));
alert(index);
})
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="single-row">
<p class="product-name">product name 1</p>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="somediv2">
<div class="somediv3">
<div class="somediv4">
<div class="single-row">
<p class="product-name">product name 2</p>
</div>
</div>
</div>
</div>
</div>
<div class="somediv1">
<div class="single-row">
<p class="product-name">product name 3</p>
</div>
</div>
<div class="single-row">
<p class="product-name">product name 4</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

How to run a function when one button is clicked without changing other id values

I have 2 columns with same ID, each have 1 button. How to run a function when one button is clicked without changing other ID values?
Here is my code:
<div class="row">
<!--- column 1 ------>
<div class="column nature">
<div class="content">
<img src="images/pic.jpg" alt="Jane" style="width:100%">
<div class="container">
<p class="title" style="text-align:center;">SCA5-01</p>
<div style="text-align:center;">
<div id="hrg" style="font-size:5vw;font-weight:bold;">2000</div>
<div id="per">/500</div>
</div>
<div style="width:100%;margin:0px 5%;display:block;">
<div style="font-size:2vw;">
<br>Spect :
<br>- New
<br>- Fresh
</div>
</div>
<p>
<div style="width:100%;margin:0px auto;text-align:center;">
<input id="jmlh" type="number" value="500" style="width:50%;">
<button onclick="price();">chek</button>
</div>
</p>
<p>
<button class="button">Order</button>
</p>
</div>
</div>
</div>
<!--- column 1 ------>
<div class="column nature">
<div class="content">
<img src="images/pic.jpg" alt="Jane" style="width:100%">
<div class="container">
<p class="title" style="text-align:center;">SCA5-01</p>
<div style="text-align:center;">
<div id="hrg" style="font-size:5vw;font-weight:bold;">2000</div>
<div id="per">/500</div>
</div>
<div style="width:100%;margin:0px 5%;display:block;">
<div style="font-size:2vw;">
<br>Spect :
<br>- New
<br>- Fresh
</div>
</div>
<p>
<div style="width:100%;margin:0px auto;text-align:center;">
<input id="jmlh" type="number" value="500" style="width:50%;">
<button onclick="price();">chek</button>
</div>
</p>
<p>
<button class="button">Order</button>
</p>
</div>
</div>
</div>
</div>
Here is my function:
<script>
function price(){
var qty = document.getElementById("jmlh").value;
var prc = Math.ceil((1000000 / qty)/100)*100;
document.getElementById("hrg").innerHTML = prc;
document.getElementById("per").innerHTML = "/" + qty;
}
</script>
The problem here is that function only runs on 'column 1' & doesn't work on 'column 2'.
Where exactly am I going wrong?
id should be unique in the same document. Use classes or other attributes instead of id.
If you want centralized function to handle clicks, submit the clicked element itself to that function, so it would know which column was clicked:
<div class="column nature">
<div class="content">
<img src="images/pic.jpg" alt="Jane" style="width:100%">
<div class="container">
<p class="title" style="text-align:center;">SCA5-01</p>
<div style="text-align:center;">
<div class="hrg" style="font-size:5vw;font-weight:bold;">2000</div>
<div class="per">/500</div>
</div>
<div style="width:100%;margin:0px 5%;display:block;">
<div style="font-size:2vw;">
<br>Spect :
<br>- New
<br>- Fresh
</div>
</div>
<p>
<div style="width:100%;margin:0px auto;text-align:center;">
<input class="jmlh" type="number" value="500" style="width:50%;">
<button onclick="price(this);">chek</button>
</div>
</p>
<p>
<button class="button">Order</button>
</p>
</div>
</div>
</div>
function price(el){
const elContainer = el.closest(".container");// find parent
var qty = elContainer.querySelector(".jmlh").value;
var prc = Math.ceil((1000000 / qty)/100)*100;
elContainer.querySelector(".hrg").innerHTML = prc;
elContainer.querySelector(".per").innerHTML = "/" + qty;
}
Note, that all id were replaced by class attribute and in javascript instead of searching entire document with document.getElementById() it's now only searching children inside the .container element.

How to create a Javascript loop to cycle through numbers for HTML IDs

I have a ton of modals on a page and I'm using this script to link the ID of an HTML button to the ID of the modal and it's close button:
var target = document.getElementById('show1');
var currentOpacity = 0;
$(document).ready(function () {
$("#hide1").click(function () {
$("#details1").hide();
target.style.opacity = currentOpacity + 1;
});
$("#show1").click(function () {
$("#details1").show();
target.style.opacity = currentOpacity - 1;
});
});
const button1 = document.querySelector("#show1");
const readout1 = document.querySelector("p");
button1.addEventListener("mousemove", (e) => {
const {
x,
y
} = button1.getBoundingClientRect();
button1.style.setProperty("--x", e.clientX - x);
button1.style.setProperty("--y", e.clientY - y);
});
This works but I have 56 buttons... How could I write this script so that #show1 #details1 #hide1, #show2 #details2 #hide2, #show3 #details3 #hide3 etc. all the way to 56 work without duplicating this code block 56 times?
EDIT
Here is the HTML for an item:
<section id="photo01" class="item-module-wrap">
<div class="item-module">
<div class="blurred-image" style="background-image: url('xxxxx');"></div>
<div class="dot-texture"></div>
<article>
<div class="dgov-grid">
<div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
<div class="main-photo-module">
<div class="sticky">
<h2>xxxxx</h2>
</div>
<div class="sticky"><span>xxxxx</span></div>
<div class="sticky">
<button type="button" id="show1" class="details-button shiny">Details</button>
</div>
<img src="xxxxx" alt="xxxxx"/> </div>
</div>
<div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
<div class="aside-module">
<div class="details" id="details1">
<div class="close" id="hide1"><i class="fa fa-times" aria-hidden="true"></i></div>
<p class="description">xxxxx</p>
<p class="extra">xxxxx</p>
<p class="extra">xxxxx</p>
<div class="social">
xxxxx
</div>
</div>
<div class="sticky">
<time> 1 of 56 </time>
</div>
<div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
</div>
</div>
</div>
</article>
</div>
</section>
When attaching similar events or actions to a module ( section in this case ) where in the structure is exactly the same and the only difference is just the variation of certain ids, the first thing that should come to mind is to swap out ids with classes and use the HTML structure to an advantage.
Swap ids with classes for show1, hide1 and details1.
var target = document.getElementById('show1');
var currentOpacity = 0;
$(document).ready(function() {
// use event delegation and attach event to elements with show class inside a section
$('section').on('click', '.show', () => {
// get the closest element with class details inside the current section
const $details = $(this).closest('section').find('.details');
// get the closest element with class hide inside the current section
const $hide = $(this).closest('section').find('.hide');
$details.show();
$hide.show();
});
// use event delegation and attach event to elements with hide class inside a section
$('section').on('click', '.hide', () => {
// get the closest element with class details inside the current section
const $details = $(this).closest('section').find('.details');
// get the closest element with class show inside the current section
const $show = $(this).closest('section').find('.show');
$details.show();
$show.show();
});
});
<section id="photo01" class="item-module-wrap">
<div class="item-module">
<div class="blurred-image" style="background-image: url('xxxxx');"></div>
<div class="dot-texture"></div>
<article>
<div class="dgov-grid">
<div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
<div class="main-photo-module">
<div class="sticky">
<h2>xxxxx</h2>
</div>
<div class="sticky"><span>xxxxx</span></div>
<div class="sticky">
<button type="button" class="details-button shiny show">Details</button>
</div>
<img src="xxxxx" alt="xxxxx" /> </div>
</div>
<div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
<div class="aside-module">
<div class="details">
<div class="close" class="hide"><i class="fa fa-times" aria-hidden="true"></i></div>
<p class="description">xxxxx</p>
<p class="extra">xxxxx</p>
<p class="extra">xxxxx</p>
<div class="social">
xxxxx
</div>
</div>
<div class="sticky">
<time> 1 of 56 </time>
</div>
<div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
</div>
</div>
</div>
</article>
</div>
</section>
Here is one way of doing it (without using jQuery). I chose to work with a delegated event handling. The "onclick" event ist defined on the parent element <section> in which we find all <article> elements and their show-buttons, close-elements and detail-divs.
In the event handler function I used relative DOM navigation:
with .closest("article") I find the parent article element to the clicked element in which I then
look for the ".details"-div with .querySelector(".details").
With if(trg.classList.contains("details-button")) ... I check whether the details button was clicked and then set the display value for the details div accordingly.
The clickable elements and the ".detail" divs still have their id attributes but these are no longer referred to in my script. They can safely be removed.
document.querySelectorAll(".details").forEach(d=>d.style.display="none");
document.querySelector("section").onclick=ev=>{
const trg=ev.target, dsty=trg.closest("article").querySelector(".details").style;
if(trg.classList.contains("details-button")) dsty.display="";
if(trg.classList.contains("fa-times")) dsty.display="none";
}
.close {cursor:pointer}
<section id="photo01" class="item-module-wrap">
<div class="item-module">
<div class="blurred-image" style="background-image: url('xxxxx');"></div>
<div class="dot-texture"></div>
<article>
<div class="dgov-grid">
<div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
<div class="main-photo-module">
<div class="sticky">
<h2>First heading h2</h2>
</div>
<div class="sticky"><span>xxxxx</span></div>
<div class="sticky">
<button type="button" id="show1" class="details-button shiny">Details</button>
</div>
<img src="xxxxx" alt="xxxxx" /> </div>
</div>
<div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
<div class="aside-module">
<div class="details" id="details1">
<div class="close" id="hide1"><i class="fa fa-times" aria-hidden="true">close</i></div>
<p class="description">Hidden description (first p)</p>
<p class="extra">second p</p>
<p class="extra">third p</p>
<div class="social">
paragraph with social media information
</div>
</div>
<div class="sticky">
<time> 1 of 56 </time>
</div>
<div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
</div>
</div>
</div>
</article>
<article>
<div class="dgov-grid">
<div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
<div class="main-photo-module">
<div class="sticky">
<h2>Second heading h2</h2>
</div>
<div class="sticky"><span>xxxxx</span></div>
<div class="sticky">
<button type="button" id="show2" class="details-button shiny">Details</button>
</div>
<img src="xxxxx" alt="xxxxx" /> </div>
</div>
<div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
<div class="aside-module">
<div class="details" id="details2">
<div class="close" id="hide2"><i class="fa fa-times" aria-hidden="true">close</i></div>
<p class="description">Hidden description (first p)</p>
<p class="extra">second p</p>
<p class="extra">third p</p>
<div class="social">
paragraph with social media information
</div>
</div>
<div class="sticky">
<time> 2 of 56 </time>
</div>
<div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
</div>
</div>
</div>
</article>
<article>
<div class="dgov-grid">
<div class="dgov-col-sm-7 dgov-col-md-8 dgov-col-lg-9">
<div class="main-photo-module">
<div class="sticky">
<h2>Third heading h2</h2>
</div>
<div class="sticky"><span>xxxxx</span></div>
<div class="sticky">
<button type="button" id="show3" class="details-button shiny">Details</button>
</div>
<img src="xxxxx" alt="xxxxx" /> </div>
</div>
<div class="dgov-col-sm-5 dgov-col-md-4 dgov-col-lg-3">
<div class="aside-module">
<div class="details" id="details3">
<div class="close" id="hide3"><i class="fa fa-times" aria-hidden="true">close</i></div>
<p class="description">Hidden description (first p)</p>
<p class="extra">second p</p>
<p class="extra">third p</p>
<div class="social">
paragraph with social media information
</div>
</div>
<div class="sticky">
<time> 3 of 56 </time>
</div>
<div class="item-number layer" data-px-per-scroll="0.5" data-initial-position="450">01</div>
</div>
</div>
</div>
</article>
</div>
</section>

How can I add new list items on field input?

I am working on a simple to-do app.
I would like to add a new element after user clicks on enter in the input box, and nothing happen. I tried lot of ways, I will share the recent code. Do you have any suggestions? Thanks a lot.
UPDATE: It finally works.
UPDATE: It finally works.
UPDATE: It finally works.
$(document).ready(function() {
// Input - creating a new element //
$(':input').on('keypress', function(e) {
if (e.which == 13 && $('#text').val().length != 0) {
var input = ($this).val()
$('.elements').append('<div class="text-box"></div>');
// i would like to add other elements inside a div, but i need to first get it work. //
}
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<img src="img/bg-desktop-dark.jpg" alt="background">
</header>
<section>
<div class="container section-content">
<div class="headline">
<h1>TODO</h1>
<img src="img/icon-sun.svg" class="switcher" alt="switcher">
</div>
<div class="create">
<p class="circle"></p>
<form><input type="text" placeholder="Create a new todo" id="text"></form>
</div>
<div class="elements">
<div class="text-box">
<p class="circle"><img class="img-inactive" src="img/icon-check.svg"></p>
<p class="text">Vytvořit todo appku</p>
</div>
<div class="text-box">
<p class="circle"><img class="img-inactive" src="img/icon-check.svg"></p>
<p class="text">Vytvořit todo appku</p>
</div>
<div class="text-box">
<p class="circle"><img class="img-inactive" src="img/icon-check.svg"></p>
<p class="text">Vytvořit todo appku</p>
</div>
</div>
<div class="bottom">
<p class="items-left">5 items left</p>
<div class="functions">
<p class="all">All</p>
<p class="active">Active</p>
<p class="completed">Completed</p>
</div>
<p class="clear">Clear completed</p>
</div>
</div>
</div>
</section>
You are very close, a few things to make this work are:
You are using a <form> tag which will (by default) try to submit a form on enter. If you aren't sending anything to a server you can just remove this html tag
($this) should be $(this) because you want to use the jquery constructor to create a jquery object from the this context.
You are just appending an empty div which you won't see on the screen. You have to add the input text to the body of the div.
$(document).ready(function() {
// Input - creating a new element //
$(':input').on('keypress', function(e) {
if (e.which == 13 && $('#text').val().length != 0) {
var input = $(this).val()
$('.elements').append(`<div class="text-box">${input}</div>`);
// i would like to add other elements inside a div, but i need to first get it work. //
}
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<img src="img/bg-desktop-dark.jpg" alt="background">
</header>
<section>
<div class="container section-content">
<div class="headline">
<h1>TODO</h1>
<img src="img/icon-sun.svg" class="switcher" alt="switcher">
</div>
<div class="create">
<p class="circle"></p>
<input type="text" placeholder="Create a new todo" id="text">
</div>
<div class="elements">
<div class="text-box">
<p class="circle"><img class="img-inactive" src="img/icon-check.svg"></p>
<p class="text">Vytvořit todo appku</p>
</div>
<div class="text-box">
<p class="circle"><img class="img-inactive" src="img/icon-check.svg"></p>
<p class="text">Vytvořit todo appku</p>
</div>
<div class="text-box">
<p class="circle"><img class="img-inactive" src="img/icon-check.svg"></p>
<p class="text">Vytvořit todo appku</p>
</div>
</div>
<div class="bottom">
<p class="items-left">5 items left</p>
<div class="functions">
<p class="all">All</p>
<p class="active">Active</p>
<p class="completed">Completed</p>
</div>
<p class="clear">Clear completed</p>
</div>
</div>
</div>
</section>

Cannot get element inside distant parent div using jQuery

In a dom which has many of the blocks like the one below, I'd like to get name of pid element (i.d 123) when link is clicked:
<div class="a-post">
<a class="pid" name="123"></a>
<div class="row">
<p>Some text</p>
</div>
<br>
<div class="row">
<div class="col-xs-12">
<p>Othe text </p>
</div>
<br>
<div class="row">
<div class="col-xs-1">
<img class="link" src="link.svg">
</div>
</div>
</div>
</div>
Here is my jQuery:
$(document).ready(function () {
$(".link").click(function () {
let pid = $(this).parent(".a-post").find(".pid").attr('name');
console.log('pid is:', pid);
}
});
But I get pid is: undefined
How can I fix this?
You have to use .closest() and not .parent(), because .parent() only goes 1 step up. .closest() will continue until it reach the top or finds the element.
$(document).ready(function() {
$(".link").click(function() {
let pid = $(this).closest(".a-post").find(".pid").attr('name');
console.log('pid is:', pid);
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="a-post">
<a class="pid" name="123"></a>
<div class="row">
<p>Some text</p>
</div>
<br>
<div class="row">
<div class="col-xs-12">
<p>Othe text </p>
</div>
<br>
<div class="row">
<div class="col-xs-1">
<img class="link" src="link.svg">
</div>
</div>
</div>
</div>

fadeOut() only fades out the first element

By default, I have several DIVs hidden and then I fade them in when the user clicks on a certain button. That works fine but when I try to close a .holder DIV using a span within said .holder DIV, only the first one works. When I click the others, nothing happens. I get no error or any sort of visual feedback whatsoever.
The markup:
<div class="holder" id="window_one">
<div class="title_bar">
<p>Window 1</p>
<div class="control_holder">
<span class="controls" id="close">X</span>
<span class="controls" id="minimize">_</span>
</div>
</div>
<div class="interface">
<p>Testing123</p>
</div>
</div>
<div class="calculator" id="window_two">
<div class="title_bar">
<p>Window 2</p>
<div class="control_holder">
<span class="controls" id="close">X</span>
<span class="controls" id="minimize">_</span>
</div>
</div>
<div class="interface">
<p>Testing123</p>
</div>
</div>
The jQuery:
$(document).ready(function() {
$('#close').click(function() {
$(this).parents('.holder').fadeOut(250);
});
});
What exactly am I doing wrong here? I'm using jQuery 1.10.2 if that makes any difference.
I'd demo the code on jsFiddle but is seems to be down atm.
You can not have the same id of two element on the page. If you want to do that give it as a class name like -
<div class="holder" id="window_one">
<div class="title_bar">
<p>Window 1</p>
<div class="control_holder">
<span class="controls close">X</span>
</div>
</div>
<div class="interface">
<p>Testing123</p>
</div>
</div>
<div class="calculator" id="window_two">
<div class="title_bar">
<p>Window 2</p>
<div class="control_holder">
<span class="controls close">X</span>
</div>
</div>
<div class="interface">
<p>Testing123</p>
</div>
</div>
and the Jquery like -
$(document).ready(function() {
$('.close').click(function() {
$(this).parents('.holder').fadeOut(250);
});
});
Hope this will help.
Here is how it should be:
<div class="holder" id="window_one">
<div class="title_bar">
<p>Window 1</p>
<div class="control_holder">
<span class="controls close">X</span>
</div>
</div>
<div class="interface">
<p>Testing123</p>
</div>
</div>
<div class="calculator" id="window_two">
<div class="title_bar">
<p>Window 2</p>
<div class="control_holder">
<span class="controls close">X</span>
</div>
</div>
<div class="interface">
<p>Testing123</p>
</div>
</div>
and the JavaScript:
$(document).ready(function() {
$('.close').click(function(e) {
$(this).parents('.holder').forEach(function(){
$(this).fadeOut(250);
});
e.preventDefault();
});
});

Categories

Resources