jak volit
This commit is contained in:
294
jakvolit.php
Normal file
294
jakvolit.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
|
||||
$maxVotes = 9;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="cs">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Jak správně volit & Simulátor</title>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-teal: #008080;
|
||||
--primary-dark: #005b5b;
|
||||
--accent-blue: #006699;
|
||||
--bg-light: #f4f8f8;
|
||||
--text-color: #2c3e50;
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; scroll-padding-top: 70px; }
|
||||
body {
|
||||
background-color: #ffffff; color: var(--text-color);
|
||||
margin: 0; padding: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
position: sticky; top: 0; z-index: 1000;
|
||||
background: linear-gradient(135deg, var(--primary-teal), var(--accent-blue));
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.navbar-container { max-width: 1300px; margin: 0 auto; display: flex; justify-content: center; padding: 0 10px; }
|
||||
.navbar nav { display: flex; gap: 10px; }
|
||||
.navbar a {
|
||||
color: #ffffff; text-decoration: none; padding: 15px 20px;
|
||||
font-weight: 600; font-size: 15px; transition: background 0.2s; display: block; text-align: center;
|
||||
}
|
||||
.navbar a:hover { background-color: rgba(255, 255, 255, 0.15); }
|
||||
|
||||
.container { max-width: 1300px; margin: 0 auto; padding: 20px; }
|
||||
section { padding: 40px 0; border-bottom: 1px solid #e0ecec; }
|
||||
section:last-of-type { border-bottom: none; }
|
||||
h2 { text-align: center; color: var(--primary-dark); font-size: 28px; margin-top: 0; margin-bottom: 30px; position: relative; }
|
||||
h2::after { content: ''; display: block; width: 50px; height: 3px; background: var(--primary-teal); margin: 8px auto 0; border-radius: 2px; }
|
||||
h3 { color: var(--primary-teal); margin-top: 30px; }
|
||||
|
||||
.info-box { background-color: var(--bg-light); padding: 25px; border-radius: 8px; border-left: 5px solid var(--primary-teal); line-height: 1.6; max-width: 1000px; margin: 0 auto; }
|
||||
|
||||
/* Pravidla */
|
||||
.voting-rules { line-height: 1.7; margin-bottom: 30px; font-size: 15px; }
|
||||
.voting-rules li { margin-bottom: 12px; }
|
||||
.voting-rules.mistakes li { color: #a72828; }
|
||||
.voting-rules.mistakes strong { color: #dc3545; }
|
||||
|
||||
/* Simulátor a křížky */
|
||||
.sim-wrap { margin-top: 40px; }
|
||||
.sim-grid { display: flex; gap: 15px; margin-top: 20px; }
|
||||
@media (max-width: 768px) { .sim-grid { flex-direction: column; } }
|
||||
|
||||
.party-col { flex: 1; border: 1px solid #b8d8d8; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
|
||||
.party-header { background: var(--bg-light); padding: 15px 12px; font-weight: bold; border-bottom: 3px solid var(--primary-teal); display: flex; align-items: center; gap: 12px; }
|
||||
|
||||
.candidate-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-bottom: 1px solid #f0f0f0; font-size: 14px; transition: background 0.3s; }
|
||||
|
||||
.big-cross, .small-cross {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
background-color: #fff;
|
||||
border: 2px solid #b8d8d8;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.big-cross { width: 26px; height: 26px; }
|
||||
.small-cross { width: 20px; height: 20px; }
|
||||
|
||||
.big-cross:hover, .small-cross:hover { border-color: var(--primary-teal); }
|
||||
|
||||
.big-cross:checked, .small-cross:checked {
|
||||
border-color: var(--primary-dark);
|
||||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%232c3e50" stroke-width="4" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>');
|
||||
background-size: 80%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.candidate-row.gets-vote { background-color: #d4edda; border-left: 4px solid #28a745; }
|
||||
.candidate-row.wasted-cross:not(.gets-vote) { background-color: #fff3cd; border-left: 4px solid #ffc107; color: #856404; text-decoration: line-through;}
|
||||
.candidate-row.gets-vote.wasted-cross { background: repeating-linear-gradient(45deg, #d4edda, #d4edda 10px, #e8f5e9 10px, #e8f5e9 20px); border-left: 4px solid #28a745; }
|
||||
|
||||
.sim-result { margin-top: 25px; padding: 20px; border-radius: 8px; text-align: center; border: 2px solid #ccc; background: #f9f9f9; }
|
||||
.sim-result.valid { border-color: #28a745; background: #e8f5e9; }
|
||||
.sim-result.invalid { border-color: #dc3545; background: #fbeee8; }
|
||||
.sim-result.neutral { border-color: var(--primary-teal); background: var(--bg-light); }
|
||||
#sim-status { font-weight: bold; font-size: 22px; margin-bottom: 8px; }
|
||||
#sim-text { font-size: 15px; line-height: 1.5; }
|
||||
|
||||
.legend { display: flex; gap: 15px; margin-top: 15px; font-size: 13px; justify-content: center; flex-wrap: wrap; }
|
||||
.legend-item { display: flex; align-items: center; gap: 6px; }
|
||||
.legend-box { width: 16px; height: 16px; border-radius: 3px; }
|
||||
.lb-green { background: #d4edda; border: 1px solid #28a745; }
|
||||
.lb-yellow { background: #fff3cd; border: 1px solid #ffc107; }
|
||||
.lb-striped { background: repeating-linear-gradient(45deg, #d4edda, #d4edda 5px, #e8f5e9 5px, #e8f5e9 10px); border: 1px solid #28a745; }
|
||||
|
||||
.cand-details { display: flex; flex-direction: column; cursor: pointer; line-height: 1.3; }
|
||||
.cand-name { font-weight: 600; font-size: 15px; color: var(--primary-dark); }
|
||||
.cand-role { font-size: 13px; color: #666; margin-top: 2px; }
|
||||
.candidate-row label { flex-grow: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="navbar">
|
||||
<div class="navbar-container">
|
||||
<nav>
|
||||
<a href="jakvolit.php">Jak volit</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- SEKC 3: JAK VOLIT -->
|
||||
<section id="jak-volit">
|
||||
<h2>Jak správně volit?</h2>
|
||||
|
||||
<h3>3 možné způsoby, jak vyplnit volební lístek:</h3>
|
||||
<ul class="voting-rules">
|
||||
<li><strong>1. Velký kříž jedné straně:</strong> Uděláte jeden velký křížek v rámečku u názvu zvolené strany. Hlas tak dáváte prvním <?php echo $maxVotes; ?> kandidátům této strany (odshora dolů).</li>
|
||||
<li><strong>2. Křížky jednotlivcům:</strong> Křížkem označíte konkrétní kandidáty napříč všemi stranami. Zaškrtnout můžete maximálně <?php echo $maxVotes; ?> osob.</li>
|
||||
<li><strong>3. Kombinace (tzv. panašování):</strong> Uděláte velký kříž jedné straně a zároveň malé křížky kandidátům z <em>jiných</em> stran. Nejdříve se započítají hlasy zakřížkovaným jednotlivcům. Zbylé hlasy do počtu <?php echo $maxVotes; ?> pak připadnou kandidátům strany s velkým křížem (opět v pořadí odshora dolů).</li>
|
||||
</ul>
|
||||
|
||||
<h3>Nejčastější omyly, kterým se vyhnout:</h3>
|
||||
<ul class="voting-rules mistakes">
|
||||
<li><strong>Více velkých křížů:</strong> Pokud zaškrtnete velkým křížem více než jednu stranu, je celý lístek <strong>neplatný</strong>.</li>
|
||||
<li><strong>Příliš mnoho malých křížků:</strong> Pokud zakřížkujete více než <?php echo $maxVotes; ?> kandidátů, je lístek <strong>neplatný</strong>.</li>
|
||||
<li><strong>Zbytečné křížky (Kříž straně + křížky jejím kandidátům):</strong> Pokud dáte velký kříž straně a zároveň uděláte malé křížky u kandidátů <em>této stejné strany</em>, zákon tyto malé křížky zcela ignoruje. Strana zkrátka dostane hlasy postupně od shora, preferovat konkrétního kandidáta ve vlastní zakřížkované straně nelze.</li>
|
||||
</ul>
|
||||
|
||||
<!-- INTERAKTIVNÍ SIMULÁTOR -->
|
||||
<div class="sim-wrap">
|
||||
<h2 style="margin-top: 50px;">Simulátor volebního lístku nanečisto</h2>
|
||||
<div class="info-box">
|
||||
Do obecního zastupitelstva se volí <strong><?php echo $maxVotes; ?></strong> kandidátů a každý volič má tedy <strong><?php echo $maxVotes; ?></strong> hlasů, které může rozdělit dle následujícího. Pro označení ve volebním lístku použijte křížek.
|
||||
</div>
|
||||
|
||||
<div class="sim-grid">
|
||||
<div class="party-col">
|
||||
<div class="party-header">
|
||||
<input type="checkbox" class="big-cross" data-party="0" id="p0">
|
||||
<label for="p0">Společně pro Přišimasy</label>
|
||||
</div>
|
||||
<div class="candidate-list">
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_1"><label for="c0_1" class="cand-details"><span class="cand-name">1. Ing.arch. Naděžda Čermáková</span><span class="cand-role">podnikatelka, 34 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_2"><label for="c0_2" class="cand-details"><span class="cand-name">2. Jaroslav Havlín</span><span class="cand-role">projektový manažer,technik, 41 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_3"><label for="c0_3" class="cand-details"><span class="cand-name">3. Martin Foltýnek</span><span class="cand-role">podnikatel, 47 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_4"><label for="c0_4" class="cand-details"><span class="cand-name">4. Ondřej Šmejkal</span><span class="cand-role">zámečník,mechanik, 25 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_5"><label for="c0_5" class="cand-details"><span class="cand-name">5. Jan Formánek</span><span class="cand-role">expedient, 41 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_6"><label for="c0_6" class="cand-details"><span class="cand-name">6. Ing. Libor Kusák</span><span class="cand-role">obchodní manažer, 52 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_7"><label for="c0_7" class="cand-details"><span class="cand-name">7. Mgr. Ludmila Klejchová</span><span class="cand-role">učitelka, 46 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_8"><label for="c0_8" class="cand-details"><span class="cand-name">8. Rostislav Chalupský</span><span class="cand-role">IT technik, 34 let</span></label></div>
|
||||
<div class="candidate-row" data-party="0"><input type="checkbox" class="small-cross" id="c0_9"><label for="c0_9" class="cand-details"><span class="cand-name">9. Tomáš Jelen</span><span class="cand-role">řidič, 53 let</span></label></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- === DRUHÁ STRANA (Pravý sloupec) === -->
|
||||
<div class="party-col">
|
||||
<div class="party-header">
|
||||
<input type="checkbox" class="big-cross" data-party="1" id="p1">
|
||||
<label for="p1">Pro obnovu a rozvoj Přišimas</label>
|
||||
</div>
|
||||
<div class="candidate-list">
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_1"><label for="c1_1" class="cand-details"><span class="cand-name">1. Bc. Šárka Rumanová</span><span class="cand-role">starostka obce, 52 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_2"><label for="c1_2" class="cand-details"><span class="cand-name">2. Ing. Jiří Procházka</span><span class="cand-role">produktový manažer, 47 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_3"><label for="c1_3" class="cand-details"><span class="cand-name">3. Michal Strnad</span><span class="cand-role">podnikatel,místostarosta obce, 47 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_4"><label for="c1_4" class="cand-details"><span class="cand-name">4. Radek Studničný</span><span class="cand-role">underwriter specialista,místostarosta obce, 49 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_5"><label for="c1_5" class="cand-details"><span class="cand-name">5. PhDr. Václav Červenka</span><span class="cand-role">psycholog, 47 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_6"><label for="c1_6" class="cand-details"><span class="cand-name">6. Stanislava Řádková</span><span class="cand-role">důchodkyně, 67 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_7"><label for="c1_7" class="cand-details"><span class="cand-name">7. Jakub Macháček</span><span class="cand-role">podnikatel, 39 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_8"><label for="c1_8" class="cand-details"><span class="cand-name">8. Libor Syrový</span><span class="cand-role">lakýrník, 47 let</span></label></div>
|
||||
<div class="candidate-row" data-party="1"><input type="checkbox" class="small-cross" id="c1_9"><label for="c1_9" class="cand-details"><span class="cand-name">9. Roman Frank</span><span class="cand-role">stavební technik, 33 let</span></label></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Výsledkový box simulátoru -->
|
||||
<div class="sim-result neutral" id="sim-result-box">
|
||||
<div id="sim-status">Prázdný lístek</div>
|
||||
<div id="sim-text">Zkuste zaškrtnout stranu nebo kandidáty.</div>
|
||||
</div>
|
||||
|
||||
<!-- Legenda barev -->
|
||||
<div class="legend">
|
||||
<div class="legend-item"><div class="legend-box lb-green"></div> Kandidát získá Váš hlas</div>
|
||||
<div class="legend-item"><div class="legend-box lb-striped"></div> Kandidát získá hlas (díky velkému kříži, váš malý se ignoruje)</div>
|
||||
<div class="legend-item"><div class="legend-box lb-yellow"></div> Kandidát hlas <strong>nezíská</strong> (zákon zbytečný křížek škrtne)</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const MAX_VOTES = <?php echo isset($maxVotes) ?$maxVotes : 9; ?>;
|
||||
|
||||
function updateSimulator() {
|
||||
try {
|
||||
const bigCrosses = document.querySelectorAll('.big-cross:checked');
|
||||
const smallCrosses = document.querySelectorAll('.small-cross:checked');
|
||||
|
||||
const resultBox = document.getElementById('sim-result-box');
|
||||
const resultStatus = document.getElementById('sim-status');
|
||||
const resultText = document.getElementById('sim-text');
|
||||
|
||||
if (!resultBox || !resultStatus || !resultText) return;
|
||||
|
||||
document.querySelectorAll('.candidate-row').forEach(row => {
|
||||
row.classList.remove('gets-vote', 'wasted-cross');
|
||||
});
|
||||
|
||||
let activeBigCross = bigCrosses.length === 1 ? bigCrosses[0].dataset.party : null;
|
||||
|
||||
let crossData = Array.from(smallCrosses).map(cb => {
|
||||
let row = cb.closest('.candidate-row');
|
||||
if (!row) return null;
|
||||
return { party: row.dataset.party, el: row };
|
||||
}).filter(item => item !== null);
|
||||
|
||||
if (bigCrosses.length > 1) {
|
||||
resultBox.className = 'sim-result invalid';
|
||||
resultStatus.innerText = 'Neplatný lístek!';
|
||||
resultText.innerText = 'Zaškrtli jste velký kříž u více než jedné volební strany. Váš hlas zcela propadá.';
|
||||
} else if (!activeBigCross) {
|
||||
if (crossData.length > MAX_VOTES) {
|
||||
resultBox.className = 'sim-result invalid';
|
||||
resultStatus.innerText = 'Neplatný lístek!';
|
||||
resultText.innerText = `Zaškrtli jste příliš mnoho kandidátů (${crossData.length} z ${MAX_VOTES}). Hlas propadá.`;
|
||||
} else {
|
||||
resultBox.className = 'sim-result ' + (crossData.length > 0 ? 'valid' : 'neutral');
|
||||
resultStatus.innerText = crossData.length === 0 ? 'Prázdný lístek' : 'Platný lístek';
|
||||
resultText.innerText = `Rozdělili jste ${crossData.length} z ${MAX_VOTES} hlasů. Zbývá Vám ${MAX_VOTES - crossData.length} nevyužitých.`;
|
||||
crossData.forEach(c => c.el.classList.add('gets-vote'));
|
||||
}
|
||||
} else {
|
||||
let otherParties = crossData.filter(c => c.party !== activeBigCross);
|
||||
let sameParty = crossData.filter(c => c.party === activeBigCross);
|
||||
|
||||
if (otherParties.length > MAX_VOTES) {
|
||||
resultBox.className = 'sim-result invalid';
|
||||
resultStatus.innerText = 'Neplatný lístek!';
|
||||
resultText.innerText = `Zaškrtli jste příliš mnoho kandidátů u jiných stran (${otherParties.length} z ${MAX_VOTES}).`;
|
||||
} else {
|
||||
resultBox.className = 'sim-result valid';
|
||||
let remaining = MAX_VOTES - otherParties.length;
|
||||
|
||||
if (otherParties.length === 0) {
|
||||
resultStatus.innerText = 'Platný lístek (Velký kříž)';
|
||||
resultText.innerText = `Všech ${remaining} hlasů připadlo straně s velkým křížem.`;
|
||||
} else {
|
||||
resultStatus.innerText = 'Platný lístek (Kombinace)';
|
||||
resultText.innerText = `Jiné strany dostaly ${otherParties.length} hlasů. Zbylých ${remaining} hlasů si bere strana s velkým křížem.`;
|
||||
}
|
||||
|
||||
otherParties.forEach(c => c.el.classList.add('gets-vote'));
|
||||
sameParty.forEach(c => c.el.classList.add('wasted-cross'));
|
||||
|
||||
let bigPartyRows = document.querySelectorAll(`.candidate-row[data-party="${activeBigCross}"]`);
|
||||
for (let i = 0; i < remaining; i++) {
|
||||
if (bigPartyRows[i]) bigPartyRows[i].classList.add('gets-vote');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("KRITICKÁ CHYBA SIMULÁTORU:", err);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('change', function(e) {
|
||||
if (e.target && (e.target.classList.contains('big-cross') || e.target.classList.contains('small-cross'))) {
|
||||
updateSimulator();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', updateSimulator);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user