【问题标题】:jQuery ui sortable inaccurate placeholder placement in nested sortablesjQuery ui sortable 在嵌套可排序中放置不准确的占位符
【发布时间】:2014-10-25 00:53:13
【问题描述】:

我在另一个可排序元素中有一个可排序元素。两者都相互连接。 按照示例标记:

<div id='container'>
  <div class='parent'>
    <div class='child'>1</div>
    <div class='child'>2</div>
    <div class='child'>3</div>
    <div class='child'>4</div>
  </div>
  <div class='parent'>
    <div class='child'>5</div>
    <div class='child'>6</div>
    <div class='child'>7</div>
    <div class='child'>8</div>
  </div>
</div>

我要做的是在.parent's 和#container 之间拖动多个项目。

以下是JS:

$("#container").on('click', '.child', function () {
  $(this).toggleClass('selected');
});

$('.parent').sortable({
  appendTo: "#container",
  connectWith: '.parent, #container',
  revert: 0,
  helper: function (e, item) {
    if (!item.hasClass('selected')) {
        item.addClass('selected').siblings().removeClass('selected');
    }
    var elements = $('#container').find('.selected').clone();
    $('#container').find('.selected').not(item).addClass('hidden');
    var helper = $('<div/>', {
        class: 'parent'
    });
    return helper.append(elements);
  },
  start: function (e, ui) {
    var len = ui.helper.children().length;
    var width = ui.item.width() + 2;
    ui.helper.width((len * width));
    ui.placeholder.width((len * width));
  },
  stop: function (e, ui) {
    $('.selected').removeClass('selected');
  }
});

$('#container').sortable({
  connectWith: '.parent',
  tolerance: "pointer"
});

以下

JSFiddle

使用整个代码(我删除了附加项目的代码以最小化代码,因为这与占位符位置无关)演示了我面临的问题:

我可以将项目从.parent 拖到#container,如下所示:

  • 通过拖动项目到#container左侧如下图:
  • 通过将#container 上方的项目拖动到.parents 之间的空间(这有点棘手,但当中心正好悬停在空间上时它可以工作),如下所示:

但是一旦我将一个项目拖到外面,占位符不会出现在#container 的右侧,即使我直接将项目悬停在它上面。

预期输出:

当前结果:

如图所示,占位符在 .parent 内,即使项目远离它,在 #container 内。

根据我的尝试,问题出在以下几点:

 $('#container').find('.selected').not(item).addClass('hidden');

我使用display:none 隐藏所选项目的地方,可能会导致 jQuery UI 计算错误。

所以我在start 事件中尝试了refreshrefreshPositions,就像在这个JSFiddle 中一样,它产生了预期的输出,但它不再正确地在另外两个中显示#container 中的占位符场景。

我想做的是能够将项目从.parent拖到#container by

  1. 将项目拖到#container 的左侧
  2. #container 上方的项目拖过.parents 之间的空格
  3. 将项目拖动到#container 的右侧

旁注:大部分sortable options 是在尝试解决问题时添加的,css 尺寸仅用于演示目的,如有必要,可以添加或删除。

更新:这似乎是一个错误,我报告了here。 jQuery UI 团队回复说他们正在重写所有交互。所以希望这将在下一个版本中得到解决。

【问题讨论】:

  • 首先你说As shown in the image, the placeholder is inside the .parent even though the item is away from it, inside #container. ..我刚刚检查了一下,占位符在父级之外,只是容器的一个子级,对吗?检查此屏幕截图prntscr.com/4j2qpl
  • 好吧,您可能从第二把小提琴中截取了该屏幕截图,其中我无法在左侧容器中创建占位符以及我在问题中提到的其他问题...您检查了吗您是否可以在同一个小提琴中执行所有三个操作?

标签: javascript jquery html jquery-ui jquery-ui-sortable


【解决方案1】:

在我的代码中,将这个记录不充分的 hack 应用于 Sortable 的 overout 回调函数几乎已成为惯例:

if($.ui.ddmanager.current)
    $.ui.ddmanager.prepareOffsets($.ui.ddmanager.current, null);

