Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion static/bargraph/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ path.domain {
display: inline-block;
}

#faq-text {
.faq-text {
width: 100%;
max-width: 750px;
padding: 5px 10px 0px 10px;
Expand Down
4 changes: 4 additions & 0 deletions static/pie/pie.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
max-width: 800px;
width: 100%;
}

#pie-wrapper {
max-width: 800px;
}
116 changes: 8 additions & 108 deletions templates/bargraph/barchart-interactive-nonblocking.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,96 +2,9 @@

<script type="text/javascript">

const idOfWhyButton = "#bargraph-interactive-why-button";
// Raising the scope for other methods to access
let barchartRoundPlayer = null;
let scrollbarLocked = false;

function showTextOnRoundDescriber(description, keepFAQButtonHidden) {
// While playing, don't update the description text for the round
if (barchartRoundPlayer.playing()) {
return;
}

const idOfLegendOrRoundDescriber = "#bargraph-interactive-round-description";

// Don't re-render and transition if text already matches
if (d3.select(idOfLegendOrRoundDescriber).text() === description) {
return;
}

d3.select(idOfLegendOrRoundDescriber)
.transition()
.duration(100)
.delay(0)
.style("opacity", "0");
d3.select(idOfWhyButton)
.transition()
.duration(100)
.delay(0)
.style("opacity", "0");

d3.select(idOfLegendOrRoundDescriber)
.transition()
.delay(350)
.style("opacity", "1")
.text(description);

if (!keepFAQButtonHidden) {
d3.select(idOfWhyButton)
.transition()
.delay(350)
.style("opacity", "1");
}
};


function descriptionOfCurrRound(round) {
const roundData = humanFriendlyEventsPerRound[round];

let roundText = roundData.map(function(event) {
return event.description;
}).reduce(function(totalString, currText) {
return totalString + "\n" + currText;
}, "");

const roundIdentifier = `Round ${round + 1}. `;
return roundIdentifier + roundText;
}


function lockScrollbarIfNeeded() {
// Don't allow the animation to shift horizontally when a scrollbar is added
// and removed -- if a scrollbar is ever visible, keep it there.
if (scrollbarLocked) return;

const hasVerticalScrollbar = document.documentElement.scrollHeight > window.innerHeight;

if (hasVerticalScrollbar) {
document.body.style.overflowY = 'scroll';
scrollbarLocked = true;
}
}

function updateFaqText(round) {
const faqsPerRound = {{ faqsPerRound|safe }};
const idOfFaqTextDiv = "faq-text";
const text = faqsPerRound[round]
.map(d => "<p class='faq-q'>" + d['question'] + "</p>" +
"<p class='faq-a'>" + d['answer'] + "</p>")
.reduce((accum, val) => accum + val);
document.getElementById(idOfFaqTextDiv).innerHTML = `<h3 class="faq-description-header">Round ${round + 1} Explanation</h3> ${text}`;
setTimeout(lockScrollbarIfNeeded, 0); // Needs to run after the DOM is updated
}

function showFaqs() {
makeFaqSectionVisible();
document.getElementById("faq-text").scrollIntoView({ behavior: "smooth" })
}

function makeFaqSectionVisible() {
document.getElementById("faq-text").style.display = "block";
}
const bargraphInteractiveIds = makeRoundComponentIds("bargraph-interactive");

function makeInteractiveGraph() {
{{ bargraphjs|safe }}
Expand Down Expand Up @@ -124,44 +37,31 @@

function sliderValueChangedCallback(round) {
transitionEachBarForRound(round);
showTextOnRoundDescriber(descriptionOfCurrRound(round), false);
updateFaqText(round);
showTextOnRoundDescriber(descriptionOfCurrRound(round), false, bargraphInteractiveIds);
updateFaqText(round, bargraphInteractiveIds);
}

barchartRoundPlayer = RoundPlayer({
container: document.getElementById("bargraph-slider-container"),
totalRounds: numRounds,
onChange: sliderValueChangedCallback,
onPlay: function() {
showTextOnRoundDescriber(humanFriendlySummary, false);
showTextOnRoundDescriber(humanFriendlySummary, false, bargraphInteractiveIds);
}
});
activeRoundPlayer = barchartRoundPlayer;

// After creating the slider, make the default text the summary
// round summary, with the FAQ button showing.
showTextOnRoundDescriber(humanFriendlySummary, false);
showTextOnRoundDescriber(humanFriendlySummary, false, bargraphInteractiveIds);

// On load, show the FAQs if not in an iframe
if (window.self === window.top) {
makeFaqSectionVisible();
makeFaqSectionVisible(bargraphInteractiveIds);
}

// Populate the FAQ with initial description for the last round
updateFaqText(numRounds - 1);
}

