Skip to content

How to correctly get the clicked element after adding addEventListener with javascript?

I am trying to create a calculator-like screen using JavaScript. I created the number pad buttons using the following HTML template

<button type="button" class="calulator_button" data-default-value="{NUMBER_VALUE}">
    <div class="card-body pl-0 pr-0">
        <p class="card-text display-4">{NUMBER_VALUE}</p>
    </div>
</button>

When the button that has the class calulator_button is clicked, I want to add the data-default-value to the display screen.

I created the following JS code which listens for a click event on the button.calulator_button selector and fires appendNumberToCalulator function.

Currently, I am using event.target to find the clicked element to determine the data-default-value attribute.

Problem

Depending where the user clicks on the button, the event.target may return different result.

For example, if the user clicks on the number inside the button directly, the event.target returns the <p>1</p> element inside the button. If the user clicks little further than the number, the <div></div> wrapping the <p></p> element is returned. Finally, if the user clicks around the edge of the button “just outside the <div></div> element”, the actual button is returned.

Question

How can I ensure that the button element is returned regardless of where the user clicks?

Here is the complete snippet

var calulatorButtons = document.querySelectorAll('button.calulator_button');
for (var i = 0; i < calulatorButtons.length; i++) {
    calulatorButtons[i].addEventListener('click', appendNumberToCalulator);
}

function getCalculatorDisplayElement() {
    return document.getElementById('Calculator_Total');
}

function appendNumberToCalulator(event) {

    var valueToAppend = event.target.getAttribute('data-default-value');
    var totalDisplay = getCalculatorDisplayElement();

    if (valueToAppend == '.' && totalDisplay.value.indexOf('.') > -1) {

        return;
    }

    totalDisplay.value += valueToAppend;
}


/* Handle Clear Screen */
document.getElementById('Calulator_Clear').addEventListener('click', function (_event) {
    getCalculatorDisplayElement().value = '';
});


/* Handle Clear Backspace */
document.getElementById('Calulator_Backspace').addEventListener('click', function (_event) {
    var value = getCalculatorDisplayElement().value;
    if (!value) {
        return;
    }
    getCalculatorDisplayElement().value = value.slice(0, -1);
});
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
                
    <div class="form-row align-items-center">
        <div class="col-8">
            <label class="sr-only" for="Calculator_Total"></label>
            
            <input class="form-control" data-val="true" id="Calculator_Total" name="Calculator_Total" type="text" value="">
        </div>

        <div class="col-sm-2">
            <button type="button" class="btn btn-primary w-100" id="Calulator_Backspace">«</button>
        </div>

        <div class="col-sm-2">
            <button type="button" class="btn btn-primary w-100" id="Calulator_Clear">C</button>
        </div>
    </div>

    <div class="card-deck mr-0 ml-0">
        

        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="1">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">1</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="2">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">2</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="3">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">3</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="4">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">4</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="5">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">5</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="6">
            <div class="card-body pl-0 pr-0" >
                <p class="card-text display-4">6</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="7">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">7</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="8">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">8</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="9">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">9</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="00">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">00</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value="0">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">0</p>
            </div>
        </button>


        <button type="button" data-action-type="Calculator" class="card text-white bg-secondary text-center calulator_button" style="min-width: 32%; max-width: 32.5%" data-id="" data-default-value=".">
            <div class="card-body pl-0 pr-0">
                <p class="card-text display-4">.</p>
            </div>
        </button>

    </div>

Answer

You need to use the currentTarget property, rather than target. The introduction to the linked MDN article explains the difference, and why you want currentTarget in this case, better than I can.