How do I detect a HTML5 drag event entering and leaving the window, like Gmail does?

后端 未结 12 954
醉话见心
醉话见心 2020-12-13 20:16

I\'d like to be able to highlight the drop area as soon as the cursor carrying a file enters the browser window, exactly the way Gmail does it. But I can\'t make it work, an

12条回答
  •  被撕碎了的回忆
    2020-12-13 20:42

    really sorry to post something that is angular & underscore specific, however the way i solved the problem (HTML5 spec, works on chrome) should be easy to observe.

    .directive('documentDragAndDropTrigger', function(){
    return{
      controller: function($scope, $document){
    
        $scope.drag_and_drop = {};
    
        function set_document_drag_state(state){
          $scope.$apply(function(){
            if(state){
              $document.context.body.classList.add("drag-over");
              $scope.drag_and_drop.external_dragging = true;
            }
            else{
              $document.context.body.classList.remove("drag-over");
              $scope.drag_and_drop.external_dragging = false;
            }
          });
        }
    
        var drag_enters = [];
        function reset_drag(){
          drag_enters = [];
          set_document_drag_state(false);
        }
        function drag_enters_push(event){
          var element = event.target;
          drag_enters.push(element);
          set_document_drag_state(true);
        }
        function drag_leaves_push(event){
          var element = event.target;
          var position_in_drag_enter = _.find(drag_enters, _.partial(_.isEqual, element));
          if(!_.isUndefined(position_in_drag_enter)){
            drag_enters.splice(position_in_drag_enter,1);
          }
          if(_.isEmpty(drag_enters)){
            set_document_drag_state(false);
          }
        }
    
        $document.bind("dragenter",function(event){
          console.log("enter", "doc","drag", event);
          drag_enters_push(event);
        });
    
        $document.bind("dragleave",function(event){
          console.log("leave", "doc", "drag", event);
          drag_leaves_push(event);
          console.log(drag_enters.length);
        });
    
        $document.bind("drop",function(event){
          reset_drag();
          console.log("drop","doc", "drag",event);
        });
      }
    };
    

    })

    I use a list to represent the elements that have triggered a drag enter event. when a drag leave event happens i find the element in the drag enter list that matches, remove it from the list, and if the resulting list is empty i know that i have dragged outside of the document/window.

    I need to reset the list containing dragged over elements after a drop event occurs, or the next time I start dragging something the list will be populated with elements from the last drag and drop action.

    I have only tested this on chrome so far. I made this because Firefox and chrome have different API implementations of HTML5 DND. (drag and drop).

    really hope this helps some people.

提交回复
热议问题