BarelyAwake
BarelyAwake

Reputation: 1

Children Buttons not executing JS when clicked. Click registers and executes JS for parent div

I have a group of buttons that do not console.log when they are clicked. They are nested within a few divs and have been appended through another function. When the .finger buttons are clicked, they do not become active, even though they are supposed to change their background color through CSS when being clicked. The .stopButton does not become active/change its background color even though it is specified through CSS. The .startButton, when clicked, appends these new buttons and works.

Below is my code. If you need the rest of it, please let me know.

JS (Using JQuery)

//What will happen when the start button is pressed. Basically, reset everything
//and take to first stage of game. Must clear the Start Button and title if pressed.
function startButtonPressed(indexStartButton){
    hideStartScreenEle(indexStartButton);
    startGame();
}


//Hides display of startScreen ele
function hideStartScreenEle(indexStartButton){
    $(".startScreen").eq(0).css("display", "none");
    $(".startButton").eq(indexStartButton).css("display", "none");
}


//Sets up game, assumes everything else is already hidden
function startGame(){
    //Appends the flex containers
    $(".appendToMe").append("<div class='handHolder'><div class='fingerHolder'></div></div>");
    //Appends the thumb
    $(".fingerHolder").append("<button class= 'fingerButton thumb'></button>");
    //Appends the other fingers
    for (let i = 0; i < 1; i++) {
        $(".fingerHolder").append("<button class='fingerButton'></button>");
    }

    //Appends the stop button
    $(".appendToMe").append("<button class='stopButton'>Stop?</button>");
}

//Original button that runs the function that appends the rest of the buttons. Works
//After being pressed, it and the div it is contained in have their display changed to none
$(".startButton").on("click", function() {
    startButtonPressed($(this).index(".startButton"));
} );

//One stop button. Does not work, but becomes active.
$(".stopButton").on("click", function() {
    console.log("stop button pressed");
} );

//There are five fingers, each is a button. Does not work when clicked, but becomes active.
$(".fingerButton").on("click", function() {
    console.log("finger clicked");
} );

CSS

body {
    overflow: hidden;
    margin: 0;
    padding: 0;
    background: chartreuse;
}

.startScreen {
    text-align: center;
    width: 100vw;
    background: blue;
}

.startButtonDiv {
    background: yellow;
}

.startButton {
    width: 20vw;
    height: 20vh;
    background: red;
}

.appendToMe {
    width: 100vw;
    text-align: center;
    background: cyan;
    pointer-events: none;
}

.handHolder {
    background: steelblue;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    justify-content: center;
    width:760px;
    margin-left: auto;
    margin-right: auto;
    display: block;
    pointer-events: none;
}

.thumb {
    width: 200px;
    background: goldenrod;
}

.fingerButton {
    pointer-events: all;
    width: 140px;
    height: 340px;
    background: burlywood;
    border-width: 0px;
}

.fingerButton:active {
    background: orange;
}

.stopButton{
    background: firebrick;
    font-size: 80px;
    width: 10vw;
    height: 10vh;
}

.stopButton:active {
    background: blue;
}

HTML on Page Load

<!DOCTYPE html>
<html>
    <head>
        <title>Free Your Fingers 2.0.0</title>
        <script  src="https://code.jquery.com/jquery-3.7.1.min.js"
  integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
  crossorigin="anonymous"></script>
        <script type="text/javascript" src="../js/freeYourFingers_2_0_0.js" defer></script>
        <link rel="stylesheet" type="text/css" href="../css/freeYourFingers_2_0_0.css">
    </head>
    <body>
        <div class="appendToMe"></div>
        <div class="startScreen">
            <div class="startButtonDiv">
                <button class="startButton">Start</button>
            </div>
        </div>
    </body>
</html>

//What will happen when the start button is pressed. Basically, reset everything
//and take to first stage of game. Must clear the Start Button and title if pressed.
function startButtonPressed(indexStartButton) {
  hideStartScreenEle(indexStartButton);
  startGame();
}


//Hides display of startScreen ele
function hideStartScreenEle(indexStartButton) {
  $(".startScreen").eq(0).css("display", "none");
  $(".startButton").eq(indexStartButton).css("display", "none");
}


//Sets up game, assumes everything else is already hidden
//Creates div with 2 fingers
function startGame() {
  //Appends the flex containers
  $(".appendToMe").append("<div class='handHolder'><div class='fingerHolder'></div></div>");
  //Appends the thumb
  $(".fingerHolder").append("<button class= 'fingerButton thumb'></button>");
  //Appends the other fingers
  for (let i = 0; i < 1; i++) {
    $(".fingerHolder").append("<button class='fingerButton'></button>");
  }
  //Appends the stop button
  $(".appendToMe").append("<button class='stopButton'>Stop?</button>");
}

