3

我知道这里有很多类似的问题,但是,当把它们付诸行动时,我仍然解决了同样的问题。

我有 2 个角度指令(拖放)和一个角度工厂(dndAPI)。这一切都基于fisshy 在 github 上的 Angular Drag and Drop

我终于让 Firefox 通过向事件添加数据来接受和拖动移动,但是我似乎无法阻止它执行默认行为(并将该数据加载为 url)。我也很抱歉,我根本无法让它在 jsfiddle 上工作......根本。如果有人看不出我是否做错了什么,我会再试一次。

angular.module('dragAndDrop', [])
.directive('drag',function (dndApi) {

    var drags = [],
        dragging = new RegExp('(\\s|^)dragging(\\s|$)');

    return {
        restrict: 'A',
        scope: {
            item: '=drag',
            whenStart: '&',
            whenEnd: '&',
            dropzones: '='
        },
        link: function (scope, elem, attr, ctrl) {

            elem.bind('dragstart', function (e) {
                angular.element('query-tool-tip').removeClass('active');
                //if ( drags.length === 0 ) {
                drags = document.querySelectorAll('.drop');
                //}

                angular.forEach(drags, function (value, key) {
                    if (scope.dropzones.indexOf(value.getAttribute('drop')) >= 0) {
                        value.className = value.className + ' dragging';
                    }
                });

                elem.addClass('dragging');

                dndApi.setData(scope.item, scope.dropzones);

                e.originalEvent.dataTransfer.effectAllowed = 'move';

                //KEEPS FIREFOX FROM CRAPPING OUT:
                e.originalEvent.dataTransfer.setData( 'text/plain', 'stop' );

                scope.$apply(function () {
                    scope.whenStart({ data: dndApi.getData() });
                });

            });

            elem.bind('dragleave', function(e){});

            elem.bind('dragend', function (e) {

                elem.removeClass('dragging');

                angular.forEach(drags, function (value, key) {
                    value.className = value.className.replace(dragging, '');
                });

                scope.$apply(function () {
                    scope.whenEnd({ data: dndApi.getData() });
                });

                dndApi.removeData();

                e.preventDefault();

            });

            elem[0].draggable = true;

            elem[0].className = elem[0].className + ' drag';

        }
    };
}).directive('drop',function (dndApi) {

    var drags = [],
        dragging = new RegExp('(\\s|^)dragging(\\s|$)');

    return {
        scope: {
            drop: '=drop',
            whenDrop: '&',
            whenEnter: '&',
            whenLeave: '&',
            queryIndex: "=queryIndex",
            hideElem: '='
        },
        link: function (scope, elem, attr, ctrl) {

            var left = elem[0].offsetLeft,
                right = left + elem[0].offsetWidth,
                top = elem[0].offsetTop,
                bottom = top + elem[0].offsetHeight;

            elem.bind('drop', function (e) {

               // e.originalEvent.preventDefault();


                //if (e.stopPropagation()) {
               // e.stopPropagation();
                //e.originalEvent.stopPropagation();
                    //e.preventDefault();
                //e.originalEvent.preventDefault();
                //}

                e.originalEvent.dataTransfer.clearData();

                if (dndApi.getDropZones().indexOf(scope.drop) >= 0) {
                    scope.$apply(function () {
                        scope.whenDrop({ data: dndApi.getData(), queryI: scope.queryIndex });
                    });
                }

                if (drags.length === 0) {
                    drags = document.querySelectorAll('.drop');
                }

                angular.forEach(drags, function (value, key) {

                    value.className = value.className.replace(dragging, '');

                });

                dndApi.removeData();

                e.stopPropagation();
                e.originalEvent.stopPropagation();
                e.preventDefault();
                e.originalEvent.preventDefault();

            });

            elem.bind('dragenter', function (e) {
                e.preventDefault();
                e.originalEvent.preventDefault();

                if (elem[0] == e.target) {
                    scope.$apply(function () {
                        scope.whenEnter({ data: dndApi.getData() });
                    });
                }


                return false;

            });

            elem.bind('dragleave', function (e) {
                e.preventDefault();
                e.originalEvent.preventDefault();


                if ((e.x < left || e.x > right) ||
                    (e.y < top || e.y > bottom)) {
                    scope.$apply(function () {
                        scope.whenLeave({ data: dndApi.getData() });
                    });
                }

                return false;
            });

            elem.bind('dragover', function (e) {

                //if (e.preventDefault) {
                    e.preventDefault();
                e.originalEvent.preventDefault();
                //}

                return false;

            });

            elem[0].className = elem[0].className + ' drop';
            scope.$watch('hideElem', function () {
                if (scope.hideElem === true) {
                    elem.hide();
                } else {
                    elem.show();
                }
            });

        }
    };
}).factory('dndApi', function () {

    var dnd = {
        dragObject: {},
        dropzones: []
    };

    return {
        setData: function (data, areas) {
            dnd.dragObject = data;
            dnd.dropzones = areas;
        },
        removeData: function () {
            dnd.dragObject = null;
            dnd.dropZones = [];
        },
        getData: function () {
            return dnd.dragObject;
        },
        getDropZones: function () {
            return dnd.dropzones;
        }
    };
});

我已经做了很多关于其他问题的建议。我已将 event.preventDefault() 添加到 dragenter 和 dragleave 点。然后当这不起作用时,我将它们添加到任何地方。我觉得这与我的 drop 方法有关。如果我将 event.prevendDefault() 放在绑定的开头,则不会执行其余代码。

任何建议,即使是我可能忽略的小事,都会有所帮助。

谢谢!

4

1 回答 1

2

您正在调用e.originalEvent.dataTransfer.clearData();drop 事件处理程序,这将导致引发异常(您无权更改原始 dataTransfer 对象)。这是防止e.originalEvent.preventDefault();被调用。

于 2013-09-19T15:41:36.157 回答