-4

I can't access the variable from the marked point. The error console says the variable isn't declared. I've had the problem few years ago and I solved it, but I was googling for several hours and I can't find the solution anymore. Do you have an idea, what the problem is and how I can solve it?

Thanks in advance.

var smileys = [
    [":smile:", "smile.png"],
    [":sad:", "sad.png"],
    [":love:", "love.png"],
    [":angry:", "angry.png"],
    [":amazed:", "amazed.png"],
    [":laugh:", "laugh.png"],
    [":wink:", "wink.png"],
    [":crying:", "crying.png"],
];

$(document).ready(function(){

    for(var i=0; i<smileys.length; i++){
        var smiley = document.createElement("img");
        smiley.src = "./res/" + smileys[i][1];
        smiley.style.width = "24px";
        smiley.style.height = "24px";
        smiley.onclick = function(){
            alert(smileys[i][0]);
            // $("#chat-input").append(smileys[i][0]);
        };

        $("#smileys").append(smiley);
    }
});
Reese
  • 253
  • 5
  • 15
  • 3
    can you add the code around it? so we can see the scope of the variable – Shlomi Haver Jul 03 '16 at 12:40
  • https://jsfiddle.net/05ze77r8/ works – Madhawa Priyashantha Jul 03 '16 at 12:46
  • 3
    Possible duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). Use `(function(i){smiley.onclick = function(){alert(smileys[i][0]);};})(i);` instead of your `smiley.onclick` line. Your problem is not that you can’t access `smileys`. Your variable `i` is an index outside the array when your `onclick` function gets executed. – Sebastian Simon Jul 03 '16 at 12:47
  • @FastSnail Please take a look on my code. There is an "onclick" function. Within this function, I can't access the array. – Reese Jul 03 '16 at 12:47
  • @Reese can you show the console error too? – Shlomi Haver Jul 03 '16 at 12:49
  • @ShlomiHaver "TypeError: smileys[i] is undefined" – Reese Jul 03 '16 at 12:50
  • 3
    Of course you can access the array in your `onclick` function because the array is global. Your problem is the `I` being 8 which is out of range. – Racil Hilan Jul 03 '16 at 12:50
  • @RacilHilan Yes, that seemed to be the problem. Thank y'all. – Reese Jul 03 '16 at 12:56
  • 4
    If you couldn’t access `smileys`, you would’ve gotten `ReferenceError: smileys is not defined`. Precisely read the error: you’ve got a `TypeError` here. So all variables are found, but you’re trying to access a property of an undefined value, namely `smileys[i]`. And that’s because `i` is 8. – Sebastian Simon Jul 03 '16 at 12:59

1 Answers1

0

In the code that you provided, you can access the smileys array in your onclick function because the smileys is a global variable. Your problem is the i index of the loop being 8 in the onclick event which is out of range.

One good way to solve it is to save the value of the i in each smiley image and then access it inside the event like this:

var smileys = [
  [":smile:", "smile.png"],
  [":sad:", "sad.png"],
  [":love:", "love.png"],
  [":angry:", "angry.png"],
  [":amazed:", "amazed.png"],
  [":laugh:", "laugh.png"],
  [":wink:", "wink.png"],
  [":crying:", "crying.png"],
];

$(document).ready(function() {

  for (var i = 0; i < smileys.length; i++) {
    var smiley = document.createElement("img");
    smiley.src = "./res/" + smileys[i][1];
    smiley.style.width = "24px";
    smiley.style.height = "24px";
    smiley.value = i;

    smiley.onclick = function() {
      alert(smileys[this.value][0]);
    };

    $("#smileys").append(smiley);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="smileys"></div>
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
  • Thanks, but the result is the same. – Reese Jul 03 '16 at 12:46
  • Hm… a closure in the loop or the `let` statement would be a better solution; storing an arbitrary attribute to an element (without using `data-` attributes) is a weird and instable workaround… – Sebastian Simon Jul 03 '16 at 13:02
  • @Xufox You absolutely can use a `data-` attribute if you don't care to support old browsers. However, the `value` attribute works for all browsers. It is not an "arbitrary attribute", it is part of the HTML specs. – Racil Hilan Jul 03 '16 at 13:04
  • 1
    Yeah, but images don’t have a `value` attribute. It’s not a global attribute. Of course you can use `data-` attributes, that’s why I excluded them (“without using `data-` attributes”) from being a weird workaround. – Sebastian Simon Jul 03 '16 at 13:07
  • @Xufox What I was trying to say is that the `data-` attributes are part of HTML 5, while "custom" attributes have been supported by all browsers for a long time now. Yes, `value` is not a global attribute, so if you add it to the image, it becomes a "custom attribute". If you want your code to be more modern, then I fully agree with you that using `data-` attributes is the way to go. – Racil Hilan Jul 03 '16 at 13:17