//Original button that runs the function that appends the rest of the buttons. Works
//After being pressed, it and the div it is contained in have their display changed to none
$(".startButton").on("click", function() {
  startButtonPressed($(this).index(".startButton"));
});

//One stop button. Does not work, but becomes active.
$(".stopButton").on("click", function() {
  console.log("stop button pressed");
});

//There are five fingers, each is a button. Does not work when clicked, but becomes active.
$(".fingerButton").on("click", function() {
  console.log("finger clicked");
});
body {
  overflow: hidden;
  margin: 0;
  padding: 0;
  background: chartreuse;
}

.startScreen {
  text-align: center;
  width: 100vw;
  background: blue;
}

.startButtonDiv {
  background: yellow;
}

.startButton {
  width: 20vw;
  height: 20vh;
  background: red;
}

.appendToMe {
  width: 100vw;
  text-align: center;
  background: cyan;
  pointer-events: none;
}

.handHolder {
  background: steelblue;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: center;
  width: 760px;
  margin-left: auto;
  margin-right: auto;
  display: block;
  pointer-events: none;
}

.thumb {
  width: 200px;
  background: goldenrod;
}

.fingerButton {
  pointer-events: all;
  width: 140px;
  height: 340px;
  background: burlywood;
  border-width: 0px;
}

.fingerButton:active {
  background: orange;
}


.stopButton {
  background: firebrick;
  font-size: 80px;
  width: 10vw;
  height: 10vh;
}

.stopButton:active {
  background: blue;
}

.mission{
  margin-left: auto;
  margin-right: auto;
  display: block;
  background: chocolate;
  width: 70vw;
}
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>

<div class="appendToMe"></div>
<div class="startScreen">
  <div class="gameTitle">
    <h1>Free Your Fingers</h1>
  </div>
  <div class="startButtonDiv">
    <button class="startButton">Start</button>
  </div>
</div>

I have tried changing the visibility of the different divs. The parent divs were set to hidden while the buttons that needed to be pressed were set to visible. This did not result in any change.

When I set the parents' pointer-events to none and the buttons' pointer-events to all, the buttons became active (change their background color), but did not execute any code.

When I had both the parents' visibilities' set to hidden, the buttons' visibilities' set to visible and the parents' pointer-events set to none and the buttons' pointer-events to all, the buttons would become active (change background color), but would not execute code.

I also tried event.stopPropagation(), but I most likely did not implement it properly and would be willing to try other solutions involving it.

I tried completely removing the .startScreen with .remove(). This did not have any effect on the problem.

I tried implementing different console.logs on different levels of div. It seems that the click is registering for the appendToMe div but not the children.

Upvotes: 0

Views: 99

Answers (1)

BarelyAwake
BarelyAwake

Reputation: 1

Figured it out. You can compare the event.target and this. This will be the .appendToMe div, but the target of the event will be the child button. The result of event.target is the DOM element of the target.

You can make the button execute your desired JS by getting the .classList of the event target and checking to see if it contains one of the buttons' classes. If it does, you can place your desired code under the corresponding branch of the if statement.

$(".appendToMe").on("click", function(event) {
    if (event.target !== this)
        var targetClassList = event.target.classList;
        if (targetClassList.contains('fingerButton') == true) {
            console.log("Clicked a finger");
            return;
        } else if (targetClassList.contains("stopButton") == true) {
            console.log("Clicked the stop button");
            return;
        } else {
            console.log("Something else");
        }
        return;
    alert("Clicked only on .appendToMe");
} );

If there is more than one button of a certain class and you want each button to have a different effect, but you don't want to give each one an ID, you can create an array of the existing buttons as DOM elements using .get(index). From there, you can get the index of the element by using .indexOf(event.target) on the list of DOM elements.

If I am wrong or if there are areas that can be improved upon, please add to this answer. This is probably not the most ideal solution, but it works.

$(".appendToMe").on("click", function(event) {
    if (event.target !== this)
        var targetClassList = event.target.classList;
        if (targetClassList.contains('fingerButton') == true) {
            console.log("Clicked a finger");
            var everyFinger = [];
            for (let i = 0; i < 5; i++) {
                everyFinger.push($(".fingerButton").get(i));
            } 
            fingerIndex = everyFinger.indexOf(event.target);
            console.log("fingerIndex: " + fingerIndex);
            return;
        } else if (targetClassList.contains("stopButton") == true) {
            console.log("Clicked the stop button");
            return;
        } else {
            console.log("Something else");
        }
        return;
    alert("Clicked only on .appendToMe");
} );

Upvotes: 0

Related Questions