Sostituire e.target con evento onclick

di il
10 risposte

Sostituire e.target con evento onclick

Salve ho una pagina del tris dove il click delle caselle per mettere "X" o "O" è gestito tramite e.target, quello che vorrei fare è gestire il click delle caselle con l'evento onclick ma non saprei come fare. Allego il link della pagina e il codice della pagina:
function TicTacToe(selector) {

    var main_element = $(selector)[0],
        score_X = $('.score.X')[0],
        score_O = $('.score.O')[0],
        board = $('.board')[0],
        grid_options = $('.grid-options')[0],
        reset_btn = $('.btn-reset')[0];

    var grid_size = 3,
        moves = 0,
        scores = {
            X: 0,
            O: 0
        },
        data = {};

    $('.grid-options').change(function(e) {
      grid_size = $(this).val();
      init();
    });

    init();
    
    $('.btn-reset').click(function(e) {
      reset_btn = init();
    });

    function paint() {
        var table = '<table>';
        for (var i = 0; i < grid_size; i++) {
            table += '<tr>';
            for (var j = 0; j < grid_size; j++) {
                table += '<td row="' + i + '" column="' + j + '"></td>';
            }
            table += "</tr>";
        }
        $(board).html(table);

        var columns = $('td');
        for (i = 0; i < columns.length; i++) {
            $(columns[i]).click(function(e) {
            td = mark(e);
            })
        }

    }

    function mark(e) {

        var evt = e || event;
        var td = evt.target || evt.srcElement;

        if ($(td).html()) {
            return;
        }

        var row = $(td).attr('row'),
            column = $(td).attr('column');

        var current_mark = moves % 2 === 0
            ? 'X'
            : 'O';

        $(td).html(current_mark);
        $(td).addClass(current_mark);
        data[row + '' + column] = current_mark;

        moves++;

        if (didWin(current_mark)) {
            alert(current_mark + ' vince la partita!');
            scores[current_mark]++;
            updateScoreboard();
            empty();
        } else if (moves === Math.pow(grid_size, 2)) {
            alert("Pareggio!");
            empty();
        }

    }

    function didWin(mark) {

        var vertical_count = 0,
            horizontal_count = 0,
            right_to_left_count = 0,
            left_to_right_count = 0;

        for (var i = 0; i < grid_size; i++) {

            vertical_count = 0;
            horizontal_count = 0;

            for (var j = 0; j < grid_size; j++) {

                if (data[i + '' + j] == mark) {
                    horizontal_count++;
                }

                if (data[j + '' + i] == mark) {
                    vertical_count++;
                }

            }

            if (data[i + '' + i] == mark) {
                left_to_right_count++;
            }

            if (data[(grid_size - 1 - i) + '' + i] == mark) {
                right_to_left_count++;
            }

            if (horizontal_count == grid_size || vertical_count == grid_size) {
                return true;
            }

        }

        if (left_to_right_count == grid_size || right_to_left_count == grid_size) {
            return true;
        }

        return false;
    }

    function empty() {
        moves = 0;
        paint();
        data = {};
    }

    function init() {
        empty();
        scores = {
            X: 0,
            O: 0
        };
        updateScoreboard();
    }

    function updateScoreboard() {
        $('.score.X').html(scores.X);
        $('.score.O').html(scores.O);
    }

}
TicTacToe('.game-panel');
Nel codice var td = evt.target || evt.srcElement che si occupa del click delle caselle per mettere "X" o "O" è gestito tramite e.target ma vorrei sostituire il metodo e.target con un evento onclick ma non saprei come fare.

