Inscrption

 »,
‘initial’ => ’20’,
‘city’ =>  », // ex: Royan (facultatif)
], $atts, ‘inscription_concours’);

$email = is_email(trim($atts[’email’])) ? trim($atts[’email’]) :  »;
$initial = max(0, intval($atts[‘initial’]));
if ($initial === 0) { $initial = 20; }
$pref_city = sanitize_text_field($atts[‘city’]);

// — Données
$cities = [
‘Loudéac’,
‘Lampertheim’,
‘Royan’,
‘Château-Gontier’,
‘Lannemezan’,
‘Réquista’,
‘Crêches-sur-Saône’,
‘Mouans-Sartoux’,
‘Noyon’,
];
$categories = [«  », « A », « P », « OP », « S », « OB », « B », « AS », « G », « T », « SX »];

// — Marqueurs uniques (si plusieurs shortcodes sur la même page)
$uid = uniqid(‘fc_’, false);

ob_start();
?>
<div id=" » class= »fc-inscription » style= »margin:16px 0″
data-initial= » »>
<form action=" » method= »POST »
onsubmit= » »>

#, # * { box-sizing: border-box; }
# .bloc{border:1px solid #e5e7eb;border-radius:10px;padding:12px;margin-bottom:12px;background:#fff}
# h3{margin:0 0 8px 0;font:600 15px/1.2 system-ui}
# label{display:block;font:500 12px/1.2 system-ui;color:#6b7280;margin:6px 0 4px}
# input,# select{width:100%;padding:6px 8px;border:1px solid #e5e7eb;border-radius:8px;font:13px/1.25 system-ui}
# .grid{display:grid;gap:10px}
# .g2{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
@media (max-width:800px){ # .g2{grid-template-columns:1fr} }
# .table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid #e5e7eb;border-radius:10px}
# table{width:100%;min-width:980px;border-collapse:separate;border-spacing:0;table-layout:fixed}
# thead th{position:sticky;top:0;z-index:1;background:#f8fafc;text-align:left;padding:10px 8px;font:600 12px system-ui;border-bottom:1px solid #e5e7eb;white-space:nowrap}
# tbody td{border-bottom:1px solid #f1f5f9;padding:6px 4px;vertical-align:middle}
# tbody tr:last-child td{border-bottom:none}
# .num{width:40px;text-align:center;color:#6b7280;font-variant-numeric:tabular-nums;font-size:12px}
# col.num{width:44px}
# col.nom{width:200px}
# col.prenom{width:160px}
# col.sexe{width:80px}
# col.categorie{width:160px}
# col.morceau{width:auto}
# .actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:12px}
# button{cursor:pointer;padding:10px 14px;border-radius:10px;border:1px solid #e5e7eb;background:#eff6ff;font:600 14px;color:#1d4ed8}
# .secondary{background:#fff;color:#111827}
@media print{
# .actions{display:none}
# .table-wrap{overflow:visible;border:none}
# table{min-width:100%}
# thead th{background:#eee !important;-webkit-print-color-adjust:exact;print-color-adjust:exact}
}

Informations concours

<label for="_ville »>Ville (Concours à)
<select id="_ville » name= »ville » required>

<option >

Professeur

<label for="_prof_nom »>Nom
<input id="_prof_nom » name= »prof_nom » type= »text » required>
<label for="_prof_prenom »>Prénom
<input id="_prof_prenom » name= »prof_prenom » type= »text » required>

<label for="_adresse »>Adresse
<input id="_adresse » name= »adresse » type= »text » placeholder= »Rue, CP, Ville »>
<label for="_mail »>Mail
<input id="_mail » name= »mail » type= »email » placeholder= »exemple@domaine.fr » required>

Nom des élèves (en MAJUSCULES)

# NOM PRÉNOM M/F CATÉGORIE * MORCEAU IMPOSÉ
Légende : A (Accordéon), P (Piano), OP (Orgue Piano), S (Synthé), OB (Orgue Boutons), B (Batterie), AS (Accordéon Sup.), G (Guitare), T (Trompette), SX (Saxophone)
+ Ajouter une ligne
Réinitialiser
Envoyer l’inscription

<?php

// Enregistre les données pour le JS en pied de page
// (plus fiable que d'injecter dans le contenu)
$store = [
‘uid’ => $uid,
‘initial’ => $initial,
‘categories’ => $categories,
];
// Empile les instances (si plusieurs shortcodes sur la page)
$instances = (array) wp_cache_get(‘fc_instances’, ‘inscription_concours’);
$instances[] = $store;
wp_cache_set(‘fc_instances’, $instances, ‘inscription_concours’);

return ob_get_clean();
});
});

// Script en pied de page pour initialiser tous les formulaires présents
add_action(‘wp_footer’, function () {
$instances = (array) wp_cache_get(‘fc_instances’, ‘inscription_concours’);
if (empty($instances)) { return; }

// On imprime une seule fois le script + on passe les instances en JSON.
?>

(function(){
var instances = ;
if (!Array.isArray(instances)) return;

function buildRow(tbody, idx, categories){
var tr = document.createElement(‘tr’);

var tdNum = document.createElement(‘td’);
tdNum.className = ‘num’; tdNum.textContent = idx;
tr.appendChild(tdNum);

var tdNom = document.createElement(‘td’);
var nom = document.createElement(‘input’);
nom.type = ‘text’; nom.name = ‘eleves[‘+idx+’][nom]’; nom.placeholder = ‘NOM’; nom.style.textTransform=’uppercase’;
tdNom.appendChild(nom); tr.appendChild(tdNom);

var tdPrenom = document.createElement(‘td’);
var prenom = document.createElement(‘input’);
prenom.type = ‘text’; prenom.name = ‘eleves[‘+idx+’][prenom]’;
tdPrenom.appendChild(prenom); tr.appendChild(tdPrenom);

var tdSexe = document.createElement(‘td’);
var sexe = document.createElement(‘select’);
sexe.name = ‘eleves[‘+idx+’][sexe]’;
[ », ‘M’, ‘F’].forEach(function(v){ var o=document.createElement(‘option’); o.value=v; o.textContent=v; sexe.appendChild(o); });
tdSexe.appendChild(sexe); tr.appendChild(tdSexe);

var tdCat = document.createElement(‘td’);
var cat = document.createElement(‘select’);
cat.name = ‘eleves[‘+idx+’][categorie]’;
categories.forEach(function(v){ var o=document.createElement(‘option’); o.value=v; o.textContent=v; cat.appendChild(o); });
tdCat.appendChild(cat); tr.appendChild(tdCat);

var tdMorceau = document.createElement(‘td’);
var morceau = document.createElement(‘input’);
morceau.type = ‘text’; morceau.name = ‘eleves[‘+idx+’][morceau]’; morceau.placeholder = ‘Titre du morceau imposé’;
tdMorceau.appendChild(morceau); tr.appendChild(tdMorceau);

tbody.appendChild(tr);
}

function initOne(inst){
var root = document.getElementById(inst.uid);
if (!root || root.dataset.initialized === ‘1’) return;
var tbody = root.querySelector(‘.fc-eleves’);
var addBtn = root.querySelector(‘.fc-add’);
if (!tbody || !addBtn) return;

var count = 0;
function addRow(){ count += 1; buildRow(tbody, count, inst.categories || []); }

for (var k=0; k<(inst.initial || 20); k++) addRow();
addBtn.addEventListener('click', addRow, false);

root.dataset.initialized = '1';
}

// DOM prêt
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function(){ instances.forEach(initOne); });
} else {
instances.forEach(initOne);
}
})();

<?php
}, 100);