2

Edit: Topic has been marked as duplicate. I just wanted to say that im not happy with the answers of the other post. The accepted answer uses a not so nice way of dealing with such problem. Apart from that I made it clear that I read all those posts before and have difficulties understanding that particular problem area in javascript.

I dont get this at all. I really do a lot of reading, especially about closures but I dont get this...im on it for hours. Why does the following code fail to work? Im absolutely lost now and I need someone who could really point out how I can overcome situations like these where my index fails to be recognized within my event function.

How does this work? My addEventListener just wont work since the index is only recognized outside of it.

var lastResponse;
var alpha = document.getElementById('alpha');
var httpRequest;

function initAjax(url) {
  httpRequest = new XMLHttpRequest();
  httpRequest.open('POST', url, true);
  httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  httpRequest.send();

  httpRequest.onreadystatechange = function() {
    if (httpRequest.readyState === 4 && httpRequest.status === 200) {
        var response = httpRequest.responseText;
        document.getElementById("omega").innerHTML = response;
        fn();
    }
  }
}

alpha.addEventListener("click", function() {
  initAjax("test.php");
});

var x = document.getElementById("omega").children;

function fn() {
    for(var i=0; i < x.length; i++){
        console.log(x.length);
        document.getElementById("omega").addEventListener("click", function(event){
            hello(i, event);
        }, false);
    }
}

function hello(index, event){
    console.log(event.currentTarget.children[index]);
}

Updated code

  • Ajax gets content with their respective divs
  • When request is completed javascript injects the returned data from the server to omega.
  • Omega has children.
  • Now I want to click on one of those children and get their index.
38
  • 1
    Maybe try document.getElementById("omega").addEventListener("click", function(event){ hello(i, event); }.bind({}), false); Commented Jan 1, 2016 at 4:17
  • 1
    #omega is the only element that's an event.target ,is in a loop, why ? I think you need to include the HTML, because I'm having a hard time trying to visualize a button#omega? These children of #omega are what and how many? Commented Jan 1, 2016 at 4:21
  • 1
    @asperger I think it would a lot more easier if you could create a failing bin on jsbin.com. Cause ur use case doesn't seem straightforward and everyones guessing or assuming. You could simulate ajax by just return some data in setTimeout. Commented Jan 1, 2016 at 4:49
  • 1
    @Asperger is this what u need jsfiddle.net/9wLhqfnf/1 Commented Jan 1, 2016 at 5:04
  • 1
    @Asperger I cant. this question is now marked as duplicate. Well I just get the 'currentTarget' which is parent element and the 'target' element which is clicked element and use a array indexOf method. But in actual code u may need to do some checks to make sure what the clicked element is if you nest other tags in a item. Commented Jan 1, 2016 at 5:09

1 Answer 1

1

As this question marked as duplicate before @blessenm adds his answer, I'm just rewriting my answer so that his elegant solution will be visible to someone looking in this question in the future. I've posted different answer before the question was closed, so I'm still able to edit my answer. All credits to @blessenm:

function start() {
  omega.addEventListener("click", function(evt) {
    alert([].indexOf.call(evt.currentTarget.children, evt.target)); 
  }, false);
}

[].indexOf is shortcut of Array.prototype.indexOf function. The first argument you're passing is the context, the second argument is the item you're searching in that array. DOM elements array-like objects but are not actual arrays therefore they don't have the array methods in Array.prototype - that's why you cannot use alert(evt.currentTarget.children.indexOf(evt.target)). To do array operations on a DOM we use the call method of Array prototype.

Sign up to request clarification or add additional context in comments.

10 Comments

I dont want to add an event listener to every child which is why ive done this event.currentTarget.children[index] which is far better
ok, then why you keep var getting # of children outside of your fn() function? at the time you call fn (async), x equals to the number of children under omega before you call fn. i updated the answer, can you check?
Im getting undefined
Which line do you get undefined? I changed the code a bit passing number of divs under omega as argument to function fn, so you don't need var x = document.getElementById("omega").children; can you check if it works?
Pls check again, using forEach loop should handle the closure problem.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.