Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript objects: 'addEventListener is not a function'

I create an array of JavaScript objects called elements and loop through it in order to draw every one on a canvas as well as hooking up a few event handlers to it. However, I get an error stating that

'Uncaught TypeError: elements[i].addEventListener is not a function'

Here is the code:

$(document).ready(onDocumentReady);
function onDocumentReady() {
    var COLOR_NORMAL = '#005A84';
    var COLOR_SELECTED = '#00F2F2';
    var COLOR_MOUSEOVER = '#5BA621';

    var canvas = document.getElementById("mapCanvas");
    var context = canvas.getContext('2d');
    var data = @Html.Raw(Json.Encode(Model.DiePrintList));
    var elem =
        canvas,
        left = elem.offsetLeft,
        top = elem.offsetTop,
        context = elem.getContext('2d'),
        elements = [];
    for (var i = 0; i < data.length; i++) {
        elements.push({
            color: '#0489B1',
            width: 15,
            height: 15,
            row: data[i].Row,
            col: data[i].Col,
            top: data[i].Row * 20,
            left: data[i].Col * 20
        });
    }
    for (var i = 0; i < elements.length; i++) {
        elements[i].addEventListener('click', function(event) {
            var hitElement = getHitElement(elements, event.pageX - left, event.pageY - top);
            hitElement.color = COLOR_SELECTED;
            drawElement(context, hitElement);
        }, false);
        elements[i].addEventListener('mouseover', function(event) {
            var hitElement = getHitElement(elements, event.pageX - left, event.pageY - top);
            hitElement.color = COLOR_MOUSEOVER;
            drawElement(context, hitElement);
        }, false);
        elements[i].addEventListener('mouseout', function(event) {
            var hitElement = getHitElement(elements, event.pageX - left, event.pageY - top);
            hitElement.color = COLOR_SELECTED;
            drawElement(context, hitElement);
        }, false);
        drawElement(context, elements[i]);
    }
}
function drawElement(context, element) {
    context.fillStyle = element.color;
    context.fillRect(element.left, element.top, element.width, element.height);
}
function getHitElement(elements, x, y) {
    var hitElement;
    for (var i = 0; i < elements.length; i++) {
        if (y > elements[i].top && y < elements[i].top + elements[i].height && 
            x > elements[i].left && x < elements[i].left + elements[i].width) {
            hitElement = elements[i];
        }
    }
    return hitElement;
}

Why is it that I cannot hook up an event handler to each individual element?

like image 214
kformeck Avatar asked Jun 19 '15 19:06

kformeck


People also ask

What is a addEventListener in JavaScript?

The addEventListener() is an inbuilt function in JavaScript which takes the event to listen for, and a second argument to be called whenever the described event gets fired. Any number of event handlers can be added to a single element without overwriting existing event handlers.

Is addEventListener a callback function?

If a click is detected, JavaScript should fire the clicked function. So, in this case, clicked is the callback while addEventListener is a function that accepts a callback.

Is addEventListener the same as on ()?

addEventListener() is a method of a normal DOM element and . on() is a jQuery object method. As you probably know, a jQuery object can represent more than one element and when you use the . on() method you are attaching and event handler to every element in the collection.


1 Answers

Your specific error:

'Uncaught TypeError: elements[i].addEventListener is not a function'

is because elements[i].addEventListener is undefined and thus is not a function. The reason it is undefined is because your elements array contains regular Javascript objects. Those objects do not have a .addEventListener() method. That is a method on DOM objects that are an EventTarget, not regular Javascript objects (unless you make your own method called addEventListener and add it to your Javascript objects).

Since I don't see a corresponding array of DOM elements in your code, it appears like you're trying to attach eventListeners to rectangles you draw on your Canvas which is not something you can do in that way. T'he things you've drawn on a Canvas object are basically like a bitmap. It doesn't retain a knowledge of objects you drew on it other than the resulting pixels. You draw on it and the result is pixels on the canvas, not a persistent set of objects such as DOM objects. If you want to later do hit testing versus things you drew on the canvas, then you'd have to put an eventListener on the canvas object itself to get the input event, keep track yourself of what object you drew where on the canvas and then when the event triggers on your canvas listener, you can do your own hit testing versus that data of what you put where.

like image 136
jfriend00 Avatar answered Sep 19 '22 14:09

jfriend00