oTree Forum >

Dynamically removing row from common table removes only for player who did action

#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 }}

Write a reply

Set forum username