Miokloń
Miokloń

Reputation: 315

Can't pass argument to the function onmouseover - javascript

On the top of the code I declared table of objects. Then ,in function setup(), I'm trying to, foreach object in a table, add onmouseover function and pass each object as an argument for function pickUp(pick), but then I mouse over this object, console says "pick is undefined". It's weird for me, because I passed pickUps[0] for example and typeof(pickUps[0]) gives me "object". Can someone explain and help with passing each object as an argument?

Code:

var locked = "#4C8299";
var pickedUp = "#CC1B2B";
var released = "#19FFC8";

var pickUps = document.getElementsByClassName("pickUpSquare");

function pickUp(pick){
    if (pick.style.background == released){
        pick.style.background = pickedUp;
    }
}

function setup(){
    for (var i = 0; i < pickUps.length; i++){
        pickUps[i].onmouseover = function(){
            pickUp(pickUps[i]);
       }
    }   
}

window.onload = setup;

Upvotes: 1

Views: 2467

Answers (3)

P.S.
P.S.

Reputation: 16392

First, you have to check rgb, rgba and hex in your case, because the computed background color can be stored as rgb, or rgba, or as hex in different browsers (I have converted it to rgb and rgba too, you can do it for example via this online converter: http://hex2rgba.devoth.com/). If you want to get the computed style of the element, you should do it like this: window.getComputedStyle(element).getPropertyValue(property) instead of pick.style.background. And in provided code, pickUp(pickUps[i]); doesn't pass to function an element, and the error occurred:

Uncaught TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'

So I replaced it by this keyword.

Below is the working snippet:

var lockedRgb = "rgb(76, 130, 153)";
var lockedRgba = "rgba(76, 130, 153, 1)";
var lockedHex = "#4C8299";
var pickedUpRgb = "rgb(204, 27, 43)";
var pickedUpRgba = "rgba(204, 27, 43, 1)";
var pickedUpHex = "#CC1B2B";
var releasedRgb = "rgb(25, 255, 200)";
var releasedRgba = "rgba(25, 255, 200, 1)";
var releasedHex = "#19FFC8";

var pickUps = document.getElementsByClassName("pickUpSquare");

function pickUp(pick){
    var currentBgc = window.getComputedStyle(pick).getPropertyValue("background-color");
    if (currentBgc === releasedRgb || currentBgc === releasedRgba || currentBgc === releasedHex){
        pick.style.backgroundColor = pickedUpRgb;
    }
}

function setup(){
    for (var i = 0; i < pickUps.length; i++){
        pickUps[i].onmouseover = function(){
            pickUp(this);
       }
    }   
}

window.onload = setup;
.pickUpSquare {
  background-color: rgb(25,255,200);
}
<div class="pickUpSquare">1</div>
<div class="pickUpSquare">2</div>
<div class="pickUpSquare">3</div>

Upvotes: 0

Problem is your loop. The last value of "i" is what is being passed in. In this case, "i" is one more than the length of your pickups array, so it is always undefined.

You'll have to restructure your loop to not depend on i, but also to not produce var's that are just copies of i. This seems to work:

for (let pu of pickUps){
    pu.onmouseover = function(){
        pickUp(pu);
   }
}

Hope this helps, or at least suggests an answer

Upvotes: 0

janos
janos

Reputation: 124804

The problem is that variable i in the loop of the setup function is part of the closure of the inner anonymous function definition. As such, at the moment when the pickUps[i] gets used, the loop has long finished and the value of i is pickUps.length, and so the value of pickUps[i] is undefined (it's pointing to a value just beyond the bounds of the array).

One way to fix is to use a function that returns a function, and pass to it i or pickUps[i] as a parameter:

pickUps[i].onmouseover = (function(pick) {
    return function() { pickUp(pick); }
})(pickUps[i]);

If you can use ES6, then a simpler solution is to replace var i with let i in the for loop (thanks @alex-kudryashev).

Upvotes: 1

Related Questions