Browse Source

Ajoute une option `onglet` aux fieldsets pour les afficher sous forme d'onglet.

* Fonctionne quelque soit la position du fieldset et son niveau d'imbrication
* Fonctionne avec l'option pour activer les étapes
* Incompatible avec l'option `pliable`
pull/62/head
tcharlss 2 years ago
parent
commit
ee0fa72719
  1. 27
      css/formulaires_constructeur.css
  2. 55
      formulaires/construire_formulaire.html
  3. 9
      formulaires/construire_formulaire.php
  4. 128
      javascript/saisies.js
  5. 2
      lang/saisies_fr.php
  6. 45
      saisies.css.html
  7. 7
      saisies/fieldset.html
  8. 6
      saisies/fieldset.yaml
  9. 4
      saisies_pipelines.php

27
css/formulaires_constructeur.css

@ -40,33 +40,6 @@
margin: 1em -8px 0;
}
.formulaire_construire_formulaire .formulaire_configurer .formulaire_configurer-onglets {
overflow:auto;
}
.formulaire_construire_formulaire .formulaire_configurer .formulaire_configurer-onglets li{
float:left;
width:auto;
clear:none;
padding:0;
background:#eee;
border:1px solid #ddd;
margin-right:1px;
-moz-border-radius:5px 5px 0 0;
-webkit-border-radius:5px 5px 0 0;
-o-border-radius:5px 5px 0 0;
border-radius:5px 5px 0 0;
}
.formulaire_construire_formulaire .formulaire_configurer .formulaire_configurer-onglets li.actif{
background:white;
border-bottom:1px solid white;
}
.formulaire_construire_formulaire .formulaire_configurer .formulaire_configurer-onglets li.erreur a{
color:#CC3300;
}
.formulaire_construire_formulaire .formulaire_configurer .formulaire_configurer-onglets li a{
display:block;
padding:.5em;
}
.formulaire_construire_formulaire .formulaire_configurer .boutons { margin-bottom: -20px; }
.formulaire_construire_formulaire .editer.obligatoire .formulaire_configurer label {

55
formulaires/construire_formulaire.html

@ -85,58 +85,6 @@
<script type="text/javascript">
(function($){
function formulaire_configurer_onglets() {
var $formulaire_configurer = $('.formulaire_configurer');
var $onglets = $('<ul class="formulaire_configurer-onglets"></ul>');
var $contenus = $formulaire_configurer.find('> .editer-groupe > .fieldset');
// On ajoute le conteneur des onglets
$formulaire_configurer.prepend($onglets);
// On parcourt les contenus pour générer les onglets
$contenus.each(function(i){
// On ajoute un identifiant et une classe
$(this)
.attr('id', 'formulaire_configurer-contenu-'+i)
.addClass('formulaire_configurer-contenu');
// On récupère le titre (en le cachant au passage)
var titre = $(this).find('legend').eq(0).hide().text();
// On crée un onglet
var $onglet = $('<li><a href="#formulaire_configurer-contenu-'+i+'">'+titre+'</a></li>');
$onglet
.click(function(){
$contenus.hide();
$(
$(this)
.siblings()
.removeClass('actif')
.end()
.addClass('actif')
.find('a')
.attr('href')
).show();
return false;
});
// On active le premier onglet au démarrage
if (i == 0) {
$onglet.addClass('actif');
}
// S'il y a des erreurs dans cette partie du contenu, on met une classe "erreurs" à l'onglet aussi
if ($(this).find('.editer.erreur').length > 0) {
$onglet.addClass('erreur');
}
// On ajoute l'onglet
$onglets.append($onglet);
})
.hide()
.eq(0)
.show();
}
/* enlever les required */
$('.formulaire_#FORM .editer.obligatoire').find('input, textarea, select').each(function(){
if ($(this).prop('required')) {
@ -172,9 +120,6 @@
.end()
.end();
// On lance la création des onglets
formulaire_configurer_onglets();
// Gérer la liste des vérifications
$('.liste_verifications').each(function(){
var $options = $(this).siblings('.options_verifier').hide();

9
formulaires/construire_formulaire.php

@ -596,7 +596,7 @@ function construire_formulaire_generer_saisie_configurable($saisie, $env) {
'saisie' => 'fieldset',
'options' => array(
'nom' => "saisie_modifiee_${nom}[options][description]",
'label' => _T('saisies:option_groupe_description')
'label' => _T('saisies:option_groupe_description'),
),
'saisies' => array()
),
@ -620,6 +620,13 @@ function construire_formulaire_generer_saisie_configurable($saisie, $env) {
$chemin_description
);
// Fieldsets racines en onglets forcés
foreach ($formulaire_config as $k => $saisie_config) {
if ($saisie_config['saisie'] === 'fieldset') {
$formulaire_config[$k]['options']['onglet'] = 'oui';
}
}
$env2['saisies'] = $formulaire_config;
// Un test pour savoir si on prend le _request ou bien

128
javascript/saisies.js

@ -1,8 +1,16 @@
jQuery(function(){
saisies_fieldset_pliable();
saisies_fieldset_onglet();
onAjaxLoad(saisies_fieldset_pliable);
onAjaxLoad(saisies_fieldset_onglet);
});
/**
* Rend certains fieldsets pliables
*
* Il s'agit des fieldsets portant les classes "fieldset.pliable"
* Non cumulable avec les fieldsets en onglets.
*/
function saisies_fieldset_pliable(){
// On cherche les groupes de champs pliables
jQuery('.fieldset.pliable')
@ -36,6 +44,126 @@ function saisies_fieldset_pliable(){
});
};
/**
* Tranforme certains fieldsets en onglets
*
* Il s'agit des fieldsets portant les classes "fieldset.fieldset_onglet"
* Les onglets sont accessibles à l'exception de la navigation au clavier.
* Non cumulable avec les fieldsets pliables.
*
* Inspiré de https://van11y.net/fr/onglets-accessibles/
*/
function saisies_fieldset_onglet() {
// Classes utilisées pour le menu
var classes = {
tablist: 'menu-onglets',
tablist_item: 'menu-onglets__item',
tablist_link: 'menu-onglets__lien',
tabcontent: 'panneau-onglet',
active: 'actif',
error: 'erreur',
}
// Sélecteur pour les fieldsets à transformer en onglets
var selecteur_fieldset = '.fieldset.fieldset_onglet:not(.pliable)';
var index_onglet = 0;
var activer_onglet = function( $onglet ) {
$(
$onglet.children('a').addClass(classes.active).attr('aria-selected', true).removeAttr('tabindex').attr('href')
).show().removeAttr('hidden');
}
var desactiver_onglet = function( $onglet ) {
$(
$onglet.children('a').removeClass(classes.active).attr('aria-selected', false).attr('tabindex', -1).attr('href')
).hide().attr('hidden', '');
}
// @param object $fieldset *Un seul* fieldset
var ongletiser_fieldsets = function ( $fieldset ) {
var
$fieldsets = $fieldset.add($fieldset.siblings(selecteur_fieldset)), // fieldsets du même niveau
$menu = $('<ul class="'+classes.tablist+'" role="tablist" aria-label=""></ul>'),
has_menu = false;
$fieldsets.each(function(i) {
index_onglet++;
var $parent = $(this).parent('.editer-groupe');
var id_panneau = 'saisies-onglet-'+index_onglet+'-panneau';
var id_onglet = 'saisies-onglet-'+index_onglet;
// On ajoute le menu des onglets avant le parent du 1er fieldset
if (!has_menu) {
$menu.insertBefore($parent);
}
// On ajoute les attributs nécessaire : identifiant, classe, role et aria
// puis on le cache d'office et on le déplace au début de son parent
$(this)
.attr('id', id_panneau)
.addClass(classes.tabcontent)
.attr('role', 'tabpanel')
.attr('labelledby', id_onglet)
.hide().attr('hidden', '')
.prependTo($parent);
// On récupère le titre et on le cache
var titre = $(this).find('> fieldset > legend').hide().text();
// On crée l'onglet qui va avec
var $onglet = $('<li class="'+classes.tablist_item+'"><a class="'+classes.tablist_link+'" href="#'+id_panneau+'" id="'+id_onglet+'" aria-controls="'+id_panneau+'">'+titre+'</a></li>');
$onglet
.click(function() {
activer_onglet($onglet);
$onglet.siblings().each(function() {
desactiver_onglet($(this));
});
return false;
});
// On active le premier onglet au démarrage
if (i == 0) {
activer_onglet($onglet);
}
// S'il y a des erreurs dans cette partie du contenu, on met une classe "erreur" à l'onglet aussi
if ($(this).find('.editer.erreur').length > 0) {
$onglet.children('a').addClass(classes.error);
}
// On ajoute l'onglet
$menu.append($onglet);
});
// Puis on relance pour tous les fieldsets imbriqués
var $sous_fieldsets = $fieldset.find(selecteur_fieldset);
if ($sous_fieldsets.length > 0) {
ongletiser_fieldsets($sous_fieldsets.first());
}
}
// On maraboute tous les formulaires Spip
$('.formulaire_spip').each( function(i) {
var
$formulaire = $(this),
init = $formulaire.data('saisies_onglets_init') || false,
$fieldsets = $formulaire.find(selecteur_fieldset);
// On parcourt les fieldsets *niveau par niveau*
if (!init) {
$formulaire.data('saisies_onglets_init', true);
ongletiser_fieldsets($fieldsets.first());
}
});
}
function saisies_date_jour_mois_annee_changer_date(me, datetime) {
var champ = jQuery(me);
var li = champ.closest('.editer');

2
lang/saisies_fr.php

@ -166,6 +166,8 @@ Vous trouverez la <a href="https://contrib.spip.net/5080" target="_blank" rel="n
'option_pliable_label_case' => 'Le groupe de champs pourra être replié.',
'option_plie_label' => 'Déjà plié',
'option_plie_label_case' => 'Si le groupe de champs est pliable, il sera déjà plié à l’affichage du formulaire.',
'option_onglet_label' => 'Onglet',
'option_onglet_label_case' => 'Afficher sous forme d’onglet.',
'option_poster_afficher_si_label_case' => 'Poster les valeurs de toutes les saisies masquées',
'option_previsualisation_explication' => 'Si le porte-plume est activé, ajoute un onglet pour prévisualiser le rendu du texte saisi.',
'option_previsualisation_label' => 'Activer la prévisualisation',

45
saisies.css.html

@ -3,6 +3,12 @@
#HTTP_HEADER{Content-Type: text/css; charset=utf-8}
#HTTP_HEADER{Vary: Accept-Encoding}
/* Variables pour changer facilement les couleurs et cie côté privé ou public */
:root {
[--saisies-couleur-accent: #(#ENV{couleur_foncee});]
--saisies-couleur-erreur: #CC3300;
}
#SET{left,#LANG_DIR|choixsiegal{ltr,left,right}}
#SET{right,#LANG_DIR|choixsiegal{ltr,right,left}}
#SET{fleche,#LANG_DIR|choixsiegal{ltr,#CHEMIN{images/deplierhaut.gif},#CHEMIN{images/deplierhaut_rtl.gif}}}
@ -75,3 +81,42 @@ fieldset {
.choix_grille_wrapper {
overflow-x: auto;
}
/* Onglets stylés ici à d'un composant fourni par le core */
.formulaire_spip .menu-onglets {
display: flex;
list-style: none;
padding: 0;
margin: 0;
border-bottom: 1px solid hsla(0, 0%, 0%, 0.1);
}
.formulaire_spip .menu-onglets__item {}
.formulaire_spip .menu-onglets__lien {
display: block;
padding: 0.5em 1em;
border-bottom: 2px solid transparent;
color: inherit;
text-decoration: none;
text-transform: uppercase;
font-weight: 500;
font-size: 0.85em;
transition: 0.05s all;
}
.formulaire_spip .menu-onglets__lien.actif {
border-bottom-color: var(--saisies-couleur-accent, black);
color: var(--saisies-couleur-accent);
}
.formulaire_spip .menu-onglets__lien:hover,
.formulaire_spip .menu-onglets__lien:focus {
transition-duration: 0.2s;
}
.formulaire_spip .menu-onglets__lien:hover {
background-color: hsla(0, 0%, 0%, 0.05);
}
.formulaire_spip .menu-onglets__lien:focus {
background-color: hsla(0, 0%, 0%, 0.15);
}
.formulaire_spip .menu-onglets__lien.erreur {
color: var(--saisies-couleur-erreur);
border-bottom-color: var(--saisies-couleur-erreur);
}

7
saisies/fieldset.html

@ -1,5 +1,6 @@
#SET{pliable,#ENV{pliable}|et{#ENV{pliable}|!={non}}|?{'pliable', ''}}
#SET{plie,#ENV{plie}|et{#ENV{plie}|!={non}}|?{'plie', ''}}
#SET{classe_pliable,#ENV{pliable}|et{#ENV{pliable}|!=={non}}|?{pliable}}
#SET{classe_plie,#ENV{plie}|et{#ENV{plie}|!=={non}}|?{plie}}
#SET{classe_onglet,#ENV{onglet}|et{#ENV{onglet}|!=={non}}|?{fieldset_onglet}}
[(#REM) S'il y a des erreurs pour au moins un des champs internes, on ne plie pas ! ]
#SET{champs_internes, #ENV{saisies}|saisies_lister_par_nom}
@ -10,7 +11,7 @@
]
#SET{erreur_ici,#ENV**{erreurs/#ENV{nom}}}
<[(#ENV{saisies_base_conteneur,#DIV|sinon{li}})] class="fieldset[ fieldset_(#ENV{nom}|saisie_nom2classe)][ (#ENV{conteneur_class,#ENV{li_class}})][ (#ENV{type_saisie}|saisie_type2classe)][ (#GET{pliable})[ (#GET{plie})]]"[ data-id="(#ENV{id_saisie})"][ data-afficher_si="(#ENV*{afficher_si}|saisies_afficher_si_js{#ENV{_saisies}})"]>
<[(#ENV{saisies_base_conteneur,#DIV|sinon{li}})] class="fieldset[ fieldset_(#ENV{nom}|saisie_nom2classe)][ (#ENV{conteneur_class,#ENV{li_class}})][ (#ENV{type_saisie}|saisie_type2classe)][ (#GET{classe_pliable})[ (#GET{classe_plie})]][ (#GET{classe_onglet})]"[ data-id="(#ENV{id_saisie})"][ data-afficher_si="(#ENV*{afficher_si}|saisies_afficher_si_js{#ENV{_saisies}})"]>
#ENV*{inserer_debut}
<fieldset>

6
saisies/fieldset.yaml

@ -71,6 +71,12 @@ options:
nom: 'plie'
label: '<:saisies:option_plie_label:>'
label_case: '<:saisies:option_plie_label_case:>'
-
saisie: 'case'
options:
nom: 'onglet'
label: '<:saisies:option_onglet_label:>'
label_case: '<:saisies:option_onglet_label_case:>'
-
saisie: 'input'
options:

4
saisies_pipelines.php

@ -21,7 +21,9 @@ function saisies_header_prive($flux) {
$js = find_in_path('javascript/saisies.js');
$flux .= "\n<script type='text/javascript' src='$js'></script>\n";
include_spip('inc/filtres');
$css = produire_fond_statique('saisies.css');
include_spip('inc/filtres_ecrire');
parse_str(parametres_css_prive(), $params_css);
$css = produire_fond_statique('saisies.css', $params_css);
$flux .= "\n<link rel='stylesheet' href='$css' type='text/css' media='all' />\n";
$css_constructeur = find_in_path('css/formulaires_constructeur.css');
$flux .= "\n<link rel='stylesheet' href='$css_constructeur' type='text/css' />\n";

Loading…
Cancel
Save