hash functionality and styling for generador

This commit is contained in:
Carlos Galindo 2026-01-23 20:49:33 +01:00
commit e81f07ac08
2 changed files with 105 additions and 20 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
public/ public/
audios/ audios/
songs.dat songs.dat
generador_public/

View file

@ -4,19 +4,19 @@
<title>Generador de cancioneros</title> <title>Generador de cancioneros</title>
<meta charset='utf-8' /> <meta charset='utf-8' />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="https://canciones.sanleandrovalencia.es/favicon.svg"/>
<link rel="stylesheet" type="text/css" href="https://canciones.sanleandrovalencia.es/main.css"/>
<link rel="stylesheet" type="text/css" href="https://canciones.sanleandrovalencia.es/index.css">
<link rel="stylesheet" type="text/css" href="https://canciones.sanleandrovalencia.es/song.css">
<style> <style>
.chorded .hideChorded { button.external,
display: none;
}
.lyrics .hideLyrics {
display: none;
}
a.external { a.external {
background-image: url(img/link-external.svg); background-image: url(img/link-external.svg);
background-position: center right; background-size: 0.9em;
padding-right: 1.8em;
background-position-x: 96%;
background-position-y: center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 0.857em;
padding-right: 1em;
} }
a { a {
color: #36c; color: #36c;
@ -24,6 +24,30 @@ a {
a:hover { a:hover {
color: #3056a9; color: #3056a9;
} }
#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;
}
</style> </style>
</head> </head>
<body> <body>
@ -39,9 +63,6 @@ a:hover {
<legend>Propiedades de página</legend> <legend>Propiedades de página</legend>
<p class="hideChorded"> <p class="hideChorded">
Tamaño del papel: Tamaño del papel:
<label><input class="lyricsonly" type="number" size="4" name="paperheight" id="paperheight" required>&nbsp;mm (alto)</label> &times;
<label><input class="lyricsonly" type="number" size="4" name="paperwidth" id="paperwidth" required>&nbsp;mm (ancho)</label>
<strong>o</strong> elige un tamaño estándar
<select class="lyricsonly" onchange="setPaperSize(event)"> <select class="lyricsonly" onchange="setPaperSize(event)">
<option value=""></option> <option value=""></option>
<option value="paperheight=297,paperwidth=210">A4 (vertical)</option> <option value="paperheight=297,paperwidth=210">A4 (vertical)</option>
@ -50,6 +71,10 @@ a:hover {
<option value="paperheight=148,paperwidth=210">A5 (horizontal)</option> <option value="paperheight=148,paperwidth=210">A5 (horizontal)</option>
<option value="paperheight=210,paperwidth=99">Cancionero San Leandro</option> <option value="paperheight=210,paperwidth=99">Cancionero San Leandro</option>
</select> </select>
<strong>o</strong>
elige tú
<label><input class="lyricsonly" type="number" size="4" name="paperheight" id="paperheight" required>&nbsp;mm (alto)</label> &times;
<label><input class="lyricsonly" type="number" size="4" name="paperwidth" id="paperwidth" required>&nbsp;mm (ancho)</label>
</p><p> </p><p>
Columnas: <label> Columnas: <label>
<input type="checkbox" name="ifcolumns" value="true" checked onclick="toggleCols(event)">&nbsp;Habilitar</label> | <label><input type="number" name="columns" id="columns" value="2" size="3" min="1" max="10" required> columnas</label> <input type="checkbox" name="ifcolumns" value="true" checked onclick="toggleCols(event)">&nbsp;Habilitar</label> | <label><input type="number" name="columns" id="columns" value="2" size="3" min="1" max="10" required> columnas</label>
@ -84,12 +109,24 @@ a:hover {
<label>Título del cancionero: <input type="text" name="title" size="40" value="Cancionero" required></label> <label>Título del cancionero: <input type="text" name="title" size="40" value="Cancionero" required></label>
</p> </p>
<h2>Lista de canciones</h2> <h2>Lista de canciones</h2>
<p> <p class="controls mainButtons">
<input type="button" value="Borrar todas" onclick="clearSongs()"> Añadir
<input type="button" value="Añadir canción" onclick="addSong()"> <span class="buttonpair flex-reverse">
<input type="button" value="Añadir canción aleatoria" onclick="addRandomSong()"> <button type="button" class="icon right pair-sub" title="Añadir una canción aleatoria" onclick="addRandomSong()">
<input type="button" value="Añadir la primera canción de cada sección" onclick="addFirstSongs()"> aleatoria <img class="greenFilter" src="https://canciones.sanleandrovalencia.es/svg/random.svg"></button>
<input type="button" value="Añadir una canción por sección (aleatorias)" onclick="addRandomSongs()"> <button type="button" class="icon left pair-sup" title="Añadir una canción vacía" onclick="addSong()">
<img class="greenFilter" src="https://canciones.sanleandrovalencia.es/svg/new.svg"> una canción</button>
</span>
<br>
Añadir
<span class="buttonpair flex-reverse">
<button type="button" class="icon right pair-sub" title="Añade una canción aleatoria por categoría" onclick="addRandomSongs()">
aleatorias <img class="greenFilter" src="https://canciones.sanleandrovalencia.es/svg/random.svg"></button>
<button type="button" class="icon left pair-sup" title="Añade una canción por categoría" onclick="addFirstSongs()">
<img class="greenFilter" src="https://canciones.sanleandrovalencia.es/svg/new.svg"> varias canciones</button>
</span>
<br>
<button type="button" class="icon" onclick="clearSongs()"><img class="redFilter" src="https://canciones.sanleandrovalencia.es/svg/trash.svg"> Borrar todas</button>
</p> </p>
<ol id='songlist'></ol> <ol id='songlist'></ol>
<template id='songtemplate'> <template id='songtemplate'>
@ -107,11 +144,16 @@ a:hover {
</template> </template>
<h2>Generar el cancionero</h2> <h2>Generar el cancionero</h2>
<p> <p>
<input type="submit" value="Generar cancionero en PDF"> <button type="submit">Generar cancionero en PDF</button>
<input type="reset" value="Restablecer formulario"> <button type="button" class="external" onclick="goToSongWebsite(event)">Web con lista de canciones</button>
<button type="reset">Restablecer formulario</button>
</p> </p>
</form> </form>
<script> <script>
function goToSongWebsite() {
window.navigation.navigate("https://canciones.sanleandrovalencia.es/preparar-misa.html" + window.location.hash);
}
function addSong() { function addSong() {
let ol = document.getElementById("songlist"); let ol = document.getElementById("songlist");
let node = document.getElementById("songtemplate").content.firstElementChild.cloneNode(true); let node = document.getElementById("songtemplate").content.firstElementChild.cloneNode(true);
@ -142,6 +184,7 @@ function songDelete(event) {
const li = event.target.parentElement; const li = event.target.parentElement;
const ol = li.parentElement; const ol = li.parentElement;
ol.removeChild(li); ol.removeChild(li);
regenHash();
} }
function clearSongs() { function clearSongs() {
@ -158,6 +201,17 @@ function selectRandomizeOptions(select, optionParent) {
select.dispatchEvent(new Event("change")); select.dispatchEvent(new Event("change"));
} }
function addSpecificSong(n) {
const li = addSong();
const select = li.firstElementChild;
for (let opt of select.options) {
if (opt.textContent.slice(0, opt.textContent.indexOf(".")) == n) {
select.value = opt.value;
break;
}
}
}
function addRandomSong() { function addRandomSong() {
const li = addSong(); const li = addSong();
const select = li.firstElementChild; const select = li.firstElementChild;
@ -187,6 +241,27 @@ function addSongs(random) {
li.parentElement.removeChild(li); li.parentElement.removeChild(li);
} }
function getSongList() {
const ol = document.getElementById("songlist");
let res = [];
for (let li of ol.childNodes) {
let opt = li.firstElementChild.selectedOptions[0];
if (opt.value) {
let num = opt.textContent.substring(0, opt.textContent.indexOf('.'));
res.push(num);
}
}
return res;
}
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 setChorded(event) { function setChorded(event) {
const radio = event.target; const radio = event.target;
const chorded = radio.checked && radio.value === "true"; const chorded = radio.checked && radio.value === "true";
@ -232,6 +307,7 @@ function setSong(event) {
a.href = "" a.href = ""
a.classList = []; a.classList = [];
} }
regenHash();
} }
function toggleCols(event) { function toggleCols(event) {
@ -253,6 +329,14 @@ function toggleColSep(event) {
colsep.value = ""; colsep.value = "";
colsep.disabled = !input.checked; colsep.disabled = !input.checked;
} }
window.addEventListener("load", function () {
if (window.location.hash) {
// Load songs
for (let n of window.location.hash.slice(1).split(","))
addSpecificSong(n);
}
});
</script> </script>
</body> </body>
</html> </html>