function showFaqButton() {
d3.select(idOfWhyButton)
.transition()
.delay(300)
.duration(300)
.style("opacity", "100%");
}

function showFaqButtonNow() {
// Just used for integration testing
d3.select(idOfWhyButton)
.style("opacity", "100%");
updateFaqText(numRounds - 1, bargraphInteractiveIds);
}

makeInteractiveGraph();
Expand Down
14 changes: 2 additions & 12 deletions templates/bargraph/barchart-interactive.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,11 @@

<div class="container-fluid">
<div class="row d-flex flex-column justify-content-left align-items-start">
<div class="round-description-container">
<div id="round-description-wrapper" class="round-description-wrapper" role="alert">
<div class="round-description-text">
<span id="bargraph-interactive-round-description">
</span>
<span id="bargraph-interactive-why-button">
<a role="button" tabindex="0" onclick="showFaqs()">Read a detailed explanation</a>.
</span>
</div>
</div>
</div>
{% include "visualizer/round-describer.html" with prefix="bargraph-interactive" %}
<div class="shadow-wrapper col-md-12 col-xl-10" id="bargraph-interactive-body">
<div id="bargraph-slider-container" class="ml-auto mr-auto">
</div>
</div>
<div id="faq-text"></div>
{% include "visualizer/round-faq.html" with prefix="bargraph-interactive" %}
</div>
</div>
17 changes: 16 additions & 1 deletion templates/pie/pie-nonblocking.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,22 @@
// Append it to the div
document.getElementById("pie-body").appendChild(pieChart);

const pieNumRounds = {{ config.numRounds }};
const pieIds = makeRoundComponentIds("pie");

const pieRoundPlayer = RoundPlayer({
container: document.getElementById('pie-slider-container'),
totalRounds: {{ config.numRounds }},
totalRounds: pieNumRounds,
onChange: updatePieChartRound,
timeBetweenStepsMs: 3000,
firstStepHoldTimeMs: 500,
});
activeRoundPlayer = pieRoundPlayer;

function updatePieChartRound(sliderIndex) {
pieChart.currentRound = sliderIndex+1;
showTextOnRoundDescriber(descriptionOfCurrRound(sliderIndex), false, pieIds);
updateFaqText(sliderIndex, pieIds);
}

// When the pie chart is animating it knows it is advancing rounds, but to avoid reactive
Expand All @@ -53,6 +59,15 @@
function updateRound(roundNum) {
pieChart.currentRound = roundNum;
pieRoundPlayer.setStep(roundNum - 1);
showTextOnRoundDescriber(descriptionOfCurrRound(roundNum - 1), false, pieIds);
updateFaqText(roundNum - 1, pieIds);
}

// Show summary text and last-round FAQ on load
showTextOnRoundDescriber(humanFriendlySummary, false, pieIds);
updateFaqText(pieNumRounds - 1, pieIds);
if (window.self === window.top) {
makeFaqSectionVisible(pieIds);
}

</script>
9 changes: 9 additions & 0 deletions templates/pie/pie.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
{% load static %}
{% load compress %}

{% compress css file %}
<link rel="stylesheet" type="text/css" href="{% static 'pie/pie.css' %}">
{% endcompress %}

<!-- Embed JSON Data -->
{{ rawData|json_script:"rawDataId" }}

{% include "visualizer/round-describer.html" with prefix="pie" %}

<div id="pie-wrapper" class="shadow-wrapper">
<div id="pie-slider-container"></div>
<div id="pie-body" style="width: 100%; max-width: 800px; aspect-ratio: 1; margin: 0 auto;"></div>
</div>

{% include "visualizer/round-faq.html" with prefix="pie" %}
12 changes: 11 additions & 1 deletion templates/tabular/tabular-by-round-interactive-nonblocking.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@

