Eos/eosweb/core/static/nunjucks/question/preferential/selections_make.html

205 lines
7.6 KiB
HTML

{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
<h2>{{ questionNum + 1 }}. {{ election.questions.__getitem__(questionNum).prompt }}</h2>
<p><small>
Vote for
{% if election.questions.__getitem__(questionNum).min_choices == election.questions.__getitem__(questionNum).max_choices %}
exactly {{ election.questions.__getitem__(questionNum).min_choices }}
{% else %}
between {{ election.questions.__getitem__(questionNum).min_choices }} and {{ election.questions.__getitem__(questionNum).max_choices }}
{% endif %}
choices. Click and drag the choices from the grey box to the blue box in order from most-preferred to least-preferred. It is in your best interests to vote for as many choices as you can.
</small></p>
<div id="question-choices-selected" class="preferential-choices">
<div style="color: #3465a4;">Options voted for:</div>
<div class="dragarea">
<div class="dragarea-hint"></div>
</div>
</div>
<div class="ui hidden message" id="message-max-choices">
<p>You have now selected the maximum allowed number of choices. If you wish to add different choices, you must deselect some choices by dragging them from the blue box back to the grey box.</p>
</div>
<div class="ui hidden error message" id="message-too-many-choices">
<p>You have selected more than the maximum allowed number of choices. To proceed, you must deselect some choices by dragging them from the blue box back to the grey box.</p>
</div>
{% set flat_choices = election.questions.__getitem__(questionNum).flatten_choices() %}
{% macro printchoice(choice, ticket=None) %}
<div class="preferential-choice" data-choiceno="{{ flat_choices.indexOf(choice) }}">
<div class="number">
<select>
<option selected></option>
{% for i in range(flat_choices|length) %}
<option>{{ i + 1 }}</option>
{% endfor %}
</select>
</div>
<div class="content">
<div class="candidate-name">{{ choice.name }}</div>
{% if choice.party %}
{% if (ticket and choice.party != ticket.name) or not ticket %}
<div class="party-name">{{ choice.party }}</div>
{% else %}
<div class="ticket-party-name">{{ choice.party }}</div>
{% endif %}
{% elif ticket %}
<div class="ticket-party-name">{{ ticket.name }}</div>
{% endif %}
</div>
</div>
{% endmacro %}
<div id="question-choices-remaining" class="preferential-choices">
<div>Options not yet voted for:</div>
<div class="dragarea">
<div class="dragarea-hint"></div>
{% for choice in election.questions.__getitem__(questionNum).randomised_choices().impl %}
{% if choice.choices %}
{# Ticket #}
<div class="preferential-choice ticket">
<div class="number">
<select>
<option selected></option>
{% for i in range(flat_choices|length) %}
<option>{{ i + 1 }}</option>
{% endfor %}
</select>
</div>
<div class="content">
<div class="party-name">{{ choice.name }}</div>
<div class="ticket-choices">
{% for choice2 in choice.choices.impl %}
{{ printchoice(choice2, choice) }}
{% endfor %}
</div>
</div>
</div>
{% else %}
{{ printchoice(choice) }}
{% endif %}
{% endfor %}
</div>
</div>
<script>
var allowAdding = true;
var flat_choices = election.questions.__getitem__(booth.questionNum).flatten_choices();
function choicesChanged() {
// Recalculate numbers
$(".preferential-choices .preferential-choice .number select").each(function(i, el) {
$(el).val("");
});
var selectedChoices = $("#question-choices-selected .dragarea > .preferential-choice > .number select");
selectedChoices.each(function(i, el) {
$(el).val(i + 1);
});
var selectedCandidates = $("#question-choices-selected .preferential-choice:not(.ticket) .number select");
if (selectedCandidates.length >= election.questions.__getitem__(booth.questionNum).max_choices) {
// Prevent making any more selections
allowAdding = false;
$("#question-choices-remaining .preferential-choice .number select").prop("disabled", true);
if (selectedCandidates.length > election.questions.__getitem__(booth.questionNum).max_choices) {
// Prevent progression
$(".primary.button").addClass("disabled");
$("#message-too-many-choices").removeClass("hidden");
} else {
$(".primary.button").removeClass("disabled");
$("#message-max-choices").removeClass("hidden");
}
} else {
allowAdding = true;
$("#question-choices-remaining .preferential-choice .number select").prop("disabled", false);
$(".primary.button").removeClass("disabled");
$("#message-max-choices").addClass("hidden");
$("#message-too-many-choices").addClass("hidden");
}
}
// Fill in ballot with previous selections
if (booth.q_state[booth.questionNum]) {
$("#question-choices-selected .dragarea").html(booth.q_state[booth.questionNum][0]);
$("#question-choices-remaining .dragarea").html(booth.q_state[booth.questionNum][1]);
choicesChanged();
}
var dragulaChoices = dragula(
[document.querySelector("#question-choices-selected .dragarea"), document.querySelector("#question-choices-remaining .dragarea")].concat([].slice.apply(document.querySelectorAll(".ticket-choices"))),
{
moves: function(el, source, handle, sibling) {
if ("dragarea-hint" in el.classList) {
return false;
}
if ($.contains(document.querySelector("#question-choices-remaining"), el)) {
return allowAdding;
}
return true;
},
mirrorContainer: document.querySelector("#question-choices-remaining")
}
);
function breakTicket(ticket) {
ticket.find(".ticket-choices .preferential-choice").each(function(i, el) {
$(el).detach().insertAfter(ticket);
});
ticket.remove();
}
dragulaChoices.on("drop", function(el, target, source, sibling) {
// If the source or target is a ticket, break the ticket
if ($(source).parents(".ticket").length > 0) {
breakTicket($(source).parents(".ticket").first())
}
if ($(target).parents(".ticket").length > 0) {
breakTicket($(target).parents(".ticket").first())
}
choicesChanged();
});
function saveSelections() {
selections = [];
$("#question-choices-selected .preferential-choice:not(.ticket)").each(function(i, el) {
selections.push(parseInt(el.dataset.choiceno));
});
if (selections.length < election.questions.__getitem__(booth.questionNum).min_choices) {
if (!window.confirm('You have selected fewer than the minimum required number of choices. If you proceed to cast this ballot, it will **NOT** be counted. If this was not your intention, please click the "Cancel" button below now, and correct your selections.')) {
return false;
}
}
answer = eosjs.eos.base.election.__all__.PreferentialAnswer(eosjs.__kwargtrans__({choices: selections}));
booth.answers[booth.questionNum] = eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(answer);
booth.q_state[booth.questionNum] = [$("#question-choices-selected .dragarea").html(), $("#question-choices-remaining .dragarea").html()]; // wew lad
return true;
}
</script>