【问题标题】:jQueryUI Auto Scroll on DragjQueryUI 拖动时自动滚动
【发布时间】:2016-01-23 11:15:39
【问题描述】:

http://jsfiddle.net/ujty083a/4/

  $(document).ready(function(){
        $(".left ul li").draggable({
            refreshPosition: true,
            revert: true
        });

        $(".right li").droppable({
            drop:   function(e, ui){
                alert(ui.draggable.text()+" "+$(this).text());
            }
        });

    });

我有三个列表,一个可以拖动,另外两个可以拖放。正确的列表可能有也可能没有滚动条,但总会有 2 个或更多。

我发现的第一个问题是,当顶部列表有滚动条并且您尝试将项目放到第二个列表中时,会触发两个事件。一个用于隐藏列表,一个用于可见列表。

第二个问题是当其中一个列表有滚动条时,当用户将项目拖入其中时它不会自动滚动。

【问题讨论】:

    标签: jquery-ui draggable


    【解决方案1】:

    我认为您需要修改 droppable 并以这种方式大幅修改一些行为:

    • 您需要添加一个选项来定义 droppable 是否应该是 可滚动与否。
    • 那么您需要某种验证来确定哪个droppable 是否可见。
    • 你需要调整一些已经存在的滚动行为 jquery ui 小部件。

    这并不完美,但应该能给你一些想法:

     $.widget('ui.droppable', $.ui.droppable, {
    
            _over: function (e, ui) {
                var draggable = $.ui.ddmanager.current;
                if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
    
                // this to make sure the droppable is visible
                this.scrollVisible = this._isScrollIntoView();
    
                if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element)) && (!this.options.scrollable || this.scrollVisible)) {
    
                    if (this.options.hoverClass) {
                        this.element.addClass(this.options.hoverClass);
                    }
                    // to activate scrollable you need to change scrollParent of the draggable
                    // and adjust some calculations
                    if (this.options.scrollable) {
                        draggable.overflowOffset = $(this.element).scrollParent().offset();
                        draggable.scrollParent = $(this.element).scrollParent();
                        draggable.offsetParent = $(this.element).scrollParent();
                        draggable.offset.parent.top = $(this.element).scrollParent().scrollTop();
                    }
                    this._trigger('over', event, this.ui(draggable));
                }
    
    
            },
            _out: function (event) {
    
                this._super();
                var draggable = $.ui.ddmanager.current;
    
                // remove scrollable 
                if (this.options.scrollable) {
                    draggable.scrollParent = $(document);
                    draggable.offsetParent = $(document);
                    draggable.overflowOffset = $(document).offset();
                    draggable.offset.parent.top = $(document).scrollTop();
                }
            },
            _drop: function (event, custom) {
    
                var draggable = custom || $.ui.ddmanager.current;
                if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
    
                var childrenIntersection = false;
                this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function () {
                    var inst = $.data(this, 'droppable');
                    if (
                    inst.options.greedy && !inst.options.disabled && inst.options.scope == draggable.options.scope && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && $.ui.intersect(draggable, $.extend(inst, {
                        offset: inst.element.offset()
                    }), inst.options.tolerance)) {
                        childrenIntersection = true;
                        return false;
                    }
                });
                if (childrenIntersection) return false;
    
                // same as for over, you need to validate visibility of the element
                this.scrollVisible = this._isScrollIntoView();
    
                if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element)) && (!this.options.scrollable || this.scrollVisible)) {
                    if (this.options.activeClass) this.element.removeClass(this.options.activeClass);
                    if (this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
                    this._trigger('drop', event, this.ui(draggable));
                    return this.element;
                }
    
                return false;
    
            },
            // a function to check visibility. Taken here:
            //http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling
            _isScrollIntoView() {
    
                var $elem = $(this.element);
                var $parent = $(this.element).scrollParent();
    
                var docViewTop = $parent.parent().scrollTop();
                var docViewBottom = docViewTop + $parent.parent().height();
    
                var elemTop = $elem.offset().top;
                var elemBottom = elemTop + $elem.height();
    
                return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
            }
        });
    
    
    
        $(document).ready(function () {
            $(".left ul li").draggable({
                refreshPosition: true,
                revert: true,
    
            });
    
            $(".right .top li").droppable({
                scrollable: true,
    
                drop: function (e, ui) {
                    alert(ui.draggable.text() + " " + $(this).text());
                }
            });
            $(".right .bottom li").droppable({
                scrollable: false,
    
                drop: function (e, ui) {
                    alert(ui.draggable.text() + " " + $(this).text());
                }
            });
    
        });
    

    http://jsfiddle.net/ejv32oen/4/

    【讨论】:

    • 它肯定会让我接近。感谢您的帮助。
    猜你喜欢
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多