Comment puis-je détecter qu'un fichier est traîné plutôt qu'un élément draggable sur ma page?

J'utilise les événements html5 pour permettre le glisser-déplacer des fichiers et des éléments. J'ai attaché l'événement dragover au corps et j'utilise les délégations d'événements pour montrer où un draggable peut être abandonné. Ma question est de savoir comment puis-je savoir si un fichier est traîné par rapport à un élément avec draggable = true. Je sais que je peux détecter l'élément en cours de déplacement via e.target. Mais, comment puis-je savoir s'il s'agit d'un fichier.

Jquery est disponible.

Aussi, ne pas parler de jquery-ui draggable ici.

Je commence à penser que le seul moyen de détecter le fichier sera par l'exclusion et la détection des éléments à la place. Si nous ne traînons pas un élément, supposons qu'il s'agisse d'un fichier. Cela nécessitera un travail supplémentaire, car les images et les liens peuvent être déplacés par défaut, donc je devrais y ajouter des événements ou les empêcher de glisser.

Vous pouvez détecter ce qui est traîné en inspectant dataTransfer.types . Ce comportement n'est pas (toujours) cohérent dans les navigateurs, donc vous devez vérifier l'existence de 'Files' (Chrome) et 'application/x-moz-file' (Firefox).

 // Show the dropzone when dragging files (not folders or page // elements). The dropzone is hidden after a timer to prevent // flickering to occur as `dragleave` is fired constantly. var dragTimer; $(document).on('dragover', function(e) { var dt = e.originalEvent.dataTransfer; if (dt.types && (dt.types.indexOf ? dt.types.indexOf('Files') != -1 : dt.types.contains('Files'))) { $("#dropzone").show(); window.clearTimeout(dragTimer); } }); $(document).on('dragleave', function(e) { dragTimer = window.setTimeout(function() { $("#dropzone").hide(); }, 25); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="dropzone" style="border: 2px dashed black; background: limegreen; padding: 25px; margin: 25px 0; display: none; position"> 🎯 Drop files here! </div> 📄 hover files here 

Amélioration de la réponse de bouke:

Étant donné que les appels chrome entraînent le document sur chaque élément de chaque élément, il peut provoquer un scintillement de la zone de déclenchement, surtout s'il existe de nombreux éléments imbriqués.

 $(document).on('dragleave', function(e) { dragTimer = window.setTimeout(function() { $("#dropzone").hide(); }, 25); }); 

Ce que j'ai fait pour résoudre le problème pour moi, c'est augmenter le temps d'arrêt un peu et ajouter clearTimeout avant de définir chaque délai d'attente, car dans certains cas, il y aurait plus d'un délai d'attente qui n'est pas effacé lors de l'événement dragover, puisque DragTimer ne stocke que le dernier un. La version du résultat:

 $(document).on('dragleave', function(e) { window.clearTimeout(dragTimer); dragTimer = window.setTimeout(function() { $("#dropzone").hide(); }, 85); }); 

Btw, merci pour l'idée! Mon autre solution était une douleur absolue 🙂

Je l'utilise simplement pour détecter les fichiers dans l'événement dragover :

 Array.prototype.indexOf.call(files, "Files")!=-1 // true if files 

Je ne comprends pas complètement votre situation actuelle, mais si votre élément est un objet traînant, je suppose que vous pouvez l'envelopper dans un autre objet avec un identifiant différent pour le fichier et les éléments normaux? Donc, lorsque vous appelez un événement, vous pouvez vérifier son identifiant avant de le traiter. J'espère que cela peut vous aider! =)

Utilisez la fonction ci-dessous pour vérifier si la source de glissement est un fichier externe.

Testé sur Windows 7 avec:

  • Firefox version 39
  • Version 44 de Chrome
  • Safari version 5.1.7
 function isDragSourceExternalFile(dataTransfer){ // Source detection for Safari v5.1.7 on Windows. if (typeof Clipboard != 'undefined') { if (dataTransfer.constructor == Clipboard) { if (dataTransfer.files.length > 0) return true; else return false; } } // Source detection for Firefox on Windows. if (typeof DOMStringList != 'undefined'){ var DragDataType = dataTransfer.types; if (DragDataType.constructor == DOMStringList){ if (DragDataType.contains('Files')) return true; else return false; } } // Source detection for Chrome on Windows. if (typeof Array != 'undefined'){ var DragDataType = dataTransfer.types; if (DragDataType.constructor == Array){ if (DragDataType.indexOf('Files') != -1) return true; else return false; } } } 

Exemple d'utilisation avec JQuery

 $(document).on('dragover', function(e){ var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer); console.log(IsFile); });