web-dev-qa-db-fra.com

Existe-t-il une pseudo-classe CSS ": drop-hover"?

Dire que j'ai un input type="file" champ. On peut déposer un fichier sur ce input (comme dans Firefox) au lieu de cliquer sur "parcourir" et de sélectionner le fichier.

Maintenant, je veux le personnaliser un peu, en changeant la couleur d'arrière-plan du champ quand on est sur le point de déposer un fichier dans le input. Je ne peux pas vraiment utiliser :hover car il correspond même lorsque vous ne faites pas glisser-déposer. Existe-t-il une CSS (pseudo-classe) pour le faire?

Et existe-t-il un moyen CSS de style différent si le fichier déposé n'est pas accepté et s'il l'est? Disons que si le champ accepte uniquement les fichiers PNG en utilisant les attributs accept, je le rendrais vert si vous êtes sur le point d'y déposer un fichier PNG et rouge s'il s'agit d'un autre type de fichier.

Existe-t-il un CSS moyen de les faire aujourd'hui? Existe-t-il un moyen prévu de le faire dans CSS (comme dans les spécifications à venir/dans les spécifications actuelles mais pas implémenté nulle part)?

20
Xenos

MISE À JOUR: Merci au commentaire de @ Renato, selon https://github.com/w3c/csswg-drafts/issues/2257 , la pseudo-classe drop a été supprimée maintenant.


Il y a :drop Et :drop() pseudo-classe, qui est actuellement à l'état Working Draft .

Selon http://css4.rocks/selectors-level-4/drag-and-drop-pseudo-class.php , le support du navigateur n'est pas bon.

Pour le cas où "le fichier déposé n'est pas accepté", :drop(invalid active) devrait fonctionner à l'avenir.

12
shaochuancs

J'avais la même question et je l'ai résolue un peu différemment de Nashcheez. Toujours en utilisant JavaScript, cependant (j'ai utilisé jQuery ici pour simplifier les choses):

function drag(ev) {
  ev.dataTransfer.setData("text", "foo");
}

function allowDrop(ev) {
  $(ev.target).attr("drop-active", true);
  ev.preventDefault();
}

function leaveDropZone(ev) {
  $(ev.target).removeAttr("drop-active");
}

function drop(ev) {
  ev.preventDefault();
  $(ev.target).removeAttr("drop-active");
  alert(ev.dataTransfer.getData("text"));
}
#draggableItem {
  height: 50px;
  width: 150px;
  background-color: #eee;
}

#dropZone {
  height: 50px;
  width: 150px;
  background-color: #efe;
}

#dropZone[drop-active=true] {
  box-shadow: inset 0px 0px 0px 2px #00C;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="draggableItem" draggable="true" ondragstart="drag(event);">Drag Me</div>

<div id="dropZone" ondragover="allowDrop(event);" ondragleave="leaveDropZone(event);" ondrop="drop(event);">Drop Here</div>

J'ai testé cela sur Safari, Firefox et Chrome, mais je n'ai pas essayé IE. J'enfreins probablement une règle avec l'attribut personnalisé, mais cela semble fonctionner pendant que j'attends CSS4.

8
TobyRush

Il n'y a absolument aucune solution css pure cross-browser actuellement pour changer les propriétés d'un élément lors du glisser-déposer d'éléments dans la fenêtre du navigateur.

Ce que vous essayez de faire ici peut être réalisé par Javascript/jQuery en utilisant un conteneur caché et en l'affichant uniquement lorsque l'objet est à l'intérieur du conteneur déplaçable.

Il y a cette démo que j'avais enregistrée plus tôt si vous souhaitez jeter un œil à:

var resetTimer;

var reset = function() {
  $('#d1').hide();
};

var f = function(e) {
  var srcElement = e.srcElement ? e.srcElement : e.target;

  if ($.inArray('Files', e.dataTransfer.types) > -1) {
    e.stopPropagation();
    e.preventDefault();

    e.dataTransfer.dropEffect = (srcElement.id == 'd1') ? 'copy' : 'none';

    if (e.type == "dragover") {
      if (resetTimer) {
        clearTimeout(resetTimer);
      }
      $('#d1').show();
      console.info('dropped on <' + srcElement.tagName.toLowerCase() + ' id="' + srcElement.id + '">\n\ne.dataTransfer.types is ' + e.dataTransfer.types + '\n\ne.dataTransfer.files.length is ' + (e.dataTransfer.files ? e.dataTransfer.files.length : 0));

    } else if (e.type == "dragleave") {
      resetTimer = window.setTimeout(reset, 25);
    } else if (e.type == "drop") {
      reset();
      alert('dropped on <' + srcElement.tagName.toLowerCase() + ' id="' + srcElement.id + '">\n\ne.dataTransfer.files.length is ' + (e.dataTransfer.files ? e.dataTransfer.files.length : 0));
    }
  }
};

document.body.addEventListener("dragleave", f, false);
document.body.addEventListener("dragover", f, false);
document.body.addEventListener("drop", f, false);
body {
  border: 1px solid black;
}

#d0,
#d2 {
  border: 1px solid black;
}

#d1 {
  border: 1px solid black;
  display: none;
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <div id="d0">drag files onto this page</div>
  <div id="d1">-&gt; drop here &lt;-</div>
  <div id="d2">and stuff will happen</div>
</body>
2
nashcheez