10 Risposte

  • Re: Sostituire e.target con evento onclick

    fede220 ha scritto:


    Nel codice var td = evt.target || evt.srcElement che si occupa del click delle caselle per mettere "X" o "O" è gestito tramite e.target ma vorrei sostituire il metodo e.target con un evento onclick ma non saprei come fare.
    Quanto dici non ha molto senso, sotto diversi punti di vista.

    Innanzitutto, e.target non è un metodo: la proprietà target ti indica l'elemento su cui è stato eseguito il clic, quindi non può essere sostituito, e soprattutto non ha senso dire di sostituirlo con un evento onclick, in quanto l'evento ti segnala l'avvenuto clic, mentre il target ti indica su quale elemento è stato fatto il clic.

    In sintesi, JavaScript ti informa dell'azione dell'utente e dell'elemento HTML che ne è interessato: sta a te gestire nel modo opportuno l'evento riconoscendo l'elemento e quello che rappresenta per andare ad aggiornare di conseguenza le variabili di gioco.

    A mio avviso, ti conviene prima documentarti e chiarire bene gli elementi che utilizzi nel codice e il loro scopo, poi da qui decidere come proseguire nell'implementazione.

    Ciao!
  • Re: Sostituire e.target con evento onclick

    Ciao fede,
    concordo con quanto dice Alka, inoltre volevo farti notare che, tramite JQuery, stai già utilizzando l'evento "onclick". Lo hai utilizzato in queste righe (appena prima di aver dichiarato la funzione):
    
    	...
    	$(columns[i]).click(function(e) {
                td = mark(e);
            });
            ...
    
  • Re: Sostituire e.target con evento onclick

    Ciao andread dev ho provato questo codice:
    function TicTacToe(selector) {
    
        var main_element = $(selector)[0],
            score_X = $('.score.X')[0],
            score_O = $('.score.O')[0],
            board = $('.board')[0],
            grid_options = $('.grid-options')[0],
            reset_btn = $('.btn-reset')[0];
    
        var grid_size = 3,
            moves = 0,
            scores = {
                X: 0,
                O: 0
            },
            data = {};
    
        $('.grid-options').change(function(e) {
          grid_size = $(this).val();
          init();
        });
    
        init();
    	
    	$('.btn-reset').click(function(e) {
    	  reset_btn = init();
    	});
    
        function paint() {
            var table = '<table>';
            for (var i = 0; i < grid_size; i++) {
                table += '<tr>';
                for (var j = 0; j < grid_size; j++) {
                    table += '<td row="' + i + '" column="' + j + '"></td>';
                }
                table += "</tr>";
            }
            $(board).html(table);
    
            var columns = $('td');
            for (i = 0; i < columns.length; i++) {
                $(columns[i]).click(function(e) {
    			td = mark(e);
    			})
            }
    
        }
    
        function mark(e) {
    
           $('td').click(function() {
    	
            var td = $(this);
    
            if ($(td).html()) {
                return;
            }
    
            var row = $(td).attr('row'),
                column = $(td).attr('column');
    
            var current_mark = moves % 2 === 0
                ? 'X'
                : 'O';
    
            $(td).html(current_mark);
            $(td).addClass(current_mark);
            data[row + '' + column] = current_mark;
    
            moves++;
    
            if (didWin(current_mark)) {
    			alert(current_mark + ' vince la partita!');
                scores[current_mark]++;
                updateScoreboard();
                empty();
            } else if (moves === Math.pow(grid_size, 2)) {
    			alert("Pareggio!");
                empty();
            }
            })
        }
    
        function didWin(mark) {
    
            var vertical_count = 0,
                horizontal_count = 0,
                right_to_left_count = 0,
                left_to_right_count = 0;
    
            for (var i = 0; i < grid_size; i++) {
    
                vertical_count = 0;
                horizontal_count = 0;
    
                for (var j = 0; j < grid_size; j++) {
    
                    if (data[i + '' + j] == mark) {
                        horizontal_count++;
                    }
    
                    if (data[j + '' + i] == mark) {
                        vertical_count++;
                    }
    
                }
    
                if (data[i + '' + i] == mark) {
                    left_to_right_count++;
                }
    
                if (data[(grid_size - 1 - i) + '' + i] == mark) {
                    right_to_left_count++;
                }
    
                if (horizontal_count == grid_size || vertical_count == grid_size) {
                    return true;
                }
    
            }
    
            if (left_to_right_count == grid_size || right_to_left_count == grid_size) {
                return true;
            }
    
            return false;
        }
    
        function empty() {
            moves = 0;
            paint();
            data = {};
        }
    
        function init() {
            empty();
            scores = {
                X: 0,
                O: 0
            };
            updateScoreboard();
        }
    
        function updateScoreboard() {
            $('.score.X').html(scores.X);
            $('.score.O').html(scores.O);
        }
    
    }
    
    Funziona ma chi inizia la partita (con la griglia vuota) il giocatore deve cliccare 2 volte sulla casella per riempirla come se il primo click non viene rilevato. Ti allego il link della pagina aggiornata se provi a cliccare su una casella il primo click non funziona ma se riclicchi di nuovo (secondo click) si riempie la casella e non riesco a capire perchè il primo click non funziona.
  • Re: Sostituire e.target con evento onclick

    Ciao Fede,
    Il problema nel tuo codice è il modo in cui aggiungi l'event listener ai td.
    Nella funzione "paint" aggiungi ad ogni "td" un listener che richiama la funzione "mark". Però in questa funzione cosa succede? Vengono aggiunti nuovamente degli event listener, che modificano i vari td.
    Quindi cosa fa il tuo codice?

    Primo click:
    Viene richiamata la funzione "mark" che, al posto di segnare con una X o un O la casella, aggiunge degli event listener sui td.

    Secondo click:
    Viene richiamata la funzione "mark" (di nuovo), e verranno aggiunti ulteriori event listener (e questo è potrebbe essere definito un memory leak).
    Viene richiamata la funzione anonima che era stata aggiunta nel click precedente, e che imposterà la casella come "X" o "O".

    La soluzione al problema, è semplicemente quella di non creare dei nuovi event listener. La funzione "mark" dovrebbe semplicemente segnare la casella, e nient'altro. Quindi ti consiglierei di rimuovere la prima e l'ultima riga all'interno della funzione "mark".

  • Re: Sostituire e.target con evento onclick

    Ciao andreadev per prima riga all'interno della funzione mark intendi questo:
    $('td').click(function() {
    e ultima riga all'interno della funzione mark intendo questo:
    if (didWin(current_mark)) {
    			alert(current_mark + ' vince la partita!');
                scores[current_mark]++;
                updateScoreboard();
                empty();
            } else if (moves === Math.pow(grid_size, 2)) {
    			alert("Pareggio!");
                empty();
            }
            })
        }
    Ho provato ma visualizzo l'errore che mark e TicTacToe non sono definiti.

    Poi ho provato ad definire l'evento onclick direttamente sulla funzione "mark":
    function TicTacToe(selector) {
    
        var main_element = $(selector)[0],
            score_X = $('.score.X')[0],
            score_O = $('.score.O')[0],
            board = $('.board')[0],
            grid_options = $('.grid-options')[0],
            reset_btn = $('.btn-reset')[0];
    
        var grid_size = 3,
            moves = 0,
            scores = {
                X: 0,
                O: 0
            },
            data = {};
    
        $('.grid-options').change(function(e) {
          grid_size = $(this).val();
          init();
        });
    
        init();
    	
    	$('.btn-reset').click(function(e) {
    	  reset_btn = init();
    	});
    
        function paint() {
            var table = '<table>';
            for (var i = 0; i < grid_size; i++) {
                table += '<tr>';
                for (var j = 0; j < grid_size; j++) {
                    table += '<td row="' + i + '" column="' + j + '"></td>';
                }
                table += "</tr>";
            }
            $(board).html(table);
    
            var columns = $('td');
            for (i = 0; i < columns.length; i++) {
                $(columns[i]).click(function(e) {
    			td = $('td');
    			})
            }
    
        }
    
        $('td').click(function mark(e) {
    	
            var td = $(this);
    
            if ($(td).html()) {
                return;
            }
    
            var row = $(td).attr('row'),
                column = $(td).attr('column');
    
            var current_mark = moves % 2 === 0
                ? 'X'
                : 'O';
    
            $(td).html(current_mark);
            $(td).addClass(current_mark);
            data[row + '' + column] = current_mark;
    
            moves++;
    
            if (didWin(current_mark)) {
    			alert(current_mark + ' vince la partita!');
                scores[current_mark]++;
                updateScoreboard();
                empty();
            } else if (moves === Math.pow(grid_size, 2)) {
    			alert("Pareggio!");
                empty();
            }
    
        })
    
        function didWin(mark) {
    
            var vertical_count = 0,
                horizontal_count = 0,
                right_to_left_count = 0,
                left_to_right_count = 0;
    
            for (var i = 0; i < grid_size; i++) {
    
                vertical_count = 0;
                horizontal_count = 0;
    
                for (var j = 0; j < grid_size; j++) {
    
                    if (data[i + '' + j] == mark) {
                        horizontal_count++;
                    }
    
                    if (data[j + '' + i] == mark) {
                        vertical_count++;
                    }
    
                }
    
                if (data[i + '' + i] == mark) {
                    left_to_right_count++;
                }
    
                if (data[(grid_size - 1 - i) + '' + i] == mark) {
                    right_to_left_count++;
                }
    
                if (horizontal_count == grid_size || vertical_count == grid_size) {
                    return true;
                }
    
            }
    
            if (left_to_right_count == grid_size || right_to_left_count == grid_size) {
                return true;
            }
    
            return false;
        }
    
        function empty() {
            moves = 0;
            paint();
            data = {};
        }
    
        function init() {
            empty();
            scores = {
                X: 0,
                O: 0
            };
            updateScoreboard();
        }
    
        function updateScoreboard() {
            $('.score.X').html(scores.X);
            $('.score.O').html(scores.O);
        }
    
    }
    Funziona al primo click ma il problema che quando si cambia la dimensione della griglia o quando la partita è terminata le caselle non sono più cliccabili e penso il problema possa dipendere dall'evento onclick sulla funzione "mark". Allego il link della pagina aggiornato . Quello che sto cercando di fare è sostituire event.target con l'evento onclick per riempire le caselle con "X" o "O" ma non saprei come fare. Grazie per la cordialità.
  • Re: Sostituire e.target con evento onclick

    Ciao Fede,
    con la prima riga intendo proprio quella, ma con "l'ultima riga" intendevo solo la chiusura delle parentesi, per evitare errori di sintassi

    Il tuo secondo tentativo è simile a quello che pensavo, solo che dovresti spostare l'aggiunta della funzione "mark" come event listener all'interno della funzione "paint".
    L'idea è che, appena l'HTML viene costruito e aggiunto alla pagina, si aggiungano anche tutti gli event listener.
  • Re: Sostituire e.target con evento onclick

    Ciao andreadev ho provato ad aggiungere la funzione "mark" come event listener all'interno della funzione "paint" e funziona perfettamente. Qui il codice penso che sia corretto così:
    function TicTacToe(selector) {
    
        var main_element = $(selector)[0],
            score_X = $('.score.X')[0],
            score_O = $('.score.O')[0],
            board = $('.board')[0],
            grid_options = $('.grid-options')[0],
            reset_btn = $('.btn-reset')[0];
    
        var grid_size = 3,
            moves = 0,
            scores = {
                X: 0,
                O: 0
            },
            data = {};
    
        $('.grid-options').change(function(e) {
          grid_size = $(this).val();
          init();
        });
    
        init();
    	
    	$('.btn-reset').click(function(e) {
    	  reset_btn = init();
    	});
    
        function paint() {
            var table = '<table>';
            for (var i = 0; i < grid_size; i++) {
                table += '<tr>';
                for (var j = 0; j < grid_size; j++) {
                    table += '<td row="' + i + '" column="' + j + '"></td>';
                }
                table += "</tr>";
            }
            $(board).html(table);
    
            var columns = $('td');
            for (i = 0; i < columns.length; i++) {
                $(columns[i]).click(function(e) {
    			td = $('td');
    			})
            }
            $('td').click(function mark(e) {
    	
            var td = $(this);
    
            if ($(td).html()) {
                return;
            }
    
            var row = $(td).attr('row'),
                column = $(td).attr('column');
    
            var current_mark = moves % 2 === 0
                ? 'X'
                : 'O';
    
            $(td).html(current_mark);
            $(td).addClass(current_mark);
            data[row + '' + column] = current_mark;
    
            moves++;
    
            if (didWin(current_mark)) {
    			alert(current_mark + ' vince la partita!');
                scores[current_mark]++;
                updateScoreboard();
                empty();
            } else if (moves === Math.pow(grid_size, 2)) {
    			alert("Pareggio!");
                empty();
            }
    
        })
        }
    
        function didWin(mark) {
    
            var vertical_count = 0,
                horizontal_count = 0,
                right_to_left_count = 0,
                left_to_right_count = 0;
    
            for (var i = 0; i < grid_size; i++) {
    
                vertical_count = 0;
                horizontal_count = 0;
    
                for (var j = 0; j < grid_size; j++) {
    
                    if (data[i + '' + j] == mark) {
                        horizontal_count++;
                    }
    
                    if (data[j + '' + i] == mark) {
                        vertical_count++;
                    }
    
                }
    
                if (data[i + '' + i] == mark) {
                    left_to_right_count++;
                }
    
                if (data[(grid_size - 1 - i) + '' + i] == mark) {
                    right_to_left_count++;
                }
    
                if (horizontal_count == grid_size || vertical_count == grid_size) {
                    return true;
                }
    
            }
    
            if (left_to_right_count == grid_size || right_to_left_count == grid_size) {
                return true;
            }
    
            return false;
        }
    
        function empty() {
            moves = 0;
            paint();
            data = {};
        }
    
        function init() {
            empty();
            scores = {
                X: 0,
                O: 0
            };
            updateScoreboard();
        }
    
        function updateScoreboard() {
            $('.score.X').html(scores.X);
            $('.score.O').html(scores.O);
        }
    
    }
    Allego il link della pagina aggiornato . Ma il metodo jQuery click corrisponde all'evento onclick. Grazie di tutto per la disponibilità e cordialità.
  • Re: Sostituire e.target con evento onclick

    Ciao fede,
    sì, le due righe che ti propongo sotto sono uguali:
    
    // jQuery
    $("#mio-elemento").click(function () {
    	console.log("Cliccato");
    });
    
    // Javascript puro
    document.getElementById("mio-elemento").addEventListener("click", function () {
    	console.log("Cliccato");
    });
    
    Anche se personalmente continuo ad usare il javascript classico (a parte quando uso questo piccolo script), riesco a capire che sia per questo motivo che molti hanno iniziato ad usare jQuery
  • Re: Sostituire e.target con evento onclick

    Ciao andreadev ma il codice della pagina del tris è corretto?
    
    //jQuery
    $("element").click(function () {
    	console.log("Cliccato");
    });
    
    // Javascript puro
    document.getElementById("element").onclick = function() {
    	console.log("Cliccato");
    });
    
    Grazie per la disponibilità e cordialità.
  • Re: Sostituire e.target con evento onclick

    Ciao Fede,
    Le righe sopra te le ho messe solo come esempi per mettere a confronto le 2 sintassi, non sono da inserire nel tuo progetto, tranquillo
    Hai già utilizzato il codice jQuery simile a quello che ti ho messo giù, il messaggio sopra era solo per mostrarti come sarebbe stato scritto se non avessi dovuto utilizzare jQuery (onclick e addEventListener("click") sono la stessa cosa).
Devi accedere o registrarti per scrivere nel forum
10 risposte