error: Uncaught TypeError: Cannot set property 'innerHTML' of null after adding and deleting an Event

StackOverflow https://stackoverflow.com/questions/21594766

Вопрос

I have this unfinished tic-tac-toe game and i'm having trouble when i finish the first game, then press "iniciar" to play again. I get this innerHTML error, can't figure out why is this happening and i would really appreciate some help.

It actually works like this: "Iniciar" to start playing When game finishes if it's a tie "Iniciar" again If there is a winner the scoreboard changes. "Iniciar" (here is when the error occurs)

"Reiniciar" resets the score and start a new game. This gives an error too.

It's weird because when it's a TIE, there's no problem with #errorenTurno But when there's a winner and i start over, the error is there.

<html>

<head>
    <link href='http://fonts.googleapis.com/css?family=Peralta' rel='stylesheet' type='text/css'>
</head>

<body>

    <script type="text/javascript">
        var turno = 1,
            puntosX = 0,
            puntosCero = 0; // some globals
        window.addEventListener('load', start, false);

        function start() {

            document.getElementById('empezar').addEventListener('click', inicio, false); // yellow buttons
            document.getElementById('reiniciar').addEventListener('click', reinicio, false);
        }

        function reinicio() { // yellow buttons
            document.getElementById('ganX').innerHTML = 0;
            document.getElementById('gandO').innerHTML = 0;
            inicio();
        }


        function inicio() { // adds listener to all spans in the table
            var x;

            for (x = 0; x <= 8; x++) {
                document.getElementById('boton' + x).innerHTML = '';
            }
            for (x = 0; x <= 8; x++) {
                document.getElementById('boton' + x).addEventListener('click', jugada, false);
            }
        }

        function jugada(evt) { // checks the move
            document.getElementById('errorenTurno').innerHTML = '';
            var bloqueJugado = evt.target;
            if (turno === 1) {
                if (bloqueJugado.innerHTML === 'O' || bloqueJugado.innerHTML === 'X') {
                    document.getElementById('errorenTurno').innerHTML = 'Ya se ha jugado aquíx'; // already marked
                    return;
                } else {
                    if (bloqueJugado.innerHTML !== 'X') {
                        evt.target.innerHTML = 'X';
                    }
                }
                verificarGan('X', 1);
                turno = 0;
                return;
            }

            if (turno === 0) {
                if (bloqueJugado.innerHTML === 'X' || bloqueJugado.innerHTML === 'O') {
                    document.getElementById('errorenTurno').innerHTML = 'Ya se ha jugado aquí0'; // already marked
                    return;
                } else {
                    if (bloqueJugado.innerHTML !== 'O') {
                        evt.target.innerHTML = 'O';
                    }
                }
                verificarGan('O', 2);
                turno = 1;
                return;
            }
        }

        function verificarGan(mov, jug) { // verifies if there is a winning move
            var j1 = document.getElementById('boton0');
            var j2 = document.getElementById('boton1');
            var j3 = document.getElementById('boton2');
            var j4 = document.getElementById('boton3');
            var j5 = document.getElementById('boton4');
            var j6 = document.getElementById('boton5');
            var j7 = document.getElementById('boton6');
            var j8 = document.getElementById('boton7');
            var j9 = document.getElementById('boton8');
            var detuvo = 0;

            function detener(gano) { // deletes the event listener from spans in table
                if (gano == 1) {
                    for (x = 0; x <= 8; x++) {
                        document.getElementById('boton' + x).removeEventListener('click', jugada);
                    }
                }
            }

            function puntoTablero() { // adds points to scoreboard, since i added this i started having trouble
                if (jug == 1) {
                    puntosX = puntosX + 1;
                    document.getElementById('ganX').innerHTML = puntosX;
                }
                if (jug == 2) {
                    puntosCero = puntosCero + 1;
                    document.getElementById('gandO').innerHTML = puntosCero;
                }
            }

            // checking all winning moves one by one. Then it applies the needed functions.
            if (j1.innerHTML == mov && j2.innerHTML == mov && j3.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j4.innerHTML == mov && j5.innerHTML == mov && j6.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j7.innerHTML == mov && j8.innerHTML == mov && j9.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j1.innerHTML == mov && j4.innerHTML == mov && j7.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j2.innerHTML == mov && j5.innerHTML == mov && j8.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j3.innerHTML == mov && j6.innerHTML == mov && j9.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j1.innerHTML == mov && j5.innerHTML == mov && j9.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }
            if (j7.innerHTML == mov && j5.innerHTML == mov && j3.innerHTML == mov) {
                document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
                detener(1);
                puntoTablero();
            }




        }
    </script>
    <style>
        .laVieja {
            font-family: Peralta;
            position: fixed;
            left: 0px;
            top: 100px;
            cursor: default;
            color: black;
            background-color: lightgrey;
        }
        .laVieja td {} .laVieja span {
            font-size: 100px;
            display: inline-block;
            border: 1px solid white;
            width: 160px;
            height: 160px;
            text-align: center;
            line-height: 150px;
        }
        span {
            clear: both;
        }
        .botonZ {
            font-family: Peralta;
            border: 1px solid black;
            text-align: center;
            padding-top: 18px;
            cursor: pointer;
            width: 150px;
            height: 40px;
            background-color: lightyellow;
            display: inline-block;
            position: relative;
            top: 90px;
            left: 10px;
        }
        .botonZ:hover {
            background-color: yellow;
        }
        #reiniciar {} * {
            font-family: Peralta;
        }
        #ganador {
            font-size: 30px;
            border: 1px solid white;
            text-align: center;
            position: relative;
            width: 100%;
            height: 130px;
            top: 80px;
            display: block;
            color: green;
        }
        #estadisticas {
            width: 350px;
            height: 400px;
            position: fixed;
            top: 100px;
            left: 530px;
            border: 1px solid white;
        }
        #ganadasX {
            font-size: 20px;
        }
        #ganadasO {
            font-size: 20px;
        }
        #ganX {
            font-size: 30px;
            color: green;
        }
        #gandO {
            font-size: 30px;
            color: red;
        }
    </style>
    <table border="1" class="laVieja">
        <tr>
            <td><span id="boton0">1</span>
            </td>
            <td><span id="boton1">2</span>
            </td>
            <td><span id="boton2">3</span>
            </td>
        </tr>
        <tr>
            <td><span id="boton3">4</span>
            </td>
            <td><span id="boton4">5</span>
            </td>
            <td><span id="boton5">6</span>
            </td>
        </tr>
        <tr>
            <td><span id="boton6">7</span>
            </td>
            <td><span id="boton7">8</span>
            </td>
            <td><span id="boton8">9</span>
            </td>
    </table>
    <div id="estadisticas">

        <p><span id="ganadasX">Ganadas X:&nbsp&nbsp  </span><span id="ganX">10</span>
        </p>
        <p><span id="ganadasO">Ganadas O:&nbsp&nbsp  </span><span id="gandO">5</span>
        </p>
        <p><span id="ganador"><span id="errorenTurno"></span></span>
        </p>
        <div id="empezar" class="botonZ">Iniciar</div>
        <div id="reiniciar" class="botonZ">Reiniciar Juego</div>

    </div>


    </tr>
</body>

</html>
Это было полезно?

Решение

While checking your inner moves the innerHTML of the div with id ganador is replaced by Ha ganado el jugador. SO now what happens is that the span with id errorenTurno is lost.

Your errorenTurno span is inside the ganador span.

<p><span id="ganador"><span id="errorenTurno"></span></span>

So either you have to append the message to ganador or move out the errorenTurno span out side of ganador. once the message is displayed there is no longer an element named errorenTurno

Другие советы

Add a null check to element before using it:

function jugada(evt) { // checks the move
    if(document.getElementById('errorenTurno')!== null )
         document.getElementById('errorenTurno').innerHTML = '';

and initialize x variable used in loop using var keyword:

function detener(gano) { // deletes the event listener from spans in table
    if (gano == 1) {
        for (var x = 0; x <= 8; x++) {
            document.getElementById('boton' + x).removeEventListener('click', jugada);
        }
    }
}

and your html contain not closed tr tag and an extra tr close tag just before html end:

 <tr>
     <td><span id="boton6">7</span>
     </td>
     <td><span id="boton7">8</span>
     </td>
     <td><span id="boton8">9</span>
     </td>
  <!-- add here closing tr tag-->
 </tr>
</table>

Here is Demo JsFiddle

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top