admin管理员组

文章数量:1415684

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.

本文标签: javascriptjQuery ui sortable inaccurate placeholder placement in nested sortablesStack Overflow