Determine what is being dragged from dragenter & dragover events

前端 未结 9 1904
梦毁少年i
梦毁少年i 2020-12-04 17:35

I\'m trying to use the HTML5 draggable API (though I realize it has its problems). So far, the only showstopper I\'ve encountered is that I can\'t figure out a way to determ

相关标签:
9条回答
  • 2020-12-04 17:46

    You can determine what is being dragged when the drag starts and save this in a variable to use when the dragover/dragenter events are fired:

    var draggedElement = null;
    
    function drag(event) {
        draggedElement = event.srcElement || event.target;
    };
    
    function dragEnter(event) {
        // use the dragged element here...
    };
    
    0 讨论(0)
  • 2020-12-04 17:46

    I think you can get it by calling e.relatedTarget See: http://help.dottoro.com/ljogqtqm.php

    OK, I tried e.target.previousElementSibling and it works, sorta.... http://jsfiddle.net/Gz8Qw/4/ I think it hangs up because the event is being fired twice. Once for the div and once for the text node (when it fires for text node, it is undefined). Not sure if that will get you where you want to be or not...

    0 讨论(0)
  • 2020-12-04 17:49

    To check if it is a file use:

    e.originalEvent.dataTransfer.items[0].kind
    

    To check the type use:

    e.originalEvent.dataTransfer.items[0].type
    

    i.e. I want to allow only one single file jpg, png, gif, bmp

    var items = e.originalEvent.dataTransfer.items;
    var allowedTypes = ["image/jpg", "image/png", "image/gif", "image/bmp"];
    if (items.length > 1 || items["0"].kind != "file" || items["0"].type == "" || allowedTypes.indexOf(items["0"].type) == -1) {
        //Type not allowed
    }
    

    Reference: https://developer.mozilla.org/it/docs/Web/API/DataTransferItem

    0 讨论(0)
  • 2020-12-04 17:54

    I wanted to add a very clear answer here so that it was obvious to everyone who wanders past here. It's been said several times in other answers, but here it is, as clear as I can make it:

    dragover DOES NOT HAVE THE RIGHTS to see the data in the drag event.

    This information is only available during the DRAG_START and DRAG_END (drop).

    The issue is it's not obvious at all and maddening until you happen to read deeply enough on the spec or places like here.

    WORK-AROUND:

    As a possible work-around I have added special keys to the DataTransfer object and tested those. For example, to improve efficiency I wanted to look up some "drop target" rules when my drag started instead of every time a "drag over" occurred. To do this I added keys identifying each rule onto the dataTransfer object and tested those with "contains".

    ev.originalEvent.dataTransfer.types.includes("allow_drop_in_non_folders")
    

    And things like that. To be clear, that "includes" is not a magic bullet and can become a performance concern itself. Take care to understand your usage and scenarios.

    0 讨论(0)
  • 2020-12-04 17:58

    Given the current spec, I don't think there is any solution that isn't a "hack". Petitioning the WHATWG is one way to get this fixed :-)

    Expanding on the "(very inelegant) solution" (demo):

    • Create a global hash of all elements currently being dragged:

      var dragging = {};
      
    • In the dragstart handler, assign a drag ID to the element (if it doesn't have one already), add the element to the global hash, then add the drag ID as a data type:

      var dragId = this.dragId;
      
      if (!dragId) {
          dragId = this.dragId = (Math.random() + '').replace(/\D/g, '');
      }
      
      dragging[dragId] = this;
      
      e.dataTransfer.setData('text/html', dragId);
      e.dataTransfer.setData('dnd/' + dragId, dragId);
      
    • In the dragenter handler, find the drag ID among the data types and retrieve the original element from the global hash:

      var types = e.dataTransfer.types, l = types.length, i = 0, match, el;
      
      for ( ; i < l; i++) {
          match = /^dnd\/(\w+)$/.exec(types[i].toLowerCase());
      
          if (match) {
              el = dragging[match[1]];
      
              // do something with el
          }
      }
      

    If you keep the dragging hash private to your own code, third-party code would not be able to find the original element, even though they can access the drag ID.

    This assumes that each element can only be dragged once; with multi-touch I suppose it would be possible to drag the same element multiple times using different fingers...


    Update: To allow for multiple drags on the same element, we can include a drag count in the global hash: http://jsfiddle.net/jefferyto/eKHap/2/

    0 讨论(0)
  • 2020-12-04 17:59

    From what I have read on MDN, what you are doing is correct.

    MDN lists some recommended drag types, such as text/html, but if none are suitable then just store the id as text using the 'text/html' type, or create your own type, such as 'application/node-id'.

    0 讨论(0)
提交回复
热议问题