这将确保刷新位置,并且与内置的 refreshrefreshPositions 方法相比,它似乎有效。

你能试试这个方法,看看它是否能改善你的 Sortable 的行为?

【讨论】:

  • 老兄,你成就了我的一天!正如您所说,与记录在案的 refresh 和 refreshPositions 方法不同,这实际上似乎有效!
  • 您是说将其添加到用户定义的函数中,还是添加到核心 Jquery UI 代码库中的函数中?
【解决方案2】:

编辑:

别介意第三方插件,看看这个,让我知道你是否想要这个:http://jsfiddle.net/6opxyvkp/7/ - old

http://jsfiddle.net/6opxyvkp/9/ -

HTML

<div id='container'>
    <div class='parent'>
        <div class='child'>1</div>
        <div class='child'>2</div>
        <div class='child'>3</div>
        <div class='child'>4</div>
    </div>
    <div class='parent'>
        <div class='child'>5</div>
        <div class='child'>6</div>
        <div class='child'>7</div>
        <div class='child'>8</div>
    </div>
</div>

CSS

#container {
    display: inline-block;
    height:60px;
    background:dodgerblue;
}
.parent {
    float:left;
    height:58px;
    margin:0 15px;
    border:0px solid red;
    background:silver;
}
.child {
    float:left;
    width:50px;
    height:60px;
    text-align: left;
    background:#fff;
    border:1px solid;
    margin:0px;
}
.ui-sortable-placeholder {
    visibility: visible !important;
    border: none;
    padding:1px;
    background:rgba(0, 0, 0, 0.5) !important;
}
.selected {
    background:red;
}
.hidden {
    display:none !important;
}

JS

$("#container").on('click', '.child', function () {
    $(this).toggleClass('selected');
});

$('.parent').sortable({
    connectWith: '.parent, #container',
    appendTo: '#container',
    revert: 0,
    helper: 'clone',
    helper: function (e, item) {
        var helper = $('<div/>');
        if (!item.hasClass('selected')) {
            item.addClass('selected').siblings().removeClass('selected');
        }
        var elements = item.parent().children('.selected').clone();
        item.data('multidrag', elements).siblings('.selected').remove();
        return helper.append(elements);
    },
    start: function (e, ui) {
        var len = ui.helper.children().length;
        var width = ui.item.width() + 2;
        ui.helper.width((len * width));
        ui.placeholder.width((len * width));
    },
    stop: function (e, info) {
        info.item.after(info.item.data('multidrag')).remove();
    }
});

$('#container').sortable({
    connectWith: '.parent',
    tolerance: 'pointer'
});

如果允许使用第三方jQuery 插件,请查看https://github.com/shvetsgroup/jquery.multisortable

【讨论】:

  • 您好,感谢您的回复。它似乎按原样工作,但不幸的是,当我在我的演示中向容器添加全宽时,这会产生相同的结果:jsfiddle.net/6opxyvkp/8 - 将一个项目拖出容器,然后将其悬停在右侧.. . 占位符还在.parent...
  • @TJ 这是一个已知的sortable 故障。它实际上可以工作,但是您需要将其移到容器之外,然后将其缓慢地向左移动(当您想将它们添加到容器的右侧时)将为您提供将其插入父项之外的选项。如果我不能按照我的意思为你截屏,希望这有意义吗?
  • @TJ 你可以在右边和中间添加&lt;div class="left"&gt;&lt;/div&gt; 并使用一点填充,这样你就可以更容易地添加块。只是为你准备了一个新的小提琴。
  • @TJ 请在上面找到新的小提琴链接。没关系他们每个人的红色背景,他们只是作为指导。
  • 对不起,在DOM 中添加新元素根本不是一个选项...这只是一个演示,新的父组将由用户交互生成,所以如果有 20 个父组,那么我'将不得不生成 21 个额外元素,跟踪它们并根据用户交互将其删除...这就是为什么我被要求使用可排序选项和 css 进行修复(如果可能)...
猜你喜欢
  • 2013-11-12
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 2017-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多