jQuery UI可排序滚动辅助元素偏移Firefox问题

56

我在使用jQuery UI 1.7.2中的可排序列表时,在Firefox 3.6中遇到了问题,但IE7-8正常工作。当我向下滚动一点时,助手元素似乎有一个相同高度的偏移量,这使得原来开始拖动的项变得不可见。

如何修复此问题或解决此问题?如果没有解决方案,有没有非常好的替代可拖动插件?

以下是我的可排序初始化参数。

$("#sortable").sortable( {placeholder: 'ui-state-highlight'  } );
$("#sortable").disableSelection();

4
这是一个演示错误的GIF(引用自jQuery论坛帖子中被接受的答案):http://i.imgur.com/phYGO.gif - mcw
16个回答

132
如果您想防止浏览器嗅探,仅使用CSS的解决方案是将ul或容器样式设置为overflow: auto。如果您通过Firebug查看源代码,则可以在jQuery在其示例中使用此方法。

1
这对我在所有浏览器上都完美地运行,而且肯定是最简单/最干净的解决方案。干杯! - deshg
9
绝对是最干净的解决方案。不能定义一个容器为 position:relative 是一个相当严重的限制。 - Bart Gloudemans
3
谢谢,这对我很有效,而position:relative则无效。 - Björn
1
position: static;overflow: auto;的组合对我很有帮助。 - Pierluc SS
谢谢 @munch。这在一个相当复杂的页面上起作用了。根据您的建议,我将 overflow: auto 应用于包含 2 个可排序列表的 div。 - Ken Palmer
显示剩余10条评论

48

对我来说使用overflow: auto;不是一种选项。我通过使用这个 sort 事件处理程序解决了这个问题:

使用overflow: auto;不可行,我通过sort事件处理程序解决了此问题:

$(...).sortable({
    ...
    sort: function(event, ui) {
        var $target = $(event.target);
        if (!/html|body/i.test($target.offsetParent()[0].tagName)) {
            var top = event.pageY - $target.offsetParent().offset().top - (ui.helper.outerHeight(true) / 2);
            ui.helper.css({'top' : top + 'px'});
        }
    },
    ...
});

虽然不完美,但它不需要浏览器嗅探。在IE8、Chrome和Firefox中经过测试。

编辑:这是使用jQuery 1.10.0和jQuery UI 1.10.3。


8
天啊,这是一个绝妙的解决方案!我喜欢它,因为它不测试用户代理,并且不需要更改可能会破坏其他网站页面布局的内容。 - Dethariel
1
终于有一个有效的解决方案了!非常感谢。你已经赢得了我家三代人的好感。 - mydoglixu
最后,它也与jQuery UI 1.11.4兼容,谢谢! - eXe
1
这解决了问题,但使containment选项无用。 - zykadelic
1
您这位先生的解决方案真是太棒了,非常感谢。 - WebDevNerdStuff
可以运行,但我必须先删除包含选项。 - Unicco

25

1
对我来说起作用了,但由于其他原因,我无法删除position:relative。相反,@rtcherry的解决方案在我的情况下起作用:https://dev59.com/4HE95IYBdhLWcg3wHqIV#20225012 - Diego Jancic

20

我也遇到了这个问题,并通过以下代码解决了它:

var wscrolltop = 0;
$sortable_elements.sortable({ 
    start: function(event, ui) {
        wscrolltop = $(window).scrollTop();
    },
    sort: function(event, ui) {                   
        ui.helper.css({'top' : ui.position.top + wscrolltop + 'px'});
    }
});

我发现,如果您在可排序元素上滚动,仍然存在问题。也许有人能够为此提供解决方案?

更新: 解决方法如下:

$sortable_elements.sortable({ 
    connectWith: '#personal-favs ul.fitems',
    sort: function(event, ui) {  
        ui.helper.css({'top' : ui.position.top + $(window).scrollTop() + 'px'});
    }
});

但是,如果你要离开这个列表,排序事件好像会停止。


这对我有用,因为对我来说,溢出:自动不是一个选项。 - Shawn V

9

您还需要考虑到这是针对Firefox特定的情况,以下是我使用的片段——我从Harris的解决方案中找到了正确的方法。当可排序的元素位于相对定位的容器中时,我在不使用helper时遇到了这个问题。

  var options = { 
   handle: '.mover', 
   update:updateSorting 
 };
  var userAgent = navigator.userAgent.toLowerCase();
  if(userAgent.match(/firefox/)) {
    options["start"] = function (event, ui) { ui.item.css('margin-top', $(window).scrollTop() ); };
    options["beforeStop"] = function (event, ui) { ui.item.css('margin-top', 0 ); };
  }
  $("#" + list_id+"").sortable(options);
  $("#" + list_id+"").disableSelection();

您也可以在服务器上进行此检查,然后根据浏览器进行两个不同的调用。

