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 :

Tri par glisser-déposer sans jQuery


Sujet :

JavaScript

  1. #1
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 351
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 351
    Points : 15 697
    Points
    15 697
    Par défaut Tri par glisser-déposer sans jQuery
    Cela fait un an environ que j'essaye de ne plus utiliser jQuery et ça avance bien puisque je n'utilise plus que le datepicker.
    La dernière chose sur laquelle j'ai travaillé est un système de tri par glisser-déposer pour lequel j'utilisais jQuery UI comme l'exemple là :
    https://jqueryui.com/sortable/#placeholder

    Je suis arrivé à faire un test qui me plait bien à l'aide des informations là :
    https://developer.mozilla.org/fr/doc...ent/drop_event
    Il fonctionne exactement comme je le souhaite mais d'une ligne de code avec jQuery, je passe à plusieurs pavés avec 5 addEventListener.
    J'ai donc peur que si je dois réutiliser ça dans 2 mois, je ne comprenne plus trop comment fonctionne mon code et je m'emmêlerai les pinceaux à chaque nouveau projet.

    Est ce que vous avez des idées pour mieux organiser mon code ?
    Peut-être qu'il y a des parties qui peuvent être simplifiées ou écrites autrement ?

    Voilà le code complet d'une page html où tout fonctionne.
    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
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    <!DOCTYPE html>
    <html lang="fr">
    <head>
    	<meta charset="UTF-8"/>
    	<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </head>
    <body>
     
    <style>
     
    body
    {
            display : flex;
    }
     
    body > div
    {
            flex-grow : 1;
    }
     
    .depot
    {
            background : #CDE;
            
            margin : 0.4em;
            padding : 0.5em;
            
    }
     
     
    .deplacable
    {
            background : #666;
            color : #EEE;
            
            padding : 1em;
            
    }
     
    .deplacement_en_cours
    {
            background : #993;
    }
     
     
    .resultat
    {
            background : #FFC;
            padding : 1em;
    }
     
    .resultat div
    {
            margin : 0.4em;
    }
     
     
    </style>
     
    <script>
    "use strict";
     
     
    function preparer_tri()
    {
            
            const conteneur = document.getElementsByClassName(`conteneur`)[0];
            
            
            conteneur.addEventListener("dragenter", e => {
                    
                    const depot_cible = e["target"].closest(`.depot`);
                    
                    if (null !== depot_cible) {
                            
                            const deplace = document.getElementsByClassName(`deplacement_en_cours`)[0];
                            
                            deplace
                                    .closest(`.depot`)
                                    .appendChild(depot_cible.getElementsByClassName(`deplacable`)[0])
                            ;
                            
                            depot_cible.appendChild(deplace);
                            
                    }
                    
            });
            
            
            [...conteneur.getElementsByClassName(`depot`)].forEach(depot => {
                    
                    
                    depot.addEventListener("dragover", e => {
                            e.preventDefault(); // pour autoriser l'évènement drop
                    });
                    depot.addEventListener("drop", e => {
                            document
                                    .getElementsByClassName(`deplacement_en_cours`)[0]
                                    ["classList"].remove(`deplacement_en_cours`)
                            ;
                            
                            affiche_ordre();
                    });
                    
                    
                    const deplacable = depot.getElementsByClassName(`deplacable`)[0];
                    
                    
                    deplacable.addEventListener("dragstart", e => {
                            e["target"]["classList"].add(`deplacement_en_cours`);
                    });
                    
                    deplacable.addEventListener("drag", e => {
                            
                            console.log([`élément déplacé`, e["target"]]);
                            
                    });
                    
                    
            });
            
            
            affiche_ordre();
            
    }
     
     
    function affiche_ordre()
    {
            
            const resultat = document.getElementsByClassName(`resultat`)[0];
            
            resultat["innerHTML"] = ``;
            
            [...document.getElementsByClassName(`deplacable`)].forEach(div => {
                    
                    resultat.enfant({
                            "balise" : "div",
                            "texte" : div.getAttribute("data-nombre"),
                    });
                    
            });
            
            
    } // function affiche_ordre()
     
     
    </script>
     
    <script>
    "use strict";
     
     
    document.addEventListener("DOMContentLoaded", e => {
            
            
            const conteneur = document["body"].enfant({
                    "balise" : "div",
                    "classes" : `conteneur`,
            });
            
            document["body"].enfant({
                    "balise" : "div",
                    "classes" : `resultat`,
            });
            
            
            const nombre_elements = 7;
            
            
            for (let id = 1; id <= nombre_elements; id++) {
                    
                    const depot = conteneur.enfant({
                            "balise" : "div",
                            "classes" : `depot`,
                    });
                    
                    const deplacable = depot.enfant({
                            "balise" : "div",
                            "classes" : `deplacable`,
                            "texte" : String.fromCodePoint(id + 64) + ` - ` + id,
                    });
                    
                    deplacable.setAttribute("data-nombre", id);
                    deplacable.setAttribute("draggable", true);
                    
                    
            } // FIN for (let id = 1; id <= nombre_elements; id++) {
            
            
            preparer_tri();
            
            
    }); // FIN document.addEventListener("DOMContentLoaded", e => {
     
     
    Node["prototype"]["enfant"] = function (p) {
            
            const enfant = document.createElement(p["balise"]);
            
            if ("classes" in p) {
                    enfant["classList"].add(...p["classes"].split(" "));
            }
            
            if ("texte" in p) {
                    enfant["textContent"] = p["texte"];
            }
            
            if ("html" in p) {
                    enfant["innerHTML"] = p["html"];
            }
            
            this.appendChild(enfant);
            
            
            return enfant;
            
    };
     
     
    </script>
     
     
    </body>
     
    </html>
    Dans cet exemple, j'ai séparé la génération des balises dans une 2e balise "script" puisque dans mes projets, les balises sont souvent générées en PHP donc c'est la 1re partie du code que je vais réutiliser pour faire le système de tri.

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 075
    Points : 44 679
    Points
    44 679
    Par défaut
    Bonjour,
    Il fonctionne exactement comme je le souhaite mais d'une ligne de code avec jQuery, je passe à plusieurs pavés avec 5 addEventListener.
    Il sera difficile de faire autrement attendu que les événements Drag sont au nombre de 7. De plus tu as l'avantage que ce que tu vas faire fonctionnera sur tactile !

    Cependant tu peux toujours te créer ta propre classe pour optimiser tous cela dans tes futurs besoins.


    Est ce que vous avez des idées pour mieux organiser mon code ?
    Tu peux également rendre cela plus concis en écrivant une base comme :
    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
    const dragEvent = "drag;dragend;dragenter;dragleave;dragover;dragstart;drop".split(";");
     
    function handleDrag(e) {
      const type = e.type;
      const elem = e.target;
      switch (type) {
        case "drag":
          break;
        case "dragend":
          break;
        case "dragenter":
          break;
        case "dragleave":
          break;
        case "dragover":
          break;
        case "dragstart":
          break;
        case "drop":
          break;
      }
    }
     
    function initDrag(selector) {
      const all = document.querySelectorAll(selector)
      all.forEach((el) => {
        dragEvent.forEach((type) => {
          el.addEventListener(type, handleDrag);
        })
      })
    }
    Ça c'est style une seule entrée.

    Je pense qu'en même que pour une meilleur maintenance tu aurais intérêt de ne passer aux addEventListener que la référence à la fonction et ne pas mettre tous le code dans une fonction anonyme.

    J'avais fait : Drag and drop, il y a pas mal de temps et je l'ai compris en le relisant même si tout n'est pas top

  3. #3
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 886
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 886
    Points : 3 725
    Points
    3 725
    Par défaut
    Salut,

    Citation Envoyé par mathieu Voir le message
    Il fonctionne exactement comme je le souhaite mais d'une ligne de code avec jQuery,
    Une seule ligne de code avec jQuery, certes, mais il faut ajouter deux librairies js (jquery et jquery-ui) plus les fichiers CSS... Du coup je préfère le code que tu as fais qui est au final beaucoup plus court et c'est aussi plus instructif (on voit les différentes étapes contrairement à la boite noire avec jquery)

    Citation Envoyé par mathieu Voir le message
    ... je passe à plusieurs pavés avec 5 addEventListener.
    Ben en fait il y en a plus que 5... En effet des écouteurs pour les événements "dragover", "drop", "dragstart" et "drag" sont ajoutés à chaque élément (ayant la class "depot") du conteneur...

    Tu peux éviter cela en faisant de la délégation : tu mets ces écouteurs uniquement sur le conteneur (comme ce que tu as d'ailleurs fait avec l’événement "dragenter")

    Exemple pour "dragstart" et "dragover" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    conteneur.addEventListener("dragstart", e => {
        e["target"]["classList"].add(
            `deplacement_en_cours`);
    });
     
    conteneur.addEventListener("dragover", e => {
        const depot_cible = e["target"].closest(`.depot`);
     
        if (null !== depot_cible) {
            e.preventDefault(); // pour autoriser l'évènement drop     
        }
    });
    Je ne mets pas le code pour les événements "drag" (car je pense que tu peux le supprimer, tu t'en sert juste pour déboguer apparemment) et "drop" car je te conseil de le remplacer par "dragend" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    conteneur.addEventListener("dragend", e => {
        conteneur.getElementsByClassName(`deplacement_en_cours`)[0]["classList"].remove(`deplacement_en_cours`);
    });
    Pourquoi ? Parce que dans ton code lorsqu'il y a un "glisser" mais pas de "déposer" la class 'deplacement_en_cours' n'est pas supprimée... Tu peux voir cela par exemple en faisant un "glisser" et tu vas par exemple au-dessus de la div de class "resultat" et tu fait un "lâcher"...

    -----------

    Pour ce qui est du gestionnaire pour l’événement "dragenter" :

    - Il est possible de le supprimer et de le mettre dans le gestionnaire de l’événement "dragover".
    - On pourrait l'optimiser si tu veux :

    1- Si tu ajoutes un consol.log tu verras que le partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    deplace
    .closest(`.depot`)
    .appendChild(depot_cible.getElementsByClassName(`deplacable`)[0]);
     
    depot_cible.appendChild(deplace);
    est exécutée à chaque fois que le curseur (de la souris) entre dans un descendant du conteneur... Ce n'est pas trés grave mais on peut l'éviter en ajoutant juste avant la condition suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (depot_cible.firstChild == deplace)
        return
    2- Tu pourrais d'ailleurs remplacer cette partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    deplace
        .closest(`.depot`)
        .appendChild(depot_cible.getElementsByClassName(`deplacable`)[0]);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    deplace
        .parentElement 
        .appendChild(depot_cible.firstChild)

  4. #4
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 886
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 886
    Points : 3 725
    Points
    3 725
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    Tu peux également rendre cela plus concis en écrivant une base comme :
    Ah je trouve cela intéressant...

    Mais il faut remplir le switch, n'est-ce pas ? C'est-à-dire qu'il faut ajouter le code pour chaque événement ? Du coup ce sera les mêmes codes pour tous les éléments html...

    La fonction handleDrag pourrait aussi retourner une fonction correspondant à l’événement...

    Citation Envoyé par NoSmoking Voir le message
    J'avais fait : Drag and drop, il y a pas mal de temps et je l'ai compris en le relisant même si tout n'est pas top
    Oh joli !

    Citation Envoyé par Beginner. Voir le message
    Pour ce qui est du gestionnaire pour l’événement "dragenter" :

    - Il est possible de le supprimer et de le mettre dans le gestionnaire de l’événement "dragover".
    Avec tous les changements que j'ai mentionnés, on obtient cette fonction :

    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
    function preparer_tri() {
        const conteneur = document.getElementsByClassName(`conteneur`)[0];
     
        conteneur.addEventListener("dragstart", e => {
            e["target"]["classList"].add(
                `deplacement_en_cours`);
        });
     
        conteneur.addEventListener("dragover", e => {
            const depot_cible = e["target"].closest(`.depot`);
     
            if (null !== depot_cible) {
                e.preventDefault(); // pour autoriser l'évènement drop
     
                const deplace = conteneur.getElementsByClassName(`deplacement_en_cours`)[0];
                if (depot_cible.firstChild == deplace)
                    return
     
                deplace
                    .parentElement // devrait être plus rapide que .closest(`.depot`)
                    .appendChild(depot_cible.firstChild);// devrait être plus rapide que  .appendChild(depot_cible.getElementsByClassName(`deplacable`)[0]);
     
                depot_cible.appendChild(deplace);            
            }
     
        });
     
        conteneur.addEventListener("dragend", e => {
            conteneur.getElementsByClassName(`deplacement_en_cours`)[0]["classList"].remove(`deplacement_en_cours`);
            affiche_ordre();
        });
    }

  5. #5
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 351
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 351
    Points : 15 697
    Points
    15 697
    Par défaut
    merci NoSmoking et Beginner. pour toutes ces remarques. ça ma rassure déjà d'avoir une bonne base même si j'ai encore beaucoup de travail pour l'améliorer.

    Citation Envoyé par NoSmoking Voir le message
    tu as l'avantage que ce que tu vas faire fonctionnera sur tactile !
    je n'ai pas compris si c'est mon code actuel qui fonctionne déjà sur tactile ? ou alors je dois ajouter la gestion de dragend et dragleave pour ça ?

    Citation Envoyé par NoSmoking Voir le message
    Tu peux également rendre cela plus concis en écrivant une base comme :
    je sais que moins il y a de lignes de code et plus vite elles sont lues et comprises mais là on s'approche de mon seuil opposé. quand c'est trop compact, j'ai aussi du mal à comprendre le code donc je pense que je vais m'orienter vers du code un peu plus aéré que cet exemple.

    Citation Envoyé par Beginner. Voir le message
    Ben en fait il y en a plus que 5... En effet des écouteurs pour les événements "dragover", "drop", "dragstart" et "drag" sont ajoutés à chaque élément
    oui c'est vrai que la boucle multiplie les écoutes mais là c'est plutot le nombre dans la lecture de mon code qui me chagrinait.
    ensuite je ne me suis pas encore posé la question d'optimisation des ressources. est ce qu'il vaut mieux une écoute générale sur le conteneur ou plusieurs sur chaque élément ?
    dans le pire des cas, je pense que ce code s'occupera sur une même page de 3 tris d'une vingtaine d'éléments donc intuitivement, je pense qu'aucune des 2 façons de faire ne risque de saturer le processeur ou la mémoire.

    Citation Envoyé par Beginner. Voir le message
    lorsqu'il y a un "glisser" mais pas de "déposer" la class 'deplacement_en_cours' n'est pas supprimée... Tu peux voir cela par exemple en faisant un "glisser" et tu vas par exemple au-dessus de la div de class "resultat" et tu fait un "lâcher"...
    oh merci ! j'avais vu ce bug quand je déposais l'élément en bas après le conteneur mais j'avais oublié de chercher à le corriger.

    Citation Envoyé par Beginner. Voir le message
    Je ne mets pas le code pour les événements "drag" (car je pense que tu peux le supprimer, tu t'en sert juste pour déboguer apparemment)
    je le garde surtout dans mon code de test comme base de connaissances. mais c'est clair quand que je l'utiliserai pour un tri simple, cette partie du code disparaitra rapidement.

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 075
    Points : 44 679
    Points
    44 679
    Par défaut
    je n'ai pas compris si c'est mon code actuel qui fonctionne déjà sur tactile ? ou alors je dois ajouter la gestion de dragend et dragleave pour ça ?
    je disais que le plugin jQ-ui n'est pas compatible tablette.

    Par contre je n'avais pas observé de près ta structure, j'ai l'impression que seul ton conteneur devrait avoir la class="depot".

  7. #7
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 351
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 351
    Points : 15 697
    Points
    15 697
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    Par contre je n'avais pas observé de près ta structure, j'ai l'impression que seul ton conteneur devrait avoir la class="depot".
    les éléments avec la classe "depot" sont les zones où les éléments glissés peuvent être déposés. j'en ai besoin pour savoir où a été déposé l'élément pendant qu'il est déplacé. ou alors il y a peut-être une autre façon de savoir ça ?


    Citation Envoyé par Beginner. Voir le message
    Avec tous les changements que j'ai mentionnés, on obtient cette fonction :
    j'ai encore du mal à comprendre le mélange de dragenter et dragover donc pour le moment je vais les laisser séparés et j'ai ça comme dernière version :
    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
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    <!DOCTYPE html>
    <html lang="fr">
    <head>
    	<meta charset="UTF-8"/>
    	<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </head>
    <body>
     
    <style>
     
    body
    {
            display : flex;
    }
     
    body > div
    {
            flex-grow : 1;
    }
     
    .depot
    {
            background : #CDE;
            
            margin : 0.4em;
            padding : 0.5em;
            
    }
     
     
    .deplacable
    {
            background : #666;
            color : #EEE;
            
            padding : 1em;
            
    }
     
    .deplacement_en_cours
    {
            background : #993;
    }
     
     
    .resultat
    {
            background : #FFC;
            padding : 1em;
    }
     
    .resultat div
    {
            margin : 0.4em;
    }
     
     
    </style>
     
    <script>
    "use strict";
     
     
    function preparer_tri()
    {
            
            const conteneur = document.getElementsByClassName(`conteneur`)[0];
            
            /* * /
            conteneur.addEventListener("drag", e => {
                    console.log([`élément déplacé`, e["target"]]);
            });
            /* */
            
            conteneur.addEventListener("dragstart", e => {
                    e["target"]["classList"].add(`deplacement_en_cours`);
            });
            
            conteneur.addEventListener("dragenter", e => {
                    
                    const depot_cible = e["target"].closest(`.depot`);
                    
                    if (null !== depot_cible) {
                            
                            const deplace = document.getElementsByClassName(`deplacement_en_cours`)[0];
                            
                            // l'élément qui est dans le nouveau dépot de l'élément glissé
                            // est mis dans le dépot précédent de l'élément glissé
                            deplace["parentElement"].appendChild(depot_cible["firstChild"]);
                            
                            depot_cible.appendChild(deplace);
                            
                    }
                    
            });
            
            conteneur.addEventListener("dragend", e => {
                    document
                            .getElementsByClassName(`deplacement_en_cours`)[0]
                            ["classList"].remove(`deplacement_en_cours`)
                    ;
                    
                    affiche_ordre();
            });
            
            conteneur.addEventListener("dragover", e => {
                    e.preventDefault(); // pour autoriser l'évènement drop
            });
            
            
            affiche_ordre();
            
    }
     
     
    function affiche_ordre()
    {
            
            const resultat = document.getElementsByClassName(`resultat`)[0];
            
            resultat["innerHTML"] = ``;
            
            [...document.getElementsByClassName(`deplacable`)].forEach(div => {
                    
                    resultat.enfant({
                            "balise" : "div",
                            "texte" : div.getAttribute("data-nombre"),
                    });
                    
            });
            
            
    }
     
     
    </script>
     
    <script>
    "use strict";
     
     
    document.addEventListener("DOMContentLoaded", e => {
            
            
            const conteneur = document["body"].enfant({
                    "balise" : "div",
                    "classes" : `conteneur`,
            });
            
            document["body"].enfant({
                    "balise" : "div",
                    "classes" : `resultat`,
            });
            
            
            const nombre_elements = 7;
            
            
            for (let id = 1; id <= nombre_elements; id++) {
                    
                    const depot = conteneur.enfant({
                            "balise" : "div",
                            "classes" : `depot`,
                    });
                    
                    const deplacable = depot.enfant({
                            "balise" : "div",
                            "classes" : `deplacable`,
                            "texte" : String.fromCodePoint(id + 64) + ` - ` + id,
                    });
                    
                    deplacable.setAttribute("data-nombre", id);
                    deplacable.setAttribute("draggable", true);
                    
                    
            } // FIN for (let id = 1; id <= nombre_elements; id++) {
            
            
            preparer_tri();
            
            
    }); // FIN document.addEventListener("DOMContentLoaded", e => {
     
     
    Node["prototype"]["enfant"] = function (p) {
            
            const enfant = document.createElement(p["balise"]);
            
            if ("classes" in p) {
                    enfant["classList"].add(...p["classes"].split(" "));
            }
            
            if ("texte" in p) {
                    enfant["textContent"] = p["texte"];
            }
            
            if ("html" in p) {
                    enfant["innerHTML"] = p["html"];
            }
            
            this.appendChild(enfant);
            
            
            return enfant;
            
    };
     
     
    </script>
     
     
     
    </body>
     
    </html>

  8. #8
    Modérateur

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

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 075
    Points : 44 679
    Points
    44 679
    Par défaut
    les éléments avec la classe "depot" sont les zones où les éléments glissés peuvent être déposés. j'en ai besoin pour savoir où a été déposé l'élément pendant qu'il est déplacé.
    Ok, ton approche est intéressante et limite effectivement pas mal le code.

    Remarque :
    Pour moi, le drop ne devrait être effectif qu'au lâché du pointeur et non durant. Lorsque l'on veut interrompre un glissé/déposé il suffit de sortir de la zone et relâcher le pointeur, dans ton cas la modification est irréversible. C'est donc une autre approche.

    Il y a pas mal de conventions à définir au départ, comme par exemple :
    • Si je dépose au dessus d'un élément, j'insère au dessus ;
    • Si je dépose en dessous d'un élément, j'insère en dessous ;
    • Si je dépose sur un élément, on échange les éléments ou ... cela peut également dépendre des parents, drop d'une zone dans une autre ...!
    • ...


    Quoiqu'il arrive je pense qu'il y a pas mal de garde fous à mettre en place ce qui explique le succès des plugins plus ou moins bien fait.

    ...ou alors il y a peut-être une autre façon de savoir ça ?
    Pour le principe, il suffit de regarder où le pointeur se trouve au lâché et de le comparer aux position des éléments enfants du conteneur dans lequel on dépose. Cela fera quoiqu'il arrive plus de code que ta façon de faire.


    PS : Je mettrai quand même, sur le dragstart l'objet que l'on déplace en « cache », ldragElement = e.target pour une meilleur lisibilité.

Discussions similaires

  1. [WD15] Manipuler un onglet par glisser/déposer
    Par omgirl dans le forum WinDev
    Réponses: 4
    Dernier message: 16/11/2010, 18h23
  2. Glisser-déposer sans effet
    Par poupoune1974 dans le forum VB.NET
    Réponses: 0
    Dernier message: 18/09/2010, 20h31
  3. [Batch] Modification d'un fichier txt par glisser/déposer
    Par L.rod dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 18/09/2009, 13h41
  4. Tri par ordre alphabétique sans tenir compte d'une chaîne
    Par Msieurduss dans le forum Requêtes
    Réponses: 3
    Dernier message: 24/06/2008, 10h32
  5. Ajouter un enregistrement par glisser/déposer
    Par KonTiKI dans le forum IHM
    Réponses: 3
    Dernier message: 08/03/2007, 17h59

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