11574 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous
Cela fait pas mal de temps que je n'ai pas programmé de fonction drag and drop et j'ai du mal à m'en sortir, d'autant que la dernière fois que je l'ai fait (il y a au moins 10 ans) la version de JavaScript n'était pas la même.
L'objectif: changer l'ordre des li dan un ul.
Auriez vous un modèle de code à me proposer ?
Merci de votre aide.
Merci beaucoup, je vais regarder ces solutions.
J'en avais bien trouvé une sur Internet, mais c'était un (très bon) tuto YouTube, sauf que le code était affiché à l'écran et donc difficile à copier.
En prenant modèle sur ces codes, j'ai écrit un programme de test.
https://alma-musica.net/html/tests/test-progarea.html
Le but est de déplacer une texte dans la même zone ou dans l'autre zone.
Ce qui marche: déplacer un texte sur un autre texte place le texte déplacé avant le texte cible.
Ce qui ne marche pas: déplacer un texte dans une zone (cadre gris) en dehors du cadre vert.
L'évènement drop sur la zone n'a pas lieu.
Je suppose que c'est gros comme une maison, mais je ne vois pas comment corriger ça.
Une idée?
Merci de votre aide.
Bonsoir,

Les éléments font partie d'un "ul" ('proglist' selon css)

Le deplacement fait en sorte qu'on enleve un element de l'ul pour l'ajouter à l'autre ul.

Et l'ul n'est que dans le cadre vert.
Salut,

Intéressant ! je prends.

Moi je ferais ainsi :

getBoundingClientRect() donne la position et les dimensions de l'élément cible, donc :
- Si la souris est dans la moitié haute -> insertBefore(element, target)
- Si la souris est dans la moitié basse -> insertBefore(element, target.nextSibling)

Pour connaître la position verticale de la souris dans l'élément, utiliser e.clientY - rect.top.

Toutes ces classes CSS sur lesquelles le JavaScript s'appuie dans la démo... elles ne sont pas nécessaire : juste une classe sur les <ul> pour scoper les éléments draggables (ici .drag-list) avec ce comportement spécifique sur la page et pour les items on s'appuie sur l'attribut natif draggable="true", c'est tout.

Ça donne ceci : CodePen

---

PS : j'ai enlevé les classes JS car c'est du sucre syntaxique en ECMAScript, verbeux et sous performant (j'exagère un peu).

PS du PS : le window.addEventListener c'est parce que je suis sur CodePen, mais chez toi tu peux faire mieux en utilisant DOMContentLoaded.

PS du PS du PS : je conseille de donner du feed-back pour les utilisateurs, sinon l'expérience n'est pas très agréable :
.drag-list {
  &.drag-list-empty {
    /* Hauteur minimale pour drop si liste vide : */
    display: grid;
    min-height: 3em;
    width: 100%;
    outline: .1em dashed #777;

    &::before {
      content: 'Glissez vos items';
      align-content: center;
      text-align: center;
    }
  }
  
  li[draggable="true"] {
      cursor: grab;
  }

  li[draggable="true"].dragged,
  li[draggable="true"].over-top,
  li[draggable="true"].over-bottom {
      opacity: 0.4;
  }
}

Édit : correction du JS qui accepte des items si parent .drag-list vide, sinon on est bloqué.
Modifié par Olivier C (14 Jun 2026 - 10:26)
Merci de t’être donné tant de mal, mais ce que tu fais c’est reprogrammer le test, qui ne présente en soi aucun intérêt. Je n’ai nulle part dans mon projet besoin de déplacer des textes entre deux zones. Ce n’est qu’un test bâclé pour comprendre comment fonctionne le mécanisme des événements DnD.
Je n’ai pas de réponse à ma question: pourquoi l’événement drop ne se déclenche pas sur la zone ? Est-ce que j’ai omis quelque chose dans les événements écoutés sur la zone ? Y a-t-il quelque chose à faire dans la déclaration de la zone?
PapyJP a écrit :
Merci de t’être donné tant de mal, mais ce que tu fais c’est reprogrammer le test, qui ne présente en soi aucun intérêt.

Sympa. Pas grave : de toute façon si j'interviens sur ce forum c'est que la problématique ou fonctionnalité m'intéresse. Donc ce n'est pas du temps perdu pour moi, je capitalise sur les réponses que je donne ici.
PapyJP a écrit :
Je n’ai nulle part dans mon projet besoin de déplacer des textes entre deux zones.

À la lecture de tes premiers messages ce n'est pas évident à déduire, mais j'entends.
PapyJP a écrit :
Est-ce que j’ai omis quelque chose dans les événements écoutés sur la zone ?

Oui : l'oubli de preventDefault() dans tes gestionnaires. Pour qu'un élément accepte un drop, il faut obligatoirement appeler preventDefault() dans le gestionnaire dragover et, dans une moindre mesure, pour dragenter.

preventDefault() annule le comportement par défaut du navigateur pour cet événement. Dans le cas du drag & drop, le comportement par défaut du navigateur pour dragover est de refuser le drop. Le navigateur part du principe qu'un élément n'accepte pas qu'on dépose quelque chose dessus, sauf si tu le lui demande explicitement.
Modifié par Olivier C (14 Jun 2026 - 13:12)
Meilleure solution
OK je l'ai mis dans dragover sur l'une de mes classes mais pas dans l'autre, ou plutôt j'ai mis stopPropagation au lieu de preventDefault
Je me doutais bien que c'était quelque chose de ce genre mais j'ai été incapable de le voir.
Comme je disais, c'est gros comme une maison...
Merci beaucoup
Smiley smile
Modifié par PapyJP (14 Jun 2026 - 18:20)