#1 by papayapap
I am using live method to create a market. One type of player can send offers, the others see them as rows in a table with a button to accept for each row. I then created a function to remove the row that is clicked using .parentNode. This works well for the player who click on the button. However, the button remains visible for other players with the same role. Why does it not delete the row also for other players? Simplified code here: ################### init.py ################################# from otree.api import * doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'mwe' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): job_id = models.IntegerField(initial=0) class Player(BasePlayer): is_employer = models.IntegerField() current_offer = models.IntegerField() offer_accepted = models.IntegerField(initial=0, min=0, max=1) employed_worker = models.IntegerField(initial=0, min=0, max=1) num_workers = models.IntegerField(initial=0, min=0, max=3) class JobOffer(ExtraModel): # things that get saved without creating a variable player = models.Link(Player) job_id = models.Link(Group) # FUNCTIONS def creating_session(subsession: Subsession): players = subsession.get_players() if subsession.round_number == 1: employers = [] workers = [] for p in players: employer = p.id_in_group % 2 == 0 if employer: p.participant.is_employer = True employers.append(p) else: p.participant.is_employer = False workers.append(p) for p in players: if p.participant.is_employer: p.is_employer = 1 else: p.is_employer = 0 # PAGES class MyPage(Page): form_model = "player" @staticmethod def js_vars(player: Player): return dict(my_id=player.id_in_group, is_employer=player.is_employer) @staticmethod def live_method(player: Player, data): group = player.group players = group.get_players() employers = [p for p in players if p.is_employer] workers = [p for p in players if not p.is_employer] print(data) if data["information_type"] == "offer": group.job_id = group.job_id + 1 return {0: {'information_type': 'offer', 'from': player.id_in_group, 'job_id': group.job_id, 'accepted': player.offer_accepted, 'effort': data['effort'], 'wage': data['wage']}} if data["information_type"] == 'accept': print('acceptance arrived!') print(data) to = data['to'] return {to: {'information_type': 'accept', 'from': data['from'], 'job_id': data['job_id'], 'accepted': data['status'], 'effort': data['effort_accepted'], 'wage': data['wage_accepted']}} class ResultsWaitPage(WaitPage): pass class Results(Page): pass page_sequence = [MyPage, ResultsWaitPage, Results] ################### MyPage.html ################################# {{ block content }} {% if player.is_employer == 1 %} <p> <h2>Please make an offer</h2><br> Wage <input type="number" id="wage"><br> Effort <input type="number" id="effort"><br><br> <button type="button" id="my_offer" onclick="sendOffer()"> Submit </button><br><br> </p> {% else %} <p> Job offers will appear below. You can accept at most one this round.<br> <div class="container"> <h2> Job offers </h2> <table class="table"> <tbody id="offers_table_workers"> </tbody> </table> </div> </p> {% endif %} <script> function liveRecv(data) { if (data["information_type"] == "offer") { let current_offer = data["wage"]; let player_offer = data["from"]; let requested_effort = data["effort"]; let job_id = data["job_id"]; document.getElementById("offers_table_workers").innerHTML += `<tr id="${job_id}"><td> Player <span id="employerJ${job_id}"> ${player_offer} </span> offered a wage of <span id="wageJ${job_id}"> ${current_offer} </span> for <span id="effortJ${job_id}"> ${requested_effort} </span> effort <button class="button" type="button" onclick="acceptOffer(this)"> Accept </button> </td></tr>`; } } function sendOffer() { let effort = parseInt(document.getElementById("effort").value); let offered_wage = parseInt(document.getElementById("wage").value); let status = 0; let my_id = js_vars.my_id; if (isNaN(offered_wage) || isNaN(effort)) { alert("Error: Please enter a number in both fields before sending offer."); return; } else if (offered_wage < 0 || offered_wage > 100) { alert("Error: Please specify a wage between 0 and 100."); return; } else if (effort < 0 || effort > 10) { alert("Error: Please specify a requested effort between 0 and 10."); return; } else { liveSend({ "information_type": "offer", "from": my_id, "status": status, "wage": offered_wage, "effort": effort }); document.getElementById("effort").value = ""; document.getElementById("wage").value = ""; } } function acceptOffer(el) { let status = 1; let my_id = js_vars.my_id; let job_id = el.parentNode.parentNode.id; let employerid = "employerJ" + job_id; let wageid = "wageJ" + job_id; let effortid = "effortJ" + job_id; let wage_accepted = parseInt(document.getElementById(`${wageid}`).innerHTML); let effort_accepted = parseInt(document.getElementById(`${effortid}`).innerHTML); let employer = parseInt(document.getElementById(`${employerid}`).innerHTML); liveSend({ "information_type": "accept", "from": my_id, "to": employer, "job_id": job_id, "status": status, "wage_accepted": wage_accepted, "effort_accepted": effort_accepted }); el.parentNode.parentNode.parentNode.removeChild(el.parentNode.parentNode); return false; } </script> {{ endblock }}