太好了,你在这里帮我省了很多麻烦。 - Dan Fuller
这对我来说是一个很好的解决方案,因为我正在使用jQuery 1.4.2和jQuery-UI.1.8.23,所以我遇到了这个问题,现在它将被解决。 使用jquery.1.8.js也可以解决这个问题,但当我将我的jquery.1.4.2替换为jquery.1.8.js时,我遇到了很多问题,所以谢谢。 - Mrugen Ramani
让我做这件事真是让我感到恶心,但这是唯一一个实际起作用的解决方案(在 50235289 个解决方案中)。但说真的,我感到非常难受。唉。 - Jason
实际上,我通过在我的CSS中删除html { overflow-x: hidden; }来解决了这个问题。不可思议。 - Jason

7
我成功找到了解决方法:

我成功找到了解决方法:

$( "items" ).sortable({
start: function (event, ui) {
 if( ui.helper !== undefined )
  ui.helper.css('position','absolute').css('margin-top', $(window).scrollTop() );
},
beforeStop: function (event, ui) {
 if( ui.offset !== undefined )
  ui.helper.css('margin-top', 0);
},
placeholder: 'placeholder-class'
});

基本上,您需要监听可排序列表的“start”事件,将浏览器当前的scrollTop()值添加到helper的位置,然后您需要监听可排序列表的“beforeStop”事件,在项目被正式放置回新位置之前删除该偏移量。

希望对某人有所帮助!


4

我在网站上强制使用滚动条,因此这个可滚动的偏移问题是由于我的CSS中有html { overflow-y: scroll }引起的。

当我打开和关闭可滚动性时,我使用以下方法来解决它。我只在IE8、FF12和Chrome中测试过...

  turnSortingOnOff:function(e) {
    e.preventDefault();

    if (stopOrdering()) {
      // get rid of the hacky css on the html element
      $('html').css({ 'overflow-y': '' });
      $('html').css({ 'margin-right': '' });

      elmt.sortable('disable');
    }
    else if (startOrdering()) {
      // if the body is smaller than the window
      // then there aren't any scrollbars
      // in which case, add a right hand margin of 16px
      // to the html to prevent the site wobbling
      if ($('body').outerHeight() <= $(window).height()) {
        $('html').css({ 'margin-right': 16 });
      }

      // then override the { overflow-y: scroll }
      // in the css by setting it to a nice, safe inherit
      $('html').css({ 'overflow-y': 'inherit' });

      elmt.sortable('enable');
    }
  }

显然,这并不是百分之百可靠的——如果在排序过程中文档大小发生变化,则需要进行其他操作。但是,在我的经验中,在这种情况下看起来不那么奇怪。


1
对于未来的读者 我遇到了一个类似的问题,当在bootstrap对话框的滚动div内拖动时,助手元素具有偏移量。释放拖动对象时,动画会将拖动的辅助元素发送到其新位置,而不考虑页面的滚动部分,这给用户带来了令人困惑的反馈。
为了使相对位置和对话框容器中的overflow-y:auto正常工作,我的解决方案是:
1- 在排序开始事件中,在助手对象的margin-top上添加scrollTop()偏移量;
2- 在beforeStop事件中删除margin-top 这修复了拖动后动画的偏差,但是在页面的滚动部分拖动时,助手对象被推到光标下面。最后的修复是
3- 使用排序事件计算并设置助手对象的top属性,相对于指针和容器偏移量。
$(...).sortable({
...
start: function (event, ui) {  
    ui.helper.css('margin-top', $("#mybootstrap-dialog").scrollTop()); 
},
beforeStop: function (event, ui){ 
    ui.helper.css('margin-top',0); 
},
sort: function(event, ui) {
    var top = event.clientY - $('#my-sortable-ul').offset().top  -  $("#mybootstrap-dialog").scrollTop();
    ui.helper.css({'top' : top + 'px'});
    }
},
...

});

希望这有所帮助。


1

我使用更新的jQuery/jQuery UI版本“修复”了这个问题。

  • jQuery 1.8.0
  • jQuery UI 1.8.23

3
我正在使用jQuery 1.8.2和jQuery UI 1.9,但仍然存在问题。 - Jason

0
为了总结您的努力并提供一个完整的解决方案,以下内容似乎适用于Chrome 40+和Firefox 30+。
var isFirefox = /firefox/.test(navigator.userAgent.toLowerCase());
$('#target').sortable({
    connectWith: '#target-holder .elements',
    handle: ".element-header",
    start: function(ev, ui) {
        if( isFirefox ) {
            ui.item.css('margin-top', $(window).scrollTop() );
        }
    },
    sort: function(ev, ui) {
        if( isFirefox) {
            ui.helper.css({'top' : ui.position.top - $(window).scrollTop() + 'px'});
        } else {
            ui.helper.css({'top' : ui.position.top + $(window).scrollTop() + 'px'});
        }
    },
    beforeStop: function (ev, ui) {
        if( isFirefox ) {
            ui.item.css('margin-top', 0 );
        }
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接