Documentation du site écrire.fun

Vous êtes ici : Accueil » Construire et gérer un blog avec WordPress » Documentation du site écrire.fun

Il est fortement conseillé de documenter votre site si vous voulez retrouver vos petits. Voici un exemple de ce que ça peut donner.

Guide utilisateur


Guide utilisateur à l’attention des créateurs de sites.

Les possibilités de l’extension

Le code court lire_la_suite

[lire_la_suite] dans un bloc Code court
Modifier l’apparence

Pour simplement modifier l’apparence. actuelle (Lire la suite : cliquer sur titre ou image), modifier le code du Code court lire_la_suite qui se trouve dans /wp-content /plugins /ecrire-fun-2022 /includes /mesfonctions.php.

Modifier l’apparence et créer un lien vers le document
  1. Editer le modèle du document concerné avec wp-admin /Apparence /Editer /Modèles
  2. Dans le bloc Modèle de publication, supprimer le bloc Code court qui se trouve sous le bloce Extrait
  3. Utiliser le champ Texte du lien « Lire la suite » du bloc Extrait

Le code court wpversion

[wpversion couleur="#605924" taille="2rem"] ou
[wpversion couleur="red" taille="10px"] etc.
dans un bloc Code court

Affiche la version de WP utilisée par le site

Valeurs par défaut :

  • couleur du texte : « black » (noir)
  • taille du texte : « 1rem »

Le code court bouton_top

[bouton_top] dans un bloc Code court
Permet de remonter en haut du document

Le code court sommaire_simple

[sommaire_simple h=n] dans un bloc Code court
avec n valant 2, 3, 4, 5 ou 6 (3 par défaut)

On peut l’utiliser plusieurs fois par document, quelle que soient les profondeurs.

Permet d’afficher un sommaire de profondeur h : par exemple, si n vaut 2, le Sommaire n’affichera que les titre de type H2.

Chaque ligne du sommaire porte un lien interne.

Si vous ne voulez pas utiliser le code court, vous pouvez créer un bloc Groupe et lui attribuer une classe de la forme class-div-sommaire-n avec n valant 2, 3, 4, 5 ou 6, en fonction de la profondeur attendue.

Les div id= »class-div-sommaire-n » sont initialisées (avec leurs liens) par le script sommaires-h2-h6-dans-class-div-sommaire-n.js qui se charge également d’attribuer un id à tous les titres qui n’en ont pas.

Exemple avec 2 groupes de classe class-div-sommaire-2

J’ai ajouté un arrière-plan et un rayon (10px) aux 2 groupes ci-dessous.

Le code court sommaire_double

[sommaire_double h=n] dans un bloc Code court
avec n valant 2, 3, 4, ou 5 (3 par défaut)

On ne peut l’utiliser qu’une seule fois par document.

Permet d’afficher un sommaire de profondeur h : par exemple, si n vaut 2, le Sommaire n’affichera que les titre de type H2.

Le 2e sommaire (Détail) affiche à la demande tous les titres jusqu’à H6 (qui est le maximum).

Les 2 sommaires sont créés une fois pour toute, les boutons ne faisant que les masquer/démasquer (donc pas de problème de charge).

Ce code court a été utilisé pour faire le sommaire de ce document (avec h=2).

Le code court sommaire_au_choix

[sommaire_au_choix h=n] dans un bloc Code court
avec n valant 2, 3, 4, 5, ou 6 (3 par défaut)

On ne peut l’utiliser qu’une seule fois par document.

Permet d’afficher un sommaire de niveau modifiable : par exemple, si n vaut 2, le sommaire n’affichera que les titre de type H2 (et le niveau affiché à l’internaute dans la liste déroulante sera 1). Le niveau est modifiable : le choix maximum proposé dépend du tag de titre de niveau le plus élevé.

Ce code court a été utilisé pour faire le sommaire de ce document (avec h=3).

La gestion des liens dans les menus

Le principe est le suivant :

  • Neutraliser le lien du menu qui pointe vers la page elle-même ou vers la catégorie dont on vient de lister les articles
  • et de colorer différemment ce lien et son chemin (en fait le niveau du dessus).

Pour les pages, on a besoin d’un 3e niveau, dans le menu principal par exemple : c’est le cas du parcours Jeux /Rhétorique /La comparaison (ou l’une des 2 autres pages, La métaphore, et La métonymie) :

  • Le mécanisme de base va désactiver le lien vers la page affichée (La comparaison) et va griser les 2 derniers niveaux (/Réthorique /La comparaison)
  • Le niveau supplémentaire (Jeux) est géré au cas par cas, en dur, dans le script wp-content /plugins /ecrire-fun-2022 /includes /js /effacer-auto-liens.js où il faut renseigner l’avant dernier niveau (ici Rhétorique) dans le tableau niveau3 :
    • var niveau3 = [« Rhétorique« ];
  • Si un autre parcours à 3 niveaux devenait nécessaire, il faudrait modifier le code en ajoutant le nouvel-avant-dernier-niveau dans le tableau niveau3 :
    • var niveau3 = [« Rhétorique », « nouvel-avant-dernier-niveau« ];
  • Je n’ai pas réussi à mettre en place un algorithme satisfaisant quel que soit le nombre de niveaux.

Pour les articles, les parcours à 3 niveaux ne sont pas gérés dans le script wp-content /plugins /ecrire-fun-2022 /includes /js /effacer-auto-liens-et-categorie.js

  • On pourrait facilement l’envisager mais les articles ont besoin de moins de niveaux que les pages qui ont tendance à être davantage hiérarchisées.

Exclure certains articles

Pour exclure des articles de la liste des articles de la Home (page d’accueil ou page blog) et des archives (Category), il faut :

D’une part :

  1. Récupérer l’identifiant de l’article à exclure : WP-admin /Articles /Tous les articles : positionner la souris sur l’article sans cliquer et lire en bas à gauche l’info post=le n° à récupérer
  2. Editer le fichier /www /wp-content /plugins /ecrire-fun-2022 /includes /mesfonctions.php
  3. Trouver la fonction mes_articles_affichables_filter( $query )
  4. Ajouter l’identifiant de l’article à exclure, dans le tableau (array) $articlesAExclureTests
Fonction mes_articles_affichables_filter( $query )
/* EXCLURE LES ARTICLES DE TEST DE LA LISTE DES ARTICLES ET DES CATEGORIES */

add_filter('pre_get_posts','mes_articles_affichables_filter');
function mes_articles_affichables_filter( $query )
{
    //Les id des articles de test à exclure :
    $articlesAExclureTests = array(24035); //article-test
    $articlesAExclure = array_merge($articlesAExclureTests);
    if ( $query->is_home || $query->is_archive){ 
        $query->set('post__not_in', $articlesAExclure);
    }
}

D’autre part :

  1. Dans le même fichier, trouver la fonction ma_recherche_filter( $query )
  2. Ajouter, dans le tableau (array) $articlesAExclureTests, l’identifiant de l’article à exclure (pour l’exclure des résultats de recherche)
Début de la fonction ma_recherche_filter( $query )
add_filter('pre_get_posts','ma_recherche_filter');

