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

时间:2010-03-16 01:07:39

标签: jquery firefox scroll offset jquery-ui-sortable

我在Firefox 3.6中有一个jQuery UI 1.7.2可排序列表的问题,IE7-8工作正常。当我向下滚动一点时,辅助元素似乎有一个与我相同高度的偏移量 从鼠标指针向下滚动,这使得无法看到您最初开始拖动的项目。 我该如何解决这个问题或解决这个问题?如果没有修复什么是一个非常好的替代可拖动插件?

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

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

15 个答案:

答案 0 :(得分:126)

如果您想阻止浏览器嗅探,那么仅CSS解决方案是将ul或容器样式设置为overflow: auto。如果你通过firebug查看源代码,那就是jQuery在example中执行它的方式。

答案 1 :(得分:41)

使用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。

答案 2 :(得分:23)

我看到了这个问题,并且能够通过删除css规则位置来解决它:相对于我页面上包含的div之一。另见:http://forum.jquery.com/topic/sortable-offset-when-element-is-dragged-and-page-scrolled-down-ff

答案 3 :(得分: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-element滚动仍然存在问题。也许有人有解决方案吗?

更新: 修复是:

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

但是仍然 - 如果您要离开列表,排序事件似乎就会停止。

答案 4 :(得分:9)

你还需要考虑这个特定于firefox的事实,这是我正在使用的片段 - 我从Harris的解决方案中得到了正确的指导。当sortable在相对定位的容器中时,我遇到了这个问题,没有使用帮助器。

  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();

您也可以在服务器上执行此检查,然后根据浏览器进行2次不同的呼叫。

答案 5 :(得分: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'
});

基本上,你需要监听sortable的“start”事件,将浏览器的当前scrollTop()值添加到帮助者的位置,然后你需要监听sortable的“beforeStop”事件,在之前删除该偏移量。 item已正式回到新位置的列表中。

希望这对某人有帮助!

答案 6 :(得分: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');
    }
  }

显然它不是防弹的 - 如果文件大小在排序时发生变化,那么其他事情就必须完成。但是,根据我的经验,在这种情况下它看起来不那么奇怪。

答案 7 :(得分:1)

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

  • jQuery 1.8.0
  • jQuery UI 1.8.23

答案 8 :(得分:0)

设置overflow: auto会使Firefox开始拖动指针下的元素,但它也会阻止自动滚动正常工作。您可以在jQuery Sortable示例中看到这一点,如果您使窗口足够小以至于需要滚动。

我在html标签上有overflow: scroll,但即使删除它,(我认为)所有相对包含的元素也没有完全解决问题(意味着拖动正确启动并且自动滚动工作)。我还尝试了一个对_findRelativeOffset的mozilla-sniffing补丁(我认为就是这样),但它没有帮助。

我的用例的帮助只是拖动了一个克隆(helper: 'clone'在可拖动的构造函数中)。为了使它看起来像克隆不存在,我添加了启动和停止方法,只是将visibilty设置为隐藏然后返回。

我上面会评论,但我还没有得分。

答案 9 :(得分:0)

有同样的问题。在我的情况下,它不可能使用“overflow:auto”-fix。所以这就是我所做的。

var pos_fixed = 1;        // switch variable (the fix should only be fired ones)
$('.drag').draggable({
 start: function(event, ui){
  pos_fixed = 0;            // we're about to start, set to not fixed yet
 },
 drag: function(event, ui){
  if(pos_fixed == 0){       // check if the fix hasn't been fired for this instance yet
   var help_pos = $(ui.helper).offset().top, // get helpers offset
   targ_pos = $(event.target).offset().top,  // get targets(the dragged elements) offset
   marg = targ_pos-help_pos; // calculate the margin the helper has to have to put it on the same y-position as our target
   $(ui.helper).css('margin-top', marg); // put our helper on the same y-position as the target
   pos_fixed = 1;            // we've fixed it, we don't want it to fire again
  }
 }
});

修复程序并不关心您使用的浏览器。当拖动开始时,它总是确保辅助对象具有与目标相同的y偏移量。

答案 10 :(得分:0)

对于有此问题的未来读者。 我从jqueryui 1.8升级到1.10.3,问题解决了,没有css修复。

http://jqueryui.com/

我也从jquery 1.8升级到1.10.2

http://jquery.com/

答案 11 :(得分:0)

对于未来的读者 我遇到了一个类似的问题,其中辅助元素在引导对话框的滚动div内拖动时有一个偏移量。当释放拖动的对象时,动画将拖动的辅助元素发送到它的新位置,而不考虑页面的滚动部分,这给用户带来了令人困惑的反馈。

为了使对象容器中的position:relative和overflow-y:auto保持一致,我的解决方案是

1-将scrollTop()偏移添加到sort start事件中辅助对象的margin-top;

2-删除beforeStop事件中的margin-top

这修复了动画在拖动后关闭的问题,但是当拖动页面中的滚动部分时,辅助对象被推到光标下方。最后一个修复是

3-在相对于指针和容器偏移量拖动(使用sort事件)的同时计算并设置辅助对象的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'});
    }
},
...

});

帮助帮助

答案 12 :(得分: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 );
        }
    }
});

答案 13 :(得分:-1)

我的解决方案:&#34; .sortable&#34;添加&#34;位置:relative&#34;

$(".sortable").sortable({
      sort: function(event, ui) {
           ui.position.top = ui.position.top + $(window).scrollTop();
      },
});

PS使用jQuery UI 1.12.0和jQuery 2.2.4

答案 14 :(得分:-2)

sort: function(e, ui){
        var tempVariable = $(ui.item.get(0));
        tempVariable.css('top', (e.clientY)-(tempVariable.css("height").replace("px", "")));
    }