HTML5 Drag&丢弃:当“dragover”和“drop”事件被监听时,不会调用“dragleave”

时间:2015-11-03 11:03:51

标签: html5 javascript-events drag-and-drop draggable drag

我将div包含在另一个允许“drop”的父div中 两种情况:

  • 案例1:不允许丢弃事件:
    当我在子框中删除元素时都执行dragleave事件,因此正确删除了两个元素的红色类,但未执行drop

  • 案例2:允许删除事件(通过删除js代码中的注释):
    当我在子框中删除元素时,不执行dragleave事件,我只删除子元素上的红色类(“drop”事件监听器中包含的代码)

    问题:
    在案例2中,如果我将元素放入div命名子项中,则红色类仅在子div中删除,而不在父div中删除。如何在不经过event.path对象的情况下删除所有父母的课程?

    以下是案例1的Fiddler 以下是案例2的Fiddler

    var myApp = angular.module('myApp',[]);
    
     myApp.controller('MyCtrl', ['$scope', function ($scope)
                {
                }]);
    
    
    myApp.directive('drop', function() {
    return{
     	restrict: "A",
        replace: false,
    
        link: function (scope, element, attrs, ctlr) {
        	var obj = element[0];
    		var DragLeaveCounter=0;
            
            obj.addEventListener("dragenter", function (eventObject) {
                eventObject.preventDefault();
                DragLeaveCounter++;
                if (DragLeaveCounter === 1) {
                        obj.classList.add( 'red' );
                    };
               console.log("enter" , obj.id , DragLeaveCounter );
            }, false);
    
            obj.addEventListener("dragleave", function (eventObject) {
                eventObject.preventDefault();
                DragLeaveCounter--;
               if (DragLeaveCounter <= 0) {
                    obj.classList.remove('red');
               }
                console.log("leave" , obj.id , DragLeaveCounter);
            }, false);
    
    
            obj.addEventListener("drop", function (eventObject) {
                eventObject.preventDefault();
                eventObject.stopPropagation();
                console.log("drop" , obj.id , eventObject);           
                obj.classList.remove("red");
                DragLeaveCounter=0;
    
            }, false);
    
    
            obj.addEventListener("dragover", function (eventObject) {
               //TODO Remove comment in next line: 
               eventObject.preventDefault();
                console.log("dragover");
            }, false);
    
            
        }
        
    }
    });
    /* Styles go here */
    
    #parent{
        width:200px;
        height:200px;
        border:1px solid red;
        position:relative;
    }
    
    #child{
      position:absolute;
      left:50px;
      top:50px;
      width:50px;
      height:50px;
      background-color:#c7a499;
    }
    #child2{
      position:absolute;
      left:50px;
      top:110px;
      width:50px;
      height:50px;
      background-color:#c7a499;
    }
    
    .red {
        background-color: red !important;
    }
    .green {
        background-color: green;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="myApp" ng-controller="MyCtrl" >
        <i> Remove comment on line 43 in js to see what the difference (Please open the console)</i>
        <div id="drag"  draggable="true">drag me</div>
        <hr>
    
        <div id="parent" drop>
            Parent
            <div id="child" drop> 
                child
            </div>
            <div id="child2" > 
                child 2
            </div>
            
            </div>
    </div>

  • 1 个答案:

    答案 0 :(得分:0)

    drop事件被触发时,拖放功能的正确行为是不会触发dragleave事件。如果您未在event.preventDefault()事件上使用drop,则浏览器会尝试执行该删除操作(IE:在浏览器中删除链接时加载链接)。这导致leave事件被触发。

    更多信息:https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#drop

    您应该让drop事件向上传播以在父级中收集事件,从而删除drop listener中的eventObject.stopPropagation();