80

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

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

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

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

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

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

4

21 回答 21

108

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

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

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

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;
   }
});
于 2011-04-26T20:09:59.247 回答
46

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

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

帮助器可以是需要返回要拖动的 DOM 元素的函数。

于 2012-09-28T15:04:18.963 回答
11

这对我有用:

start: function (event, ui) {
   $(this).data("startingScrollTop",window.pageYOffset);
},
drag: function(event,ui){
   var st = parseInt($(this).data("startingScrollTop"));
   ui.position.top -= st;
},
于 2014-01-24T19:02:50.860 回答
8

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

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

于 2012-07-13T17:01:50.967 回答
7

看起来这个错误经常出现,每次都有不同的解决方案。以上都没有,或者我在互联网上找到的任何其他东西都不起作用。我正在使用 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,我还没有在其他浏览器中测试过。

于 2013-06-04T06:22:47.847 回答
5

我删除溢出:

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

而且效果很好!

于 2012-09-27T08:27:16.467 回答
5

此错误已移至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(下面的评论)解决了这个问题。

于 2013-12-22T02:04:27.263 回答
4

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

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

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

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

于 2012-08-15T11:21:45.317 回答
3

我所做的是:

$("#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);
         }
        });
于 2014-04-13T13:53:08.330 回答
1

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

(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 年前的错误最终能得到纠正,那就太好了:/)

于 2012-07-26T10:04:21.810 回答
1

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

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

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

于 2013-06-18T16:05:36.523 回答
1

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

$(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 是具有溢出的父级或祖先:auto;

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

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

于 2013-07-01T13:03:03.267 回答
1

这似乎可以解决问题,而无需在父级中使用 position:absolute :)

$("body").draggable({
     drag: function(event, ui) { 
         return false; 
     } 
});
于 2014-02-01T21:24:16.120 回答
1

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

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

使用的 jQuery 版本:

  • jQuery - 1.7.2
  • jQuery UI - 1.11.4
于 2016-04-30T10:21:43.583 回答
1

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

可以看到在Chrome调试工具中,在Elements界面,点击<body>标签,会看到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,他为我指明了正确的方向。干杯!

于 2017-04-22T15:00:46.807 回答
0

我放弃了使用 jQueryUi draggable 并转而使用一个更好的插件jquery.even.drag,代码更小,没有 jQueryUI 的所有废话。

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

演示

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

于 2012-11-09T05:03:34.013 回答
0

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

于 2014-01-16T19:08:12.593 回答
0

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

$('{selector}').draggable({
    start: function(event, ui) {
        ui.position.top -= $(document).scrollTop();
    },
    drag: function(event, ui) {
        ui.position.top -= $(document).scrollTop();
    }
});
于 2014-01-24T12:20:20.890 回答
0

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

sort: function(e, ui) {
    $(".ui-sortable-handle.ui-sortable-helper").css({'top':e.pageY});
}
于 2015-01-03T01:35:49.563 回答
0

使用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'
于 2019-04-11T14:49:03.687 回答
0

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

html {
  overflow-x: unset;
}

body {
  overflow-x: hidden;
}
于 2019-05-20T19:59:20.560 回答