-1

So I'm trying to set .onclick functions that will change the color of whatever object I click to a large number of objects, lets just say they're <div> objects.

var myArrayOfObjects = [...]; //get desired <div>s here
for(var i = 0; i < myArrayOfObjects.length; i++){
     myArrayOfOjects[i].onclick = myFunction(i);
}

function myFunction(index){
     //Make some edit to the <div> myArrayOfObjects[i] here
}

But setting object.onclick equal to any function that takes any parameters makes the function run automatically and not when the particular object is clicked. If I try to access I any way other than passing it, it will always result in being myArrayOfObjects.length. Is there a way to get the clicked <div> to recognize exactly which object was clicked so it will know which one to change?

zigzaugg
  • 61
  • 10
  • possible duplicate of [How do JavaScript closures work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Jeremy J Starcher Aug 20 '14 at 16:54
  • What you are trying to do is: `myArrayOfOjects[i].onclick = (function() { myFunction(i); });`, however what you really need to do is understand closures, which is the question I linked to in the other comment. – Jeremy J Starcher Aug 20 '14 at 16:56
  • Maybe the answer to my question involves that, but our questions are pretty much not at all the same. – zigzaugg Aug 20 '14 at 16:56
  • Hence my other comment, where I do answer your specific question. :) – Jeremy J Starcher Aug 20 '14 at 16:57
  • `index` still appears to be `myArrayOfObjects.length` regardless of which object I'm clicking. – zigzaugg Aug 20 '14 at 17:02
  • Exactly... which is why you need closures, which is the *first* link I pointed to. This is a very, very common issue for folks new to JavaScript -- but the short answer is -- there is only one value of `i` and so all of the click handlers use the same `i`. You need closures to make a local copy of the variable. – Jeremy J Starcher Aug 20 '14 at 17:03
  • @zigzaugg: *"index still appears to be myArrayOfObjects.length regardless of which object I'm clicking"* see http://stackoverflow.com/q/750486/218196 for a solution – Felix Kling Aug 20 '14 at 17:06
  • I understand that there can only be one value of `i` at a time, and that any time post the running of the for loop (less than a second into the site), it would be the same as `myArrayOfObjects.length`. My question is on how to solve the problem with this foreknowledge. – zigzaugg Aug 20 '14 at 17:07
  • 2
    @JeremyJStarcher: No, the way closures work is *the problem* that leads to this behavior. The event handler bound inside the loop *is* a closure. The solution is to call a function to create a new scope. Whether that function is a closure or not is irrelevant. (theoretically every function in JS is a closure, technically they don't have to be (browser optimizations)) – Felix Kling Aug 20 '14 at 17:08
  • @zigzaugg: See my comment just before yours. – Felix Kling Aug 20 '14 at 17:09
  • @FelixKling: That is much more helpful! I'll explore for a minute and see if I can get it to work. – zigzaugg Aug 20 '14 at 17:13
  • Maybe this would make a better meta-post, but why would this question be considered a duplicate just because it involves a similar topic matter? – zigzaugg Aug 20 '14 at 17:16

1 Answers1

-1

DO THIS

var myArrayOfObjects = [...]; //get desired <div>s here
for(var i = 0; i < myArrayOfObjects.length; i++){
     myArrayOfOjects[i].onclick = function () {
      //Make some edit to the <div> myArrayOfObjects[i] here
      // here "this" will reder to "myArrayOfObjects[i]" So, you can do something to that div like this 
      // this.doSomething()
     };
}
Cute_Ninja
  • 4,742
  • 4
  • 39
  • 63
  • I already tried this solution. Again, `i` will still be the same as `myArrayOfObjects.length` since the for loop runs the loop before the button is clicked – zigzaugg Aug 20 '14 at 17:10
  • Why do you need i when you have access to that DOM element that is clicked itself. I think this is a better solution – Cute_Ninja Aug 20 '14 at 17:14
  • 1
    @zigzaugg: I agree with Ishita. Check first if you actually need the index or if you actually need the DOM Element. `this.doSomething()` won't work of course since DOM elements don't have a such a method, but `doSomething(this)` might be what you want. If you can avoid relying on the loop variable, you should! – Felix Kling Aug 20 '14 at 17:17
  • doSomething will not work -- that is ture.. But, I used that just to explain that you can dos omething with that DOM element there. For example you could do - this.html('Hello, you just clicked me'); – Cute_Ninja Aug 20 '14 at 17:25
  • 1
    Yup, this works! The code I was using to test it was poorly designed on my part, so even though it was my initial attempt at solving my problem, it failed. Works well though, thanks! Time to go learn about closure... EDIT: I'm not enacting methods either, I'm editing properties (this.style.backgroundColor = #xxxxxx;) – zigzaugg Aug 20 '14 at 17:33