cancionero-web/res/templates/preparar-misa.html

285 lines
9.2 KiB
HTML

<!DOCTYPE html>
<html lang="es">
<head>
{% include "head.html" with path=path title=title only %}
<link rel="stylesheet" type="text/css" href="{{ path|urlencode }}/index.css">
<link rel="stylesheet" type="text/css" href="{{ path|urlencode }}/song.css">
<script src="{{ path|urlencode }}/song.js"></script>
<style>
.hideControls .controls {
display: none;
}
.hidePreview .preview {
display: none;
}
#songlist > *,
.mainButtons input[type="button"],
.mainButtons button {
margin-bottom: .5em;
}
label.forCheckbox {
text-wrap: nowrap;
}
button.icon img {
width: 1em;
height: 0.9em;
pointer-events: none;
}
img.redFilter {
filter: invert(55%) sepia(67%) saturate(876%) hue-rotate(-40deg) brightness(90%) contrast(103%);
}
img.greenFilter {
filter: invert(61%) sepia(78%) saturate(626%) hue-rotate(43deg) brightness(70%) contrast(102%);
}
span.songSelector {
display: flex;
flex-wrap: nowrap;
column-gap: 0.3em;
}
input[type="button"].copy-success,
input[type="button"].copy-error {
color: white;
transition-duration: 0s;
}
input[type="button"].copy-success {
background-color: #4d9800;
}
input[type="button"].copy-error {
background-color: #e96857;
}
</style>
</head>
<body>
{% include "header.html" %}
<main>
<h1>Preparar una misa</h1>
<p>A continuación puedes crear una web con una lista de canciones y compartirla copiando el enlace.</p>
<p>
<label class="forCheckbox"><input class="init" id="controlsCheckbox" type="radio" name="mode" onchange="toggleControls(event)" checked> Modificar la lista</label>
<label class="forCheckbox"><input class="init" id="previewCheckbox" type="radio" name="mode" onchange="togglePreview(event)"> Ver las canciones</label>
<label class="forCheckbox"><input id="showChords" type="checkbox" checked onchange="showChords(this.checked)"/> Mostrar acordes</label>
</p>
<p class="controls mainButtons">
Añadir
<span class="buttonpair flex-reverse">
<button class="icon right pair-sub" title="Añadir una canción aleatoria" onclick="addRandomSong()">
aleatoria <img class="greenFilter" src="svg/random.svg"></button>
<button class="icon left pair-sup" title="Añadir una canción vacía" onclick="addSong()">
<img class="greenFilter" src="svg/new.svg"> una canción</button>
</span>
<br>
Añadir
<span class="buttonpair flex-reverse">
<button class="icon right pair-sub" title="Añade una canción aleatoria por categoría" onclick="addRandomSongs()">
aleatorias <img class="greenFilter" src="svg/random.svg"></button>
<button class="icon left pair-sup" title="Añade una canción por categoría" onclick="addFirstSongs()">
<img class="greenFilter" src="svg/new.svg"> varias canciones</button>
</span>
<br>
<button class="icon" onclick="clearSongs()"><img class="redFilter" src="svg/trash.svg"> Borrar todas</button>
</p>
<div id="songlist"></div>
<input type="button" onclick="shareLink(event)" value="Copiar enlace al cancionero">
{% if links %}<input type="button" onclick="sharePDF(event)" value="Crear un PDF ⤴">{% endif %}
<template id='songtemplate'>
<div><span class="controls songSelector"><select name="songs[]" required onchange="songSelect(event)">
<option value="">Selecciona una canción</option>{% for category, songs in categorized_songs %}
<optgroup label="&mdash; {{ category }}">{% for s in songs %}
<option value="{{ s.number }}">{{ s.number }}. {{ s.name }}</option>{% endfor %}
</optgroup>{% endfor %}
</select>
<button class="icon" title="Subir" onclick="songUp(event)"><img class="greenFilter" src="svg/up.svg"></button>
<button class="icon" title="Bajar" onclick="songDown(event)"><img class="greenFilter" src="svg/down.svg"></button>
<button class="icon" title="Quitar" onclick="songDelete(event)"><img class="redFilter" src="svg/trash.svg"></button>
</span>
<div class="preview"></div>
</div>
</template>
</main>
<script>
function addSong() {
let ol = document.getElementById("songlist");
let node = document.getElementById("songtemplate").content.firstElementChild.cloneNode(true);
ol.appendChild(node);
return node;
}
function songUp(event) {
const li = event.target.parentElement.parentElement;
const prev = li.previousElementSibling;
const ol = li.parentElement;
if (prev)
ol.insertBefore(li, prev);
}
function songDown(event) {
const li = event.target.parentElement.parentElement;
const next = li.nextElementSibling;
const after = next?.nextElementSibling;
const ol = li.parentElement;
if (after)
ol.insertBefore(li, after);
else if (next)
ol.appendChild(li);
}
function songDelete(event) {
const li = event.target.parentElement.parentElement;
const ol = li.parentElement;
ol.removeChild(li);
regenHash();
}
function songSelect(event) {
const option = event.target.selectedOptions[0];
const div = event.target.parentElement.parentElement.getElementsByClassName("preview")[0];
if (option.value) {
fetch("./{{ parts_dir }}/" + String(option.value).padStart(3, '0') + ".html")
.then(r => r.text())
.then(text => div.innerHTML = text);
} else {
div.innerHTML = "";
}
if (loadComplete) regenHash();
}
function regenHash() {
const list = getSongList();
if (list.length == 0)
history.replaceState(null, "", window.location.pathname + window.location.search);
else
history.replaceState(null, "", "#" + getSongList().join(","));
}
function clearSongs() {
const ol = document.getElementById("songlist");
ol.replaceChildren();
regenHash();
}
function selectRandomizeOptions(select, optionParent) {
const options = optionParent.getElementsByTagName("option");
do {
const i = Math.floor(Math.random() * options.length);
select.value = options[i].value;
} while (!select.value);
select.dispatchEvent(new Event("change"));
}
function addSpecificSong(n) {
const li = addSong();
const select = li.firstElementChild.firstElementChild;
select.value = n;
select.dispatchEvent(new Event("change"));
}
function addRandomSong() {
const li = addSong();
const select = li.firstElementChild.firstElementChild;
selectRandomizeOptions(select, select);
}
function addFirstSongs() {
addSongs(false);
}
function addRandomSongs() {
addSongs(true);
}
function addSongs(random) {
const li = addSong();
const groups = li.firstElementChild.firstElementChild.getElementsByTagName("optgroup");
for (let g of groups) {
const select = addSong().firstElementChild.firstElementChild;
if (random) {
selectRandomizeOptions(select, g);
} else {
select.value = g.firstElementChild.value;
select.dispatchEvent(new Event("change"));
}
}
li.parentElement.removeChild(li);
}
function getSongList() {
const ol = document.getElementById("songlist");
let res = [];
for (let li of ol.childNodes) {
let value = li.firstElementChild.firstElementChild.value;
if (value)
res.push(value);
}
return res;
}
function toggleControls(event) {
toggleMode(event.target.checked);
}
function togglePreview(event) {
toggleMode(!event.target.checked);
}
function toggleMode(controls) {
if (controls) {
document.body.classList.remove("hideControls");
document.body.classList.add("hidePreview");
} else {
document.body.classList.add("hideControls");
document.body.classList.remove("hidePreview");
}
}
function shareLink(event) {
const button = event.target;
const oldvalue = button.value;
button.style.width = button.offsetWidth + "px";
if (location.hash != "") {
navigator.clipboard.writeText(window.location.href)
.then(() => {
button.value = "¡Copiado!";
button.classList.add("copy-success");
}, () => {
button.value = "Error al copiar";
button.classList.add("copy-error");
});
} else {
button.value = "¡No hay canciones!";
button.classList.add("copy-error");
}
setTimeout(() => {
button.value = oldvalue;
button.classList.remove("copy-success", "copy-error");
button.style.width = '';
}, 2000);
}
function sharePDF(event) {
window.location.href = "https://cgj.es/cancionero-generador/" + window.location.hash;
}
var loadComplete = false;
window.addEventListener("load", function () {
for (let e of document.getElementsByClassName("init")) {
e.dispatchEvent(new Event("change"));
}
if (window.location.hash) {
// Load songs
for (let n of window.location.hash.slice(1).split(","))
addSpecificSong(n);
// Set default settings
let controls = document.getElementById("controlsCheckbox");
controls.checked = false;
controls.dispatchEvent(new Event("change"));
let preview = document.getElementById("previewCheckbox");
preview.checked = true;
preview.dispatchEvent(new Event("change"));
}
loadComplete = true;
});
</script>
{% include "footer.html" %}
</body>
</html>