IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Appel de fonction dans une checkbox


Sujet :

JavaScript

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 5
    Points : 2
    Points
    2
    Par défaut Appel de fonction dans une checkbox
    Bonjour à tous,

    J'ai un souci que je n'arrive pas à résoudre en JS avec les checkbox. Je suis en train de coder une to-do list où lorsque je clique sur un bouton cela m'ouvre une fenêtre pour que je tape au clavier la nouvelle tache. La nouvelle tache apparait donc à l'écran avec une checkbox que je coche lorsque la tache est terminé.
    Quand une tache n'est pas réalisé elle reste dans la section "a faire", lorsque je réalise une tache je coche la checkbox et celle ci passe dans la section "fait"(voir photo).

    Nom : Capture.PNG
Affichages : 109
Taille : 18,7 Ko

    J'aimerai pouvoir, lorsque je décoche une tache, que celle ci retourne dans la catégorie "A faire". Le souci c'est que cela ne fonctionne pas dans mon code et je ne comprend pas pourquoi.

    Voici mon code ci dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    //Ajouter une nouvelle tache 
    addElt.addEventListener("click", addTask);
     
    const addTask = (e) => {
     
        //ouvre une fenêtre textuelle pour renseigner sa tâche
        let taskName = window.prompt('Renseigner une nouvelle tâche',e.target.textContent);
        //Si une tâche est renseigné :
        if (taskName!==null){
            //Création d'une nouvelle ligne de lisgne avec une checkbox + tache
            let liElt = document.createElement("li");
            let ulElt = document.getElementById("liste");
            let checkBoxElt = document.createElement("input");
            let labelElt = document.createElement("label");
            let idt = getId(taskList,idTab); //appel de la fonction qui génère un id unique pour les checkbox
     
            checkBoxElt.type = 'checkbox';
            checkBoxElt.id = idt;
            checkBoxElt.value = idt;
            liElt.id = "li" + idLi;
            checkBoxElt.onchange= doneTask; 
            labelElt.setAttribute("for", checkBoxElt.id );
            labelElt.textContent = taskName;
     
            ulElt.appendChild(liElt);
            liElt.appendChild(checkBoxElt);
            liElt.appendChild(labelElt);
     
            let newTask = new task(taskName,false,idt);
            taskList.push(newTask);
            idLi++; // on incrémente l'id à chaque nouvelle tache
        }
    }
     
    //Fonction qui gère la réalisation d'une tache
    const doneTask = (e) => {
        let thisId = e.target.parentElement.id;  
        //Si aucune tâche ne sont encore réalisé :
        if ( document.getElementById("done") === null){
            //Création de la section "done"
            let sectionElt = document.createElement("section");
            let titleElt = document.createElement("h2");
            let ulElt = document.createElement("ul");
            titleElt.textContent = "Fait";
            sectionElt.id = "done";
            ulElt.id = "checkListDone";
     
            document.getElementById("todo").appendChild(sectionElt);
            sectionElt.appendChild(titleElt);
            sectionElt.appendChild(ulElt);
     
            document.getElementById("checkListDone").style.textDecoration = "line-through";
        } 
        //Si la checkbox est bien coché, on duplique la tache, on l'insère dans la section "done" et on la supprime de la section "todo"
        if (e.target.checked){
            let liElt = document.createElement("li");
            liElt = document.getElementById(thisId).cloneNode(true);
            // Récupération de l'id pour la tache réalisé
            let doneId = e.target.id.match(/\d+/g).join('');
            liElt.id = "done" + doneId;
            document.getElementById("checkListDone").appendChild(liElt);
            //Suppression de la tache dans la section "Fait"
            document.getElementById("liste").removeChild(document.getElementById(thisId));
     
            //On passe le booléen "done" du tableau tasklist à true
            for (let i in taskList){
                if (e.target.id === taskList[i].idt){
                    taskList[i].done = true;
                }
            } 
        } else {
            let liElt = document.createElement("li");
            liElt = document.getElementById(thisId).cloneNode(true);
            let returnId = e.target.id.match(/\d+/g).join('');
            liElt.id = "li" + returnId;
            document.getElementById("liste").appendChild(liElt);
            document.getElementById("checkListDone").removeChild(document.getElementById(thisId));
        }
    }
    Pour l'instant ma fonction fonctionne quand je coche ma checkbox, mais lorsque je veux la décocher, plus rien. Auriez vous une idée de pourquoi cela ma fonction "doneTask" n'est pas appelé à chaque fois que je coche/décoche ma checkbox ?

    J'espère que j'ai pu être clair.

    Merci d'avance pour vos réponse.

  2. #2
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    août 2003
    Messages
    3 642
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : août 2003
    Messages : 3 642
    Points : 5 060
    Points
    5 060
    Par défaut
    Bonjour,

    Peut-être un problème avec tes clonages? je ne comprends pas pourquoi tu clones un élément avant de le changer de place, ce qui t'obliges à faire un append + un remove;

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    J'avoue ne pas comment faire autrement pour faire un coupé collé d'un élément à un autre emplacement, je débute en JS. Pourquoi penses tu que cela viennes du clonage ? Ma fonction doneTask ne devrait elle pas être appeler à chaque fois que je clique sur une checkbox ?

  4. #4
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    août 2003
    Messages
    3 642
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : août 2003
    Messages : 3 642
    Points : 5 060
    Points
    5 060
    Par défaut
    - vérifie aussi la valeur de thisId dans la console: je n'ai pas vu exactement à quoi correspondait e.target.parentElement.id mais c'est dangereux dans le contexte d'une checkbox dans un li;

  5. #5
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    janvier 2011
    Messages
    15 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : janvier 2011
    Messages : 15 779
    Points : 40 083
    Points
    40 083
    Par défaut
    Bonjour et bienvenue sur DVP.

    Peut-être te compliques tu la vie inutilement, dans un premier temps.

    La méthode append fait le job à ta place, elle déplace d'un endroit à un autre l'élément passé en paramètre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    parent1.append(element); // déplace element dans parent1 et non pas une copie
    parent2.append(element); // déplace element dans parent2 et non pas une copie
    // et ainsi de suite ...
    Donc dans ton cas cela se résume à déplacer la <li> qui contient ton <input type="checkbox"> dans une liste <ul> ou une autre suivant que l'<input> est coché ou non.

    Pour se faire il suffit, après création, d'affecter un événement, via addEventListener à ton <input type="checkbox"> et dans ce cas ta fonction reste des plus basique.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // affectation fonction sur le click
    elCheck.addEventListener("click", handleClick);
    La fonction handleClick basique ressemblant à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // transfert d'une liste à l'autre
    function handleClick(e) {
      let parent;
      if (this.checked) {
        parent = document.getElementById("list-do")
      }
      else {
        parent = document.getElementById("list-todo");
      }
      parent.append(this.closest("li"))
    }
    Tu peux tester le résultat avec comme HTML
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <fieldset>
      <legend>A faire</legend>
      <ul id="list-todo">
        <li><label><input type="checkbox">Tâche #1</label>
        <li><label><input type="checkbox">Tâche #2</label>
      </ul>
    </fieldset>
    <fieldset>
      <legend>Fair</legend>
      <ul id="list-do">
      </ul>
    </fieldset>
    et script
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function handleClick(e) {
      let parent;
      if (this.checked) {
        parent = document.getElementById("list-do")
      }
      else {
        parent = document.getElementById("list-todo");
      }
      parent.append(this.closest("li"))
    }
    const elements = document.querySelectorAll("[type='checkbox']");
    elements.forEach((el) => {
      el.addEventListener("click", handleClick);
    });

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Il semble que cela venait effectivement du cloneNode, je me suis trop compliqué la tête avec ça. Merci à vous deux cela fonctionne comme je le voudrais maintenant.

    Pour répondre à ta question javatwister, e.target.parentElement.id fait référence au parent de ma checkbox à savoir le li :

    Nom : Capture.PNG
