web-dev-qa-db-fra.com

Comment détecter un fichier en train de glisser plutôt qu'un élément déplaçable sur ma page?

J'utilise les événements html5 pour activer le glisser-déposer d'éléments et d'éléments. J'ai attaché l'événement dragover au corps et j'utilise des délégations d'événements pour indiquer où un objet déplaçable peut être supprimé. Ma question est de savoir comment puis-je savoir si un fichier est en train d'être déplacé par rapport à un élément avec draggable = true. Je sais que je peux détecter l'élément déplacé via e.target. Mais comment puis-je savoir s’il s’agit d’un fichier?.

jquery est disponible.

Aussi, pas parler de jquery-ui glissable ici.

Je commence à penser que le seul moyen de détecter le fichier sera d'exclure et de détecter les éléments. Si nous ne faisons pas glisser un élément, supposons qu'il s'agisse d'un fichier. Cela nécessitera un travail supplémentaire, car les images et les liens sont déplaçables par défaut. Je vais donc devoir leur ajouter des événements ou les empêcher de les faire glisser.

37
aepheus

Vous pouvez détecter ce qui est déplacé en inspectant dataTransfer.types. Ce comportement n'est pas (encore) cohérent sur tous les navigateurs, vous devez donc 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

61
bouke

Amélioration de la réponse de Bouke:

Puisque chrome appelle dragleave de document sur chaque élément du centre pour chaque élément, il peut provoquer le scintillement de la zone de dépôt, en particulier 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égler le problème pour moi, c’est d’augmenter un peu le délai d’attente et d’ajouter clearTimeout avant chaque réglage, car dans certains cas, il existait parfois plusieurs délais qui n'étaient pas supprimés dans l’événement dragover, car un. La version du résultat:

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

au fait, merci pour l'idée! Mon autre solution était une douleur absolue :)

6
elanoism

Je viens de l'utiliser pour détecter les fichiers dans l'événement dragover:

Array.prototype.indexOf.call(files, "Files")!=-1 // true if files
4
Tomáš Zato

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 
  • Chrome version 44
  • 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);
});
0
Shannon