Sortable: Animation flipping out

Created on 8 Jul 2016  路  15Comments  路  Source: SortableJS/Sortable

I am using SortableJS with a flex box positioned grid, and when I enabled animations the whole grid starts to flip out. It seems the animation is causing the items to be pushed to the next row for a brief moment.

Illustration of the problem:

ss

I am using this with the Angular binding, but I think the problem is with Sortable itself.

CSS and markup for the grid (use whatever for the variables):

<ul class="sort-container" ng-sortable="sortable">
      <li ng-repeat="suggestion in suggestions">
        <span>{{suggestion.name}}</span>
      </li>
</ul>
.sort-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  position: relative;
  width: 100%;
  height: 100%;
  li {
    position: relative;
    cursor: move;
    list-style: none;
    flex: 1;
    max-width: calc(16.67% - 1rem);
    min-width: calc(16.66% - 1rem);
    height: auto;
    border: 1px solid black;
    padding: 1rem;
    margin: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    &:before {
      content: '';
      float: left;
      padding-top: 100%;
    }
  }
  .sortable-ghost {
    opacity: 0.4;
    background: none;
    border: 1px dashed black;
  }
}
$scope.sortable = {
  animation: 150
};

Any thoughts as to why this is happening? It seems to only occur when both the min-width and max-width properties of the items are set.

All 15 comments

No solutions, only disable the animation.

Do you know what the problem is? Is it in sortable's animation code?

The same problem happens without animation actually, it's just a bit less funky because there is no animation. But the elements are still pushed down to the next line, and then back to the previous line.

It seems to happen when hovering over the margin area of the items. The placeholder is dropped at the end of the list in that case, instead of between the items.

@RubaXa have a look at this Plunkr: https://embed.plnkr.co/aiecTBYAioYQ9KJnovny/

Try to move block D between blocks E and F and you will see block D ghost placeholder is moved to the end of the list.

The same is happening without flexbox, with the items as inline-block: https://embed.plnkr.co/dsKzewYwiD2bHsh3sSRX/

And the same was happening in my project with float: left on the items. So it doesn't seem to matter how the items are positioned.

Removing the margins of the items is the only thing that seems to fix it.

I have fixed the margin issue by wrapping the content with a span which contains the margin instead of the list items. However, when enabling the animation, the "flipping" still occurs.

https://plnkr.co/edit/TZcdSG9D8bQoKBO7yXVN?p=preview

Try to move an item to the end of the list first, and then to the back of the one before last row:

ss

Hi Adam, I had the same problem when i was using display:inline-block on list elements.
I've changed it to display:block;float:left and it works.

Hi @rhoman hmm, I think I tried that too, but still wasn't working properly. I'll give it another go tomorrow. Thanks for the tip.

@rhoman yup you're right, it's not flipping out anymore in the following plunkr;

https://plnkr.co/edit/8xFK6lYkuvUEWlGovJ6g?p=preview

However, I still think the plugin should be fixed for cases where you want to use inline-block or flexbox to position your elements.

@rhoman spoke to soon. It still fails with float: left:

https://plnkr.co/edit/1BwGaMFe979Cy4oGcSuW?p=preview

ss

Someone emailed me a simple solution which fixes this issue by specifying forceFallback: true. This is not ideal though, and I still hope this issue can be looked at further.

I think I solved this issue for myself:
In
_onDragOver: function (/**Event*/evt) {
after:
target = _closest(evt.target, options.draggable, el);
I added:
if (!target || target.animated || dragEl.animated) return;
and it seems to be working without flipping (with animation)

Had to fix some js errors after latest change, this would be patch. No idea would it work for someone else and is it 100% ok because didn't get into code too much:

@@ -601,6 +601,7 @@
                }

                target = _closest(evt.target, options.draggable, el);
+               if (!target || target.animated || dragEl.animated) return;
                dragRect = dragEl.getBoundingClientRect();

                if (revert) {
@@ -993,16 +994,19 @@
    function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
        if (el) {
            ctx = ctx || document;
-
-           do {
-               if (
-                   (selector === '>*' && el.parentNode === ctx)
-                   || _matches(el, selector)
-               ) {
-                   return el;
-               }
-           }
-           while (el = ('host' in el) ? el.host : el.parentNode)
+           try {
+               do {
+                   if (
+                       (selector === '>*' && el.parentNode === ctx)
+                       || _matches(el, selector)
+                   ) {
+                       return el;
+                   }
+               }
+               while (el = ('host' in el) ? el.host : el.parentNode)
+           } catch(e) {
+               return null;
+           }
        }

        return null;
@@ -1203,7 +1207,7 @@
                re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');

            return (
-               (tag === '' || el.nodeName.toUpperCase() == tag) &&
+               (tag === '' || (el.nodeName && el.nodeName.toUpperCase() == tag)) &&
                (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
            );
        }

I'll revert the code change and see if it's fixed in our production app

Seems to be fixed now, thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chrishaigy picture chrishaigy  路  3Comments

benfoster picture benfoster  路  3Comments

rakeshrockb picture rakeshrockb  路  3Comments

garygreen picture garygreen  路  3Comments

kevinvanmierlo picture kevinvanmierlo  路  3Comments