can't get index of current clicked element in array using javascript - javascript

This is my HTML code
var link = document.getElementsByClassName("link");
for (i = 0; i < link.length; i++) {
link[i].addEventListener("click", click);
function click() {
console.log(link.indexOf(this));
}
}
<div class="links">
<ul>
<li>
<div class="hole-counter"><span></span></div><a class="link">Home</a>
</li>
<li>
<div class="hole-counter"><span></span></div><a class="link">About</a>
</li>
<li>
<div class="hole-counter"><span></span></div><a class="link">Gallery</a>
</li>
<li>
<div class="hole-counter"><span></span></div><a class="link">Contact</a>
</li>
</ul>
</div>
And this is javascript code
i get this error in console
Uncaught TypeError: link.indexOf is not a function at HTMLAnchorElement.click (index.html:97)

Your link variable is not an Array, therefore you cannot call indexOf() on it. You must first convert link to an array.
var link = Array.from(document.getElementsByClassName("link"));

The link variable in your code is HTMLCollection, you need to convert it to an array before using indexOf
You can do this
const links = [...document.getElementsByClassName("link")];
links.forEach(link => link.addEventListener("click", click));
function click() {
console.log(links.indexOf(this))
}

The link variable is an array like element, you need to convert that to an array first:
var link = document.getElementsByClassName("link");
for (i = 0; i < link.length; i++) {
link[i].addEventListener("click", click);
}
function click() {
console.log(Array.from(link).indexOf(this));
}

Your link variable is just a variable and the indexOf function is specifically for arrays. So you should first convert your variable into an array. You can do that by either declaring it as an array or converting it into an array afterwards.

Related

How can I properly convert the following Jquery to pure Javascript?

How can I convert the Jquery below to pure JavaScript?
var $buttons = jQuery("#thePaginator li a");
for (var index = 0; index < $buttons.length; index++) {
var $button = $buttons.eq(index);
$button.click(function() {
var newPage = $(this).data("page");
jQuery("#attribute-myAttribute").val(newPage);
jQuery("#update").click();
});
}
I wouldn't normally ask a question like this, but the conversion has been difficult, especially with the event listener. Here is what I have so far:
runPaginate();
function runPaginate(){
var buttonArray = document.getElementById("paginator_TCC").querySelectorAll('li');
for(i=0;i<(buttonArray.length);i++){
buttonArray[i].addEventListener('click', runUpdate);
}
}
function runUpdate(){
console.log("runUpdate started")
// will need to add code in here for update
}
update (in Jquery) is a method that is called to update attributes on the page. Consider the runUpdate function to suffice for that method call.
I believe that I'm having so much trouble because I'm dealing with HTML Collection, so when I get the li elements (which are actually buttons) I can't seem to add an event listener to them. Below is the inspection result from Dev Tools:
<div id="thePaginator" class="simple-pagination">
<ul>
<li class="disabled">
<span class="current prev">Prev</span>
</li>
<li class="active">
<span class="current">Year 1</span>
</li>
<li class="disabled">
<span class="current next">Next</span>
</li>
</ul>
</div>
Any assistance is appreciated.
I'd use a for...of loop, and move the callback into the loop. That way you can access the iterator:
for(const button of buttonArray){
button.addEventListener('click', function runUpdate() {
const { data } = button.dataset;
//...
});
}
This is the JS equivalent of your jQuery (this just replaces the jQuery method calls with their equivalent JS method calls)
var buttons = document.querySelectorAll('#thePaginator li a');
for(var index = 0; index < $buttons.length; index++) {
var button = buttons[index];
button.addEventListener("click", function(evt) {
var newPage = this.dataset.page;
document.getElementById('attribute-myAttribute').value = newPage;
document.getElementById('update').click();
})
}

Using addEventListener and getElementsByClassName to pass an element id

