Skip to content

Commit caf803d

Browse files
authored
Merge pull request #87 from msteudtn/fenglisch-addon-permalink
Create addon_permalink_to_personal_result.js
2 parents 170277f + 4239aa4 commit caf803d

File tree

4 files changed

+172
-8
lines changed

4 files changed

+172
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// FUNKTION
2+
// Erzeuge über der Ergebnistabelle einen Button, der einen Permalink kopiert, mit man zurück zu der persönlichen Ergebnisseite gelangt
3+
4+
// 1.) Allgemeine Angaben
5+
// Text im Button
6+
const PERMALINK_BUTTON_TEXT = "Ergebnis speichern";
7+
8+
const PERMALINK_BUTTON_BACKGROUND_COLOR = "var(--secondary-color)";
9+
10+
const PERMALINK_BUTTON_TEXT_COLOR = "var(--secondary-text-color, #ffffff)";
11+
12+
// Erklärtext, der für ein paar Sekunden angezeigt wird, wenn man auf den Button klickt
13+
const PERMALINK_DESCRIPTION_TEXT =
14+
"Es wurde ein Permalink generiert und in deine Zwischenablage kopiert. Speichere diesen Link und rufe ihn später auf, um wieder zu dieser persönlichen Ergebnisseite zu gelangen - oder leite ihn weiter, um dein Ranking mit anderen zu teilen.";
15+
16+
const PERMALINK_DESCRIPTION_BORDER_COLOR = "var(--success)";
17+
18+
const PERMALINK_DESCRIPTION_BORDER_RADIUS = "var(--border-radius)";
19+
20+
// Wie viele Sekunden soll der Erklärtext angezeigt werden, bevor er wieder verschwindet?
21+
const PERMALINK_DESCRIPTION_DURATION = 8;
22+
23+
const LOADING_MODAL_TEXT = "Deine Ergebnisseite lädt...";
24+
25+
// 2.) In der DEFINITION.JS in den Erweiterten Einstellungen das Add-On eintragen.
26+
// Add the add-on to the advanced settings in DEFINITION.JS
27+
// var addons = ["extras/addon_permalink_to_personal_results.js"]
28+
29+
// 3.) Fertig.
30+
// That's it.
31+
32+
/// ////////////////////////////////////////////////////////////////////
33+
34+
// Hier kommt nur noch Quellcode. Bitte gehen Sie weiter. Hier gibt es nichts zu sehen.
35+
// That's just source code. Please move on. Nothing to see here.
36+
37+
/// ////////////////////////////////////////////////////////////////////
38+
39+
window.addEventListener("load", () => {
40+
// Suche in der URL nach Parameter und führe ggf. Funktion aus
41+
fnProcessPermalink();
42+
43+
const observerResults = new MutationObserver(fnGeneratePermalink);
44+
observerResults.observe(document.querySelector("#resultsHeading"), {
45+
childList: true,
46+
});
47+
48+
// Ist eine inner function, damit sie Zugriff auf die Variable observerResults hat (zum Disconnecten)
49+
function fnGeneratePermalink() {
50+
// Ohne .disconnect() wird die Mutation aus irgendeinem Grund doppelt getriggert -> 2 Buttons
51+
observerResults.disconnect();
52+
53+
const permalinkContainer = document.createElement("div");
54+
permalinkContainer.setAttribute("id", "permalink-container");
55+
permalinkContainer.innerHTML = `<button class="btn btn-secondary" id="permalink-button">${PERMALINK_BUTTON_TEXT}</button>
56+
<p id="permalink-description"\
57+
style="max-height: 0; border-color: transparent">\
58+
${PERMALINK_DESCRIPTION_TEXT}</p>`;
59+
const permalinkDescription = permalinkContainer.querySelector(
60+
"#permalink-description"
61+
);
62+
permalinkContainer
63+
.querySelector("#permalink-button")
64+
.addEventListener("click", () => {
65+
let permalinkUrl = window.location.origin + window.location.pathname;
66+
// Add parameter with personal positions
67+
permalinkUrl += "?personalpositions=" + arPersonalPositions.join(",");
68+
// Add parameter with voting double values, encode to numbers to avoid confusing strings like "false,false,false..." in the URL
69+
permalinkUrl +=
70+
"&votingdouble=" +
71+
arVotingDouble.map((element) => +element).join(",");
72+
navigator.clipboard.writeText(permalinkUrl);
73+
permalinkDescription.style.maxHeight =
74+
permalinkDescription.scrollHeight + 20 + "px";
75+
permalinkDescription.classList.add("permalink-description-visible");
76+
setTimeout(() => {
77+
permalinkDescription.style.maxHeight = 0;
78+
permalinkDescription.classList.remove(
79+
"permalink-description-visible"
80+
);
81+
}, PERMALINK_DESCRIPTION_DURATION * 1000);
82+
});
83+
document
84+
.querySelector("#resultsShort")
85+
.insertBefore(
86+
permalinkContainer,
87+
document.querySelector("#resultsShortTable")
88+
);
89+
}
90+
91+
addCssForPermalinkElements();
92+
});
93+
94+
function fnProcessPermalink() {
95+
const urlParams = new URLSearchParams(window.location.search);
96+
const personalPositionsFromUrl = urlParams.get("personalpositions");
97+
const votingDoubleFromUrl = urlParams.get("votingdouble");
98+
if (personalPositionsFromUrl) {
99+
// Ladebildschirm anzeigen
100+
document.querySelector(".container").classList.add("d-none");
101+
const loadingModalContainer = document.createElement("div");
102+
loadingModalContainer.innerHTML = `
103+
<div class="modal" id="loadingModal" tabindex="-1" aria-labelledby="loadingModalLabel" aria-modal="true" style="padding-right: 10px; display: block;">
104+
<div class="modal-dialog modal-dialog-centered" role="document">
105+
<div class="modal-content">
106+
<div class="modal-body" id="loadingModalBody">${LOADING_MODAL_TEXT}</div>
107+
</div>
108+
</div>
109+
</div>`;
110+
document.body.appendChild(loadingModalContainer);
111+
112+
arPersonalPositions = personalPositionsFromUrl.split(",");
113+
// Decode numbers to boolean values
114+
arVotingDouble = votingDoubleFromUrl
115+
.split(",")
116+
.map((element) => !!+element);
117+
118+
// Entferne das Statistik-Modal - an anderer Stelle eine Fehlermeldung in Kauf nehmend
119+
// const statsRecord lässt sich nicht zu "false" reassignen, daher das Modal einfach ganz entfernen
120+
let statisticsModal = document.querySelector("#statisticsModal");
121+
if (statisticsModal)
122+
statisticsModal.parentNode.removeChild(statisticsModal);
123+
124+
// Entferne den Startbildschirm, falls vorhanden. Ansonsten würde er nicht verschwinden
125+
const sectionDescription = document.querySelector("#sectionDescription");
126+
if (sectionDescription)
127+
sectionDescription.parentNode.removeChild(sectionDescription);
128+
129+
// Direkt zur Auswertung springen. Ohne Timeout würde es beim Reload z. T. zu Fehlern kommen
130+
setTimeout(() => {
131+
document.querySelector(".container").classList.remove("d-none");
132+
loadingModalContainer.classList.add("d-none");
133+
fnShowQuestionNumber(intQuestions);
134+
}, 2500);
135+
}
136+
}
137+
138+
function addCssForPermalinkElements() {
139+
const stylesheet = document.createElement("style");
140+
stylesheet.setAttribute("id", "permalinkCSS");
141+
stylesheet.textContent += `
142+
#permalink-container {
143+
display: flex;
144+
flex-direction: column;
145+
align-items: end;
146+
}
147+
148+
#permalink-button {
149+
background-color: ${PERMALINK_BUTTON_BACKGROUND_COLOR};
150+
}
151+
#permalink-description {
152+
transition: max-height .3s, border-color .3s;
153+
border: 2px solid;
154+
margin: 10px;
155+
width: max(60%, 300px);
156+
border-radius: ${PERMALINK_DESCRIPTION_BORDER_RADIUS};
157+
overflow: hidden;
158+
}
159+
160+
.permalink-description-visible {
161+
padding: 10px 15px;
162+
border-color: ${PERMALINK_DESCRIPTION_BORDER_COLOR} !important;
163+
}
164+
165+
`;
166+
document.head.appendChild(stylesheet);
167+
}