// For slider TODO sync with barchart-interactive.html
var numRounds = {{ tabularByRoundInteractive.rounds|length }};
const tabularIds = makeRoundComponentIds("tabular");

function showRound(round) {
for (let i = 0; i < numRounds; i++) {
for (let i = 0; i < numRounds; i++) {
document.getElementById("tabular_round_container_"+i).style.display = "none";
}
document.getElementById("tabular_round_container_"+round).style.display = "block";
showTextOnRoundDescriber(descriptionOfCurrRound(round), false, tabularIds);
updateFaqText(round, tabularIds);
}

showRound(numRounds-1)
Expand All @@ -20,5 +23,12 @@
totalRounds: numRounds,
onChange: showRound,
});
activeRoundPlayer = roundPlayer;

// Show summary text and last-round FAQ on load
showTextOnRoundDescriber(humanFriendlySummary, false, tabularIds);
if (window.self === window.top) {
makeFaqSectionVisible(tabularIds);
}

</script>
6 changes: 5 additions & 1 deletion templates/tabular/tabular-by-round-interactive.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{% load static %}

{% include "visualizer/round-describer.html" with prefix="tabular" %}

<div id="tabular-by-round-slider-container" class="ml-auto mr-auto">
</div>

{% include "visualizer/round-faq.html" with prefix="tabular" %}

<div id="tabularByRoundInteractiveContainer">
{% for round in tabularByRoundInteractive.rounds %}
<div id="tabular_round_container_{{ forloop.counter0 }}">
Expand All @@ -15,7 +19,7 @@ <h4 class="mt-2 text-center">Round {{ forloop.counter }}</h4>
<th scope="col">Current total votes</th>
</tr>
</thead>

<tbody>
{% for candidate in round %}
{% if candidate.wonThisRound %}
Expand Down
81 changes: 81 additions & 0 deletions templates/visualizer/round-describer-nonblocking.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<script type="text/javascript">

// Consumers must set activeRoundPlayer to their RoundPlayer instance
// before showTextOnRoundDescriber is called.
let activeRoundPlayer = null;

function makeRoundComponentIds(prefix) {
return {
describer: "#" + prefix + "-round-description",
whyButton: "#" + prefix + "-why-button",
faqText: prefix + "-faq-text"
};
}

function showTextOnRoundDescriber(description, keepFAQButtonHidden, ids) {
// While playing, don't update the description text for the round
if (activeRoundPlayer.playing()) {
return;
}

// Don't re-render and transition if text already matches
if (d3.select(ids.describer).text() === description) {
return;
}

d3.select(ids.describer)
.transition()
.duration(100)
.delay(0)
.style("opacity", "0");
d3.select(ids.whyButton)
.transition()
.duration(100)
.delay(0)
.style("opacity", "0");

d3.select(ids.describer)
.transition()
.delay(350)
.style("opacity", "1")
.text(description);

if (!keepFAQButtonHidden) {
d3.select(ids.whyButton)
.transition()
.delay(350)
.style("opacity", "1");
}
};


function descriptionOfCurrRound(round) {
const roundData = humanFriendlyEventsPerRound[round];

let roundText = roundData.map(function(event) {
return event.description;
}).reduce(function(totalString, currText) {
return totalString + "\n" + currText;
}, "");

const roundIdentifier = `Round ${round + 1}. `;
return roundIdentifier + roundText;
}


function showFaqButton(ids) {
d3.select(ids.whyButton)
.transition()
.delay(300)
.duration(300)
.style("opacity", "100%");
}

function showFaqButtonNow() {
// Just used for integration testing - targets the bargraph
const ids = makeRoundComponentIds("bargraph-interactive");
d3.select(ids.whyButton)
.style("opacity", "100%");
}

</script>
11 changes: 11 additions & 0 deletions templates/visualizer/round-describer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="round-description-container">
<div class="round-description-wrapper" role="alert">
<div class="round-description-text">
<span id="{{ prefix }}-round-description">
</span>
<span id="{{ prefix }}-why-button">
<a role="button" tabindex="0" onclick="showFaqsFor('{{ prefix }}')">Read a detailed explanation</a>.
</span>
</div>
</div>
</div>
Loading
Loading