I'm defining a list of items from a JSON file and displaying that list on a web page. The intention is for users to click on any item in that list to display more information on that item (information that is held in the same JSON file).
All items of that list are members of the same class, and each has a unique id defined from the JSON file. The HTML looks something like this:
<ul>
<li class="menu" id="bob">Robert Smith</li>
<li class="menu" id="jane">Jane Doe</li>
<li class="menu" id="sue">Susan Carter</li>
</ul>
I was planning to use something along the lines of
var userSelection = document.getElementsByClassName('menu');
in concert with
userSelection.addEventListener('click', myFunctionToPrintDetails());
but I am not sure how to pass the id from the event listener to the print function in order to determine which details to print.
I have a lot of experience with HTML/CSS but very little with JSON/AJAX, so possible I'm going about this completely bass-ackwards. If there is a more appropriate way to get this done I'm open to the feedback.
I tried both answers but neither worked. When I log userSelection.length to the console I get 0; when I log userSelection I get:
HTMLCollection(0)
> sue: li#sue.menu
length: 3
> jane: li#jane.menu
> bob: li#bob.menu
> 0: li#bob.menu
> 1: li#jane.menu
> 2: li#sue.menu
codepen demo
var userSelection = document.getElementsByClassName('menu');
for(var i = 0; i < userSelection.length; i++) {
(function(index) {
userSelection[index].addEventListener("click", function() {
console.log("Clicked index: " + index);
})
})(i);
}
As pointed out by #torazaburo in the comments, you can use the following if the browsers you want to support are complying with ECMAScript 6 (ES6), the newest version of JavaScript.
var userSelection = document.getElementsByClassName('menu');
for(let i = 0; i < userSelection.length; i++) {
userSelection[i].addEventListener("click", function() {
console.log("Clicked index: " + i);
})
}
Here's how I would do it. I would first create an array using Object values.
const userSelection = Object.values(document.getElementsByClassName('menu'));
Then I would loop through them using a foreach.
userSelection.forEach(link => {
link.addEventListener(event => {
event.preventDefault();
// more code here
});
});
Easy peasy!
You can get the id from the element that responded to the click event with this.id:
var items = document.getElementsByClassName('menu');
for (var i = 0; i < items.length; i++) {
items[i].addEventListener('click', printDetails);
}
function printDetails(e) {
console.log("Clicked " + this.id);
}
<ul>
<li class="menu" id="bob">Robert Smith</li>
<li class="menu" id="jane">Jane Doe</li>
<li class="menu" id="sue">Susan Carter</li>
</ul>
<ul id = "menuList">
<li class="menu" id="bob">Robert Smith</li>
<li class="menu" id="jane">Jane Doe</li>
<li class="menu" id="sue">Susan Carter</li>
</ul>
// JS - Event Bubbling
const menuList= document.getElementById("menuList");
menuList.addEventListener("click", function (e) {
console.log(e.target); // log clicked element
});
Here is a shorter version I'm using all the time:
[...(document.getElementsByClassName('__MYCLASSNAME__')].forEach(d => {
d.addEventListener('click', MYFUNCTION__);
})

jquery select by class then match value

I have a list like this
<ul>
<li class="somename">1</li>
<li class="somename">2</li>
<li class="somename">3</li>
<li class="somename">1</li>
</ul>
then I have a value like this
var myvalue = 1;
I want to compare myvalue with all the $(".somename).text() to find the matching ones and change the text of the matching to something else like below
<ul>
<li class="somename">changed</li>
<li class="somename">2</li>
<li class="somename">3</li>
<li class="somename">changed</li>
</ul>
$(".somename").text() give me all the text in a string like 1231
and I tried to for loop
for(i=0;i<$(".somename").length;i++){
if(myvalue == $(".somename")[i].text()){
$(this).text("changed")
}
}
$('.somename').each(function() {
var value = $(this).text();
if (value == "1") {
$(this).text("Changed")
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="somename">1</li>
<li class="somename">2</li>
<li class="somename">3</li>
<li class="somename">1</li>
</ul>
Use .each() to loop through all elements with the class.
Have a condition , if met change the text
When using the bracket object property accessor ([]) on a jQuery object you are accessing the underlying object in the collection so .text() would not be available as that is not a function on the underlying DOM object (you should have seen an error on your console)
You can use jQuery .each method to loop through the collection
$(".somename").each(function(){
//unless you are going to be doing more jQuery DOM stuff
//no need to wrap in jQuery just access the innerText
if(myvalue == this.innerText){
this.innerText = "changed";
}
});
If you dont want to use the .each method and just use the for loop you would need to use either .eq or similar method to get the jQuery wrapped object at a particular index
var elements = $(".somename");
for(i=0;i<elements.length;i++){
let element = elements.eq(i);
if(myvalue == element.text()){
element.text("changed");
}
}
Do like this...
$(".somename").each(function(e, val ){
if (myvalue == e.text){
//do stuff here
}
));
Please try this out but FYI I've not tried this on my own system.
var myvalue = 1;
var lists = document.getElementsByTagName('li');
for(var i = 0; i < lists.length; i++){
if(myvalue == lists[i].innerHTML){
//change your text here
}
}
You can use jQuery .each function.
var myvalue=1;
$('.somename').each(function(){
if($(this).text()==myvalue){
$(this).text('changed');
}
});
Few things here
1. When you search any DOM element .Try to copy it into a variable and then use it .DOM search is a costly operation
2.When you are using for loop,this would point to window object
check the following code snippet
$(document).ready(function(){
var someoneArray=$(".somename");
var someoneArrayLength=someoneArray.length;
var myValue=1;
for(var i=0;i<someoneArrayLength;i++){
var value=parseInt($(someoneArray[i]).text());
console.log(this)
if(myValue == value){
alert("here");
$(someoneArray[i]).text("changed");
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="somename">1</li>
<li class="somename">2</li>
<li class="somename">3</li>
<li class="somename">1</li>
</ul>
Hope this helps

Javascript grab a group of class names and add them as IDs

Is there a way with Javascript to store all the class names inside #links into an array and use a loop to assign each an ID of that class?
Below would be before
<div id="links">
some link
some link
some link
some link
</div>
after javascript
<div id="links">
some link
some link
some link
some link
</div>
Here are two plain-vanilla ways to do it with JavaScript (no jQuery). Of course this assumes that your only have the one class per element.
var elem = document.getElementById('links');
for (var i = 0; i < elem.getElementsByTagName('a').length; i++) {
elem.getElementsByTagName('a')[i].setAttribute('id',elem.getElementsByTagName('a')[i].className)
}
or
var links = document.getElementById('links').getElementsByTagName('a');
Array.prototype.map.call(links, function (el) {
el.setAttribute('id',el.className)
});

Get list item index in HTML ul list using Javascript

I have the following HTML page:
<html>
<head>
<script type="text/javascript" src="JavaScript/Menu.js"></script>
</head>
<body>
<ul>
<li><a onclick="GetIndex(this)">One</a></li>
<li><a onclick="GetIndex(this)">Two</a></li>
<li><a onclick="GetIndex(this)">Three</a></li>
<li><a onclick="GetIndex(this)">Four</a></li>
</ul>
</body>
</html>
And the Menu.js javascript:
function GetIndex(sender)
{
var aElements = sender.parentNode.parentNode.getElementsByTagName("a");
var aElementsLength = aElements.length;
var index;
for (var i = 0; i < aElementsLength; i++)
{
if (aElements[i] == sender) //this condition is never true
{
index = i;
return index;
}
}
}
Why is the commented condition never met? How do I compare if the two HTML elements are equal in Javascript? Thanks for all the help.
"Your code is correct"
Old Post, but here is a quick function to do this:
function nodeIndex(el) {
var i=0;
while(el.previousElementSibling ) {
el=el.previousElementSibling;
i++;
}
return i;
}
This should work with an element reference as the parameter. It basically just returns the number of previous siblings.
try to use:
if (aElements[i] === sender)
instead of
if (aElements[i] == sender)
Are you sure GetIndex function gets executed on click event on anchor tag?
Try by giving href attribute to anchor tag. You can write either
One
or
One
here is the working example http://jsfiddle.net/QfRSb/
Jquery can help using prevAll()
$(document).on("click","li",function(){
var index=$(this).prevAll();
alert(index);
});
The modern way to find index of element
[...el.parentNode.children].indexOf(el)

Categories

Resources