Как навесить AJAX на элемент, добавляемый вебсокетом без перезагрузки страницы?
В проекте джанго есть игровая комната. Решил сделать, чтобы заходящий в неё игрок добавлялся без перезагрузки. Но у каждого игрока есть несколько кнопок (смена уровня/расы и т.д.), которые работают через AJAX. Теперь получается, что мой добавляемый вебсокетами игрок не имеет этих работающих кнопок (они просто ничего не делают).
Мне вроде посоветовали вручную навесить addEventListener, но я хз, насколько это правильно и как это вообще делается)
Вот AJAX:
$(document).ready(function() { // Открытие модального окна при клике на имя игрока $('.player-date').on('click', function() { var $player = $(this).closest('.player'); var $modal = $('#playerDataEditModal'); // Заполнение полей модального окна $modal.find('.name').text($player.find('.player-name').text()); $modal.find('.name').attr('player', $player.attr('player')); $modal.find('.total').text($player.find('.total').text()); $modal.find('.level').val($player.find('.level').text()); $modal.find('.power').val($player.find('.power').text()); // Открытие модального окна $player.addClass("active"); $modal.modal('show'); }); // Закрытие модального окна и обновление значений на странице $("#playerDataEditModal").on("hide.bs.modal", function () { var $player = $('.player.active'); var $modal = $('#playerDataEditModal'); var obj = new Object(); obj.player = $modal.find('.name').attr('player'); obj.level = $modal.find('.level').val(); obj.power = $modal.find('.power').val(); obj.total = $modal.find('.total').text(); obj.user_room = $modal.find('.total').text() $player.removeClass("active"); $player.find('.level').text(obj.level); $player.find('.power').text(obj.power); $player.find('.total').text(obj.total); sendData(obj); }); // Увеличение и уменьшение уровня игрока $('.increase-level').on('click', function() { var $level = $(this).closest('.player').find('.level'); var levelValue = parseInt($level.val()); $level.val(levelValue + 1); }); $('.decrease-level').on('click', function() { var $level = $(this).closest('.player').find('.level'); var levelValue = parseInt($level.val()); if (levelValue > 1) { $level.val(levelValue - 1); } }); // Увеличение и уменьшение силы игрока $('.increase-power').on('click', function() { var $power = $(this).closest('.player').find('.power'); var powerValue = parseInt($power.val()); $power.val(powerValue + 1); }); $('.decrease-power').on('click', function() { var $power = $(this).closest('.player').find('.power'); var powerValue = parseInt($power.val()); if (powerValue > 1) { $power.val(powerValue - 1); } }); // Расчет общей силы игрока $('#playerDataEditModal').on('click', '.player-data-edit', function() { var $modal = $('#playerDataEditModal'); var levelValue = parseInt($modal.find('.level').val()); var powerValue = parseInt($modal.find('.power').val()); var total = levelValue + powerValue; $modal.find('.total').text(total); }); }); |
$(document).ready(function() { // Открытие модального окна при клике на имя игрока $('.player-date').on('click', function() { var $player = $(this).closest('.player'); var $modal = $('#playerDataEditModal'); // Заполнение полей модального окна $modal.find('.name').text($player.find('.player-name').text()); $modal.find('.name').attr('player', $player.attr('player')); $modal.find('.total').text($player.find('.total').text()); $modal.find('.level').val($player.find('.level').text()); $modal.find('.power').val($player.find('.power').text()); // Открытие модального окна $player.addClass("active"); $modal.modal('show'); }); // Закрытие модального окна и обновление значений на странице $("#playerDataEditModal").on("hide.bs.modal", function () { var $player = $('.player.active'); var $modal = $('#playerDataEditModal'); var obj = new Object(); obj.player = $modal.find('.name').attr('player'); obj.level = $modal.find('.level').val(); obj.power = $modal.find('.power').val(); obj.total = $modal.find('.total').text(); obj.user_room = $modal.find('.total').text() $player.removeClass("active"); $player.find('.level').text(obj.level); $player.find('.power').text(obj.power); $player.find('.total').text(obj.total); sendData(obj); }); // Увеличение и уменьшение уровня игрока $('.increase-level').on('click', function() { var $level = $(this).closest('.player').find('.level'); var levelValue = parseInt($level.val()); $level.val(levelValue + 1); }); $('.decrease-level').on('click', function() { var $level = $(this).closest('.player').find('.level'); var levelValue = parseInt($level.val()); if (levelValue > 1) { $level.val(levelValue - 1); } }); // Увеличение и уменьшение силы игрока $('.increase-power').on('click', function() { var $power = $(this).closest('.player').find('.power'); var powerValue = parseInt($power.val()); $power.val(powerValue + 1); }); $('.decrease-power').on('click', function() { var $power = $(this).closest('.player').find('.power'); var powerValue = parseInt($power.val()); if (powerValue > 1) { $power.val(powerValue - 1); } }); // Расчет общей силы игрока $('#playerDataEditModal').on('click', '.player-data-edit', function() { var $modal = $('#playerDataEditModal'); var levelValue = parseInt($modal.find('.level').val()); var powerValue = parseInt($modal.find('.power').val()); var total = levelValue + powerValue; $modal.find('.total').text(total); }); });
Вот script в джанго-шаблоне на добавление игрока:
<script language="javascript"> var code = "{{ room.code }}" var races = "{{ races }}" var ws_url = 'ws://' + window.location.host + '/ws/room_player/'; var gendersSocket = new WebSocket(ws_url); gendersSocket.onmessage = function(event) { var data = JSON.parse(event.data); if (data.code == code) { console.log(data) addNewPlayer(data) } }; function addNewPlayer(playerData) { var tableBody = document.querySelector('.table tbody'); // Create a new row var newRow = document.createElement('tr'); newRow.classList.add('inner-box', 'player'); newRow.setAttribute('player', playerData.pk); var genderIcon; if (playerData.gender === 'M') { genderIcon = '<i class="fa fa-mars" gender="true" aria-hidden="true"></i>'; } else if (playerData.gender === 'F') { genderIcon = '<i class="fa fa-venus" gender="true" aria-hidden="true"></i>'; } else { genderIcon = '<i class="fa fa-tree" gender="true" aria-hidden="true"></i>'; } // Create the HTML content for the row var rowContent = ` <th scope="row"> <div class="player-date" data-toggle="modal" data-target="#playerDataEditModal"> <h2><i class="fa fa-bolt" aria-hidden="true"></i> <span class='total' data-player-id-total1=${playerData.playerId}>${playerData.power + playerData.level}</span></h2> <p><i class="fa fa-line-chart" aria-hidden="true"></i> <span class='level' data-player-id-level=${playerData.playerId}>${playerData.level}</span> <i class="fa fa-gavel" aria-hidden="true"></i> <span class='power' data-player-id-power=${playerData.playerId}>${playerData.power}</span></p> </div> </th> <td> <div class="player-img player-gender" data-player-id-gender=${playerData.playerId}> ${genderIcon} <img src=${playerData.image} alt="Аватар пользователя /> </div> <div class="username"> <p>${playerData.username}</p> </div> </td> <td> <div class="player-wrap"> <div class="meta d-inline-flex"> <div class="race px-2"> <div class="d-flex align-items-center"> <i class="fa fa-user" aria-hidden="true"></i> <a href="#" class="btn btn-link dropdown-toggle player-race" data-bs-toggle="dropdown" aria-expanded="false" data-player-id=${playerData.playerId}> ${playerData.race} </a> <ul class="dropdown-menu"> {% for player_race in races %} <li><a class="dropdown-item" href="#">{{ player_race.1 }}</a></li> {% endfor %} </ul> {% comment %} </div> {% endcomment %} <div class="class px-2"> <div class="btn-group"> <i class="fa fa-gamepad" aria-hidden="true"></i> </div> <a href="#" class="btn btn-link dropdown-toggle player-class" data-bs-toggle="dropdown" aria-expanded="false" data-player-id-2=${playerData.playerId}> ${playerData.class} </a> <ul class="dropdown-menu"> {% for player_class in classes %} {% comment %} <li><a class="dropdown-item" href="#">{{ player_class.0 }}</a></li> {% endcomment %} <li><a class="dropdown-item" href="#">{{ player_class.1 }}</a></li> {% endfor %} </ul> </div> </div> </div> </div> </td> <td> <div class="primary-btn"> <a class="btn btn-primary" href="#"><i class="fa fa-bolt" aria-hidden="true"></i></a> </div> </td> `; newRow.innerHTML = rowContent; // Append the new row to the table tableBody.appendChild(newRow); } </script> |
<script language="javascript"> var code = "{{ room.code }}" var races = "{{ races }}" var ws_url = 'ws://' + window.location.host + '/ws/room_player/'; var gendersSocket = new WebSocket(ws_url); gendersSocket.onmessage = function(event) { var data = JSON.parse(event.data); if (data.code == code) { console.log(data) addNewPlayer(data) } }; function addNewPlayer(playerData) { var tableBody = document.querySelector('.table tbody'); // Create a new row var newRow = document.createElement('tr'); newRow.classList.add('inner-box', 'player'); newRow.setAttribute('player', playerData.pk); var genderIcon; if (playerData.gender === 'M') { genderIcon = '<i class="fa fa-mars" gender="true" aria-hidden="true"></i>'; } else if (playerData.gender === 'F') { genderIcon = '<i class="fa fa-venus" gender="true" aria-hidden="true"></i>'; } else { genderIcon = '<i class="fa fa-tree" gender="true" aria-hidden="true"></i>'; } // Create the HTML content for the row var rowContent = ` <th scope="row"> <div class="player-date" data-toggle="modal" data-target="#playerDataEditModal"> <h2><i class="fa fa-bolt" aria-hidden="true"></i> <span class='total' data-player-id-total1=${playerData.playerId}>${playerData.power + playerData.level}</span></h2> <p><i class="fa fa-line-chart" aria-hidden="true"></i> <span class='level' data-player-id-level=${playerData.playerId}>${playerData.level}</span> <i class="fa fa-gavel" aria-hidden="true"></i> <span class='power' data-player-id-power=${playerData.playerId}>${playerData.power}</span></p> </div> </th> <td> <div class="player-img player-gender" data-player-id-gender=${playerData.playerId}> ${genderIcon} <img src=${playerData.image} alt="Аватар пользователя /> </div> <div class="username"> <p>${playerData.username}</p> </div> </td> <td> <div class="player-wrap"> <div class="meta d-inline-flex"> <div class="race px-2"> <div class="d-flex align-items-center"> <i class="fa fa-user" aria-hidden="true"></i> <a href="#" class="btn btn-link dropdown-toggle player-race" data-bs-toggle="dropdown" aria-expanded="false" data-player-id=${playerData.playerId}> ${playerData.race} </a> <ul class="dropdown-menu"> {% for player_race in races %} <li><a class="dropdown-item" href="#">{{ player_race.1 }}</a></li> {% endfor %} </ul> {% comment %} </div> {% endcomment %} <div class="class px-2"> <div class="btn-group"> <i class="fa fa-gamepad" aria-hidden="true"></i> </div> <a href="#" class="btn btn-link dropdown-toggle player-class" data-bs-toggle="dropdown" aria-expanded="false" data-player-id-2=${playerData.playerId}> ${playerData.class} </a> <ul class="dropdown-menu"> {% for player_class in classes %} {% comment %} <li><a class="dropdown-item" href="#">{{ player_class.0 }}</a></li> {% endcomment %} <li><a class="dropdown-item" href="#">{{ player_class.1 }}</a></li> {% endfor %} </ul> </div> </div> </div> </div> </td> <td> <div class="primary-btn"> <a class="btn btn-primary" href="#"><i class="fa fa-bolt" aria-hidden="true"></i></a> </div> </td> `; newRow.innerHTML = rowContent; // Append the new row to the table tableBody.appendChild(newRow); } </script>
Дополнительно:
https://yandex.ru/search/?text=javascript+делегиро...
Ответы:
Вешай событие на боди:
$('body') .on('click', '.player-date', e => {}); |
$('body') .on('click', '.player-date', e => {});
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для навешивания AJAX на элемент, который добавляется на страницу с помощью вебсокетов без перезагрузки страницы, вам потребуется использовать следующий подход:
1. Добавьте обработчик события для вебсокета, который будет вызываться при получении новых данных с сервера. В этом обработчике вы будете обновлять содержимое страницы и инициировать AJAX-запрос для дополнительной загрузки данных.
2. Настройте AJAX-запрос для получения дополнительных данных с сервера. Обычно это делается с использованием jQuery или чистого JavaScript. Вы можете отправить запрос на определенный URL и получить ответ в формате JSON или HTML.
3. Обновите содержимое страницы с помощью полученных данных. Вы можете использовать jQuery или чистый JavaScript для обновления DOM-элементов с новой информацией.
Пример кода для реализации этого подхода:
// Обработчик события для вебсокета websocket.onmessage = function(event) { // Получаем новые данные с сервера var newData = JSON.parse(event.data); // Обновляем содержимое страницы updatePage(newData); // Инициируем AJAX-запрос для получения дополнительных данных $.ajax({ url: 'your-api-url', method: 'GET', success: function(response) { // Обновляем страницу с полученными данными updatePage(response); }, error: function(xhr, status, error) { console.error(error); } }); }; // Функция для обновления содержимого страницы function updatePage(data) { // Обновляем DOM-элементы на странице с новыми данными // Например, обновляем таблицу или список элементов }
Этот подход позволит вам динамически обновлять содержимое страницы при получении данных через вебсокеты и загружать дополнительные данные с сервера без перезагрузки страницы.