Fix object-form breaking on repeat pjax visits, and stray autofill in game rename field
object_form.js declared top-level const bindings, which pjax replays verbatim on every visit — the second visit threw "already declared" and silently broke "Ajouter un champ"/"Créer l'objet". Wrapped it in an IIFE. Also renamed the generic name="name" rename-game field to name="game_name" with autocomplete off, since browsers were autofilling it with unrelated previously-typed values.
This commit is contained in:
@@ -7,7 +7,7 @@ from core.flask_app import app
|
|||||||
|
|
||||||
@app.route("/game/<slug>/rename", methods=["POST"])
|
@app.route("/game/<slug>/rename", methods=["POST"])
|
||||||
def game_rename(slug):
|
def game_rename(slug):
|
||||||
new_name = request.form.get("name", "").strip()
|
new_name = request.form.get("game_name", "").strip()
|
||||||
if new_name:
|
if new_name:
|
||||||
db.update_game_name(slug, new_name)
|
db.update_game_name(slug, new_name)
|
||||||
return redirect(url_for("game_dashboard", slug=slug))
|
return redirect(url_for("game_dashboard", slug=slug))
|
||||||
|
|||||||
+34
-27
@@ -3,36 +3,43 @@
|
|||||||
// uniquement quand le type choisi est "relation", et l'affichage des
|
// uniquement quand le type choisi est "relation", et l'affichage des
|
||||||
// bornes mini/maxi (2.2 — bornage automatique) uniquement pour un champ
|
// bornes mini/maxi (2.2 — bornage automatique) uniquement pour un champ
|
||||||
// numérique.
|
// numérique.
|
||||||
|
//
|
||||||
|
// Tout est enfermé dans une IIFE : cette page est chargée via pjax (voir
|
||||||
|
// pjax.js), qui rejoue ce script telle-quelle à chaque visite sans
|
||||||
|
// rechargement complet — une déclaration `const`/`let` au premier niveau
|
||||||
|
// ferait planter la deuxième exécution ("already declared") et bloquerait
|
||||||
|
// silencieusement "Ajouter un champ"/"Créer l'objet" dès la deuxième visite
|
||||||
|
// de cette page dans une même session.
|
||||||
|
(function () {
|
||||||
|
var fieldsList = document.getElementById('fieldsList');
|
||||||
|
var template = document.getElementById('fieldRowTemplate');
|
||||||
|
var btnAddField = document.getElementById('btnAddField');
|
||||||
|
var NUMERIC_FIELD_TYPES = ['nombre_entier', 'nombre_decimal'];
|
||||||
|
|
||||||
const fieldsList = document.getElementById('fieldsList');
|
function wireRow(row) {
|
||||||
const template = document.getElementById('fieldRowTemplate');
|
var typeSelect = row.querySelector('.fieldTypeSelect');
|
||||||
const btnAddField = document.getElementById('btnAddField');
|
var relationWrap = row.querySelector('.relationTarget');
|
||||||
const NUMERIC_FIELD_TYPES = ['nombre_entier', 'nombre_decimal'];
|
var boundsWrap = row.querySelector('.boundsTarget');
|
||||||
|
function syncFieldTypeVisibility() {
|
||||||
|
relationWrap.style.display = typeSelect.value === 'relation' ? 'block' : 'none';
|
||||||
|
if (boundsWrap) boundsWrap.style.display = NUMERIC_FIELD_TYPES.includes(typeSelect.value) ? 'flex' : 'none';
|
||||||
|
}
|
||||||
|
typeSelect.addEventListener('change', syncFieldTypeVisibility);
|
||||||
|
syncFieldTypeVisibility();
|
||||||
|
|
||||||
function wireRow(row) {
|
row.querySelector('.btnRemoveField').addEventListener('click', function () {
|
||||||
const typeSelect = row.querySelector('.fieldTypeSelect');
|
row.remove();
|
||||||
const relationWrap = row.querySelector('.relationTarget');
|
});
|
||||||
const boundsWrap = row.querySelector('.boundsTarget');
|
|
||||||
function syncFieldTypeVisibility() {
|
|
||||||
relationWrap.style.display = typeSelect.value === 'relation' ? 'block' : 'none';
|
|
||||||
if (boundsWrap) boundsWrap.style.display = NUMERIC_FIELD_TYPES.includes(typeSelect.value) ? 'flex' : 'none';
|
|
||||||
}
|
}
|
||||||
typeSelect.addEventListener('change', syncFieldTypeVisibility);
|
|
||||||
syncFieldTypeVisibility();
|
|
||||||
|
|
||||||
row.querySelector('.btnRemoveField').addEventListener('click', () => {
|
function addFieldRow() {
|
||||||
row.remove();
|
var clone = template.content.cloneNode(true);
|
||||||
});
|
fieldsList.appendChild(clone);
|
||||||
}
|
wireRow(fieldsList.lastElementChild);
|
||||||
|
}
|
||||||
|
|
||||||
function addFieldRow() {
|
btnAddField.addEventListener('click', addFieldRow);
|
||||||
const clone = template.content.cloneNode(true);
|
|
||||||
const row = clone.querySelector('.fieldRowCard');
|
|
||||||
fieldsList.appendChild(clone);
|
|
||||||
wireRow(fieldsList.lastElementChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
btnAddField.addEventListener('click', addFieldRow);
|
// Toujours démarrer avec un premier champ prêt à remplir.
|
||||||
|
addFieldRow();
|
||||||
// Toujours démarrer avec un premier champ prêt à remplir.
|
})();
|
||||||
addFieldRow();
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
<form method="post" action="{{ url_for('game_rename', slug=game.slug) }}" class="fieldRow" style="align-items:flex-end;">
|
<form method="post" action="{{ url_for('game_rename', slug=game.slug) }}" class="fieldRow" style="align-items:flex-end;">
|
||||||
<div>
|
<div>
|
||||||
<label for="rename">Renommer le jeu</label>
|
<label for="rename">Renommer le jeu</label>
|
||||||
<input type="text" id="rename" name="name" value="{{ game.name }}" required>
|
<input type="text" id="rename" name="game_name" value="{{ game.name }}" required autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Renommer</button>
|
<button type="submit">Renommer</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in New Issue
Block a user