function ma_recherche_filter( $query )
{
    //Les id des pages et articles de test à exclure :
    $pagesAExclureTests = array(13584);    //page 'aa11-test'
    $articlesAExclureTests = array(24035); //article 'article-test'
    //Les id des pages adulte à exclure :
    $pagesAExclureAdultes = array();
    //Les id des pages filles à exclure qui parlent de WP :
    $pagesAExclureWordPress = array(13650, 13743, 13759, 13779, 13797, 13825, 13878, 14009, 14270, 14470, 14489, 14739, 14907, 14926, 15014, 15054, 15184, 15295, 15427, 15436, 16804, 18035, 18347, 18978);

    //Tableau complet des id de toutes les pages HTML à exclure :
    $pagesAExclure = array_merge($pagesAExclureTests, $articlesAExclureTests, $pagesAExclureAdultes, $pagesAExclureWordPress);

REMARQUE : si l’article à exclure n’est pas un article de test, il convient de créer un nouveau tableau (au libellé significatif) et de l’intégrer dans les concaténation (array_merge) des deux fonctions.

Exclure certaines pages

Pour exclure une page des résultats de recherche il faut :

  1. Récupérer l’id de la page à exclure : WP-admin /Pages /Tous les pages : positionner la souris sur la page de la liste sans cliquer et lire en bas à gauche l’info post=le n° à récupérer.
  2. Editer le fichier /www /wp-content /plugins /ecrire-fun-2022 /includes /mesfonctions.php
  3. Trouver la fonction ma_recherche_filter( $query )
  4. Ajouter l’identifiant de la page à exclure des résultats de recherche, dans l’un des tableaux (array) suivant :
    • $pagesAExclureTests
    • $pagesAExclureAdultes
    • $pagesAExclureWordPress
Début de la fonction ma_recherche_filter( $query )
add_filter('pre_get_posts','ma_recherche_filter');

function ma_recherche_filter( $query )
{
    //Les id des pages et articles de test à exclure :
    $pagesAExclureTests = array(13584);    //page 'aa11-test'
    $articlesAExclureTests = array(24035); //article 'article-test'
    //Les id des pages adulte à exclure :
    $pagesAExclureAdultes = array();
    //Les id des pages filles à exclure qui parlent de WP :
    $pagesAExclureWordPress = array(13650, 13743, 13759, 13779, 13797, 13825, 13878, 14009, 14270, 14470, 14489, 14739, 14907, 14926, 15014, 15054, 15184, 15295, 15427, 15436, 16804, 18035, 18347, 18978);

    //Tableau complet des id de toutes les pages HTML à exclure :
    $pagesAExclure = array_merge($pagesAExclureTests, $articlesAExclureTests, $pagesAExclureAdultes, $pagesAExclureWordPress);

REMARQUE : si la page à exclure n’entre pas dans l’une de ces 3 catégories, il convient de créer un nouveau tableau (au libellé significatif) et de l’intégrer dans la concaténation (array_merge) de cette fonction.

Les possibilités des compositions

Les compositions qui peuvent vous intéresser sont les suivantes.

Bouton fermer Détails

wp-admin /Apparence /Editeur /Compositions /Boutons

Il replie tous les blocs Détails et affiche, en haut de la page, le bloc dont l’ancre est debut (n’oubliez pas de donner cette ancre au bloc de votre choix (généralement un bloc au-dessus du bloc Détails, ou de personnaliser cette ancre (voir ci-dessous).

ATTENTION, le script ne doit figurer qu’une seule fois par page : conservez-le avec le 1er bouton et supprimez-le pour les autres boutons s’il y en a.

Vous pouvez remplacer les éléments suivants dans le HTML récupéré (composition non synchronisée) :

  • L’id « debut » par un autre id (ancre), pour repositionner la page sur un autre bloc ou si l’id debut est déjà utilisé
  • Le libeller du bouton « Replier les blocs Détails » par un autre libellé
  • La classe « nice-button » ou « nice-button2 » par une autre classe de mise en forme du bouton, à votre convenance : vous pouvez dupliquer cette classe, en renommer la copie et modifier celle-ci à votre guise (.nice-button se trouve dans wp-admin /Apparence /Personnaliser /CSS additionnel)
  • Dans le script : querySelectorAll(‘details’) par getElementsByClassName(‘classe-des-blocs-détail-a-fermer’) pour cibler un ou plusieurs blocs Détail à fermer en particulier (leur attribuer la classe choisie). Rappel, le script ne doit figurer qu’une seule fois par page.
HTML personnalisé (éléments modifiables en gras)
<!-- Bouton "Replier les blocs Détails" et afficher en haut de la page le bloc dont l'ancre est "debut" -->

<div style="text-align: center;"><br>    <button type="button" class="nice-button2" onclick="replierDetails('debut');"><big><big>Replier les galeries</big></big></button><br></div><br>

<script> //Ce script ne doit être présent qu'une seule fois par page
    function replierDetails(paragraphe){
        let details = document.querySelectorAll('details');
        for (let detail of details) detail.open = false;

        document.getElementById(paragraphe).scrollIntoView();
    }
</script>

Glossaire pour créer un Glossaire

wp-admin /Apparence /Editeur /Compositions /Document

Exemple : utilisé par la page Glossaire (slug = glossaire)

Cette composition non synchronisée peut vous faire gagner beaucoup de temps.

Elle ne présente pas de difficulté.

Visuel

Créer un article ou une page augmenté d’un quiz automatique

wp-admin /Apparence /Editeur /Compositions /Quiz : Quiz-article-21-quest-v3-auto-bonus

La composition non synchronisée Quiz-article-21-quest-v3-auto-bonus permet de récupérer tous les éléments permettant de créer un article augmenté d’un quiz à validation automatique.

Le déroulement d’un quiz conçu avec Quiz-article-21-quest-v3-auto-bonus est le suivant :

  1. L’internaute lit l’introduction, prend éventuellement connaissance du mode d’emploi puis commence le quiz en cliquant sur le bouton (Re)Commencer le quiz : la 1ère question s’affiche.
  2. L’internaute répond à la 1ère question (boîtes à cocher, radio-boutons ou liste déroulante). Il ne peut pas passer à la question suivante tant qu’il n’a pas validé sa réponse. Et dans le cas des listes déroulante ou de boutons radio, il ne peut pas valider sa réponse tant qu’il n’a pas fait un choix (dans le cas de boîtes à cocher, il peut valider sans faire de choix car l’absence de choix est une réponse possible).
  3. L’internaute valide sa réponse en cliquant sur le bouton Valider qui prend la forme OK ou KO selon qu’il a bien répondu ou non.
  4. S’il le désire, l’internaute consulte la solution et/ou l’article/la page grâce à un système de va-et-vient de boutons entre l’article/la page et la question en cours.
  5. Ainsi jusqu’à la dernière question dont le bouton Question suivante fait place à un bouton Vos résultats.
  6. En cliquant sur le bouton Vos résultats, l’internaute va pouvoir consulter son résultat (nombre de bonnes réponses et %) et, juste en dessous, son profil (il y en a 3) en fonction du % de bonnes réponses obtenu.
  7. L’internaute peut revenir au sommaire du quiz où il peut :
    • (Re)Commencer le quiz
    • Clore le quiz : retour au sommaire de l’article ou du quiz selon le paramètre passé à la fonction clore (une string contenant l’id du bloc sur lequel positionner le haut de l’écran).
  8. Le bouton Reprendre votre quiz permet de reprendre le quiz si on est passé à autre chose, sous réserve de ne pas avoir fermé l’article/la page.

La composition est constituée de 2 groupes :

  • Le premier contient les boutons que vous pouvez positionner dans votre article/page pour y faire référence depuis le bloc réponse de chaque question ; ces boutons vous permettent de revenir à la question en cours du quiz.
  • Le second contient l’ensemble du quiz proprement dit (titre, mode opératoire, 22 questions dont la dernière en bonus donne un point quelle que soit la réponse, calcul du résultat, 3 profils fonctions du résultat).

Les inputs sont des radio boutons radio, des boîtes à cocher et des listes déroulantes. Vous pouvez copier-coller certains éléments pour en remplacer d’autres, ou en supprimer certains. Dans tous les cas il vous faudra :

  • Personnaliser les contenus (questions, réponses, profils) et les inputs (bouton radio, boîte à cocher ou liste déroulante)
  • Préciser dans les input les bonne réponses en plaçant value= »1″
  • Positionner dans l’article les blocs HTML fournis dans le 1er groupe de la composition.
  • Ne pas modifier les ancres de référence :
    • sommaire-quiz (groupe du sommaire du quiz)
    • quiz (séparateur suivant le sommaire du quiz)
    • L’ancre de chaque groupe contenant une question doit être, dans l’ordre, de forme q1, q2… q22 en harmonie avec le numéro de la question.
    • Le groupe de la question bonus (si vous la conservez) doit être de forme q1
    • Le groupe de la question bonus (si vous la conservez) doit être de forme q1
    • Le groupe « de la question bonus »Le quiz est terminé doit être de forme q1 (comme si c’était la dernière question)
    • L’ancre du groupe réponse de chaque question doit être de forme q1 en harmonie avec le numéro de la question
  • S’assurer de la cohérence des ancres et identifiants et/ou des numéros entrant dans la composition des identifiants des différents blocs HTML personnalisé (le plus souvent le même que celui de l’identifiant du groupe contenant la question, parfois celui de la question suivante).
Tous les blocs fournis avec identifiants et classes

Ce format Excel peut vous donner des idées pour spécifier des besoins ou documenter une page :

Blocs HTML personnalisé à harmoniser si nécessaire
<!-- Bouton "(Re)commencer le quiz" -->
<div style="text-align: center;">
<button type="button" class="nice-button bt-vert" onclick="raz();">(Re)Commencer le quiz</button>
</div>

<!-- Bouton "Reprendre" -->
<div style="text-align: center;"><button type="button" class="nice-button bt-orange" onclick="continuerQuiz();">Reprendre votre quiz</button></div>

<!-- Bouton "Clore votre quiz" -->
<div style="text-align: center;">
<button type="button" class="nice-button bt-rouge" onclick="clore('sommaire-quiz');">Clore le quiz</button>
</div>

<input type="radio" name="q1" value="1" onchange="activerBtValiderRadio('q1')">
<input type="radio" name="q1" onchange="activerBtValiderRadio('q1')">

<input type="checkbox" name="q2">
<input type="checkbox" name="q2" value="1">

<select name="q3" onchange="activerBtValiderSelect('q3');"><option>Cliquez puis choisissez</option><option value="1">Fouines</option><option>Rats</option><option>Martres</option><option>Lynx</option><option>Chacals</option><option>Chiens</option></select>

<input id="br1cb" type="checkbox" name="bonnereponse">

<button class="bouton-retour-article" onclick="voirArticle('r1', false);">Voir l'article</button>

<button id="r1" class="bouton-retour-quiz" onclick="retourQuiz('q1');">Retour au quiz</button>

<button id="valider-q1" class="question-suivante bouton-valider bt-valider-radio" onclick="resultatQuestion('q1');">Valider</button>

<button id="next-q1" class="question-suivante bouton-question-suivante" onclick="questionSuivante('q2');">Question suivante</button>
<button id="next-q21" class="question-suivante bouton-question-suivante" onclick="questionSuivante('q22');">Question bonus</button>
<button id="next-q22" class="question-suivante bouton-question-suivante" onclick="resultatQuiz('q23');">Vos résultats</button>

<div class="div-centree"><span id="spanresult"></span></div><script>CMABONUS="q22";</script>

L’initialisation de l’article/la page, et toutes les fonctions, se trouvent sur le serveur dans le fichier /www/wp-content/plugins/ecrire-fun-2022/includes/js/quiz-dans-publication.js :

quiz-dans-publication.js
//INITIALISATION DE LA PAGE
 
//Masquer toutes les questions puis afficher la 1ère question
//Aussi utilisée par la fonction raz()
masquerQuestions();
function masquerQuestions(){
    let questions = document.getElementsByClassName("question");
    for (let question of questions){question.style.display = 'none';}
 
    document.getElementById("colonnes-profils").style.display = 'none';
}
 
//Masquer tous les boutons 'Retour au quiz' (modifiés à l'exécution en 'Retour à la question' suivi du numéro de la question)
effacerBoutonsRetourQuiz();
function effacerBoutonsRetourQuiz(){ 
    let razBoutonsRetourQuiz = document.querySelectorAll('.bouton-retour-quiz');
    for (let razBoutonRetourQuiz of razBoutonsRetourQuiz){
        razBoutonRetourQuiz.style.display = 'none';
    }
}
 
//INITIALISATION DU QUIZ
 
//oncliclick du Bouton '(Re)Commencer le quiz'
//Aussi utilisée par la fonction clore('id du bloc sur lequel positionner le haut de l'écran')
function raz(){
    //Masquer tous les blocs Réponse :
    let divsReponse = document.querySelectorAll(".div-reponse"); ///
    for (let divReponse of divsReponse) divReponse.style.display = "none"; ///  
 
    //Afficher tous les boutons Valider dans leur forme 'Valider' :
    let boutonsValider= document.querySelectorAll('.bouton-valider'); ///
    for (let boutonValider of boutonsValider) { ///
        boutonValider.disabled = false; //nécessaire pour box
        boutonValider.innerHTML = "Valider";
        boutonValider.style.color = "black";
        boutonValider.style.backgroundColor = "#F6F6F6";
    } 
    //desactiver tous les Boutons Valider radio :
    let boutonsValiderRadio = document.getElementsByClassName("bt-valider-radio");
    for (let boutonValiderRadio of boutonsValiderRadio) {
        boutonValiderRadio.disabled = true;
        boutonValiderRadio.style.color= "#B1B1B1" //entre lightgrey et grey
    }
    //desactiver tous les Boutons Valider select :
    let boutonsValiderSelect = document.getElementsByClassName("bt-valider-select");
    for (let boutonValiderSelect of boutonsValiderSelect ) {
        boutonValiderSelect.disabled = true;
        boutonValiderSelect.style.color= "#B1B1B1" //entre lightgrey et grey
    }
 
    //desactiver tous les Boutons Question Suivante :
    let boutonsQuestionSuivante = document.querySelectorAll('.bouton-question-suivante'); ///
    for (let boutonQuestionSuivante of boutonsQuestionSuivante) { ///
        boutonQuestionSuivante.disabled = true;
    }
    //Réinitialiser et réactiver tous les select :
    let selects = document.querySelectorAll('select');
    for (let select of selects) { select.selectedIndex = 0; select.disabled=false;} ///
    //Réinitialiser et réactiver tous les boutons radio :
    let radios = document.querySelectorAll('input[type=radio]');
    for (let radio of radios) { radio.checked = false; radio.disabled=false;} ///
    //Réinitialiser et réactiver toutes les checkbox :
    let boxes = document.querySelectorAll('input[type=checkbox]');
    for (let box of boxes) { box.checked = false; box.disabled=false;} ///
    //Refermer tous les blocs Details :
    let details = document.querySelectorAll('details');
    for (let detail of details) { detail.open = false;}
    //Masquer tous les bouton de retour au Quiz placés dans l'article :
    let boutonsRetourQuiz = document.querySelectorAll('.bouton-retour-quiz');
    for (let boutonRetourQuiz of boutonsRetourQuiz ) { boutonRetourQuiz.style.display = 'none';}
 
    //let texteprofils = document.getElementById("profils");
    //texteprofils.textContent = "Puis consultez votre profil qui s'affichera ci-dessous";
    //let spanresult = document.getElementById("spanresult");
    //spanresult.textContent = "";
 
    //Masquer toutes les questions puis afficher la 1ère question
    masquerQuestions();
    document.getElementById("q1").style.display= 'block';
 
    //Positionner l'écran au début du quiz :
    var quiz = document.getElementById("quiz");
    quiz.scrollIntoView();
 
    //quiz.focus();
}
 
//onclick du bouton 'Reprendre votre quiz'
function continuerQuiz(){
    let questions = document.getElementsByClassName("question");
    for (let question of questions){
        if(question.style.display == 'block'){
            question.scrollIntoView();
            return; //Sortir de la fonction si l'une des question est affichée
        };
    }
    //Aucune question affichée donc afficher q1 :
    questions[0].style.display = "block";
    questions[0].scrollIntoView();
}
 
//onclick du bouton 'Clore votre quiz'
function clore(retour){ //retour est une chaîne contenant l'id du bloc sur lequel positionner le haut de l'écran
    raz();
    document.getElementById("q1").style.display= "none";
    var sommaireQuiz = document.getElementById(retour);
    sommaireQuiz.scrollIntoView();
}
 
//GESTION DU BOUTON Valider (une réponse à une question)
 
/*
//Validation manuelle d'une réponse à une question (onclick d'un élément plus utilisé car validation automatique)
function cmaCocherDecocher(monId){
    let bac = document.getElementById(monId+"cb");
    if(bac.checked) bac.checked = false;
    else bac.checked = true;
}
*/
 
//onchange de tous les inputs select du quiz :
function activerBtValiderSelect(q){
    let boutonValiderSelect = document.getElementById("valider-"+q);
    let selects = document.getElementsByName(q); //il n'y a qu'un select avec un nom donné
 
    if (selects[0].selectedIndex == 0) {
        boutonValiderSelect.disabled = true;
        boutonValiderSelect.style.color= "#B1B1B1" //entre lightgrey et grey
    }
    else {
        boutonValiderSelect.disabled = false;
        boutonValiderSelect.style.color= "black"
    }
}
//onchange de tous les inputs radio du quiz :
function activerBtValiderRadio(q){
    let boutonValiderRadio = document.getElementById("valider-"+q);
    boutonValiderRadio.disabled = false;
    boutonValiderRadio.style.color= "black";
}
 
//Validation de la réponse : onclick de tous les boutons 'Valider'
function resultatQuestion(q){ //q id du groupe de la question dt on veut calculer le résultat, exemple 'q21'
    let N = q.replace("q", "");  //Num question
    let boxBienRepondu = document.getElementById("br"+N+"cb");
    let resultatOk = true;
///
    //Désactiver le bouton 'Valider' pour qu'on ne puisse pas revenir dessus
    let boutonValider = document.getElementById ("valider-"+q);
    boutonValider.disabled = true;
    //Réactiver le bouton 'Question suivante' 
    let boutonNext = document.getElementById ("next-"+q);
    boutonNext.disabled = false;
    //Afficher le groupe "div-reponse-"+q
    let divReponse = document.getElementById ("div-reponse-"+q);
    divReponse.style.display = "block";
 
///
    if(CMABONUS != q){
        let chrname = q;
        //Récupérer tous les input box ou radio qui ont chrname
        let inputsRadioOuBox = document.getElementsByName(chrname);
 
        for (let inputChrname of inputsRadioOuBox) { ///
            inputChrname.disabled = true;
        }
 
        if((inputsRadioOuBox.length == 1) && (inputsRadioOuBox[0].tagName == "SELECT")){
            if(inputsRadioOuBox[0].value != "1") resultatOk = false;
        }
        else{ //Radio Ou Box
            //Les parcourir : Si !(coché et value OU !coché et !value) alors resultatOk = false
            for (let inputRadioOuBox of inputsRadioOuBox){
                if(!(
                       (inputRadioOuBox.checked && (inputRadioOuBox.value=='1')) || 
                       (!inputRadioOuBox.checked && !(inputRadioOuBox.value=='1'))
                    )
                  ) resultatOk = false ; 
             }
        }
    }
    //Si resultatOk alors cocher la box avec id="br"+N+"cb" ; alert "OK" ;
    //Sinon la décocher ; alert "KO" ;
    boutonValider.style.color = "white"; ///
    if(resultatOk){
        boxBienRepondu.checked = true;
        boutonValider.innerHTML = "OK"; ///
        boutonValider.style.backgroundColor = "green"; ///
    }
    else{
        boxBienRepondu.checked = false;
        ///alert("KO");
        boutonValider.innerHTML = "KO"; ///
        boutonValider.style.backgroundColor = "red"; ///
    }
}
 
//GESTION DES BOUTONS DE VA-ET-VIENT ENTRE LE QUIZ ET LE TEXTE DE L'ARTICLE
 
// onclick de tous les boutons 'Voir l'article' du quiz (r = id élément au-dessus du bouton 'Retour à la question n') avec details = true si r est dans un DETAILS à ouvrir (au moyen de la fonction ouvrirDetails)
function voirArticle(r, details){ 
    if(details) ouvrirDetails(r, 0);
    let boutonRetourQuestion = document.getElementById(r);
    boutonRetourQuestion.style.display = "block";
    boutonRetourQuestion.innerHTML = "Retour à la question " + r.replace('r', "");
    document.getElementById(r).scrollIntoView({ behavior: "instant", block: "start"}); //block: "center", inline: "center" 
}
//Fonction récursive utilisée par la fonction voirArticle(r, details)
function ouvrirDetails(id, profondeur){
    let prof = profondeur + 1;
    if(prof < 6){
        let element = document.getElementById(id);
        let parent = element.parentElement;
        if (parent.tagName == "DETAILS"){
            parent.open = true;
            if (parent.parentElement.tagName == "DETAILS") parent.parentElement.open = true;
        }
        else if (parent.id != "") ouvrirDetails(parent.id, prof);
        else {
            parent.id = id+'-'+prof;
            ouvrirDetails(parent.id, prof);
        }
    }
}
//onclick de tous les boutons 'Retour au quiz' (modifiés à l'exécution en 'Retour à la question' suivi du numéro de la question)
function retourQuiz(q){
    document.getElementById(q).scrollIntoView();
    document.getElementById(q.replace('q', 'r')).style.display = "none";
}
 
//GESTION DU BOUTON Question suivante
 
//onclick de tous les boutons 'Question suivante' et 'Question bonus'
//Aussi utilisée par la fonction resultatQuiz(q)
function questionSuivante(q){
    document.getElementById("q" + (q.replace("q", "") -1)).style.display = 'none';
 
    let questionSuivante = document.getElementById(q);
    questionSuivante.style.display = 'block'
    questionSuivante.scrollIntoView();
}
 
//CALCUL DU RESULTAT DU QUIZ
 
//onclick du bouton 'Vos résultats' (bouton 'Question suivante' de la dernière question)
function resultatQuiz(q){
    questionSuivante(q);    
    count_chkBox();
}
 
/* Toutes les boîtes à cocher à compter dans la page doivent être définies ainsi en html : <input id="br3cb" type="checkbox" name="bonnereponse"></input> (le numéro inclus dans l'id est le n° de la question)
La zone résultat doit être de type : <span id="spanresult"></span>
NB : ces checkbox sont masquées car les groupes qui les contiennent ont la classe 'displaynone' (masqué par du CSS). Ces checkbox étaient visibles lorsque la validation était manuelle.
*/
//Utilisée par la fonction resultatQuiz(q)
function count_chkBox(){
        var nbre_check = 0;
        //variable des zones à maj dynamiquement :
        let spanresult = document.getElementById("spanresult");
        let texteprofils = document.getElementById("profils");
        texteprofils.textContent = "Consultez votre profil ci-dessous";
 
        let boites = document.getElementsByName("bonnereponse");
        const nbquestions = boites.length;
        for (i=0; i<boites.length; i++) {if (boites[i].checked) nbre_check ++ ;}
        if(nbre_check>1) spanresult.innerHTML = "<b>" + Math.abs(nbre_check).toString() + " bonnes réponses sur " + nbquestions + " soit " + (100*nbre_check/(nbquestions)).toFixed(1) + "%" + "</b>";
        else spanresult.innerHTML = "<b>" + Math.abs(nbre_check).toString() + " bonne réponse sur " + nbquestions + " soit " + (100*nbre_check/(nbquestions)).toFixed(1) + "%" + "</b>";
 
        //Fermer les 3 profils
        let details = document.querySelectorAll('.profil');
        for (let detail of details) { detail.open = false;};
 
        //Ouvrir profil1 (<=25 %)
        if(nbre_check <= nbquestions * 25/100) {
            let detail1 = document.querySelectorAll('.profil1');
            for (let detailbis of detail1) { detailbis.open = true;};
        }
 
        //Ou bien ouvrir profil2 (<= 70%)
        else if(nbre_check <= nbquestions * 70/100) {
            let detail2 = document.querySelectorAll('.profil2');
            for (let detailbis of detail2) { detailbis.open = true;};
        }
 
        //Ou bien ouvrir profil3
        else {
            let detail3 = document.querySelectorAll('.profil3');
            for (let detailbis of detail3) { detailbis.open = true;};
        }
        //Ouvrir la boîte à profils
        let box = document.querySelectorAll('.profils');
        for (let thebox of box) { thebox.open = true;};
        //Ouvrir la colonne de la boîte à profils
        let colonnesProfils = document.getElementById("colonnes-profils");
        colonnesProfils.style.display = 'block';
}
 
/*
Blocs 'HTML spécialisé'
 
<!-- Bouton "(Re)commencer le quiz" -->
<div style="text-align: center;">
<button type="button" class="nice-button bt-vert" onclick="raz();">(Re)Commencer le quiz</button>
</div>
 
<!-- Bouton "Reprendre" -->
<div style="text-align: center;"><button type="button" class="nice-button bt-orange" onclick="continuerQuiz();">Reprendre votre quiz</button></div>
 
<!-- Bouton "Clore votre quiz" -->
<div style="text-align: center;">
<button type="button" class="nice-button bt-rouge" onclick="clore('sommaire-quiz');">Clore le quiz</button>
</div>
 
<input type="radio" name="q1" value="1" onchange="activerBtValiderRadio('q1')">
<input type="radio" name="q1" onchange="activerBtValiderRadio('q1')">
 
<input type="checkbox" name="q2">
<input type="checkbox" name="q2" value="1">
 
<select name="q3" onchange="activerBtValiderSelect('q3');"><option>Cliquez puis choisissez</option><option value="1">Fouines</option><option>Rats</option><option>Martres</option><option>Lynx</option><option>Chacals</option><option>Chiens</option></select>
 
<input id="br1cb" type="checkbox" name="bonnereponse"></input><br>
 
<button class="bouton-retour-article" onclick="voirArticle('r1', false);">Voir l'article</button>
 
<button id="r1" class="bouton-retour-quiz" onclick="retourQuiz('q1');">Retour au quiz</button>
 
<button id="valider-q1" class="question-suivante bouton-valider bt-valider-radio" onclick="resultatQuestion('q1');">Valider</button>
 
<button id="next-q1" class="question-suivante bouton-question-suivante" onclick="questionSuivante('q2');">Question suivante</button>
<button id="next-q21" class="question-suivante bouton-question-suivante" onclick="questionSuivante('q22');">Question bonus</button>
<button id="next-q22" class="question-suivante bouton-question-suivante" onclick="resultatQuiz('q23');">Vos résultats</button>
 
<div class="div-centree"><br>    <span id="spanresult"></span><br></div>
*/

Le fichier quiz-dans-publication.js est chargé dans l’article/la page, par le serveur, grâce au code suivant du fichier /www/wp-content/plugins/ecrire-fun-2022/includes/mesfonctions.php :

add_action('wp_enqueue_scripts', 'cmaAjouterScriptQuizDansPublication');

function cmaAjouterScriptQuizDansPublication() {
    global $cmaWayToJs;
    //Articles et pages devant bénéficier du chargement du script :
    $articlesQuiz = array('article-test', 'voyage-cyclades');
    $pagesQuiz = array('aa11-test');
    
    if(is_single($articlesQuiz) || is_page($pagesQuiz)) {
        wp_enqueue_script('cma-quiz-dans-publication', $cmaWayToJs . 'quiz-dans-publication.js', array(), '1.0.0', true);
    }
}

IMPORTANT :

  • Pour chaque article devant utiliser ce système de quiz, vous devez ajouter son slug dans le tableau $articlesQuiz du code ci-dessus
  • Pour chaque page devant utiliser ce système de quiz, vous devez ajouter son slug dans le tableau $pagesQuiz du code ci-dessus.
  • Comportement de la fonction is_page (idem pour is_single) :
    • if is_page() : toutes les pages récupèrent le script
    • $pagesQuiz = array();
      if is_page($pagesQuiz) : toutes les pages récupèrent le script
    • $pagesQuiz = array(«  »);
      if is_page($pagesQuiz) : aucune page ne récupère le script
    • $pagesQuiz = array(‘aa11-test’);
      if is_page($pagesQuiz) : seule la page de slug aa11-test récupère le script.

REMARQUE : le libellé du bouton Voir article peut rester inchangé dans le cas d’une page car l’internaute ne fait pas de distinction entre page et article. D’autre part, un libellé Voir page serait trompeur car l’internaute assimile souvent la notion de page à la partie de la page visible à l’écran. Autant parler d’article avec l’internaute, que le support soit une page ou un article.

Pour utiliser le quiz sans question bonus :

  1. Modifier le contenu de la variable CMABONUS (recherchez la avec un Ctrl F) de telle sorte qu’elle ne contienne l’identifiant d’aucune question : CMABONUS= »q22″ devient par exemple CMABONUS= »q »
  2. Modifier ‘Question bonus » en « Question 22 »
  3. Modifier le titre du Quiz en « Quiz 22 questions »
  4. Ajouter value= »1″ dans la balise d’entête de l’option contenant la bonne réponse de la liste déroulantye : <option> devient <option value= »1″>
  5. Modifier le bouton « Question bonus » de la question précédente en « Question suivante ».

Pour utiliser le quiz sans les allers-retours entre le quiz et l’article

  1. Supprimer le 1er groupe de la composition
  2. Supprimer le bloc HTML personnalisé « Voir l’article » (button), de l’Empilement contenu dans tous les Groupes dont l’ancre est de la forme div-reponse-q1 :
    • Les rechercher avec un Ctrl F sur voirArticle

Créer un article de catégorie Voyage augmenté d’un quiz automatique

wp-admin /Apparence /Editeur /Compositions /Quiz : Article-voyage-quiz-v1

Cette composition utilise Quiz-article-21-quest-v3-auto-bonus.

Mais avant, elle propose un plan et un sommaire.


Fin du guide utilisateur


Les modèles de twentytwentytwo


wp-admin /Apparence /Editeur /Modèles

Fonctions PHP : wp-content /themes /twentytwentytwo-child/mesfonctions.php

Scripts JS : wp-content /themes /twentytwentytwo-child/js

Tableau récap
Modèle
ou Instance*
(divers) = pas de lien entre les cellules de la ligne
Elément de modèleNomcompo (* si synchro)
ou Bloc Nombloc
ou .nomclasse
Script JS (.js)
ou fonction() PHP
ou /code court/
o Index
o Page 404
Pied de page
o Index
o Accueil
En-tête (petit sombre) sans rétro-lien /En-tête sans rétro-lienMenu*/bouton_top/
Accueil (divers)Pied de pageBouton fermer Détails

Bloc Recherche
/lire_la_suite/

ma_recherche_filter()
Page (divers)WPYSEO breadcrumb*effacer-auto-liens.js

cma-sommaire-h2-h6-dans-class-div-sommaire.js

page-racine-de-recherche.js
o Page
o Page 404
o Recherche
o Archive
En tête sans menuMenu*/bouton_top/
Archive (divers)Pied de pageBloc Recherche/lire_la_suite/

effacer-auto-liens.js

categorie-de-recherche.js
ma_recherche_filter()
Recherche (divers)Pied de pageBloc Recherche/lire_la_suite/

contrainte-de-recherche.js
ma_recherche_filter()
Publications seulesEn têteMenu*/bouton_top/
Publications seules (divers)Pied de pageeffacer-auto-liens-et-categorie.js

cma-sommaire-h2-h6-dans-class-div-sommaire.js
Page*Bloc Recherche avec .racine-de-recherchema_recherche_filter()
o Page* (divers)
o Publications seules* (divers)
Groupe class-div-sommaire*/wpversion/
Tableau récap des modèles de twentytwentytwo
Rappel des noms de fichiers des différents modèles (dossier templates)
  • Page 404 : 404.html
  • Index : index.html
  • Accueil : home.html
  • Archive : archive.html
  • Recherche : search.html
  • Pages : page.html
  • Publications seules : single.html

Les barres de navigation des modèles


wp-admin /Apparence /Editeur /Compositions /Gérer tous les éléments de modèles

Il y a 3 barres de navigation différentes, correspondant à 3 éléments de modèle différents, utilisés par les 6 modèles du thème twentytwentytwo.

Tableau récap

Les éléments de modèles contenant ces barres de navigation sont mal nommés mais on ne peut pas les renommer :

Modèles WP 2022Elément de modèle de type En-têteCaractéristiques de la barre de navigation
(toutes avec compo Menu et code court /bouton_top/)
Accueil
En-tête (petit, sombre) sans rétro-lien /En-tête sans rétro-lieno Icone non cliquable
o Avec titre du site
o Sans catégorie
o Page
o Page 404
o Archive
o Recherche
En-tête sans menuo Icone cliquable
o Avec titre du site
o Sans catégorie
Publications seulesEn-têteo Icone cliquable
o Pas de titre du site
o Avec la catégorie de l’article
Tableau récapitulatif des en-têtes des modèles de twentytwentytwo
Illustration
  • Modèle Publications seules (articles) : menu et catégories (en fait un article n’appartient qu’à une seule catégorie) et sans le titre (rire et écrire) qui prendrait trop de place sur smartphone (à cause de la catégorie affichée à droite) :
  • Modèles Page, Accueil, Recherche, Archive : menu sans catégorie mais avec le titre (rire et écrire), avec une particularité pour Accueil où l’icone est non cliquable (puisqu’on est déjà sur l’écran cible) :

Dans toutes les barres :

  • Le bouton permettant de remonter en haut de la page est instancié au moyen du code court bouton_top.
  • Le menu proprement dit est la composition synchronisée Menu
  • Toutes les barres restent affichées en haut de la page grâce à l’extension myStickymenu : la classe cmaepingler a été attribuée au bloc Rangée constituant la rangée principale de chaque barre.

Compo synchro Menu

wp-admin /Apparence /Editeur /Compositions /Menu

Visuel de la compo synchronisée Menu

Description : Menu est utilisée dans les éléments de modèles d’en-tête de tous les modèles : Accueil, Archive, Recherche, Page, Publications seules et Index (le modèle par défaut).

Voici ce que ça donne dans l’élément de modèle En-tête sans rétro-lien utilisé par le Modèle Accueil

Compo synchro Menu WP

wp-admin /Apparence /Editeur /Compositions/Menu

Visuel de la compo synchro Menu

Utilisée par :

  • la composition Sommaire avec menu WP ;
  • ou directement par certaines pages filles de la page Construire et gérer un blog avec WordPress (slug = wordpress), sans sommaire : exemple, la page Check-list (slug = check-list).

Les boutons


Code court bouton_top

Appel : [bouton_top]

Utilisé par :

  • L’élément de modèle En-tête sans rétro-lien, du Modèle Accueil
  • Les éléments de modèles d’en-tête, des modèles Archive, Recherche, Page, Publications seules.

Description : ce short code appelle la fonction cma_bouton_top(). Cette fonction renvoie sous la forme d’une chaîne de caractères, l’intégralité du HTML à la composition.

mesfonctions.php : activation du short code et fonction cma_bouton_top()
function cma_bouton_top() {
    $html = '<div style="text-align: center;"><button type="button" onclick="montop();"><big>▲</big></button></div>'; 
    $html.= '<script>function montop(){ scrollTo(0,0); }</script>';

    return $html;
}

add_shortcode( 'bouton_top', 'cma_bouton_top' );

Compo non synchro Bouton fermer Détails

wp-admin /Apparence /Editeur /Compositions /Boutons

Description : replie tous les blocs Détails et affiche, en haut de la page, le bloc dont l’ancre est debut.

Utilisée par exemple dans un bloc Détails de la page Construire et gérer un blog avec WordPress (wordpress).

On peut, dans le script, modifier le libellé du bouton en fonction du contexte.

HTML script inclus
<!-- Bouton "Replier les blocs Détails" et afficher en haut de la page le bloc dont l'ancre est "debut" -->
<div style="text-align: center;">
    <button type="button" class="nice-button" onclick="replierDetails();">
        <big><big>Replier les blocs Détails</big></big>
    </button>
</div>
<script>
    function replierDetails(){
        let details = document.querySelectorAll('details');
        for (let detail of details) detail.open = false;

        document.getElementById("debut").scrollIntoView();
    }
</script>

Composer des documents


Compo non synchro Mot d’esprit

wp-admin /Apparence /Editeur /Compositions /Document

Utilisé par l’article Mots d’esprit (slug = mots-esprit)

Visuel

L’extension ecrire-fun-2022


wp-content /plugins /ecrire-fun-2022

Architecture

Les dossiers de l’extension ecrire-fun-2022
wp-content/plugins
wp-content /plugins /ecrire-fun-2022
wp-content /plugins
/ecrire-fun-2022/includes
wp-content /plugins
/ecrire-fun-2022/includes/js

L’extension contient :

  1. Le fichier ecrire-fun-2022.php définissant l’extension
    • wp-content /plugins /ecrire-fun-2022 /ecrire-fun-2022.php
    • ecrire-fun-2022.php récupère le fichier mesfonctions.php
ecrire-fun-2022.php
<?php
/*
 * Plugin Name: ecrire-fun-2022
 * Description: Utilisé par le site écrire.fun avec le thème WP 2022. Gère la Recherche sélective, la désactivation des liens inutiles, les sommaires, les short codes.
 * Author: CHIRO314
 * Version: 1.0
 */

require_onc eplugin_dir_path(__FILE__) . 'includes/mesfonctions.php';
  1. Le fichier wp-content /plugins /ecrire-fun-2022 /includes /mesfonctions.php où l’on trouve :
    • Les fonctions de filtre de l’écran d’administration des Pages WP
    • Les codes courts (fonctions et chargements)
    • Les fonctions de chargement de tous les scripts JS
    • La fonction de filtre des recherches.
  1. Le dossier contenant les scripts JS
    • wp-content /plugins /ecrire-fun-2022 /includes /js/
    • Dans le fichier mesfonctions.php, le chemin vers le dossier js est indiqué de la façon suivante :
$cmaWayToJs = plugin_dir_url( __FILE__ ) . "js/";
Intégralité du fichier mesfonctions.php
<?php
/**** Auteur : CM *************** ACCES A CE FICHIER *************************/

//dans wp-content /plugins /ecrire-fun-2022/ecrire-fun-2022.php :
//require_once plugin_dir_path(__FILE__) . 'includes/mesfonctions.php';

/************************************* VARIABLES GLOBALES ******************/

//$cmaWayToJs = get_stylesheet_directory_uri() . '/js/';    //thème enfant
//$cmaWayToJs = get_template_directory_uri() . '/js/';    //thème parent 2022
//$cmaWayToJs = get_theme_root(). '/twentytwentytwo-child/js/'; //là ça ne marche pas ??
//var_dump( $cmaWayToJs);
//$cmaWayToJs ="https://xn--crire-9ra.fun/wp-content/themes/twentytwentytwo-child/js/";  // en dur ça marche
//$cmaWayToJs ="https://xn--crire-9ra.fun/wp-content/plugins/ecrire-fun-2022/includes/js/"; // en dur ça marche

$cmaWayToJs = plugin_dir_url( __FILE__ ) . "js/";


/**************** ADMINISTRATION *************************************************/

/* Auteur : CM ****** LIEN PERSONNALISER ***************
 * j'ai constaté que le menu 'wp-admin /Apparence / Personnaliser' n'est plus affiché.
 * En attendant qu'il réapparaisse, j'ai ajouté son lien dans la barre d'outils, notamment pour pouvoir modifier mon CSS.
 * J'ai pu récupérer le lien (customize.php) sur un site de test où le menu n'avait pas disparu.
 * A toute fin utile, les 2 autres sous-menus du menu Apparence sont : themes.php et site-editor.php
*******************************************************/
add_action('admin_bar_menu', 'wpcma_barre_outils_liens', 999); 
function wpcma_barre_outils_liens($wp_admin_bar) {
    //global $wp_admin_bar;
    $args = array(
	'id' => 'cma_personnaliser',
	'title' => 'Personnaliser',
	'href' => 'https://xn--crire-9ra.fun/wp-admin/customize.php'
    );
    $wp_admin_bar->add_node($args);
}

/* Auteur : CM ************************************ COLONNE SYNCHRO dans ADMIN WP_BLOCK (COMPOSITIONS) *****************
*  Ajouter une colonne "Synchro" dans l'écran d'administration des Compositions (wp_block).
*  manage_wp_block_posts_columns : OK 
*  manage_wp_block_custom_column et manage_wp_blocks_custom_column: KO
*
*  Essai ci-dessous avec page et pages : OK
***************************************************/

/*****************************************************************
add_filter('manage_page_posts_columns', function($lesColonnes)) {
    $lesColonnes['nombre_de_mots'] = 'Nb mots';

    return $lesColonnes;
});

add_filter('manage_page_posts_columns' , 'ordre_des_colonnes');
function ordre_des_colonnes($columns) {
    return array(
        'cb' => $columns['cb'],
        'title' => $columns['title'],
        'nombre_de_mots' => $columns['nombre_de_mots'],
        'comments' => $columns['comments'],      
    );
}

******************************************************************/

//Regroupe les 2 fonctions ci-dessus : créer une colonne et ordonner les colonnes :

add_filter('manage_page_posts_columns' , 'cma_admin_pages_colonnes');
function cma_admin_pages_colonnes($columns) {
    return array(
        'cb' => $columns['cb'],
        'title' => $columns['title'],
        'date' => $columns['date'],
        'nombre_de_mots' => 'Nb mots',
        'comments' => $columns['comments']
    );
}

//Alimenter la nouvelle colonne :

add_action('manage_pages_custom_column','cma_admin_pages_nb_mots', 10, 2); //priorité : 10 par défaut, 2 : nombre d'arguments acceptés par la fonction
function cma_admin_pages_nb_mots($laColonne, $le_id){
    switch ($laColonne) {
        case 'nombre_de_mots':
            $nbMots = str_word_count( //PHP : compter les mots
                strip_tags(  //PHP : ôter les balises HTML et PHP
                    strip_shortcodes(    //WP : ôter les balises de codes courts
                        get_post_field('post_content', $le_id)  //WP : récupérer le contenu de l'élément dont l'id est dans $post_id
                    )
                )
            );
            echo $nbMots;   //PHP : cracher la valeur de $nbMots
        break;
    }
} 

/********************** 6 SHORT CODES *******************************************/

/* Auteur : CM ************************************ HAUT DE PAGE *****************
*  Bouton permettant de remonter en haut de la page.
*********************************************************************************/

add_shortcode('bouton_top', 'cma_bouton_top');
function cma_bouton_top() {

    $html = '<div style="text-align: center;"><button type="button" onclick="montop();"><big>▲</big></button></div>'; 
    $html.= '<script>function montop(){ scrollTo(0,0); }</script>';

    return $html;
}

/* Auteur : CM ************************************ FERMER DETAILS *****************
*  Bouton permettant de fermer tous les détails.
*********************************************************************************/

/***** Ne fonctionne pas : body.scrollTop est toujours = à 0

add_shortcode('fermer_details', 'cma_fermer_details');
function cma_fermer_details() {

    $html = '<div style="text-align: center;"><button type="button" onclick="fermer_details();"><big><big>●</big></big></button></div>'; 
    $html.= '<script>function fermer_details(){ 
        let scrollTop = document.body.scrollTop;
alert(scrollTop);
        let details = document.querySelectorAll("details"); for (let detail of details) detail.open = false; 
        scrollTo(0,scrollTop); }</script>';

    return $html;
}

******/

/* Auteur : CM ************************************ LIRE LA SUITE *****************
*  texte de Lire la suite
*********************************************************************************/

add_shortcode('lire_la_suite', 'cma_lire_la_suite');
function cma_lire_la_suite() {

    $html = '<p><em><strong>Lire la suite</strong> : cliquer sur titre ou image</em></p>'; 

    return $html;
}

/* Auteur : CM ************************************ VERSION WP *****************
*  numéro de la version de WP
*********************************************************************************/

add_shortcode('wpversion', 'cma_wpversion');
function cma_wpversion($atts) { 

    global $wp_version;

    //La couleur et la taille sont passées en paramètres : $atts['couleur'] vaut "black" par défaut et $atts['taille'] vaut "1rem" par défaut
    $atts = shortcode_atts( 
                array('couleur' => "black", 'taille' => "1rem"),
                $atts,
                'wpversion' );
    
    $html = '<p style="font-size: '.$atts['taille'].'; color: '.$atts['couleur'].';"><em><strong>'.$wp_version.'</strong></em></p>'; 

    return $html;
}

/* Auteur : CM **************************** SOMMAIRE SIMPLE ************
*  HTML du code court sommaire_simple h=n
**************************************************************************/

add_shortcode('sommaire_simple', 'cma_sommaire_simple');
function cma_sommaire_simple($atts) { 
    //$atts['h'] vaut 3 par défaut
    $atts = shortcode_atts(
                array('h' => 3,),
                $atts,
                'sommaire_simple' );
    
    //Contrôle de h
    if($atts['h'] !=2 and $atts['h'] !=3 and $atts['h'] !=4 and $atts['h'] !=5 and $atts['h'] !=6) $atts['h'] =3;
 
    //$html = '<div id="id-div-sommaire-'.$atts['h'].'"></div>';
    $html = '<div class="class-div-sommaire-'.$atts['h'].'"></div>';
 
    return $html;
}

/* Auteur : CM **************************** SOMMAIRE DOUBLE ************
*  HTML du code court sommaire_double h=n
**************************************************************************/

add_shortcode('sommaire_double', 'cma_sommaire_double');
function cma_sommaire_double($atts) { 
    //$atts['h'] vaut 3 par défaut
    $atts = shortcode_atts(
                array('h' => 3,),
                $atts,
                'sommaire_double' );
    
    //Contrôle de h
    if($atts['h'] !=2 and $atts['h'] !=3 and $atts['h'] !=4 and $atts['h'] !=5) $atts['h'] =3;
 
    $html = 
    '<div id="double-sommaire" style="text-align: left;">
        <button id="double-sommaire-bouton1" onclick="afficherSommaire();">
            <big><big>SOMMAIRE</big></big>
        </button>
        <button id="double-sommaire-bouton2" onclick="afficherDetail();">
            <big><big>DETAIL</big></big>
        </button>
    </div>'; 
    $html.= '<div id="sommaire-div-id"><div class="class-div-sommaire-'.$atts['h'].'"></div></div>';
    $html.= '<div id="detail-div-id"><div class="class-div-sommaire-6"></div></div>';  
 
    return $html;
}

/* Auteur : CM **************************** SOMMAIRE AU CHOIX ************
*  HTML du code court sommaire_au_choix h=n (n profondeur de 1er affichage)
**************************************************************************/

add_shortcode('sommaire_au_choix', 'cma_sommaire_au_choix');
function cma_sommaire_au_choix($atts) { 
    //$atts['h'] vaut 3 par défaut
    $atts = shortcode_atts(
                array('h' => 3,),
                $atts,
                'sommaire_au_choix' );
   
    //Contrôle de h
    //if($atts['h'] !=2 and $atts['h'] !=3 and $atts['h'] !=4 and $atts['h'] !=5 and $atts['h'] !=6) $atts['h'] =3;
    $profValeurs = [2,3,4,5,6];
    if(!in_array($atts['h'], $profValeurs)) $atts['h'] = 3;
 
    $selected = ["","","","",""];
    $selected[$atts['h']-2] = "selected";

    $html = '
        <div>
        <label for="prof-select"><b>SOMMAIRE</b> de niveau</label>
        <select name="prof-select" id="prof-select">
          <option value="2" '.$selected[0].'>1</option>
          <option value="3" '.$selected[1].'>2</option>
          <option value="4" '.$selected[2].'>3</option>
          <option value="5" '.$selected[3].'>4</option>
          <option value="6" '.$selected[4].'>5</option>
        </select>
        </div>';
    $html.= '<div id="sommaire-div-id-select"><div class="class-div-sommaire-'.$atts['h'].'"></div></div>';

    return $html;
}

/******************* LIENS - SOMMAIRES - RECHERCHES ****************************************/


/* Auteur : CM ************************************ EFFACER AUTO LIENS ***********************
*  Chargement du script cma-effacer-auto-liens pour page et category
*********************************************************************************************/

add_action('wp_enqueue_scripts', 'cmaAjouterScriptEffacerAutoLiens');

function cmaAjouterScriptEffacerAutoLiens() {  //thème enfant

    global $cmaWayToJs;
    
    if(is_category() or is_page()) {

        //$coucou = get_stylesheet_directory_uri() . '/js/effacer-auto-liens.js'; var_dump($coucou); 
        //Thème de base get_template_directory_uri   Thème enfant : get_stylesheet_directory_uri

        wp_enqueue_script('cma-effacer-auto-liens', $cmaWayToJs . 'effacer-auto-liens.js', array(), '1.0.0', true);

    }
}

/* Auteur : CM ************************************ EFFACER AUTO LIENS ET CATEGORIE ***********************
*  Chargement du script cma-effacer-auto-liens-et-categorie pour article
**********************************************************************************************************/

add_action('wp_enqueue_scripts', 'cmaAjouterScriptEffacerAutoLiensEtCategorie');
function cmaAjouterScriptEffacerAutoLiensEtCategorie() {
    global $cmaWayToJs;
    if(is_single()) {
        //Pour un thème enfant
        wp_enqueue_script('cma-effacer-auto-liens-et-categorie', $cmaWayToJs . 'effacer-auto-liens-et-categorie.js', array(), '1.0.0', true);
        //Pour un thème de base, remplacer la fonction get_stylesheet_directory_uri par get_template_directory_uri
    }
}

/* Auteur : CM ************************************ SOMMAIRES ***********************
*  Chargement des 3 scripts pour page et article
************************************************************************************/
add_action('wp_enqueue_scripts', 'cmaSommairesH2H6DansClassDivSommaireN');
function cmaSommairesH2H6DansClassDivSommaireN(){
    global $cmaWayToJs;    
    if(is_single() or is_page()) {
        wp_enqueue_script('cma-sommaires-h2-h6-dans-class-div-sommaire-n', $cmaWayToJs . 'sommaires-h2-h6-dans-class-div-sommaire-n.js', array(), '1.0.0', true);
    }
}

add_action('wp_enqueue_scripts', 'cmaSommaireDouble');
function cmaSommaireDouble(){
    global $cmaWayToJs;    
    if(is_single() or is_page()) {
        wp_enqueue_script('cma-sommaire-double', $cmaWayToJs . 'sommaire-double.js', array(), '1.0.0', true);
    }
}

add_action('wp_enqueue_scripts', 'cmaSommaireAuChoix');
function cmaSommaireAuChoix(){
    global $cmaWayToJs;    
    if(is_single() or is_page()) {
        wp_enqueue_script('cma-sommaire-au-choix', $cmaWayToJs . 'sommaire-au-choix.js', array(), '1.0.0', true);
    }
}

/* Auteur : CM ************************************ RECHERCHE ***************
*  Fonction complémentaire des scripts : categorie-de-recherche.js ; page-racine-de-recherche.js ; contrainte-de-recherche.js.
*  Selon le cas, la fonction ma_recherche_filter() :
*  o Limitera la recherche à certaines pages (les pages feuilles) quand le champ 'racine' sera présent et renseigné dans le formulaire de recherche
*  o Limitera la recherche aux articles de la catégorie quand le champ 'categorie' sera présent et renseigné dans le formulaire de recherche.
*****************************************************************************/

//Je demande que ma fonction (ma_recherche_filter) soit utilisée (add) avant (pre) de récupérer (get) les page HTML (posts) pour filtrer (filter) le résultat de la Recherche (add_filter('pre_get_posts',) : 

add_filter('pre_get_posts','ma_recherche_filter');

function ma_recherche_filter( $query )
{
    //Les id des pages de test à exclure :
    $pagesAExclureTests = array(13584);
    //Les id des pages adulte à exclure :
    $pagesAExclureAdultes = array(12575, 12563, 10874);
    //Les id des pages filles à exclure qui parlent de WP :
    $pagesAExclureWordPress = array(13650, 13743, 13759, 13779, 13797, 13825, 13878, 14009, 14270, 14470, 14489, 14739, 14907, 14926, 15014, 15054, 15184, 15295, 15427, 15436, 16804, 18035, 18347, 18978);
    //N.B. : pour éviter d'avoir à noter tous ces id, prévoir une fonction qui récupère ces id à tous les niveaux de profondeur, à partir du slug de la page parent.

    //Tableau complet des id de toutes les pages HTML à exclure :
    $pagesAExclure = array_merge($pagesAExclureTests, $pagesAExclureAdultes, $pagesAExclureWordPress);

    $libelleracine = "racine";
    $libelleracine2 = "categorie";

    //Si je ne suis pas dans WP-admin :
    if(!is_admin() && $query->is_main_query()){
        //Si la requête concerne une recherche :
        if ( $query->is_search ){ 
            //Si le formulaire contient un champ "racine" et qu'il n'est pas vide :
            if (isset($_GET[$libelleracine]) and $_GET[$libelleracine] != "" ) {
                //Je récupère l'objet associé à la page racine :
                $mypost = get_page_by_path($_GET[$libelleracine], '', 'page');
                //Je récupère les pages fille de cette page racine :
                $mypages = get_pages(array('child_of' => $mypost->ID, 'sort_column' => 'post_date', 'sort_order' => 'desc'));
                //S'il existe des pages filles :
                if(count($mypages) >0){
                    //Je mets dans un tableau l'id de chacune des pages filles :
                    foreach($mypages as $myPage) $pagesAInclure[] = $myPage->ID;
                    //Je paramètre la requête pour qu'elle se limite à rechercher parmi les pages (filles) dont je fourni le tableau des id :
                    $query->set('post__in', $pagesAInclure);
                } else{
                    //Je paramètre la requête pour qu'elle exclue toutes les pages et articles (dont je fourni le tableau des id) :
                    $toutesLesPages = get_pages();
                    foreach($toutesLesPages as $unePage) $pagesAExclure2[] = $unePage->ID;
                    $toutsLesArticles = get_posts(array('numberposts' => -1));
                    foreach($toutsLesArticles as $unArticle) $articlesAExclure[] = $unArticle->ID;
                    $pagesAExclure3 = array_merge($pagesAExclure2, $articlesAExclure);
                    $query->set('post__not_in', $pagesAExclure3);
                }
            }
            //Si le formulaire contient un champ "categorie" et qu'il n'est pas vide :
            else if (isset($_GET[$libelleracine2]) and $_GET[$libelleracine2] != "" ) {
                //Je récupère l'objet associé à la categorie :
                $mypost = get_category_by_slug($_GET[$libelleracine2]);
                //Je récupère les articles de cette categorie :
                $mypages = get_posts(array('category' => $mypost->term_id, 'sort_column' => 'post_date', 'sort_order' => 'desc', 'numberposts' => -1));
                if(count($mypages) >0){
                    //Je mets dans un tableau l'id de chacun des articles de la catégorie :
                    foreach($mypages as $myPage) $pagesAInclure[] = $myPage->ID;
                    //Je paramètre la requête pour qu'elle se limite à rechercher parmi les articles de la catégorie, dont je fourni le tableau des id :
                    $query->set('post__in', $pagesAInclure);
                } else{
                    //Je paramètre la requête pour qu'elle exclue toutes les pages et articles (dont je fourni le tableau des id) :
                    $toutesLesPages = get_pages();
                    foreach($toutesLesPages as $unePage) $pagesAExclure2[] = $unePage->ID;
                    $toutsLesArticles = get_posts(array('numberposts' => -1));
                    foreach($toutsLesArticles as $unArticle) $articlesAExclure[] = $unArticle->ID;
                    $pagesAExclure3 = array_merge($pagesAExclure2, $articlesAExclure);
                    $query->set('post__not_in', $pagesAExclure3);
                }              
            }
            //Si le formulaire ne contient ni de champ "racine", ni de champ "categorie" non vides :
            else {
                //Je paramètre la requête pour qu'elle exclue certaines pages dont je fourni le tableau des id :
                $query->set('post__not_in', $pagesAExclure);
            }
        }
    }
    //A toute fin utile, la fonction retourne la requête reparamétrée :
    return $query;
} //fin de ma fonction

/* Auteur : CM ************************************ RECHERCHE : TOUTE CATEGORIE EST UNE RACINE DE RECHERCHE **********************
*  Chargement du script cma-categorie-de-recherche pour catégorie
**********************************************************************************************************/

add_action('wp_enqueue_scripts', 'cmaAjouterScriptCategorieDeRecherche');
function cmaAjouterScriptCategorieDeRecherche() {
    global $cmaWayToJs;
    if(is_category()) {
        wp_enqueue_script('cma-categorie-de-recherche', $cmaWayToJs . 'categorie-de-recherche.js', array(), '1.0.0', true);
    }
}

/* Auteur : CM ************************************ RECHERCHE : TOUTE PAGE EST POTENTIELLEMENT RACINE DE RECHERCHE **********************
*  Chargement du script cma-page-racine-de-recherche pour catégorie
**********************************************************************************************************/

add_action('wp_enqueue_scripts', 'cmaAjouterScriptPageRacineDeRecherche');
function cmaAjouterScriptPageRacineDeRecherche() {
    global $cmaWayToJs;
    if(is_page()) {
        wp_enqueue_script('cma-page-racine-de-recherche', $cmaWayToJs . 'page-racine-de-recherche.js', array(), '1.0.0', true);
    }
}

/* Auteur : CM **************************** RECHERCHE : TOUTE RECHERCHE RESTREINTE DOIT SE POURSUIVRE AINSI **********************
*  Chargement du script cma-contrainte-de-recherche pour résultat de recherche (search)
**********************************************************************************************************/

add_action('wp_enqueue_scripts', 'cmaAjouterScriptContrainteDeRecherche');
function cmaAjouterScriptContrainteDeRecherche() {
    global $cmaWayToJs;
    if(is_search()) {
        wp_enqueue_script('cma-contrainte-de-recherche', $cmaWayToJs . 'contrainte-de-recherche.js', array(), '1.0.0', true);
    }
}

Fonctionnalités majeures

La gestion des liens dans les menus

Tout le PHP se trouve dans mesfonctions.php

Pour toutes les pages et catégories

Principe :

  • neutraliser le lien du menu qui pointe vers la page elle-même ou vers la catégorie dont on vient de lister les articles
  • et griser ce lien et son chemin.
Script effacer-auto-liens.js
//Effacer les liens de la page qui pointent vers la page elle-même :

var urlcourante = document.location.href; 
// Supprimons l'éventuel dernier slash de l'URL
urlcourante = urlcourante.replace(/\/$/, "");
// Gardons dans la variable queue_url uniquement la portion derrière le dernier slash de urlcourante
var queue_url = urlcourante.substring (urlcourante.lastIndexOf( "/" )+1 );

const liensPage = document.querySelectorAll("a");

if(liensPage.length > 0){
    var urlLien;
    var queue_urlLien;
    var parent = [];
    var niveau3 = ["Rhétorique"];

    for (let pas = 0; pas < liensPage.length; pas++) {
        if(liensPage[pas].hasAttribute("href")){
            urlLien = liensPage[pas].getAttribute("href");
            urlLien = urlLien.replace(/\/$/, "");
            queue_urlLien = urlLien.substring(urlLien.lastIndexOf("/") +1);
            if(queue_url == queue_urlLien){
                liensPage[pas].removeAttribute ('href');
                //liensPage[pas].style.background-color = 'grey'; //ne semble pas fonctionner
                liensPage[pas].setAttribute ('style','background-color:grey; color:white'); //peut écraser d'autres éléments du style
                parent = liensPage[pas].parentElement.parentElement.parentElement.querySelectorAll('a');
                parent[0].setAttribute ('style','background-color:grey; color:white');
                //Les 3e niveaux sont traités au cas par cas :
                //if (parent[0].innerHTML == "Rhétorique"){
                if (niveau3.indexOf (parent[0].innerHTML) != -1){
                    liensPage[pas].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.querySelectorAll('a')[0].setAttribute ('style','background-color:grey; color:white');
                }
            }
        }
    }
}
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaAjouterScriptEffacerAutoLiens');

function cmaAjouterScriptEffacerAutoLiens() {  //thème enfant

    global $cmaWayToJs;
    
    if(is_category() or is_page()) {

        //$coucou = get_stylesheet_directory_uri() . '/js/effacer-auto-liens.js'; var_dump($coucou); 
        //Thème de base get_template_directory_uri   Thème enfant : get_stylesheet_directory_uri

        wp_enqueue_script('cma-effacer-auto-liens', $cmaWayToJs . 'effacer-auto-liens.js', array(), '1.0.0', true);

    }
}
Pour tous les articles

Le principe est, en plus, de neutraliser et griser le lien du menu qui pointe vers la catégorie de l’article quand celui-ci est le seul de sa catégorie (si un lien vers l’article lui-même est trouvé dans le menu alors, l’article est unique dans sa catégorie, donc il faut supprimer le lien vers sa catégorie au bout de la barre de menu)

Script effacer-auto-liens-et-categorie.js
//Effacer les liens de l'article qui pointent vers l'article lui-même, et vers sa catégorie :

let urlcourante = document.location.href; 
// Supprimons l'éventuel dernier slash de l'URL
urlcourante = urlcourante.replace(/\/$/, "");
// Gardons dans la variable queue_url uniquement la portion derrière le dernier slash de urlcourante
let queue_url = urlcourante.substring (urlcourante.lastIndexOf( "/" )+1 );

const liensPage2 = document.querySelectorAll("a");
const lienCategorie = document.querySelectorAll(".taxonomy-category a");

if(liensPage2.length > 0){
    
    let urlLien;
    let queue_urlLien
    for (let pas = 0; pas < liensPage2.length; pas++) {
        if(liensPage2[pas].hasAttribute("href")){
            urlLien = liensPage2[pas].getAttribute("href");
            urlLien = urlLien.replace(/\/$/, "");
            queue_urlLien = urlLien.substring(urlLien.lastIndexOf("/") +1);
            if(queue_url == queue_urlLien){
                liensPage2[pas].removeAttribute ('href');
                liensPage2[pas].setAttribute ('style','background-color:grey');
                liensPage2[pas].parentElement.parentElement .parentElement.querySelectorAll('a')[0].setAttribute ('style','background-color:grey');

                //Si lien trouvé dans le menu pour un article alors l'article est unique dans sa catégorie, donc il faut supprimer le lien vers sa catégorie au bout du menu :
                lienCategorie[0].removeAttribute ('href');
                lienCategorie[0].setAttribute ('style','background-color:grey');
            }
        }
    }
}
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaAjouterScriptEffacerAutoLiensEtCategorie');
function cmaAjouterScriptEffacerAutoLiensEtCategorie() {
    global $cmaWayToJs;
    if(is_single()) {
        //Pour un thème enfant
        wp_enqueue_script('cma-effacer-auto-liens-et-categorie', $cmaWayToJs . 'effacer-auto-liens-et-categorie.js', array(), '1.0.0', true);
        //Pour un thème de base, remplacer la fonction get_stylesheet_directory_uri par get_template_directory_uri
    }
}

La génération des sommaires

Récap des HTML des 3 types de sommaires
HTML attendu sommaire_simple h=n
<div id="class-div-sommaire-'.$atts['h'].'"></div>
HTML attendu sommaire_double h=n
<div id="double-sommaire" style="text-align: left;">
    <button id="double-sommaire-bouton1" type="button" onclick="afficherSommaire();">
        <big><big>SOMMAIRE</big></big>
    </button>
    <button id="double-sommaire-bouton2" type="button" onclick="afficherDetail();">
        <big><big>DETAIL</big></big>
    </button>
</div>
<div id="sommaire-div-id">
    <div id="class-div-sommaire-'.$atts['h'].'"></div>
</div>
<div id="detail-div-id">
    <div id="class-div-sommaire-6"></div>
</div>
HTML attendu sommaire_au_choix h=n
<div>
    <label for="prof-select">SOMMAIRE de niveau </label>
    <select name="prof-select" id="prof-select">
        <option value="2" '.$selected[0].'>1</option>
        <option value="3" '.$selected[1].'>2</option>
        <option value="4" '.$selected[2].'>3</option>
        <option value="5" '.$selected[3].'>4</option>
        <option value="6" '.$selected[4].'>5</option>
    </select>
</div>';
<div id="sommaire-div-id-select">
    <div id="class-div-sommaire-'.$atts['h'].'"></div>
</div>';
Code court sommaire_simple h=n
Appel : [sommaire_simple h=n] (n de 2 à 6 indique la profondeur des titres à afficher)

Pour pages et articles.

Principe :

  • La div class= »class-div-sommaire-n«  du code court sommaire_simple h=n reçoit le sommaire généré par le script sommaires-h2-h6-dans-class-div-sommaire-n.js, pour les pages et les articles.
  • Le script affiche un sommaire H2-H6 avec liens internes.
  • La div (groupe) class= »class-div-sommaire-n«  peut être créée manuellement sans utiliser le code court.
HTML attendu
<div class="class-div-sommaire-'.$atts['h'].'"></div>
PHP : code court
add_shortcode('sommaire_simple', 'cma_sommaire_simple');
function cma_sommaire_simple($atts) { 
    //$atts['h'] vaut 3 par défaut
    $atts = shortcode_atts(
                array('h' => 3,),
                $atts,
                'sommaire_simple' );
    
    //Contrôle de h
    if($atts['h'] !=2 and $atts['h'] !=3 and $atts['h'] !=4 and $atts['h'] !=5 and $atts['h'] !=6) $atts['h'] =3;
 
    $html = '<div class="class-div-sommaire-'.$atts['h'].'"></div>';
 
    return $html;
}
Script sommaires-h2-h6-dans-class-div-sommaire-n.js

Chargé pour pages et articles.

Principe :

  • Donne un id à tous les titres qui n’en ont pas
  • Affiche des sommaires de titres H2 à Hn (max n = 6), avec liens internes vers les titres, dans tous les groupes de classe ‘class-div-sommaire-n‘ : le nombre n de la classe détermine la profondeur Hn des titres affichés.
Script sommaires-h2-h6-dans-class-div-sommaire-n.js
/* Ce script affiche un ou plusieurs sommaires H2-Hn avec liens dans des groupes ancrés 'class-div-sommaire-n' */

//Récupérer les div avec class-div-sommaire-n (n de 2 à 6) : il peut y avoir plusieurs sommaires par page
const divsSommaire= document.querySelectorAll('.class-div-sommaire-2,.class-div-sommaire-3,.class-div-sommaire-4,.class-div-sommaire-5,.class-div-sommaire-6');

if (divsSommaire.length > 0){
    //Déclaration des variables
    let profondeur = 0;
    let cibleComplete = "h2, h3, h4, h5, h6";
    let cible = "h2, h3, h4, h5, h6";
    let titresComplets = [];
    let titres = [];
    let titre;
    let ul = "";
    let niveauPrecedent = 2;
    let niveau = 2;
    let i = 0;

    let elementClasses;

    //Donner un id à tous les titres qui n'en ont pas
    titresComplets = document.querySelectorAll(cibleComplete);
    if (titresComplets.length > 0){
        for(titre of titresComplets){  //
            if(titre.id == "") titre.id = "sommaire" + i++; //commence avec 'sommaire0'
        }
    }

    for(let divSommaire of divsSommaire){

        //Déterminer la cible des titres :
        //Récupérer la profondeur, le n° à la fin de la classe
        elementClasses = divSommaire.classList;
        profondeur = 0;
        for(let pas = 2; pas<7; pas++){
            if(elementClasses.contains('class-div-sommaire-'+pas)) {
                profondeur = pas; break;
            }
        }

        //Récupérer les titres de niveau 2 à profondeur, inclus
        cible = "h2, h3, h4, h5, h6";
        cible = cible.substring(0, cible.indexOf(profondeur)+1);

        titres = [];
        titres = document.querySelectorAll(cible);
        if (titres.length > 0){

            //Ouverture de la liste
            ul = '<ul>';  
            niveauPrecedent = 2;
            niveau = 2;
            //Traitement de chaque titre
            for(titre of titres){
                if (titre.innerHTML != 'Laisser un commentaire'){  //Un H3 malencontreux
                    //Récupérer le niveau du titre
                    niveau = parseInt(titre.tagName.substr(-1));
                    //Gestion des ouvertures et fermetures des sous-listes
                    if(niveau > niveauPrecedent){
                        //ul+= '<ul>';
                        ul+= '<ul>'.repeat(niveau - niveauPrecedent);
                        niveauPrecedent = niveau;  
                    }
                    else if(niveau < niveauPrecedent){
                        ul+= '</ul>'.repeat(niveauPrecedent - niveau); 
                        niveauPrecedent = niveau;
                    }
                    //Affichage du titre
                    ul+= '<li><a href="#' + titre.id + '">' + titre.innerHTML + '</a></li>';
                }
            }
            //traitement des fermetures après affichage du dernier titre
            niveau = 2;
            ul+= '</ul>'.repeat(niveauPrecedent - niveau);
            //Fermeture de la liste 
            ul+= '</ul>';
            //Affichage dans la div du sommaire
            divSommaire.innerHTML = ul;
        }
    }
}
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaSommairesH2H6DansClassDivSommaireN');
function cmaSommairesH2H6DansClassDivSommaireN(){
    global $cmaWayToJs;    
    if(is_single() or is_page()) {
        wp_enqueue_script('cma-sommaires-h2-h6-dans-class-div-sommaire-n', $cmaWayToJs . 'sommaires-h2-h6-dans-class-div-sommaire-n.js', array(), '1.0.0', true);
    }
}
Compo synchro Sommaire avec menu WP

wp-admin /Apparence /Editeur /Compositions /Sommaire

Utilisée par les pages filles de la page Construire et gérer un blog avec WordPress (slug = wordpress).

La compo synchro Sommaire avec menu WP utilise :

  • La composition Menu WP
  • Le code court sommaire_simple h=3
Visuel de la compo synchro Sommaire avec menu WP
Code court sommaire_double h=n
Appel : [sommaire_double h=n] (n de 2 à 5 indique la profondeur des titres à afficher)

On ne peut utiliser ce code court qu’une seule fois par page ou article.

Utilisé par la page Documentation du site écrire.fun (slug = documentation-du-site)

Principe :

  • Le code court insère 3 div :
    • la 1ère (id= »double-sommaire ») contient les boutons SOMMAIRE et DETAIL
    • la 2e a une class=’class-div-sommaire-3′ par défaut (le chiffre final peut être passé au code court avec le paramètre h=n)
    • la 3e a une class=’class-div-sommaire-6′.
  • h est un entier valant de 2 à 5.
  • Les 2e et 3e div sont alimentées (avec leurs liens) par le script sommaires-h2-h6-dans-class-div-sommaire-n.js
  • Ce code court est animé (boutons) par le script sommaire-double.js : les boutons ne font que masquer/démasquer les 2 sommaires H2-Hn et H2-H6, créés une fois pour toute (donc pas de problème de charge).
HTML attendu
<div id="double-sommaire" style="text-align: left;">
    <button id="double-sommaire-bouton1" type="button" onclick="afficherSommaire();">
        <big><big>SOMMAIRE</big></big>
    </button>
    <button id="double-sommaire-bouton2" type="button" onclick="afficherDetail();">
        <big><big>DETAIL</big></big>
    </button>
</div>
<div id="sommaire-div-id">
    <div class="class-div-sommaire-'.$atts['h'].'"></div>
</div>
<div id="detail-div-id">
    <div class="class-div-sommaire-6"></div>
</div>
PHP : code court
add_shortcode('sommaire_double', 'cma_sommaire_double');
function cma_sommaire_double($atts) { 
    //$atts['h'] vaut 3 par défaut
    $atts = shortcode_atts(
                array('h' => 3,),
                $atts,
                'sommaire_double' );
    
    //Contrôle de h
    if($atts['h'] !=2 and $atts['h'] !=3 and $atts['h'] !=4 and $atts['h'] !=5) $atts['h'] =3;
 
    $html = 
    '<div id="double-sommaire" style="text-align: left;">
        <button id="double-sommaire-bouton1" onclick="afficherSommaire();">
            <big><big>SOMMAIRE</big></big>
        </button>
        <button id="double-sommaire-bouton2" onclick="afficherDetail();">
            <big><big>DETAIL</big></big>
        </button>
    </div>'; 
    $html.= '<div id="sommaire-div-id"><div class="class-div-sommaire-'.$atts['h'].'"></div></div>';
    $html.= '<div id="detail-div-id"><div class="class-div-sommaire-6"></div></div>';  
 
    return $html;
}
Script sommaire-double.js
Script sommaire-double.js animant la structure HTML
   let doubleSommaireSommaire = document.getElementById('sommaire-div-id');
   let doubleSommaireDetail = document.getElementById('detail-div-id');
   let doubleSommaireBouton1 = document.getElementById('double-sommaire-bouton1');
   let doubleSommaireBouton2 = document.getElementById('double-sommaire-bouton2');

   //Background color du grand-parent
   //let grandParent = doubleSommaireBouton1.parentElement.parentElement;
   //if(grandParent != null) {
   //}

if(doubleSommaireSommaire != null){
   let bgc = window.getComputedStyle(doubleSommaireBouton1.parentElement.parentElement, null).getPropertyValue("background-color");

   doubleSommaireDetail.style.display = "none";
   doubleSommaireBouton2.style.backgroundColor = "white";
   doubleSommaireBouton2.style.fontWeight = "normal";
   doubleSommaireBouton2.style.border= "1px solid";

   doubleSommaireSommaire.style.display = "block";
   doubleSommaireBouton1.style.backgroundColor = bgc; //prendra la couleur du grand-parent
   doubleSommaireBouton1.style.fontWeight = "bold";
   doubleSommaireBouton1.style.border= "none";
}
function afficherSommaire(){

   if(doubleSommaireSommaire.style.display == "none"){
      let bgc = window.getComputedStyle(doubleSommaireBouton1.parentElement.parentElement, null).getPropertyValue("background-color");

      doubleSommaireDetail.style.display = "none";
      doubleSommaireBouton2.style.backgroundColor = "white";
      doubleSommaireBouton2.style.fontWeight = "normal";
      doubleSommaireBouton2.style.border= "1px solid";

      doubleSommaireSommaire.style.display = "block";
      doubleSommaireBouton1.style.backgroundColor = bgc; //prendra la couleur du grand-parent
      doubleSommaireBouton1.style.fontWeight = "bold";
      doubleSommaireBouton1.style.border= "none";
      document.getElementById ("double-sommaire").scrollIntoView();
   }
}
function afficherDetail(){

   if(doubleSommaireDetail.style.display == "none"){
      let bgc = window.getComputedStyle(doubleSommaireBouton1.parentElement.parentElement, null).getPropertyValue("background-color");

      doubleSommaireSommaire.style.display = "none";
      doubleSommaireBouton1.style.backgroundColor = "white";
      doubleSommaireBouton1.style.fontWeight = "normal";
      doubleSommaireBouton1.style.border= "1px solid";

      doubleSommaireDetail.style.display = "block";
      doubleSommaireBouton2.style.backgroundColor = bgc; //prendra la couleur du grand-parent
      doubleSommaireBouton2.style.fontWeight = "bold";
      doubleSommaireBouton2.style.border= "none";
      document.getElementById ("double-sommaire").scrollIntoView();
   }
}
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaSommaireDouble');
function cmaSommaireDouble(){
    global $cmaWayToJs;    
    if(is_single() or is_page()) {
        wp_enqueue_script('cma-sommaire-double', $cmaWayToJs . 'sommaire-double.js', array(), '1.0.0', true);
    }
}
Code court sommaire_au_choix h=n
Appel : [sommaire_au_choix h=n] (n de 2 à 5 indique la profondeur des titres à afficher)

On ne peut utiliser ce code court qu’une seule fois par document.

Principe :

  • Affiche un sommaire de niveau modifiable par l’internaute (si le niveau choisi par l’internaute est 2, le sommaire affichera les titre H2 et H3).
  • Ne sont proposés que les choix compatibles avec les titres existants dans le document.
  • La div class=’class-div-sommaire-n‘ est initialisée (avec ses liens) par le script sommaires-h2-h6-dans-class-div-sommaire-n.js.
  • Par la suite, l’événement de changement de niveau mis en place par le script sommaire-au-choix.js supprime la div class=’class-div-sommaire-n‘ et se charge de mettre à jour sa div parente id=’sommaire-div-id-select’.
HTML attendu
<div>
    <label for="prof-select">SOMMAIRE de niveau </label>
    <select name="prof-select" id="prof-select">
        <option value="2" '.$selected[0].'>1</option>
        <option value="3" '.$selected[1].'>2</option>
        <option value="4" '.$selected[2].'>3</option>
        <option value="5" '.$selected[3].'>4</option>
        <option value="6" '.$selected[4].'>5</option>
    </select>
</div>';
<div id="sommaire-div-id-select">
    <div class="class-div-sommaire-'.$atts['h'].'"></div>
</div>';
PHP : code court
add_action('wp_enqueue_scripts', 'cmaSommaireAuChoix');
function cmaSommaireAuChoix(){
    global $cmaWayToJs;    
    if(is_single() or is_page()) {
        wp_enqueue_script('cma-sommaire-au-choix', $cmaWayToJs . 'sommaire-au-choix.js', array(), '1.0.0', true);
    }
}
Script sommaire-au-choix.js
Script sommaire-au-choix.js
let profSelect = document.getElementById("prof-select"); //le select
let sommaireDivIdSelect = document.getElementById("sommaire-div-id-select"); //div enveloppe de la div sommaire
let profondeur = 0;
let cible = "h2, h3, h4, h5, h6";
let titres ; //= [];
let titre;
let ul = "";
let niveauPrecedent = 2;
let niveau = 2;
let i = 0;

let tagMax = 0;
let options = [];

if(profSelect != null){     //le select existe

    //Simplifier le select :

    titres = document.querySelectorAll(cible); //Les titres sont récupérés dans leur ordre d'apparition dans le document.
//console. log("titres.length: |" + titres.length + "|"); // Un titre de plus si le document autorise les commentaires
    if (titres.length > 0){    //Il y a au moins un titre dans le document

        //Déterminer le tag de titre, le plus élevé
        for(titre of titres){
            if (titre.innerHTML != 'Laisser un commentaire') {
                if( tagMax < parseInt(titre.tagName.substr(-1)) ) tagMax =  parseInt(titre.tagName.substr(-1));
            }
        }

        //Rectifier la valeur du select si elle est incohérente avec le niveau de titre le plus élevé
        //if( parseInt(profSelect.value) > tagMax ) profSelect.value = tagMax.toString();
        if(profSelect.value > tagMax ) profSelect.value = tagMax; //fonctionne aussi

        //Supprimer les options inutiles dans le select
        options = profSelect.querySelectorAll("option");
        for(let option of options){
            if(parseInt(option.value) > tagMax) option.remove();
        }
    }

    //Mettre en place l'événement de changement du niveau, et son traitement
    profSelect.addEventListener("change", (event) => {

        //La div de classe class-div-sommaire-n créée par le code court est initialisée au chargement par le script sommaires-h2-h6-dans-class-div-sommaire-n.js
        //Mais après, c'est ce script qui recrée le sommaire suite au change select ; cette div de classe class-div-sommaire-n n'est donc plus utile :
        //sommaireDivClassSelect.innerHTML = '<div class="class-div-sommaire-'+ profSelect.value +'"></div>'; 
        
        //Déterminer la cible des titres à récupérer :
        //Récupérer const profondeur, le n° à la fin de l'id
        profondeur = profSelect.value;
        
        //Récupérer les titres de niveau 2 à profondeur
        cible = "h2, h3, h4, h5, h6";
        cible = cible.substring(0, cible.indexOf(profondeur)+1);

        //Récupérer les titres
        titres = [];
        titres = document.querySelectorAll(cible);

        if (titres.length > 0){
            //Inutile de donner un id aux titres qui n'en ont pas car ça a déjà été fait par le script sommaires-h2-h6-dans-class-div-sommaire-n.js
            //lors de l'initialisation de toutes les div de classe class="class-div-sommaire-n", donc :
            //for(titre of titres){
            //    if(titre.id == "") titre.id = "sommaire"+ profSelect.value +'0'+ i++; //commence avec i=0
                //ce mode de calcul est différent pour ne pas interférer avec celui des autres scripts de affichant des sommaires
            //}

            //Ouverture de la liste
            ul = '<ul>';  
            niveauPrecedent = 2;
            niveau = 2;
            //Traitement de chaque titre
            for(titre of titres){
                if (titre.innerHTML != 'Laisser un commentaire'){  //Un H3 malencontreux
                    //Récupérer le niveau du tag du titre (attention, le niveau affiché à l'internaute est inférieur d'une unité)
                    niveau = parseInt(titre.tagName.substr(-1));

                    //Gestion des ouvertures et fermetures des sous-listes
                    if(niveau > niveauPrecedent){
                        //ul+= '<ul>';
                        ul+= '<ul>'.repeat(niveau - niveauPrecedent);
                        niveauPrecedent = niveau;  
                    }
                    else if(niveau < niveauPrecedent){
                        ul+= '</ul>'.repeat(niveauPrecedent - niveau); 
                        niveauPrecedent = niveau;
                    }

                    //Ecriture du titre
                    ul+= '<li><a href="#' + titre.id + '">' + titre.innerHTML + '</a></li>';
                }
            }
            //traitement des fermetures après écriture du dernier titre
            niveau = 2;
            ul+= '</ul>'.repeat(niveauPrecedent - niveau);
            //Fermeture de la liste 
            ul+= '</ul>';
            //Affichage dans la div du sommaire //Rappel : la div de classe "class-div-sommaire-n" n'a pas été conservée car inutile ici 
            sommaireDivIdSelect.innerHTML = ul;
        }
    });
}
PHP : chargement du script
add_shortcode('sommaire_au_choix', 'cma_sommaire_au_choix');
function cma_sommaire_au_choix($atts) { 
    //$atts['h'] vaut 3 par défaut
    $atts = shortcode_atts(
                array('h' => 3,),
                $atts,
                'sommaire_au_choix' );
   
    //Contrôle de h
    //if($atts['h'] !=2 and $atts['h'] !=3 and $atts['h'] !=4 and $atts['h'] !=5 and $atts['h'] !=6) $atts['h'] =3;
    $profValeurs = [2,3,4,5,6];
    if(!in_array($atts['h'], $profValeurs)) $atts['h'] = 3;
 
    $selected = ["","","","",""];
    $selected[$atts['h']-2] = "selected";

    $html = '
        <div>
        <label for="prof-select"><b>SOMMAIRE</b> de niveau</label>
        <select name="prof-select" id="prof-select">
          <option value="2" '.$selected[0].'>1</option>
          <option value="3" '.$selected[1].'>2</option>
          <option value="4" '.$selected[2].'>3</option>
          <option value="5" '.$selected[3].'>4</option>
          <option value="6" '.$selected[4].'>5</option>
        </select>
        </div>';
    $html.= '<div id="sommaire-div-id-select"><div class="class-div-sommaire-'.$atts['h'].'"></div></div>';

    return $html;
}

Le filtre des recherches

Il y a 3 façons de gérer le bloc Recherche :

  • Si l’on effectue une recherche depuis la liste des articles d’une catégorie, on ne recherchera que dans ces articles. Sont mis en jeu :
    • Le script categorie-de-recherche.js
    • Le script contrainte-de-recherche.js
    • La fonction PHP ma_recherche_filter($query)
  • Si l’on effectue une recherche depuis une page parent, on ne recherchera que dans ses pages filles. Sont mis en jeu :
    • Le script page-racine-de-recherche.js
    • Le script contrainte-de-recherche.js
    • La fonction PHP ma_recherche_filter($query)
  • Par défaut, on cherche dans toutes les pages et articles mais pas dans les pages exclues (pages de test, pages spéciales, ou pages filles très spécialisées)
    • Cf. la fonction PHP ma_recherche_filter($query)
La fonction PHP ma_recherche_filter($query)

wp-content/plugins/ecrire-fun-2022/includes/mesfonctions.php

La fonction ma_recherche_filter() est complémentaire des scripts :

  • categorie-de-recherche.js
  • page-racine-de-recherche.js
  • contrainte-de-recherche.js.

Description : selon le cas, la fonction ma_recherche_filter() :

  • Limitera la recherche aux pages feuilles quand le champ ‘racine‘ sera présent et renseigné dans le formulaire de recherche
  • Limitera la recherche aux articles de la catégorie quand le champ ‘categorie‘ sera présent et renseigné dans le formulaire de recherche
  • Exclura par défaut de la recherche, certaines pages exclues (pages de test, pages spéciales, ou pages filles spécialisées)
PHP : fonction ma_recherche_filter
<?php
*************************** VARIABLE GLOBALE **********************************/
// Chemin du dossier /js/ contenant les scripts
$cmaWayToJs = plugin_dir_url( __FILE__ ) . "js/";

/* Auteur : CM ****************************FILTRE DES RECHERCHES ***************
*  Fonction complémentaire des scripts : categorie-de-recherche.js ; page-racine-de-recherche.js ; contrainte-de-recherche.js.
*  La fonction ma_recherche_filter() analysse le formulaire de Recherche ; selon le cas, elle  :
*  o Limitera la recherche à des pages feuilles quand le champ 'racine' sera présent et renseigné dans le formulaire de recherche (le bloc Recherche de la page mère aura pour attribut la classs racine-de-recherche) 
*  o Limitera la recherche aux articles de la catégorie quand le champ 'categorie' sera présent et renseigné dans le formulaire de recherche (systématique si le bloc Recherche est sur une Category)
*  o Exclura par défaut certaines pages de la recherche.
*****************************************************************************/

//Je demande que la fonction ma_recherche_filter soit utilisée (add) avant (pre) de récupérer (get) les page HTML (posts) pour filtrer (filter) le résultat de la Recherche (add_filter('pre_get_posts',) : 

add_filter('pre_get_posts','ma_recherche_filter');

function ma_recherche_filter( $query )
{
    //Les id des pages de test à exclure :
    $pagesAExclureTests = array(13584);
    //Les id des pages spéciales à exclure :
    $pagesAExclureSpeciales = array();
    //Les id des pages filles à exclure qui parlent de WP :
    $pagesAExclureWordPress = array(13650, 13743, 13759, 13779, 13797, 13825, 13878, 14009, 14270, 14470, 14489, 14739, 14907, 14926, 15014, 15054, 15184, 15295, 15427, 15436, 16804, 18035, 18347);
    //Amélioration à prévoir ci-dessus : pour éviter d'avoir à noter tous ces id, créer une fonction qui récupère ces id à tous les niveaux de profondeur, à partir du slug de la page parent.

    //Tableau complet des id de toutes les pages HTML à exclure :
    $pagesAExclure = array_merge($pagesAExclureTests, $pagesAExclureSpeciales, $pagesAExclureWordPress);

    $libelleracine = "racine";
    $libelleracine2 = "categorie";

    //Si je ne suis pas dans WP-admin :
    if(!is_admin() && $query->is_main_query()){
        //Si la requête concerne une recherche :
        if ( $query->is_search ){ 
            //Si le formulaire contient un champ "racine" et qu'il n'est pas vide :
            if (isset($_GET[$libelleracine]) and $_GET[$libelleracine] != "" ) {
                //Je récupère l'objet associé au slug de la page racine :
                $mypost = get_page_by_path($_GET[$libelleracine], '', 'page');
                //Je récupère les pages fille de cette page racine :
                $mypages = get_pages(array('child_of' => $mypost->ID, 'sort_column' => 'post_date', 'sort_order' => 'desc'));
                //S'il existe des pages filles :
                if(count($mypages) >0){
                    //Je mets dans un tableau l'id de chacune des pages filles :
                    foreach($mypages as $myPage) $pagesAInclure[] = $myPage->ID;
                    //Je paramètre la requête pour qu'elle se limite à rechercher parmi les pages (filles) dont je fourni le tableau des id :
                    $query->set('post__in', $pagesAInclure);
                } else{
                    /* Je paramètre la requête pour qu'elle exclue toutes les pages et articles (dont je fourni le tableau des id) afin d'éviter qu'un petit malin, pour faire remonter les pages cachées, entre dans son navigateur une adresse telle que https://xn--crire-9ra.fun/?s=le&racine=qui ('qui' étant le slug d'une page sans bloc Recherche et 'le' un mot qui se trouve dans toutes les pages) :
*/
                    $toutesLesPages = get_pages();
                    foreach($toutesLesPages as $unePage) $pagesAExclure2[] = $unePage->ID;
                    $toutsLesArticles = get_posts(array('numberposts' => -1));
                    foreach($toutsLesArticles as $unArticle) $articlesAExclure[] = $unArticle->ID;
                    $pagesAExclure3 = array_merge($pagesAExclure2, $articlesAExclure);
                    $query->set('post__not_in', $pagesAExclure3);
                }
            }
            //Si le formulaire contient un champ "categorie" et qu'il n'est pas vide :
            else if (isset($_GET[$libelleracine2]) and $_GET[$libelleracine2] != "" ) {
                //Je récupère l'objet associé à la categorie :
                $mypost = get_category_by_slug($_GET[$libelleracine2]);
                //Je récupère les articles de cette categorie :
                $mypages = get_posts(array('category' => $mypost->term_id, 'sort_column' => 'post_date', 'sort_order' => 'desc', 'numberposts' => -1));
                if(count($mypages) >0){
                    //Je mets dans un tableau l'id de chacun des articles de la catégorie :
                    foreach($mypages as $myPage) $pagesAInclure[] = $myPage->ID;
                    //Je paramètre la requête pour qu'elle se limite à rechercher parmi les articles de la catégorie, dont je fourni le tableau des id :
                    $query->set('post__in', $pagesAInclure);
                } else{
                    //Je paramètre la requête pour qu'elle exclue toutes les pages et articles (dont je fourni le tableau des id) pour la même raison que tout à l'heure :
                    $toutesLesPages = get_pages();
                    foreach($toutesLesPages as $unePage) $pagesAExclure2[] = $unePage->ID;
                    $toutsLesArticles = get_posts(array('numberposts' => -1));
                    foreach($toutsLesArticles as $unArticle) $articlesAExclure[] = $unArticle->ID;
                    $pagesAExclure3 = array_merge($pagesAExclure2, $articlesAExclure);
                    $query->set('post__not_in', $pagesAExclure3);
                }              
            }
            //Si le formulaire ne contient ni de champ "racine", ni de champ "categorie", non vides :
            else {
                //Je paramètre par défaut la requête pour qu'elle exclue certaines pages dont je fourni le tableau des id :
                $query->set('post__not_in', $pagesAExclure);
            }
        }
    }
    //A toute fin utile, la fonction retourne la requête reparamétrée :
    return $query;
} //fin de la fonction
Script categorie-de-recherche.js

wp-content/plugins/ecrire-fun-2022/includes/js/categorie-de-recherche.js

Chargé par la fonction cmaAjouterScriptCategorieDeRecherche, if(is_category())

Utilisé par les Archives.

Description : pour considérer une archive-catégorie comme catégorie des recherches, on ajoute dans le formulaire de recherche, à côté du champ de saisie (Name = ‘r’), un champ caché ayant pour valeur le slug de cette catégorie : la fonction ma_recherche_filter() limitera la recherche aux articles de cette catégorie quand ce champ sera présent et renseigné.

Script JS
//Remplace la composition S-Script categorie de recherche (sous un bloc Rechercher)

//Pour considérer une archive-catégorie comme catégorie des recherches, on ajoute dans le formulaire de recherche (à côté du champ de saisie), un champ caché ayant pour valeur le slug de cette catégorie : la fonction ma_recherche_filter() limitera la recherche aux articles de cette catégorie quand ce champ sera présent et renseigné.

let libelleracine = "categorie";
let myinput = document.createElement("input");

let urlcourante = document.location.href; 
// Supprimons l'éventuel dernier slash de l'URL
let urlcourante = urlcourante.replace(/\/$/, "");
// Gardons dans la variable queue_url uniquement la portion derrière le dernier slash de urlcourante
let queue_url = urlcourante.substring (urlcourante.lastIndexOf( "/" )+1 );

myinput.setAttribute("name", libelleracine);
myinput.setAttribute("type", "hidden");
myinput.setAttribute("value", queue_url);

let currentInput = document.getElementsByName("s");
if(currentInput.length> 0){
    //currentInput[currentInput.length - 1].parentElement.appendChild(myinput); //je prends le dernier
    currentInput[0].parentElement.appendChild(myinput); //je prends le premier bloc Recherche de la page

    //je prends le premier label de bloc Recherche de la page (il faut a priori qu'il existe) :
    document.getElementsByClassName("wp-block-search__label")[0].innerHTML = 'Rechercher dans la catégorie "'+queue_url+'"';
}
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaAjouterScriptCategorieDeRecherche');
function cmaAjouterScriptCategorieDeRecherche() {
    global $cmaWayToJs;
    if(is_category()) {
        wp_enqueue_script('cma-categorie-de-recherche', $cmaWayToJs . 'categorie-de-recherche.js', array(), '1.0.0', true);
    }
}
Script page-racine-de-recherche.js

wp-content/plugins/ecrire-fun-2022/includes/js/page-racine-de-recherche.js

Chargé par la fonction cmaAjouterScriptPageRacineDeRecherche, if(is_page())

Utilisé par la page Construire et gérer un blog avec WordPress (wordpress).

Description : pour considérer une page comme page racine d’une recherche, on ajoute dans le formulaire de recherche, à côté du champ de saisie (Name = ‘r’), un champ caché ayant pour valeur le slug de la page racine : la fonction ma_recherche_filter() limitera la recherche aux pages feuilles quand ce champ sera présent et renseigné.

Remarque : ne concerne (cf. script ci-dessous) que les pages qui possèdent un bloc Recherche appartenant à la classe « racine-de-recherche«  (à positionner manuellement). Ca permet de donner si nécessaire un bloc Recherche standard à des pages qui n’ont pas de pages filles.

Classe racine-de-recherche (en bas à droite)
Script JS
//Ne concerne que les pages (cf. la fonction PHP cmaAjouterScriptPageRacineDeRecherche) qui possèdent un bloc Recherche appartenant à la classe "racine-de-recherche" (cf. script ci-dessous). Ca permet de donner si nécessaire un bloc Recherche standard à des pages qui n'ont pas de pages filles.

//Pour considérer cette page comme page racine des recherches, on ajouter un champs caché, ayant pour valeur le nom de cette page (slug), à côté du champs de saisie de la recherche : si ce champs existe, la fonction ma_recherche_filter() limitera la recherche aux pages feuilles.

let testerRacine = document.getElementsByClassName("racine-de-recherche");
if(testerRacine.length > 0){

    let currentInput = document.getElementsByName("s");
    if(currentInput.length> 0){

        let libelleracine = "racine";
        let myinput = document.createElement("input");

        let urlcourante = document.location.href; 
        // Supprimons l'éventuel dernier slash de l'URL
        let urlcourante = urlcourante.replace(/\/$/, "");
        // Gardons dans la variable queue_url uniquement la portion derrière le dernier slash de urlcourante
        let queue_url = urlcourante.substring (urlcourante.lastIndexOf( "/" )+1 );

        myinput.setAttribute("name", libelleracine);
        myinput.setAttribute("type", "hidden");
        myinput.setAttribute("value", queue_url);

        //currentInput[currentInput.length - 1].parentElement.appendChild(myinput); //le dernier
        currentInput[0].parentElement.appendChild(myinput); //le premier

        document.getElementsByClassName("wp-block-search__label")[0].innerHTML = 'Recherche sur le thème "'+queue_url+'"';
    }
}
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaAjouterScriptPageRacineDeRecherche');
function cmaAjouterScriptPageRacineDeRecherche() {
    global $cmaWayToJs;
    if(is_page()) {
        wp_enqueue_script('cma-page-racine-de-recherche', $cmaWayToJs . 'page-racine-de-recherche.js', array(), '1.0.0', true);
    }
}
Script contrainte-de-recherche.js

wp-content/plugins/ecrire-fun-2022/includes/js/contrainte-de-recherche.js

Chargé par la fonction cmaAjouterScriptContrainteDeRecherche, if(is_search())

Description : ce script présent dans le modèle Recherche est complémentaire des scripts page-racine-de-recherche et categorie-de-recherche. Il permet de gérer les recherches successives à partir du Résultat d’une recherche : si une racine ou une catégorie est indiquée dans l’URL alors il faut en tenir compte pour la recherche suivante.

Script JS
//Remplace le script de la composition S-Recherche et html (sous un bloc Rechercher)

//Si l'on est sur une recherche à partir d'une page racine, ajouter, à côté du champs de saisie de la recherche, un champs caché ayant pour valeur le nom de la page racine (trouvée dans l'adresse de la page) : si ce champs caché est détecté par la fonction ma_recherche_filter(), celle-ci limitera la recherche aux pages feuilles de la page racine.

let libelleracine = "racine";
let libelleracine2 = "categorie";
let libracine = "&"+libelleracine+"=";
let libracine2 = "&"+libelleracine2+"=";

let urlcourante = document.location.href;
// Supprimons l'éventuel dernier slash de l'URL
urlcourante = urlcourante.replace(/\/$/, "");

//chercher libracine dans urlcourante
let indexmaracine = urlcourante.indexOf(libracine);
if(indexmaracine > -1){ //libracine trouvé dans urlcourante

    //Récupérer le nom de la racine (slug)
    var nomracine = urlcourante.substring(urlcourante.indexOf(libracine)+libracine.length, urlcourante.length);

    let myinput = document.createElement("input");
    myinput.setAttribute("name", libelleracine);
    myinput.setAttribute("type", "hidden");
    myinput.setAttribute("value", nomracine);

    let currentInput = document.getElementsByName("s");
    if(currentInput.length> 0){ 
        currentInput[currentInput.length - 1].parentElement.appendChild(myinput);
        document.getElementsByClassName("wp-block-search__label")[0].innerHTML = 'Recherche sur le thème "'+nomracine+'"';
    }
}
else{
    //chercher libracine2 dans urlcourante
    indexmaracine = urlcourante.indexOf(libracine2);
    if(indexmaracine > -1){ //libracine2 trouvé dans urlcourante

        //Récupérer le nom de la catégorie (slug)
        let nomracine2 = urlcourante.substring(urlcourante.indexOf(libracine2)+libracine2.length, urlcourante.length);

        let myinput = document.createElement("input");
        myinput.setAttribute("name", libelleracine2);
        myinput.setAttribute("type", "hidden");
        myinput.setAttribute("value", nomracine2);

        let currentInput = document.getElementsByName("s");
        if(currentInput.length> 0){ 
            currentInput[currentInput.length - 1].parentElement.appendChild(myinput);
            document.getElementsByClassName("wp-block-search__label")[0].innerHTML = 'Recherche dans la catégorie "'+nomracine2+'"';
        }
    } //fin if
} //fin else
PHP : chargement du script
add_action('wp_enqueue_scripts', 'cmaAjouterScriptContrainteDeRecherche');
function cmaAjouterScriptContrainteDeRecherche() {
    global $cmaWayToJs;
    if(is_search()) {
        wp_enqueue_script('cma-contrainte-de-recherche', $cmaWayToJs . 'contrainte-de-recherche.js', array(), '1.0.0', true);
    }
}

Autres codes courts

lire_la_suite

Appel : [lire_la_suite]

Utilisé par le Modèle de publication de la Boucle de requête des modèles Accueil, Archive, Recherche.

Description : renvoie la chaîne de caractères « Lire la suite : cliquer sur titre ou image »

PHP : short code
/* Auteur : CM ************************************ LIRE LA SUITE *****************
*  texte de Lire la suite
*********************************************************************************/

function cma_lire_la_suite() { 

    $html = '<p><em><strong>Lire la suite</strong> : cliquer sur titre ou image</em></p>'; 

    return $html;
}
add_shortcode('lire_la_suite', 'cma_lire_la_suite');

wpversion

Appel : [wpversion couleur="#605924"] par exemple
ou : [wpversion couleur="red"]

Utilisé par la page Construire et gérer un blog avec WordPress (slug = wordpress)

Description : affiche le numéro de la version de WP utilisée par le site.

Le paramètre couleur est la couleur du texte (noir par défaut).

PHP : short code
/* Auteur : CM ************************************ VERSION WP *****************
*  numéro de la version de WP
*********************************************************************************/

function cma_wpversion($atts) { 

    global $wp_version;

    //La couleur et la taille sontt passées en paramètre : $atts['couleur'] vaut "black" par défaut et $atts['taille'] vaut "1rem" par défaut
    $atts = shortcode_atts( 
                array('couleur' => "black", 'taille' => "1rem"),
                $atts,
                'wpversion' );
    
    $html = '<p style="font-size: '.$atts['taille'].'; color: '.$atts['couleur'].';"><em><strong>'.$wp_version.'</strong></em></p>'; 

    return $html;
}
add_shortcode('wpversion', 'cma_wpversion');

CSS additionnel


wp-admin /Apparence /Personnaliser /CSS additionnel

Code CSS
/*Marges suite PB avec les modèles :*/
h2{margin-top: 2rem;}
h3, h4{margin-top: 2rem; margin-bottom: 1rem;}
p{margin-top: 1.5rem;}
input[type="radio"], input[type="checkbox"] {margin-right: 5px;}
/* details *, .divm1rem>*{padding: 3px;} */
details p, .divm1rem>*{padding: 10px;}
img{padding: 10px;}

/*Hauteur trop importante du menu escamotable sur le PC sur page et article :
Navigation dans compo Menu : */
.cmamenu {max-height: 48px;}
/*.cmasousmenu {max-height: 40px;}*/


/*Ecrire une histoire /Intrigue /tableau : */

.cma-decimal-list-block{list-style-type: decimal;}
.cma-table-22-etapes tr:nth-of-type(1), .cma-table-22-etapes tr:nth-of-type(2), .cma-table-22-etapes tr:nth-of-type(5), .cma-table-22-etapes tr:nth-of-type(12), .cma-table-22-etapes tr:nth-of-type(15){
    background-color: gray;
		color: white;
}
.cma-table-22-etapes tr:nth-of-type(3) td:first-of-type, .cma-table-22-etapes tr:nth-of-type(6) td:first-of-type,
.cma-table-22-etapes tr:nth-of-type(7) td:first-of-type, .cma-table-22-etapes tr:nth-of-type(8) td:first-of-type,
.cma-table-22-etapes tr:nth-of-type(9) td:first-of-type, .cma-table-22-etapes tr:nth-of-type(10) td:first-of-type,
.cma-table-22-etapes tr:nth-of-type(13) td:first-of-type {
    border-bottom: 3px solid white;
		border-top: 1px solid white;
}
.cma-entete-tableau-gris tr:nth-of-type(1){
	background-color: gray;
	color:white;
}
.cma-lignes-2-3-tableau-gras tr:nth-of-type(2), .cma-lignes-2-3-tableau-gras tr:nth-of-type(3) {font-weight:bold;}

/*FIN DE Ecrire une histoire /Intrigue /tableau */

/* Centrer : */
.div-centree {text-align: center;}
.text-align-center {text-align: center;}

/*Justifier : */
.puce-justifiee {text-align: justify; padding-left : 1.1em;}
.justifier, p{text-align: justify;}
.text-align-start{text-align: start;}

/*Puces : */
.liste-sans-puce{list-style-type: none;}
.no-bullet {list-style-type: none}
.dialogue{list-style-type: '–  '; text-align: justify; padding-left : 1.1em;}

/*Mise en page spéciales (Les filles de Thespios) : */

.first-letter-blue::first-letter {color: blue; font-size: 3em;font-weight: bold;}
.first-letter-green::first-letter {color: green; font-size: 3em;font-weight: bold;}
.first-letter-orange::first-letter {color: orange; font-size: 3em;font-weight: bold;}
.first-letter-red::first-letter {color: red; font-size: 3em;font-weight: bold;}
.li-a-blue>a{color:blue}
.li-a-green>a{color:green}
.li-a-orange>a{color:orange}
.li-a-red>a{color:red}
.orange-checkbox {background: orange;}

/* Jolis boutons : */

.nice-button{
  width: auto;
  margin: auto;
  /*margin-top: 0.2em;*/

  color: white;
  background-color: #6495ED;
  text-shadow: 1px 1px black;

  text-decoration: none;
  text-align: center;
  padding: 2px;
  border: 3px outset #c0c0c0;
}
.nice-button2{
  width: auto;
  margin-top: 0.2em;

  color: white;
  background-color: #6495ED;
  text-shadow: 1px 1px black;

  text-decoration: none;
  text-align: center;
  padding: 7px;
  border: 3px outset #c0c0c0;
}
.clavier-glossaire *{
  width: 2.4em;
  margin: auto;
  margin-top: 0.2em;

  color: white;
  background-color: #6495ED;
  text-shadow: 1px 1px black;

  text-decoration: none;
  text-align: center;
  padding: 2px;
  border: 3px outset #c0c0c0;
}
/* FIN DE Joli boutons : */

Annexes


Liste des compositions

wp-admin /Apparence /Editeur/Compositions /Mes compositions

Les compositions sont utilisées partout : dans les modèles, les éléments de modèles, les pages et les articles.

Liste des compositions avec leurs dépendances entre elles

* = composition synchronisée

  • Recherche* (non utilisé)
  • Effacer libellé Autres pages* (non utilisé)
  • pagination large (non utilisé)
  • Quiz-bouton-Compter les cases cochées* (non utilisé)
  • WPYSEO-breadcrumb*
  • Menu*
  • Sommaire avec menu WP*
    • Menu WP*
  • Prochain cours
  • Bouton fermer Détails
  • Glossaire
  • Mot d’esprit
  • Quiz-quiz
    • Quiz-sommaire
      • Quiz-bouton-raz*
    • Quiz-Question-select
      • Quiz-case-Bonnereponse*
    • Quiz-Question-checkbox
      • Quiz-case-Bonnereponse*
    • Quiz-Question-radio
      • Quiz-case-Bonnereponse*
    • Quiz-terminé
      • Quiz-bouton-Nb réponses et ouvrir profil*
      • Quiz-bouton-raz*
    • Quiz-index

Palette de couleur

Utilisée par la page Construire et gérer un blog avec WordPress (wordpress) :

Problèmes en suspens

Sitemap

La Search Console n’arrive pas à lire le sitemap fourni par Yoast SEO

Malgré l’opération ci-dessous conseillée sur un forum : Can you please try resetting our indexables in the database tables by following the steps below?

  1. Install & activate the Yoast Test Helper plugin
  2. Go to Tools > Yoast Test
  3. Hit the “Reset indexables & migrations” button.
  4. Go to SEO > Tools, and under SEO data, click the “SEO Data Optimization” button to allow Yoast to rescan your pages.

URL

KO dans la barre du navigateur :

  • https://xn--crire-9ra.fun/ et https://www.xn--crire-9ra.fun/
  • https://xn--crire-9ra.fun/ et https://www.xn--crire-9ra.fun/
  • xn--crire-9ra.fun et www.xn--crire-9ra.fun
  • https://écrire.fun/ (Chrome => recherche Google, alors que ça marche avec Edge : résolu après avoir vidé les caches sur Chrome) et https://www.écrire.fun/
  • http://écrire.fun/ et http://www.écrire.fun/
  • écrire.fun et www.écrire.fun
  • https://ecrire.fun/ (Chrome/Edge : Ce site est inaccessible) et https://www.ecrire.fun/ (Chrome/Edge : Ce site est inaccessible)
  • http://ecrire.fun/ et http://www.ecrire.fun/
  • ecrire.fun >> http://ecrire.fun >> https://écrire.fun (https://xn--crire-9ra.fun/ à la copie) et www.ecrire.fun

Le thème enfant abandonné twentytwentytwo-child

wp-content /themes /twentytwentytwo-child

Le thème enfant twentytwentytwo-child a été abandonné en tant que tel. Il existe mais n’est pas activé.

Les dossiers du thème enfant twentytwentytwo-child
wp-content /themes
wp-content /themes/twentytwentytwo-child

Le dossier twentytwentytwo-child /templates (modèles) du thème enfant a finalement été supprimé.

Il est en effet compliqué de conserver certaines évolutions faites sur le thème enfant lorsqu’on désactive celui-ci (il faudrait probablement intégrer dans le thème enfant certains fichiers du thème parent, ce que je ne maîtrise pas).

Les modèles et les en-têtes de twentytwentytwo-child
Modèle du thème enfant (abandonné)En-tête (élément de modèle)Caractéristiques Tous avec compo Menu* et bouton_top
Accueil (home)
Header Dark small /Headero Icone non cliquable
o Avec titre site
o Sans catégorie
o Image Cocotte
Page (page)
Catégorie (category)
Recherche (search)
Header-retouro Icone cliquable
o Avec titre site
o Sans catégorie
Publications seules (single)Header-categorieo Icone cliquable
o Pas de titre site
o Avec catégorie
Tableau récapitulatif des en-têtes des modèles du thème enfant

Le modèle category est prioritaire sur archive (category est un type d’archive) mais les templates spécifiques au thème enfant ont été finalement supprimés (plus de dossier Templates).

L’élément de modèle Header Dark large /Header (image Oiseau) n’est pas utilisé.

style.css de twentytwentytwo-child
/*
Theme Name: twentytwentytwo-child
Description: Thème enfant twentytwentytwo
Author: CHIRO314
Template: twentytwentytwo
Version: 1.0
*/
functions.php de twentytwentytwo-child
<?php 
function cma_enqueue_assets(){
  wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
add_action( 'wp_enqueue_scripts', 'cma_enqueue_assets' );

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Get 30% off your first purchase

X