0

this time I got an idea to created a menu with submenus created from html dynamically and got it done (not responsive yet) but I have an issue with "scrollIntoView" that doesn't work as I imagine.

These answers didn't help me out: How to scroll to an element inside a div?

The menus should move into the view (on the left top) like on the image: enter image description here

I have a pen here: codepen

anyway, here is also what I have so far (Stripped, due to stack limitations):

window.addEventListener('DOMContentLoaded', htmlTableOfContents);

function htmlTableOfContents() {
  let headings = [].slice.call(document.querySelectorAll('article h2, article h3, article h4, article h5, article h6'));
  headings.forEach(function(heading, index) {
    var ref = "toc" + index;
    if (heading.hasAttribute("id")) {
      ref = heading.getAttribute("id");
    } else {
      heading.setAttribute("id", ref);
    }
    var link = document.createElement("a");
    link.setAttribute("href", "#" + ref);
    link.textContent = heading.textContent;
    var div = document.createElement("div");
    div.setAttribute("class", heading.tagName.toLowerCase());
    div.appendChild(link);
    toc.appendChild(div);
  });
  // define menus and activate first menu 
  let menus = [].slice.call(document.querySelectorAll('#toc .h2'));

  menus.forEach(function(menu) {
    let ref = "anchor-" + menu.nextSibling.innerText.substr(0, 2);
    var anchor = document.createElement("div");
    anchor.setAttribute("id", ref);
    menu.appendChild(anchor);
  });
  menus[0].classList.toggle('active');
  // define submenus
  let submenus = [].slice.call(document.querySelectorAll('#toc .h3'));
  submenus.forEach(function(submenu) {
    var ref = "h3 " + submenu.firstChild.innerText.substr(0, 2);
    submenu.setAttribute("class", ref);
  });
  // first active submenus
  let fA = document.querySelectorAll('.CD');
  for (var a = 0; a < fA.length; a++) {
    fA[a].classList.toggle('active');
  }
  // create menus
  for (var m = 0; m < menus.length; m++) {
    menus[m].addEventListener('click', function() {
      // Reset all menus
      menus.forEach(function(menu) {
        if (menu.classList.contains('active')) {
          menu.classList.toggle('active');
        }
      });
      // Reset all submenus
      submenus.forEach(function(submenu) {
        if (submenu.classList.contains('active')) {
          submenu.classList.toggle('active');
        }
      });
      this.classList.toggle('active');
      const anchor = this.children[1].id;
      const scrollA = document.getElementById(anchor);
      scrollA.scrollIntoView({
        block: 'end'
      });

// var topPos = this.offsetTop;
// document.getElementById('toc').scrollTop = topPos;

      let nSC = this.nextSibling.innerText.substr(0, 2);
      let sS = document.getElementsByClassName(nSC);
      for (var x = 0; x < sS.length; x++) {
        sS[x].classList.toggle('active');
      }
    });
  }
}
* {
  box-sizing: border-box;
}

html,
body {
  padding: 0;
  margin: 0;
  height: 100%;
  font-family: "Open Sans", sans-serif;
  font-style: normal;
  cursor: default;
  background-color: rgb(40 60 80);
  color: #efefef;
  scroll-behavior: smooth;
}

body::-webkit-scrollbar,
html::-webkit-scrollbar,
.body-bg::-webkit-scrollbar {
  display: none;
}

.bodyBackground {
  padding: 0;
  margin: 0;
  width: 100vw;
  height: 100%;
}

