最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery ui sortable inaccurate placeholder placement in nested sortables - Stack Overflow

programmeradmin1浏览0评论

I've a sortable element inside another sortable element. Both are connected to each other. Following the the sample markup:

<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>

What i'm trying to do is to drag multiple items between .parent's and #container.

Following is the 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"
});

The following

JSFiddle

with the whole code (I removed the code for appending items to minimize the code since that is not relevant to the placeholder position) demonstrates the issue i'm facing:

I'm able to drag items from .parent to the #container as follows:

  • By dragging the items to the left of #container as shown below:
  • By dragging items above #container through the space between .parents (This is a bit tricky but it works when the center is exactly hovered over the space) as shown below:

But Once i drag an item outside, the placeholder does not appear to the right side of #container even when i directly hover the item over it.

Expected output:

Current result:

As shown in the image, the placeholder is inside the .parent even though the item is away from it, inside #container.

From what i tried, the issue is with the following:

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

Where i hide the selected items using display:none, Possibly causing miscalculations with jQuery UI.

So i tried refresh and refreshPositions in the start event, as in this JSFiddle, Which is produces the expected output, but it no longer properly displays the placeholder in #container in the other two scenario.

What i want to do is to be able to drag items from .parent to #container by

  1. Dragging items to the left of #container
  2. Dragging items above #container through the space between .parents
  3. Dragging items to the right of #container

Side note: Most of the sortable options are added while trying to fix the issue, and the css dimensions are for demo purpose only, these can be added or removed if necessary.

Update: this seems like a bug, which i reported here. The jQuery UI team replied that they are in the process of rewriting all interactions. So hopefully this will be fixed in the next release.

I've a sortable element inside another sortable element. Both are connected to each other. Following the the sample markup:

<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>

What i'm trying to do is to drag multiple items between .parent's and #container.

Following is the 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"
});

The following

JSFiddle

with the whole code (I removed the code for appending items to minimize the code since that is not relevant to the placeholder position) demonstrates the issue i'm facing:

I'm able to drag items from .parent to the #container as follows:

  • By dragging the items to the left of #container as shown below:
  • By dragging items above #container through the space between .parents (This is a bit tricky but it works when the center is exactly hovered over the space) as shown below:

But Once i drag an item outside, the placeholder does not appear to the right side of #container even when i directly hover the item over it.

Expected output:

Current result:

As shown in the image, the placeholder is inside the .parent even though the item is away from it, inside #container.

From what i tried, the issue is with the following:

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

Where i hide the selected items using display:none, Possibly causing miscalculations with jQuery UI.

So i tried refresh and refreshPositions in the start event, as in this JSFiddle, Which is produces the expected output, but it no longer properly displays the placeholder in #container in the other two scenario.

What i want to do is to be able to drag items from .parent to #container by

  1. Dragging items to the left of #container
  2. Dragging items above #container through the space between .parents
  3. Dragging items to the right of #container

Side note: Most of the sortable options are added while trying to fix the issue, and the css dimensions are for demo purpose only, these can be added or removed if necessary.

Update: this seems like a bug, which i reported here. The jQuery UI team replied that they are in the process of rewriting all interactions. So hopefully this will be fixed in the next release.

Share Improve this question edited Sep 28, 2014 at 9:46 T J asked Aug 31, 2014 at 18:16 T JT J 43.2k13 gold badges86 silver badges142 bronze badges 2
  • First you said As shown in the image, the placeholder is inside the .parent even though the item is away from it, inside #container. .. I just checked it and the placeholders are outside the parent, just a child of container, am I right? check this screenshot prntscr./4j2qpl – Pablo Matias Gomez Commented Sep 2, 2014 at 20:44
  • Well you probably took that screenshot from second fiddle, in which i'm unable to create the placeholder in container on the left side along with other issues as i mentioned in the question... Did you check whether you can perform all the three actions in same fiddle? – T J Commented Sep 3, 2014 at 7:30
Add a ment  | 

2 Answers 2

Reset to default 1

In my code, it has almost bee a convention to just apply this poorly documented hack to Sortable’s over and out callback functions:

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

This will make sure positions are refreshed, and in contrast to the built-in refresh and refreshPositions methods, it seems to work.

Could you try this approach, and see if it improves your Sortable’s behavior?

Edit:

Never mind the third-party plugin, check this out let me know if this is what you were after: http://jsfiddle/6opxyvkp/7/ - old

http://jsfiddle/6opxyvkp/9/ - new

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'
});

If third-party jQuery plugins are allowed, take a look at https://github./shvetsgroup/jquery.multisortable.

发布评论

评论列表(0)

  1. 暂无评论