Affichages : 69
Taille : 5,5 Ko

    Pourquoi dis tu que cela est dangereux dans le contexte d'une checkbox ?

    Merci encore pour vos réponses en tout cas cela m'aide bien.

  7. #7
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    août 2003
    Messages
    3 642
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : août 2003
    Messages : 3 642
    Points : 5 060
    Points
    5 060
    Par défaut
    Oui, j'avais vu pour e.target.parentElement.id mais comme tu dupliquais des éléments, tu risquais de perdre le contrôle des "parents / enfants", d'autant plus que le texte d'une checkbox est normalement contenu dans un label

  8. #8
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    janvier 2011
    Messages
    15 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : janvier 2011
    Messages : 15 779
    Points : 40 083
    Points
    40 083
    Par défaut
    je me suis trop compliqué la tête avec ça.
    il me semblait aussi

    Exemple complet :
    Voici ce que cela pourrait donner avec la création :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    <!DOCTYPE html>
    <html lang="fr-FR">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TODO liste</title>
    <meta name="Author" content="NoSmoking">
    <meta name="DVP-discussion" content="d2099943">
    <meta name="description" content="Déplacement d'un élément d'un parent à un autre en utilisant la méthode ParentNode.append().">
    <style>
    html, body {
      margin: 0;
      padding: 0;
      font: 1em/1.5 Verdana,sans-serif;
    }
    h1, h2, h3 {
      margin: .25em 0;
      color: #069;
    }
    time {
      float: right;
      margin: .5em;
      font-size: 0.9em;
      color: #888;
    }
    main {
      display: block;
      margin: auto;
      max-width: 60em;
    }
    section {
      position: relative;
      margin: 0 2em 1em;
    }
    .cde {
      display: flex;
    }
    .cde * {
      border: 1px solid #AAA;
      font: inherit;
      line-height: 2;
    }
    #text-tache {
      margin-right: 1em;
      flex: 1 0 auto;
    }
    #create-tache {
      flex: 0 1 10em;
    }  
    [id^="list-"] {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    fieldset {
      margin-bottom: 1em;
      min-height: 8em;
      border: 1px solid #AAA;
    }
    legend {
      padding: 0 .5em;
      font-weight: 700;
      color: #069;
      background: #FFF;
    }
    label {
      cursor: pointer;
    }
    [type="checkbox"] {
      margin: 0 .5em;
    }
    #list-do label {
      text-decoration: line-through;
    }
    </style>
    </head>
    <body>
    <main>
      <header>
        <time datetime="2021-01-07">Jan. 2021</time>
        <h1>Transfert élément with <code>append()</code></h1>
      </header>
      <section>
        <h2>TODO liste</h2>
        <p class="cde">
          <input id="text-tache" value="Nouvelle tâche">
          <button id="create-tache">Ajouter la tâche</button>
        </p>
        <fieldset>
          <legend>A faire</legend>
          <ul id="list-todo"></ul>
        </fieldset>
        <fieldset>
          <legend>Fait</legend>
          <ul id="list-do"></ul>
        </fieldset>
      </section>
      <footer>
        <p>Voir la <a href="https://www.developpez.net/forums/showthread.php?t=2099943">discussion sur Developpez.com</a>
      </footer>
    </main>
    <script>
    "use strict";
    function handleClick(e) {
      const newParent = document.getElementById(this.checked ? "list-do" : "list-todo");
      newParent.append(this.closest("li"))
    }
     
    function createTache() {
      const oInput = document.getElementById("text-tache");
      const sText = oInput.value;
      if (sText) {
        const oDest = document.getElementById("list-todo");
        const oLi = document.createElement("LI");
        const oLabel = document.createElement("LABEL");
        const oCheck = document.createElement("INPUT");
          oCheck.type = "checkbox";
          oCheck.addEventListener("click", handleClick);
        oLabel.append(oCheck, sText);
        oLi.append(oLabel);
        oDest.append(oLi);
        oInput.value = "";
      }
      else {
        oInput.focus();
      }
    }
    const oBtn = document.getElementById("create-tache");;
    oBtn.addEventListener("click", createTache);
    </script>
    </body>
    </html>
    Tu devrais être proche de ce que tu cherches à faire, certaines fonctionnalités indispensables en moins comme suppression, enregistrement ...

    Fichier test en ligne :

    Ressource :

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    Ouais c'est bon j'ai réussi, j'ai pu rajouter une fonction de suppression, je rajouterais aussi une fonction de modification d'une tache puis un enregistrement (sur fichier JSON dans un premier temps ).

    Je pense que je peux clôturer le sujet du coup ? en tout cas vos conseils m'ont été vraiment très utiles

  10. #10
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 5
    Points : 2
    Points
    2
    Par défaut
    ah j'ai une autre question NoSmoking, Je vois que finalement tu n'as pas créer d'id unique pour chacune des ligne de tache.
    Perso j'ai fais en prévision justement d'un enregistrement dans un fichier JSON. J'ai donc créé une classe tache qui reprend la tache en question, l'état de celle-ci (réalisé ou pas) puis son id. Je me suis dis que comme ça cela sera plus simple pour l'enregistrement. Mais je me complique peut être encore la tache ?

    Je vois aussi que tu as fais plus simple et plus concis que moi hahah !!

  11. #11
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    janvier 2011
    Messages
    15 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : janvier 2011
    Messages : 15 779
    Points : 40 083
    Points
    40 083
    Par défaut
    Dans beaucoup de cas on peut se passer de beaucoup de chose (pensée du jour).

    Je verrais tes tâches caractérisées par
    • libellé, c'est le contenu de ton <label> ;
    • état d'avancement, c'est ton <input type="checkbox"> ;
    • date de création, là où tu mets une ID, qui ne signifiera pas grand chose, je mettrais une date de création et sauf à créer plusieurs ta^che en moins d'une seconde il ne risque pas d'y avoir de collision.


    Concernant la date il suffit, à la création, d'ajouter un attribut data-create, par exemple, en récupérant le Date.now(), cela pourra te servir pour faire du tri ou autre.
    Le code à la création ne change pour ainsi dire pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function createTache() {
      const oInput = document.getElementById("text-tache");
      const sText = oInput.value;
      if (sText) {
        const oDest = document.getElementById("list-todo");
        const oLi = document.createElement("LI");
        const oLabel = document.createElement("LABEL");
        const oCheck = document.createElement("INPUT");
          oCheck.type = "checkbox";
          oCheck.addEventListener("click", handleClick);
        oLabel.append(oCheck, sText);
        oLi.append(oLabel);
        oDest.append(oLi);
        // ajout info date création
        oLi.dataset.create = Date.now();
        oInput.value = "";
        // mise à jour liste
        getTaches();
      }
      else {
        oInput.focus();
      }
    }
    Pour la récupération des données au format JSON, pour enregistrement ou autre, on crée la fonction getTaches, elle reprend les données contenues dans les <li> et peut donc être appelée n'importe quand.
    Celle que j'ai mise dans la nouvelle version du fichier est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function getTaches() {
      const oLIs = document.querySelectorAll("#list-todo li, #list-do li");
      const result = [];
      oLIs.forEach((li) => {
        result.push({
          "date": new Date(Number(li.dataset.create)),
          "state": li.querySelector("[type='checkbox']").checked,
          "texte": li.querySelector("label").textContent
        });
      });
      // on peut trier par date de création par exemple
      result.sort((a, b) => {
        const da = new Date(a.date).getTime();
        const db = new Date(b.date).getTime();
        return da - db;
      })
      // affiche résultat lisible
      document.getElementById("result").textContent = JSON.stringify(result, null, 2);
    }
    Voilà en gros, la fichier test en ligne reprend en compte ces modifications.

    Fichier test en ligne :

  12. #12
    Expert confirmé
    Avatar de javatwister
    Homme Profil pro
    danseur
    Inscrit en
    août 2003
    Messages
    3 642
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : danseur

    Informations forums :
    Inscription : août 2003
    Messages : 3 642
    Points : 5 060
    Points
    5 060
    Par défaut
    Autre petit exemple, avec enregistrement des données: http://javatwist.imingo.net/todo.php

    L'identifiant est "Maurice" (sinon, accès en lecture uniquement).

    - Les tâches sont classées par date.
    - Par défaut, la date de création de la tâche reste en mémoire, même quand elle est résolue.
    - Recherche de texte possible.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 08/12/2006, 03h18
  2. Appel de fonction dans une action
    Par ogiacomo dans le forum Ada
    Réponses: 2
    Dernier message: 28/11/2006, 15h16
  3. Appel de fonction dans une classe
    Par saint-pere dans le forum Langage
    Réponses: 3
    Dernier message: 08/05/2006, 23h13
  4. Appel de fonction dans une page JSP
    Par Addouna dans le forum Servlets/JSP
    Réponses: 6
    Dernier message: 09/03/2006, 13h56
  5. Appel de fonction dans une classe
    Par Seth77 dans le forum Langage
    Réponses: 8
    Dernier message: 16/01/2006, 11h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo