【问题标题】:jQuery draggable shows helper in wrong place after page scrolled页面滚动后,jQuery可拖动在错误的位置显示助手
【发布时间】:2011-08-13 02:37:06
【问题描述】:

我正在使用 jQuery draggabledroppable 来开发我正在开发的工作计划系统。用户将作业拖到不同的日期或用户,然后使用 ajax 调用更新数据。

一切正常,除非我向下滚动主页(作业出现在超出浏览器窗口底部的大型周计划器上)。如果我尝试在这里拖动一个可拖动元素,该元素会出现在我的鼠标光标上方,与我向下滚动的像素数量相同。悬停状态仍然可以正常工作,并且功能正常,但看起来不正确。

我正在使用 jQuery 1.6.0 和 jQuery UI 1.8.12。

我确定我需要添加一个偏移函数,但我不知道在哪里应用它,或者是否有更好的方法。这是我的.draggable() 初始化代码:

$('.job').draggable({
  zIndex: 20,
  revert: 'invalid',
  helper: 'original',
  distance: 30,
  refreshPositions: true,
});

知道我能做些什么来解决这个问题吗?

【问题讨论】:

  • 你能提供一些工作演示吗
  • @jimy 这一切都是动态且非常安全的,所以我必须编写一个全新的示例;如果没有人尽快回答,我会这样做。
  • 您可以发布您的可拖动对象拥有或继承的所有 css 属性吗?
  • 根据我在下面的回答,这似乎是finally fixed

标签: jquery jquery-ui draggable jquery-ui-draggable


【解决方案1】:

这可能是一个相关的错误报告,它已经存在了很长一段时间:http://bugs.jqueryui.com/ticket/3740

这似乎发生在我测试的每个浏览器(Chrome、FF4、IE9)上。有几种方法可以解决此问题:

1. 在你的 CSS 中使用 position:absolute;。绝对定位的元素似乎没有受到影响。

2. 确保父元素(如果是正文则为事件)设置了overflow:auto;。我的测试表明该解决方案修复了该位置,但它禁用了自动滚动功能。您仍然可以使用鼠标滚轮或箭头键滚动。

3.手动应用上述错误报告中建议的修复并彻底测试它是否会导致其他问题。

4. 等待官方修复。计划在 jQuery UI 1.9 上进行,尽管过去曾被推迟过几次。

5.如果您确信每个浏览器都会发生这种情况,您可以将这些 hack 放入受影响的可拖动对象的事件中以更正计算。虽然有很多不同的浏览器需要测试,所以它只能作为最后的手段:

$('.drag').draggable({
   scroll:true,
   start: function(){
      $(this).data("startingScrollTop",$(this).parent().scrollTop());
   },
   drag: function(event,ui){
      var st = parseInt($(this).data("startingScrollTop"));
      ui.position.top -= $(this).parent().scrollTop() - st;
   }
});

【讨论】:

  • 太好了,谢谢! (设置溢出:自动立即修复它。我将样式应用于各个表格单元格。
  • jsfiddle.net/a2hzt/5overflow-y:在 html 元素上滚动也会在 firefox 上产生这个问题(chrome 可以),只需向下滚动并尝试拖动。
  • 这是 ba-a-ack,对于 helper: "clone"bugs.jqueryui.com/ticket/9315 级别 blocker,比专业高一个档次。 tj.vantoll 说“在 1.10.3 中出现的 6 个可拖动修复可能是可疑的。”最简单的例子:jsfiddle.net/7AxXE
  • 已确认,此错误存在于 jQuery UI 1.10.3 而不是 1.10.2
  • 看起来问题也存在于 jQuery UI 1.10.4 中。我现在只坚持 1.10.2
【解决方案2】:

此解决方案无需调整任何位置即可工作,您只需克隆元素并使其绝对定位即可。

$(".sidebar_container").sortable({
  ..
  helper: function(event, ui){
    var $clone =  $(ui).clone();
    $clone .css('position','absolute');
    return $clone.get(0);
  },
  ...
});

helper 可以是一个函数,它需要返回要拖动的 DOM 元素。

【讨论】:

  • +1 非常感谢,这适用于我的 sortable(我正要尝试类似但不太优雅的东西)。不过,您的 $j 有一个小错字! :)
  • 对我来说:拖动根本不起作用并返回错误:TypeError: this.offsetParent[0] is undefined
  • 我觉得是 ui.helper 不只是 ui
  • 谢谢你帮助我进行排序
  • 这是唯一适合我的答案,也是最容易实现的。很好的解决方案
【解决方案3】:

这对我有用:

start: function (event, ui) {
   $(this).data("startingScrollTop",window.pageYOffset);
},
drag: function(event,ui){
   var st = parseInt($(this).data("startingScrollTop"));
   ui.position.top -= st;
},

【讨论】:

  • 解决我的问题,"1.11.0"
  • 这是一个有趣的解决方案,但它只适用于存在错误的浏览器(Chrome)。没有错误的浏览器现在会有它但倒置:)
  • 注意:使用此解决方案时,一些 JS-Parsers 可能会抱怨“缺少基数”。要修复,请替换 var st = parseInt($(this).data("startingScrollTop")); with var st = parseInt($(this).data("startingScrollTop"), 10); (即提供要使用的数字系统)。 10 是默认值,但某些解析器可能仍然需要它(例如 webpack)
【解决方案4】:

很抱歉写另一个答案。 由于我无法使用上述答案中的任何解决方案,因此在找到另一个合理的解决方案之前,我进行了很多谷歌搜索并进行了许多令人沮丧的小修改。

每当任何父元素将position 设置为“相对”时,似乎都会出现此问题。我不得不重新调整我的标记并更改我的 CSS,但通过从所有父母那里删除此属性,我能够让 .sortable() 在所有浏览器中正常工作。

【讨论】:

  • 我这里也一样。任何父级中的任何position: relative; 都会导致这种情况发生。
  • 完全同意!对我来说,这只是正文中的内联样式,position: relative; 必须被删除。可拖动和正文之间的父元素似乎在这里没有问题。
  • 天哪,就是这样,谢谢,garrr 为什么人们在这个时代不使用 Dragula - 谢谢!
  • 非常感谢!有职位的父母的父母:亲戚为我造成的
  • 插话说这解决了我的问题!我正在使用 js-parsons 库,该库已多年未更新,因此它仍然使用 jQuery 1.7.2。从其父母之一删除position: relative 解决了这个问题。
【解决方案5】:

看起来这个错误经常出现,而且每次都有不同的解决方案。以上都没有,或者我在互联网上找到的任何其他东西都不起作用。 我正在使用 jQuery 1.9.1 和 Jquery UI 1.10.3。 这就是我修复它的方法:

$(".dragme").draggable({
  appendTo: "body",
  helper: "clone",
  scroll: false,
  cursorAt: {left: 5, top: 5},
  start: function(event, ui) {
    if(! $.browser.chrome) ui.position.top -= $(window).scrollTop();
  },
  drag: function(event, ui) {
    if(! $.browser.chrome) ui.position.top -= $(window).scrollTop();
  }
});

适用于 FF、IE、Chrome,我还没有在其他浏览器中测试过。

【讨论】:

  • 这对我有用,但我必须使用 ui.offset.top 而不是 ui.position.top
【解决方案6】:

我删除溢出:

html {overflow-y: scroll; background: #fff;}

而且效果很好!

【讨论】:

    【解决方案7】:

    此错误已移至http://bugs.jqueryui.com/ticket/6817,并且在大约 5 天前(2013 年 12 月 16 日左右)似乎终于得到修复。现在的建议是使用来自http://code.jquery.com/ui/jquery-ui-git.js 的最新开发版本或等待应该包含此修复的版本 1.10.4

    编辑: 看来这个修复现在可能是 http://bugs.jqueryui.com/ticket/9315 的一部分,它不会在 1.11 版之前发布。使用上面链接的 jQuery 源代码控制版本似乎确实为我和@Scott Alexander 解决了这个问题(下面的评论)。

    【讨论】:

    • 我正在使用 1.10.4 并且错误仍然存​​在,但使用了该链接并且一切正常。
    • @ScottAlexander 该修复程序可能已附加到与我想象的不同的票证上。我已经基于此编辑了我的答案。谢谢!
    【解决方案8】:

    这个错误应该这么久都没有修复,这似乎很了不起。对我来说,这在 Safari 和 Chrome(即 webkit 浏览器)上是个问题,但在 IE7/8/9 和 Firefox 上都没有问题。

    我发现设置 absolute 或 fixed,不管有没有 !important,都没有帮助,所以最后我在我的拖动处理函数中添加了一行:

    ui.position.top += $( 'body' ).scrollTop();
    

    我期待需要使该行特定于 webkit,但奇怪的是它在任何地方都可以正常工作。 (期待我很快发表评论说'不,实际上它搞砸了所有其他浏览器'。)

    【讨论】:

    • 这可行,但是当您在拖动时滚动时,它仍然会移动 y 位置。 DarthJDG 的解决方案 5 也适用于拖动时滚动。
    【解决方案9】:

    我所做的是:

    $("#btnPageBreak").draggable(
            {
              appendTo: 'body',
              helper: function(event) {
                return '<div id="pageBreakHelper"><img  id="page-break-img"  src="page_break_cursor_red.png" /></div>';
              },
              start: function(event, ui) {
              },
              stop: function(event, ui) {
              },
              drag: function(event,ui){
                ui.helper.offset(ui.position);
             }
            });
    

    【讨论】:

      【解决方案10】:

      我不完全确定这是否适用于所有情况,但这个解决方法我只是在我必须测试的所有各种情况下都为我工作(以及此处和其他地方给出的先前提出的解决方案都失败了)

      (function($){
      $.ui.draggable.prototype._getRelativeOffset = function()
      {
          if(this.cssPosition == "relative") {
              var p = this.element.position();
              return {
                  top: p.top - (parseInt(this.helper.css("top"),10) || 0)/* + this.scrollParent.scrollTop()*/,
                  left: p.left - (parseInt(this.helper.css("left"),10) || 0)/* + this.scrollParent.scrollLeft()*/
              };
          } else {
              return { top: 0, left: 0 };
          }
      };
      }(jQuery));
      

      (我将它提交给 jQuery.ui 跟踪器,看看他们是怎么想的。如果这个 4 年前的错误最终能得到纠正,那就太好了:/)

      【讨论】:

        【解决方案11】:

        我在 Firefox 21.0 上使用可拖动的 JQuery,我遇到了同样的问题。光标停留在辅助图像上方一英寸处。我认为这是 Jquery 本身的一个问题,尚未解决。我找到了解决此问题的方法,即使用可拖动的“cursorAt”属性。我使用它如下,但可以根据需要更改它。

        $('.dragme').draggable({
        helper: 'clone',    
        cursor: 'move',    
        cursorAt: {left: 50, top: 80}
        });
        

        注意: 这将适用于所有浏览器,因此在使用此代码后,请在所有浏览器中检查您的页面以获取正确的左侧和顶部位置。

        【讨论】:

          【解决方案12】:

          在调整了我所读到的关于该问题的所有内容之后,这对我有用。

          $(this).draggable({
            ...
            start: function (event, ui) {
              $(this).data("scrollposTop", $('#elementThatScrolls').scrollTop();
              $(this).data("scrollposLeft", $('#elementThatScrolls').scrollLeft();
            },
            drag: function (event, ui) {
              ui.position.top += $('#elementThatScrolls').scrollTop();
              ui.position.left += $('#elementThatScrolls').scrollLeft();
            },
            ...
          }); 
          

          *elementThatScrolls 是具有overflow:auto的父级或祖先;

          计算出滚动元素的位置,并在每次移动/拖动时添加到助手的位置。

          希望对某人有所帮助,因为我在此浪费了大量时间。

          【讨论】:

            【解决方案13】:

            这似乎不需要在父级中使用 position:absolute 的解决方法:)

            $("body").draggable({
                 drag: function(event, ui) { 
                     return false; 
                 } 
            });
            

            【讨论】:

            • 谢谢!这是唯一对我有用的东西。 (我不确定我是否理解问题..我的问题是当拖动从顶部的滚动条开始时,拖动、拖动滚动工作正常。如果滚动条开始较低,那么我会遇到偏移问题)
            【解决方案14】:

            我设法通过添加 display: inline-block 解决了同样的问题 到拖动的项目

            添加position: relative 对我不起作用(jQuery 在拖动开始时用position: absolute 覆盖它)

            使用的 jQuery 版本:

            • jQuery - 1.7.2
            • jQuery UI - 1.11.4

            【讨论】:

            • 如果您将 position: relative 移动到更高级别的容器元素,它可能会起作用。我知道它现在没有帮助,但仅供参考,也许对于未来陷入困境的开发人员。
            【解决方案15】:

            我遇到了同样的问题,发现这一切都是因为一个引导导航栏“navbar-fixed-top”类的位置固定,它向下移动了我的&lt;body&gt; 60px,低于&lt;html&gt; 顶部。因此,当我在我的网站中移动可拖动表单时,光标出现在表单上方 60 像素处。

            可以看到,在Chrome调试工具中,在Elements界面,点击&lt;body&gt;标签,会看到top和body之间有空隙。

            因为我在整个应用程序中都使用这个导航栏,并且不想修改我的初始化调用以拖动每个表单(根据 DarthJDG 的过程)。我决定以这种方式扩展可拖动小部件,并在我的可拖动初始化中简单地添加一个 yOffset。

            (function($) {
              $.widget("my-ui.draggable", $.ui.draggable, {
                _mouseDrag: function(event, noPropagation) {
            
                  //Compute the helpers position
                  this.position = this._generatePosition(event);
                  this.positionAbs = this._convertPositionTo("absolute");
            
                  //Call plugins and callbacks and use the resulting position if something is returned
                  if (!noPropagation) {
                    var ui = this._uiHash();
                    if(this._trigger('drag', event, ui) === false) {
                      this._mouseUp({});
                      return false;
                    }
                    this.position = ui.position;
                  }
                  // Modification here we add yoffset in options and calculation
                  var yOffset = ("yOffset" in this.options) ? this.options.yOffset : 0;
            
                  if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
                  if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top-yOffset+'px';
                  if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
            
                  return false;
                }
              });
            })(jQuery);
            

            现在,当我使用引导导航栏在站点中初始化可拖动元素/表单时:

            // Make the edit forms draggable
            $("#org_account_pop").draggable({handle:" .drag_handle", yOffset: 60});
            

            当然,您必须根据自己的站点进行试验以确定正确的 yOffset。

            无论如何感谢 DarthJDG,他为我指明了正确的方向。干杯!

            【讨论】:

              【解决方案16】:

              我放弃使用 jQueryUi 可拖动并转而使用一个更好的插件,称为 jquery.even.drag,代码量更小,没有 jQueryUI 的所有废话。

              我在一个容器中使用这个插件制作了一个演示页面,该容器具有位置:固定

              Demo

              希望这对某人有所帮助,因为这个问题很大。

              【讨论】:

                【解决方案17】:

                我遇到了类似的问题,只是在 Windows 8 上运行特定的 IE 10。所有其他浏览器都运行良好。删除 cursorAt: { top: 0 } 解决了这个问题。

                【讨论】:

                  【解决方案18】:

                  我在这里尝试了各种答案,包括更新 jQuery,发现这对我有用。我在最新的 chrome 和 IE 上对此进行了测试。我想这将是一个问题,具体取决于您的 UI 布局。

                  $('{selector}').draggable({
                      start: function(event, ui) {
                          ui.position.top -= $(document).scrollTop();
                      },
                      drag: function(event, ui) {
                          ui.position.top -= $(document).scrollTop();
                      }
                  });
                  

                  【讨论】:

                    【解决方案19】:

                    为什么不取光标位置?我正在使用可排序插件,并使用以下代码对其进行修复:

                    sort: function(e, ui) {
                        $(".ui-sortable-handle.ui-sortable-helper").css({'top':e.pageY});
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      使用appendTo: "body' 并使用cursorAt 设置位置。 这对我来说很好。

                      $('.js-tire').draggable
                            tolerance: 'fit',
                            appendTo: 'body',
                            cursor: 'move',
                            cursorAt:
                              top: 15,
                              left: 18
                            helper: (event) ->
                              $('<div class="tire-icon"></div>').append($('<img src="/images/tyre_32_32.png" />'))
                            start: (event, ui) ->
                              if $(event.target).hasClass 'in-use'
                                $('.js-send-to-maintenance-box').addClass 'is-highlighted'
                              else
                                $('.ui-droppable').addClass 'is-highlighted'
                            stop: (event, ui) ->
                              $('.ui-droppable')
                                .removeClass 'is-highlighted'
                                .removeClass 'is-dragover'
                      

                      【讨论】:

                        【解决方案21】:

                        我在顶部使用了一个粘性导航,并认为这是导致其他人似乎都遇到的滚动问题的原因。我用 cursorAt 尝试了其他人的想法,我尝试了遏制,除了在 CSS 中取消我的 html 溢出之外,没有任何效果!疯狂的一点 CSS 会搞砸一切。这就是我所做的,它就像一个魅力:

                        html {
                          overflow-x: unset;
                        }
                        
                        body {
                          overflow-x: hidden;
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2018-05-02
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多