system/changelog.md

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
## Versions:
2323

24+
### 0.6.0.9.20230407
25+
26+
- new addon `extras/addon_permalink_to_personal_result.js` to save a link of your result to the clipboard and come back to it later https://github.com/msteudtn/Mat-O-Wahl/pull/87 (Thanks to FEnglisch)
2427

2528
### 0.6.0.8.20230215
2629

system/general.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// License: GPL 3
44
// Mathias Steudtner http://www.medienvilla.com
55

6-
var version = "0.6.0.8.20230215"
6+
var version = "0.6.0.9.20230407"
77

88
// Globale Variablen
99
var arQuestionsShort = new Array(); // Kurzform der Fragen: Atomkraft, Flughafenausbau, ...

system/output.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,7 @@ function fnStart()
9999

100100
// (b) Antworten der Parteien und Partei-Informationen
101101
fnReadCsv("data/"+fileAnswers,fnReadPositions)
102-
103-
// arVotingDouble initialisieren
104-
for (i=0;i<arQuestionsShort.length;i++) {
105-
arVotingDouble[i]=false;
106-
arPersonalPositions[i]=99;
107-
}
108-
102+
109103
$("#votingDouble").attr('checked', false);
110104

111105
// Wenn "descriptionShowOnStart = 0" in DEFINITION.JS, dann gleich die Fragen anzeigen

0 commit comments

Comments
 (0)