.logo {
  background-image: url("logo-serena.png");
  filter: drop-shadow(1px 1px 1px #000000);
  height: 200px;
  background-position: 50% 20px;
  background-repeat: no-repeat;
  background-size: contain;
  position: relative;
}

a[href^="https"] {
  color: cornflowerblue;
}

.article {
  padding: 20px 10px;
}

.note {
  color: yellow;
}

.critical {
  color: red;
}

.link {
  color: grey;
  font-size: 0.5em;
  vertical-align: top;
}

hr {
  background: linear-gradient(to right, transparent, darkcyan, transparent);
  height: 2px;
  border: none;
  margin: 40px 0;
}

.shadow {
  background: linear-gradient(to right, transparent, rgb(0, 31, 31), transparent);
  height: 2px;
  border: none;
  margin: 20px 0 30px;
}

h1 {
  padding-top: 0;
}

h2,
h3,
h4,
h5,
h6 {
  padding-top: 20px;
  cursor: pointer;
}

h1,
h2,
h3 {
  text-shadow: 0 2px 3px black;
}

h2 {
  padding: 5px 10px;
  margin: 50px -50px 20px -12px;
  background: linear-gradient(90deg, transparent, darkcyan);
}

h5,
h6 {
  font-size: 1em;
}

.TocHeading {
  text-align: center;
  background: none;
  cursor: revert;
  margin: 20px 0 -20px 0;
  padding: 0;
}

.Version {
  font-size: 1.2em;
  margin-top: -22px;
  margin-bottom: 40px;
}

#toc {
  text-transform: uppercase;
}

#toc div.h1 {
  margin-left: 0;
}

#toc div.h2 {
  display: block;
  background-image: linear-gradient(to right, #00bbbb, transparent);
  padding: 5px 40px;
  margin-left: -10px;
  margin-bottom: 1em;
  margin-top: 1em;
  margin-right: -30px;
  font-size: 1.4rem;
  font-weight: 500;
}

#toc div.h2.active a {
  color: #39c1c7;
}

#toc div.h3.active {
  display: block;
  color: #39c1c7;
}

#toc div.h3.active a {
  color: #39c1c7;
}

#toc div.h3 {
  display: none;
  margin-left: 2em;
  margin-bottom: 1em;
  margin-top: 1em;
  font-size: 0.9rem;
}

#toc div.h4 {
  margin-left: 3em;
  margin-bottom: 1em;
  margin-top: 1em;
  font-size: 1.1rem;
}

#toc div.h5 {
  margin-left: 4em;
  margin-bottom: 0.7em;
  margin-top: 0.7em;
  font-size: 0.9rem;
}

#toc div.h6 {
  margin-left: 4.5em;
  margin-bottom: 0.7em;
  margin-top: 0.7em;
  font-size: 0.7em;
}

a {
  color: #e4e4e4;
  text-decoration: none;
  text-shadow: 0 2px 2px black;
}

#toc a:hover {
  position: relative;
  top: 1px;
  text-shadow: 0 1px 1px black, 0 0 3px white;
}

.heading {
  font-weight: bold;
}

.open {
  display: block;
}

.box {
  display: none;
  width: 100%;
}

a:hover+.box,
.box:hover {
  display: block;
  position: relative;
  z-index: 100;
}

.top-header {
  text-align: center;
  float: left;
  z-index: 2;
  position: fixed;
  width: max(500px, calc(30% - 6px));
  height: 332px;
  padding: 0 20px;
  margin: 0 -3px 0 3px;
  background-color: #3c597c;
}

#topHeader h2 {
  padding: 5px 10px;
  margin-bottom: 1em;
  margin-top: 1em;
  font-size: 1.4rem;
  font-weight: 500;
  background-image: none;
  cursor: revert;
}

