Skip to content

Instantly share code, notes, and snippets.

@ultimatedelman
Created February 10, 2013 22:53
Show Gist options
  • Save ultimatedelman/4751407 to your computer and use it in GitHub Desktop.
Save ultimatedelman/4751407 to your computer and use it in GitHub Desktop.
A CodePen by Jason Edelman. Isotope + JQuery UI Sortable - Naysayers will tell you it can't be done. But that's why they're naysayers and not yaydoers.
<ul>
<li class="isotopey">1</li>
<li class="isotopey">2</li>
<li class="isotopey">3</li>
<li class="isotopey">4</li>
<li class="isotopey">5</li>
<li class="isotopey">6</li>
<li class="isotopey">7</li>
<li class="isotopey">8</li>
<li class="isotopey">9</li>
<li class="isotopey">10</li>
<li class="isotopey">11</li>
<li class="isotopey">12</li>
<li class="isotopey">13</li>
<li class="isotopey">14</li>
<li class="isotopey">15</li>
<li class="isotopey">16</li>
<li class="isotopey">17</li>
<li class="isotopey">18</li>
<li class="isotopey">19</li>
<li class="isotopey">20</li>
<li class="isotopey">21</li>
<li class="isotopey">22</li>
<li class="isotopey">23</li>
<li class="isotopey">24</li>
</ul>
var list = $('ul');
list.isotope({
transformsEnabled: false
, itemSelector: '.isotopey'
, onLayout: function() {
list.css('overflow', 'visible');
}
});
list.sortable({
cursor: 'move'
//, tolerance: 'intersection' //'pointer' is too janky
, start: function(event, ui) {
//add grabbing and moving classes as user has begun
//REMOVE isotopey so that isotope does not try to sort our item,
//resulting in the item moving around and flickering on 'change'
ui.item.addClass('grabbing moving').removeClass('isotopey');
ui.placeholder
.addClass('starting') //adding the 'starting' class removes the transitions from the placeholder.
//remove 'moving' class because if the user clicks on a tile they just moved,
//the placeholder will have 'moving' class and it will mess with the transitions
.removeClass('moving')
//put placeholder directly below tile. 'starting' class ensures the
//placeholder simply appears and does not 'fly' into place
.css({
top: ui.originalPosition.top
, left: ui.originalPosition.left
})
;
//reload the items in their current state to override any previous
//sorting and to include placeholder, but do NOT call a re-layout
list.isotope('reloadItems');
}
, change: function(event, ui) {
//change only fires when the DOM is changed. the DOM changes when
//the placeholder moves up or down in the document order
//within the sortable container
//remove 'starting' class so that placeholder can now move smoothly
//with the interface
ui.placeholder.removeClass('starting');
//reload items to include the placeholder's new position in the DOM.
//then when you sort, everything around the placeholder moves as
//though the item were moving it.
list
.isotope('reloadItems')
.isotope({ sortBy: 'original-order'})
;
}
, beforeStop: function(event, ui) {
//in this event, you still have access to the placeholder. this means
//you know exactly where in the DOM you're going to place your element.
//place it right next to the placeholder. jQuery UI Sortable removes the
//placeholder for you after this event, and actually if you try to remove
//it in this step it will throw an error.
ui.placeholder.after(ui.item);
}
, stop: function(event, ui) {
//user has chosen their location! remove the 'grabbing' class, but don't
//kill the 'moving' class right away. because the 'moving' class is
//preventing your item from having transitions, you should keep it on
//until isotope is done moving everything around. it will "snap" into place
//right where your placeholder was.
//also, you must add the 'isotopey' class back to the box so that isotope
//will again include your item in its sorting list
ui.item.removeClass('grabbing').addClass('isotopey');
//reload the items again so that your item is included in the DOM order
//for isotope to do its final sort, which actually won't move anything
//but ensure that your item is in the right place
list
.isotope('reloadItems')
.isotope({ sortBy: 'original-order' }, function(){
//finally, after sorting is done, take the 'moving' class off.
//doing it here ensures that your item "snaps" and isn't resorted
//from its original position. since this happens on callback,
//if the user grabbed the tile again before callback is fired,
//don't remove the moving class in mid-grab
//for some reason in this code pen, the callback isn't firing predictably
console.log(ui.item.is('.grabbing'));
if (!ui.item.is('.grabbing')) {
ui.item.removeClass('moving');
}
})
;
}
});
@import "compass";
$charcoal: #6c6c6c;
ul {
width: 1000px;
border: 1px solid black;
margin: 10px;
}
li {
width: 100px;
height: 100px;
background: #ccc;
margin: 5px;
padding-top: 40px;
color: white;
font-size: 25px;
text-shadow: 0 0 5px $charcoal;
box-sizing: border-box;
text-align: center;
transition: all 500ms ease;
transition-property: transform, top, left;
&.ui-sortable-placeholder {
visibility: visible!important;
background: #aaa;
box-shadow: inset 0 0 100px $charcoal;
&.active {
box-shadow: inset 0 0 200px $charcoal;
}
&.starting {
transition-property: none;
}
}
&.grabbing {
transform: rotate(3deg);
}
&.moving {
box-shadow: $charcoal 0 0 5px 2px!important;
transition: transform 200ms ease;
}
}
/**** Isotope Filtering ****/
.isotope-item {
z-index: 2;
}
.isotope-hidden.isotope-item {
pointer-events: none;
z-index: 1;
}
@joshuaballoch
Copy link

@ultimatedelman thanks for posting this gist! I created a jsfiddle to demonstrate your code, so that other viewers can see it in action. See here: http://jsfiddle.net/j9S87/

@vishalkakadiya
Copy link

@ultimatedelman Thanks man. This works great and it saved my lots of time. Thanks again.

@nevil-contentsphere
Copy link

nevil-contentsphere commented Feb 13, 2018

@ultimatedelman ... I have modified your code a bit. What I want is whenever sorting starts I have some conditions and based upon that conditions I will decide if sorting should happen or not.

http://jsfiddle.net/j9S87/

Please add following code at line number 13 in above fiddle and check errors in the console.
list.sortable ('cancel');

Let me know if you find solution for that. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment