# Techniques avancées avec user-interfaces

# Structure HTML des éléments de user-interfaces

# Le Smart Element

La page globale d'un Smart Element HTML standard contient la structure suivante :

<html>
  <head>
    ...
  </head>
  <body>
    <div class="document">
      <div class="dcpDocument">
        <header class="dcpDocument__header">L'entête du Smart Element</header>
        <nav class="dcpDocument__menu">La barre de menu</nav>
        <section class="dcpDocument__body">Le corps du Smart Element</section>
        <footer class="dcpDocument__footer">Le pied du Smart Element</footer>
      </div>
    </div>
  </body>
</html>

Exemple : mettre un fond noir sur la page

.dcpDocument {
  background-color: black;
}
.dcpDocument .dcpDocument__header,
.dcpDocument .dcpDocument__menu,
.dcpDocument .dcpDocument__body,
.dcpDocument .dcpDocument__footer {
  background-color: inherit;
}

En fonction du mode de rendu (consultation, modification, création), une casse de style supplémentaire est ajoutée sur la div <div class="dcpDocument">.

  • Consultation : <div class="dcpDocument dcpDocument--view">,
  • Modification : <div class="dcpDocument dcpDocument--edit">,
  • Création : <div class="dcpDocument dcpDocument--edit dcpDocument--create">.

cette balise contient aussi une classe dcpFamily--[SmartStructureName] qui permet de différencier les Smart Elements par Smart Structure. SmartStructureName contient le nom logique de la Smart Structure.
Exemple: <div class="dcpDocument dcpDocument--view dcpFamily--DEVBILL"></div>.
De plus, une classe est ajoutée si le navigateur supporte les événements tactiles : <div class=dcpDocument dcpTouch">.

# Le contenu DOM du corps de Smart Element

Le contenu de rendu d'un Smart Element est inséré dans une section .dcpDocument__body.
L'exemple ci-dessous représente un Smart Element ayant la structure suivante :

  • frame f1
    • text a2
    • int a3
    • array array1
      • text a5
      • docid a6
  • tab t1
    • frame f2
      • ...
    • frame f3
      • ...
  • tab t2
    • frame f4
      • ...
    • frame f5
      • ...
<section class="dcpDocument__body">
    <div class="dcpDocument__frames">
        <div class="dcpFrame" data-attrid="f1">
            <div class="dcpFrame__label dcpLabel" data-attrid="f1">
                Label du cadre
            </div>
            <div class="dcpFrame__content" data-attrid="f1" >
                <div class="dcpAttribute dcpAttribute--type--text" data-attrid="a2" >
                    <label class="dcpAttribute__label dcpLabel dcpAttribute__label--text " data-attrid="a2">
                        Label de l'attribut
                    </label>
                    <div class="dcpAttribute__content dcpAttribute__content--text" data-attrid="a2">
                        Valeur de l'attribut
                    </div>
                </div>
                <div class="dcpAttribute dcpAttribute--type--int" data-attrid="a3">
                    <label class="dcpAttribute__label dcpLabel dcpAttribute__label--int" data-attrid="a3">
                        Label d'un autre attribut
                    </label>
                    <div class="dcpAttribute__content dcpAttribute__content--int" data-attrid="a3">
                        Valeur d'un autre attribut
                    </div>
                </div>
                <div class="dcpArray" data-attrid="array1">
                    <div class="dcpArray__label dcpLabel" data-attrid="array1">
                        Label du tableau
                    </div>
                    <div class="dcpArray__content" data-attrid="array1">
                        <table>
                            <thead class"dcpArray__head" data-attrid="array1">
                                <tr>
                                    <th class="dcpArray__head__cell dcpLabel dcpAttribute__label--text " data-attrid="a5">
                                        Label d'un attribut
                                    </th>
                                    <th class="dcpArray__head__cell dcpLabel dcpAttribute__label--docid " data-attrid="a6">
                                        Label d'un autre attribut
                                    </th>
                                </tr>
                            </thead>
                            <tbody class="dcpArray__body" data-attrid="array1">
                                <tr class="dcpArray__content__line" data-attrid="array1" data-line="0">
                                    <td class="dcpAttribute__content dcpAttribute__label--text" data-attrid="a5">
                                        Valeur d'un attribut
                                    </td>
                                    <td class="dcpAttribute__content dcpAttribute__label--docid" data-attrid="a6">
                                        Valeur d'un autre attribut
                                    </td>
                                </tr>
                                <tr class="dcpArray__content__line" data-attrid="array1" data-line="1">
                                    <td class="dcpAttribute__content dcpAttribute__label--text" data-attrid="a5">
                                        Valeur d'un attribut
                                    </td>
                                    <td class="dcpAttribute__content dcpAttribute__label--docid" data-attrid="a6">
                                        Valeur d'un autre attribut
                                    </td>
                                </tr>
                            </tbody>
                       </table>
                   </div>
                </div>
            </div>
        </div>
    </div>
    <div class="dcpDocument__tabs">
        <ul class="dcpDocument__tabs__list">
            <li class="dcpTab__label dcpLabel dcpLabel--active" data-attrid="t1">
                Label de l'onglet
            </li>
            <li class="dcpTab__label dcpLabel dcpLabel--default" data-attrid="t2">
                Label de l'onglet
            </li>
        </ul>
        <div class="dcpTab__content" data-attrid="t1">
            <div class="dcpFrame" data-attrid="f2">
                Contenu d'un cadre…
            </div>
            <div class="dcpFrame" data-attrid="f3">
                Contenu d'un autre cadre…
            </div>
        </div>
        <div class="dcpTab__content" data-attrid="t2">
            <div class="dcpFrame" data-attrid="f4">
                Contenu d'un cadre…
            </div>
            <div class="dcpFrame" data-attrid="f5">
                Contenu d'un autre cadre…
            </div>
        </div>
    </div>
</section>

# Identifier les Smart Fields dans la css

Les Smart Fields sont au sein de la section .dcpDocument__body dans une div de la forme : <div class="dcpAttribute dcpAttribute--type--***" data-attrid="***"/>.

# Label des Smart Fields

# Label en général

Tous les labels de Smart Fields peuvent être adressé avec les mêmes règles:

Règle Définition
.dcpDocument .dcpLabel Tous les labels (hormis les onglets)
.dcpDocument .dcpLabel[data-attrid="smartFieldId"] Label du Smart Field smartFieldId

Exemple :

.dcpDocument .dcpLabel {
  color: #ffff00;
  background-color: #262600;
}
.dcpDocument .dcpLabel[data-attrid="my_text"] {
  color: blue;
}
.dcpDocument .dcpLabel[data-attrid="my_number"] {
  color: #ff6d8c;
}

# Label des onglets

Les onglets (Smart Field de type tab) ont deux états:

  • active pour l'onglet sélectionné,
  • default pour les autres.

De par ces états, des règles plus précises sont nécessaires pour modifier leur apparence :

Règle Définition
.dcpDocument .dcpLabel .dcpLabel--active Label de l'onglet actif
.dcpDocument .dcpLabel .dcpLabel--default Label des onglets inactifs
.dcpDocument .dcpLabel .dcpLabel--active[data-attrid="smartFieldId"] Label de l'onglet smartFieldId lorsqu'il est actif
.dcpDocument .dcpLabel .dcpLabel--default[data-attrid="smartFieldId"] Label de l'onglet smartFieldId lorsqu'il est inactif

Les onglets ont un élément actif permettant de changer d'onglet. Cet élément est une ancre HTML (a) et sa couleur ne peut être modifiée que par des règles plus précises portant sur l'ancre elle-même :

Règle Définition
.dcpDocument .dcpLabel .dcpLabel--active[data-attrid="smartFieldId"] a Label de l'onglet smartFieldId lorsqu'il est actif
.dcpDocument .dcpLabel .dcpLabel--default[data-attrid="smartFieldId"] a Label de l'onglet smartFieldId lorsqu'il est inactif

Exemple :

.dcpDocument .dcpLabel--default[data-attrid="tst_myframe"] {
  color: violet;
  background: #fdffbb;
}
.dcpDocument .dcpLabel--active[data-attrid="tst_myframe"] {
  background: violet;
  color: #fdffbb;
}

# Contenu des Smart Fields

Le contenu des Smart Fields peut être adressé avec les règles suivantes :

Règle Définition
.dcpDocument .dcpAttribute__content Tous les contenus de Smart Fields (hormis les Smart Fields de structure)
.dcpDocument .dcpArray__content Les contenus des tableaux
.dcpDocument .dcpFrame__content Les contenus des cadres
.dcpDocument .dcpTab__content Le contenu des onglets
.dcpDocument .dcpAttribute__content["smartFieldId"] Contenu du Smart Field smartFieldId
.dcpDocument .dcpArray__content["smartFieldId"] Contenu du tableau smartFieldId
.dcpDocument .dcpFrame__content["smartFieldId"] Contenu du cadre smartFieldId
.dcpDocument .dcpTab__content["smartFieldId"] Contenu de l'onglet smartFieldId

Exemple : Changer la couleur du cadre my_frame :

.dcpFrame__content[data-attrid="my_frame"] {
  background: linear-gradient(
    45deg,
    rgba(206, 219, 233, 1) 0%,
    rgba(97, 153, 199, 1) 51%,
    rgba(65, 154, 214, 1) 84%,
    rgba(38, 85, 139, 1) 100%
  );
  color: white;
}
Figure 1. Rendu par défaut
Figure 1. Rendu par défaut
Figure 2. Rendu avec css personalisée
Figure 2. Rendu avec css personalisée

# La navigation au clavier

Afin de faciliter l'utilisation des formulaires générés au moyen de user-interfaces, seules les zones de saisie de texte sont accessibles au moyen de la touche de tabulation ().
Ainsi, un utilisateur peut saisir l'ensemble des données d'un formulaire sans quitter le clavier.
Cela veut dire que les boutons qui accompagnent les input ne sont pas accessibles au moyen du clavier. Cela inclut notamment :

  • le bouton permettant d'effacer la valeur,
  • le bouton permettant d'accéder au date-picker,
  • le bouton permettant de dérouler la liste sur les énumérés,
  • le bouton permettant de dérouler la liste sur les docid,
  • ...

Cependant, la plupart des opération correspondantes sont accessibles via le clavier.

# Cas particuliers

# Smart fields de type file ou image

Une fois que le Smart Field a obtenu le focus, il faut utiliser la touche enter () pour que la fenêtre de sélection de fichier s'ouvre.
La navigation dans cette fenêtre dépend ensuite du système d'exploitation de l'utilisateur.

# Smart Fields de type docid ou enum

La liste déroulante est accessible au moyen de la touche flèche vers le bas ().
Il est ensuite possible de sélectionner un élément au moyen de la touche enter ().
Lorsque le Smart Field est multiple, il est possible de se déplacer entre les valeurs au moyen des flèches gauche et droite. Il est ensuite possible de supprimer la valeur à gauche du curseur au moyen de la touche retour ().

# Smart Fields de type color

Le colorpicker est accessible au moyen de la touche enter ().
Il est ensuite possible de changer la couleur au moyen des flèches, puis de valider son choix au moyen de la touche enter ().

# Limitations

Pour changer d'onglet, il faut se positionner sur la barre des onglets, et utiliser les flèches latérales pour passer d'un onglet à l'autre.

# Prendre en compte la navigation au clavier dans les interfaces spécifiques

Lors du développements d'interfaces spécifiques (vues de Smart Fields notamment), il est important d'exclure certains éléments de la navigation par clavier afin de rester homogène avec l'approche des formulaires générés par user-interfaces.
Cela se fait au moyen de l'attribut tabindex auquel on donne la valeur -1.