.container-left {
  float: left;
  z-index: 1;
  position: fixed;
  width: 30%;
  min-width: 506px;
  height: 100%;
  padding: 330px 10px 0;
  background-color: #3c597c;
  overflow-x: hidden;
  -ms-overflow-style: none;
  scrollbar-width: none;
  box-shadow: 5px 0 7px black;
  border-left: 3px solid transparent;
  border-right: 3px solid transparent;
  border-image: linear-gradient(to bottom, #1b2838 0%, #3acfd5 50%) 1;
  font-size: 1.3em;
}

.container-left::-webkit-scrollbar,
.container-right::-webkit-scrollbar {
  display: none;
}

.container-right {
  z-index: 0;
  position: absolute;
  margin-left: max(506px, 30%);
  padding: 5px 45px 20px 45px;
  background-color: #1b2838;
  overflow-x: hidden;
  -ms-overflow-style: none;
  scrollbar-width: none;
  font-size: calc(8px + (20 - 8) * ((100vw - 320px) / (1600 - 320)));
}
<!DOCTYPE html>
<html lang="fr">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Charte informatique</title>
  <link rel="stylesheet" type="text/css" href="ci.css" />
  <script src="ci.js"></script>
</head>

<body>
  <div class="bodyBackground">
    <main>
      <container id="topHeader" class="top-header">
        <div class="logo">
        </div>
        <h1>Charte informatique</h1>
        <p class="Version">Vers.: 4.3 (Renow)
        </p>
        <hr class="shadow">
      </container>
      <container id="top-left" class="container-left">
        <div id="NavHead" class="NavHeader">
          <h2 class="TocHeading">Index</h2>
        </div>
        <div id="Nav" class="menu">
          <div id="toc">
          </div>
        </div>
      </container>
      <container id="top-right" class="container-right">
        <container id="0" class="sub-container">
          <article>
            <h2>Code (CD)</h2>
            <h3>CD.001 Type de codage</h3>
            <p>Chaque page comporte la déclaration de type document «!doctype html» Le code source de la page doit commencer avec l'élément :
              <br><br> &lt;CODE&gt;
              <br> &lt;!DOCTYPE html&gt;
              <br>&lt;/CODE&gt;
            </p>
          </article>
          <hr>
          <article>
            <h3>CD.002 Balise détournée</h3>
            <p>Les balises natives sont utilisées. Si une balise est détournée, les rôles associés aux composants sont utilisées de manière cohérente et en conformité des WAI-Aria.</p>
          </article>
          <hr>
          <article>
            <h3>CD.003 Structure en rôle aria</h3>
            <p>Dans chaque page Web, la structure du document vérifie-t-elle ces conditions ?
              <ul>
                <li>La zone d'en-tête de la page possède un rôle ARIA banner</li>
                <li>Le menu de navigation principal possède un rôle ARIA navigation</li>
                <li>La zone de contenu principal possède un rôle ARIA main</li>
                <li>La zone de pied de page possède un rôle ARIA contentinfo</li>
                <li>Le moteur de recherche sur le site possède un rôle ARIA search</li>
                <li>Les rôles ARIA banner, main et contentinfo sont uniques dans la page</li>
                <li>Le rôle ARIA navigation est réservé aux zones de navigations principales et secondaires.</li>
              </ul>
            </p>
          </article>
          <hr>
          <article>
            <h3>CD.004 Utilisation des textes cachés</h3>
            <p>Les textes cachés visuellement sont utilisés de manière compréhensible et ont un intérêt. Les textes masqués/affichés en css uniquement doivent être appropriés. Une alerte ou un message d'erreur doit être affiché par un script et non masqués/affichés
              en css uniquement.</p>
          </article>
          <hr>
          <article>
            <h3>CD.005 Ordre hiérarchique des titres</h3>
            <p>Dans le contenu des pages, les titres suivent l'ordre hiérarchique de titre 2 (h2) à titre 5 (h5) . Chaque bloc d'information possède un titre pertinent.</p>
          </article>
          <hr>
          <article>
            <h3>CD.006 Validité du code</h3>
            <p>Le code est valide: ID unique, balise fermée, pas d'attribut ou balise obsolètes. Vérifier avec le validateur du W3C : https://validator.w3.org/</p>
          </article>
          <hr>
          <article>
            <h3>CD.007 Langue du site</h3>
            <p>La langue par défaut est précisée dans la balise HTML du site. Au début de chaque page, la propriété lang doit être renseigné au niveau de la balise html, exemple si la page est en français: <br><br>&lt;CODE&gt;<br>&lt;html lang="fr"&gt;<br>&lt;/CODE&gt</p>
          </article>
          <hr>
          <article>
            <h3>CD.008 Changement de langue dans le contenu</h3>
            <p>Les changements de langue dans le texte sont indiquées dans l'attribut lang de la balise concernée. Pour chaque paragraphe, l'attribut lang doit être renseignée; par exemple si un paragraphe est en allemand : lang="de".
              <br><br> &lt;CODE&gt;
              <br> &lt;p lang="de">Ich bevorzuge die Deutsch sprechen.&gt;&lt;/p&gt;
              <br> &lt;/CODE&gt
            </p>
          </article>
          <hr>
          <article>
            <h3>CD.009 Utilisation des citations</h3>
            <p>Les citations doivent utiliser le balisage Q ou BLOCKQUOTE : elles ne doivent pas être simulées à l'aide de guillemets directement saisis dans le texte ou d'italique</p>
          </article>
          <hr>
          <article>
            <h3>CD.010 Contenu en liste</h3>
            <p>Les listes à puces ou numérotées sont correctement structurées (à l'aide des balises UL et OL)
            </p>
          </article>
          <hr>
          <article>
            <h3>CD.011 Alternative de contenu ou fonctionnalité</h3>
            <p>Si un contenu (notamment, emoticon, art ASCII, captcha...) ou une fonctionnalité du site nécessite une alternative pour être accessible, l'information donnée par cette alternative est équivalente à l'information fournie par la version d'origine.</p>
          </article>
          <hr>
          <article>
            <h3>CD.012 Durée de session</h3>
            <p>Si la session utilisateur est limitée en durée, l'utilisateur doit pouvoir contrôler la limite de temps. Sauf si la session est limitée à plus de 20 heures.</p>
          </article>

          <article>
            <h2>FORMULAIRE (FM)</h2>
            <h3>FM.001 Taille du champs</h3>
            <p>Taille du champ de saisie est adaptée selon le type d'information.</p>
          </article>
          <hr>
          <article>
            <h3>FM.002 Label des champs</h3>
            <p>Les champs de formulaire ont un label explicitement associé et pertinent. Le label contient la propriété for et l'input contient un id identique <code>étiquette du champs
                                <input></input></code></p>
          </article>
          <hr>
          <article>
            <h3>FM.003 Position du label</h3>
            <p>Les labels sont visibles et placés au dessus de leur champs. Pour les formulaires à champs unique, il peut être rendu visible en dupliquant le label au niveau du placeholder.</p>
          </article>
          <hr>
          <article>
            <h3>FM.004 Groupement de champs</h3>
            <p>Les champs sont visuellement regroupés (fieldset) et possèdent une légende, si cela facilite la compréhension. 2 champs ne peuvent avoir un même label sauf si un fielfset permet de les distinguer (exemple d'utilisation nécessaire : adresse
              de livraison / facturation)</p>
          </article>
          <hr>
          <article>
            <h3>FM.005 Groupement de réponse</h3>
            <p>Les groupes d'options des champs SELECT sont balisés avec des éléments OPTGROUP dotés d'un libellé via l'attribut LABEL.</p>
          </article>
          <hr>
          <article>
            <h3>FM.006 Choix explicites</h3>
            <p>Les champs SELECT, RADIO et CHECKBOX présentent des choix explicites (pas d'abréviations).
            </p>
          </article>
          <hr>
          <article>
            <h3>FM.007 Types de liste à choix</h3>
            <p>Lorsque l'utilisateur doit voir l'ensemble des choix possibles les champs INPUT RADIO ou CHECKBOX sont utilisés plutôt que les listes SELECT.</p>
          </article>
          <hr>
          <article>
            <h3>FM.008 Listes à choix uniques</h3>
            <p>Les champs INPUT RADIO sont utilisés pour des listes à choix uniques. Si les boutons radio sont simulés, ils doivent satisfaire aux mêmes contraintes d'usage que les boutons radio natifs en HTML</p>
          </article>
          <hr>
          <article>
            <h3>FM.009 Listes à choix multiples</h3>
            <p>Les champs INPUT CHECKBOX sont utilisés pour des listes à choix multiples (0,1 ou plusieurs choix possibles)</p>
          </article>
          <hr>
          <article>
            <h3>FM.010 Cohérence des formulaires</h3>
            <p>Les libellés des boutons d'action et les labels de champs sont cohérents à travers toutes les pages du site.</p>
          </article>
          <hr>
          <article>
            <h3>FM.011 Apparence des boutons d'action</h3>
            <p>Les actions de formulaires ne sont pas mis en forme comme des liens.</p>
          </article>
          <hr>
          <article>
            <h3>FM.012 Libellé des boutons d'action</h3>
            <p>Les libellés des boutons indiquent clairement l'action de manière concise. L'intitulé visible peut éventuellement être complété par un title. Il ne peut être remplacé</p>
          </article>
          <hr>
          <article>
            <h3>FM.013 Validation de formulaire</h3>
            <p>Le formulaire peut être validé à l'aide de la touche entrée. Le formulaire est validable lorsque l'utilisateur est dans le dernier champs du formulaire.</p>
          </article>
          <hr>
          <article>
            <h3>FM.014 Position des boutons d'action</h3>
            <p>Les boutons d'actions sont placés en fin de formulaire et sont alignés à gauche ou centrés.
            </p>
          </article>
          <hr>
          <article>
            <h3>FM.015 Distinction des champs obligatoires</h3>
            <p>Les champs obligatoires sont différenciés par une astérisque dans leur LABEL, sous la forme "Intitulé * :". La distinction peut être faite avec la mention (obligatoire) écrit en toute lettre. La propriété "required" doit également être présente
              sur le champs Numéro de série *
              <br><br> &lt;CODE&gt;
              <br> &lt;input type="text" id="numero-serie" required&gt;
              <br> &lt;/CODE&gt;
            </p>
          </article>
          <hr>
          <article>
            <h3>FM.016 Note champs obligatoire</h3>
            <p>La note "* Champ obligatoire" est spécifié au niveau du formulaire.</p>
          </article>
          <hr>
          <article>
            <h3>FM.017 Messages d'erreur explicites</h3>
            <p>Les messages d'erreurs indiquent la nature de l'erreur ainsi que les moyens de correction de l'erreur directement après le champ et reliés. Ajouter un document à votre dossier
              <br><br> &lt;CODE&gt;
              <br> &lt;input type="file" id="document" name="document" aria-invalid="true" aria-describedby="formats erreur" /&gt;
              <br> &lt;/CODE&gt;
            </p>
            <p>Format de fichier incorrect.</p>
            <p>Formats acceptés : pdf ou doc.</p>
          </article>
          <hr>
          <article>
            <h3>FM.018 Apparence des messages d'erreurs</h3>
            <p>Les messages d'erreurs, les libellés et les champs associés sont mis en valeur, visuellement, au moyen de 2 mécanismes différents, au moins l'un d'eux doit faire apparaitre du rouge (contraste de couleur, graisse, style, pictogramme, etc...).</p>
          </article>
          <hr>
          <article>
            <h3>FM.019 Conservation des informations saisies</h3>
            <p>En cas d'erreur, toutes les informations saisies par l'utilisateur (correctes et erronées) sont conservées et modifiables.</p>
          </article>
          <hr>
          <article>
            <h3>FM.020 Formulaire avec informations personnelles</h3>
            <p>Pour chaque formulaire recueillant des informations personnelles ou ayant des conséquences au delà du site, l'envoi des données se fait en 3 étapes distincts:
              <ul>
                <li>la saisie</li>
                <li>la confirmation (avec modification possible)</li>
                <li>résultat de l'envoi des données (avec, si réussite, récapitulatif des informations)
                </li>
              </ul>
            </p>
          </article>
          <hr>
          <article>
            <h3>FM.021 Format attendu</h3>
            <p>L'utilisateur est guidé dans les valeurs à saisir:
              <ul>
                <li>format de données attendu (type de caractère ou type de fichier...)</li>
                <li>suggestion de valeur pertinente (proposition à partir de l'historique utilisateur)
                </li>
              </ul>
              Le champs et l'aide à la saisie sont liés<label for="" document ""> Ajouter un document à
                            votre dossier </label>
              <p>Formats acceptés : pdf ou doc.</p>
              <p>Pour les champs texte qui permettent de saisir l'identité d'une personne, le champ "nom" a pour valeur de l'attribut autocomplete "family-name", le champ "prénom" la valeur "given-name", etc.
              </p>
          </article>
          <hr>
          <article>
            <h3>FM.022 Aide contextuelle masquée</h3>
            <p>Lorsqu'une aide contextuelle masquée est proposée, elle apparait dans un encart à proximité du champs tout en permettant la saisie. L'encart d'aide s'ouvre au clic.</p>
          </article>

          <article>
            <h2>Image et Multimédia (IM)</h2>
            <h3>IM.001 Alternative des images</h3>
            <p>Les alternatives textuelles d'images de contenu sont concises, limitées à l'information essentielle apportée spécifiquement par l'image. Elles ne font pas doublon avec l'information textuelle déjà présente dans le corps du texte.</p>
          </article>
          <hr>
          <article>
            <h3>IM.002 Alternative des images complexes</h3>
            <p>L'information apportée par une image complexe est explicitée dans le corps du texte, et l'image a une alternative textuelle permettant de localiser la description. Pour une balise img (canvas ou role=img ...) l'utilisation d'un aria-describedby="id",
              id faisant référence au paragraphe de la description.
              <br><br> &lt;CODE&gt;
              <br> &lt;p id="iddesc"> Détails et explications de l'image affichée. &lt;/p&gt;
              <br> &lt;/CODE&gt; ou avec une balise figure:

              <br><br> &lt;CODE&gt;
              <br> &lt;figure role="group">
              <br>&lt;figcaption>Détails et explications de l'image affichée. (ou lien vers la description)&lt;/figcaption&gt;
              <br> &lt;/figure&gt;
              <br> &lt;/CODE&gt;
              <br><br> idem pour un svg avec un aria-label ou une balise <code>
                                <title></title>
                            </code> ou un paragraphe masqué (sauf au lecteur d'écran)
            </p>
          </article>
          <hr>
          <article>
            <h3>IM.003 Alternatives des images décoratives</h3>
            <p>Les éléments graphiques qui n'apportent pas d'information nécessaires à la compréhension du contenu possèdent une alternative textuelle vide.</p>
          </article>
          <hr>
          <article>
            <h3>IM.004 Alternative des images-liens</h3>
            <p>L'alternative textuelle d'une image-lien ou d'un bouton graphique indique la cible ou la fonction du lien ou du bouton.</p>
          </article>
          <hr>
          <article>
            <h3>IM.005 Déclenchement explicite des sons et vidéos</h3>
            <p>Les sons et/ou vidéos sont uniquement déclenchés par l'utilisateur.</p>
          </article>
          <hr>
          <article>
            <h3>IM.006 Transcriptions textuelles des sons ou vidéos</h3>
            <p>L'information délivrée dans les documents audio et vidéo est reproduite sous forme de transcriptions textuelles. Une audiodescription doit être fournie si le document le nécessite. Selon le cas:
              <ul>
                <li>Les vidéos et/ ou sons pré-enregistrées ont des sous-titres et /ou audiodescription synchronisés.
                </li>
                <li>Si un média est une alternative au texte, il est légendé et clairement lié au texte.
                </li>
                <li>Pour un live, une légende doit préciser le contexte et l'interet de la vidéo: "(En direct) Conférence de ....".</li>
              </ul>
              La liaison peut se faire avec l'un des moyens suivants:
              <p>
                &lt;CODE&gt;&lt;video src="..."> Détails et explications de la vidéo affichée. &lt;/video&gt;&lt;/CODE&gt;
              </p>
              <p>
                &lt;CODE&gt;&lt;div src="vidéo" describedby=iddesc >... &lt;/div&gt;&lt;/CODE&gt;
              </p>
              <p>
                &lt;CODE&gt;&lt;video>Détails et explications de la vidéo affichée. &lt;/video&gt;&lt;/CODE&gt;


              </p>
              ou avec une balise figure:
              <code>
                                <figure role="group">
                                    <figcaption id="iddesc">Détails et explications de la vidéo affichée.</figcaption>
                                </figure>
                            </code>
            </p>
          </article>
        </container>
      </container>
    </main>
  </div>
</body>

</html>

0 Answers0