Tuesday, October 22, 2013

How to make a sortable draggable grid with isotope/masonry

If you’re here it’s probably because you want to make a masonry/isotope based grid sortable with a drag and drop function, even when drag and drop isn’t supported in masonry and isotope libraries, it is possible! Don’t worry, you are in the right place, and here you will see an example on how to do this.
Take in mind that Jquery, isotope, and Jquery UI, masonry won’t be needed since isotope is based on masonry(but with a whole bunch of improvements and extra cool functionalities.
Before we continue I want to give credit to David Desandro who developed masonry and isotope libraries and Jason Edelman who implemented draggable functionality to it with a Jquery UI implementation, the following examples are based on his original code which you can find here.
So here is a basic implementarion of the solution proposed by Jason I made, but I added a responsive css framework called skeleton and enabled the isotope’s animation engine to see how it works, looks nice!
Here are the requirements(for the code to work properly) and the code, again.. thanks to Jason Edelman for his solution and of course Dave Desandro for isotope.
Requirements:
You will need to get skeleton since I’m using its responsive framework to enable the isotope resizing.
You can get skeleton at http://www.getskeleton.com/
You will also need isotope, get it at http://isotope.metafizzy.co/
when you download the libraries remember to save them and import them correctly into you index.html document.
The code: paste it on an index.html and be sure to load the necesary libraries and resources, jquery and jquery ui are loaded using google’s public cdn, but you  need to download isotope and skeleton! and refer properly to the directories where you store them!!
001<!DOCTYPE html>
002<head>
003 
004  <meta charset="utf-8">
005  <title>Draggable isotope Grid</title>
006 
007  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
008 
009  <!-- CSS From the "SKELETON" responsive framework
010  ================================================== -->
011  <link rel="stylesheet" href="stylesheets/base.css">
012  <link rel="stylesheet" href="stylesheets/skeleton.css">
013  <link rel="stylesheet" href="stylesheets/layout.css">
014 
015<style type="text/css">
016  $charcoal: #6c6c6c;
017ul {
018/*  width: 1000px; modified original css to make ul responsive and trigger isotope's animation*/
019  border: 1px solid black;
020  margin: 10px;
021}
022li {
023  width: 200px;/*changed original size from 100px to 200px*/
024  height: 200px;
025  background: #ccc;
026  margin: 5px;
027  padding-top: 40px;
028  color: white;
029  font-size: 25px;
030  text-shadow: 0 0 5px $charcoal;
031  box-sizing: border-box;
032  text-align: center;
033  transition: all 500ms ease;
034  transition-property: transform, top, left;
035  &.ui-sortable-placeholder {
036    visibility: visible!important;
037    background: #aaa;
038    box-shadow: inset 0 0 100px $charcoal;
039    &.active {
040      box-shadow: inset 0 0 200px $charcoal;               
041    }
042    &.starting {
043      transition-property: none;
044    }
045  }
046  &.grabbing {
047    transform: rotate(3deg);           
048  }
049  &.moving {
050    box-shadow: $charcoal 0 0 5px 2px!important;
051    transition: transform 200ms ease;   
052  }
053}
054 
055/**** Isotope Filtering ****/
056 
057.isotope-item {
058  z-index: 2;
059}
060 
061.isotope-hidden.isotope-item {
062  pointer-events: none;
063  z-index: 1;
064}
065 
066  </style>
067 
068<script  type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
069<script  type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
070 
071<script type="text/javascript" src="jquery.isotope.min.js"></script>
072 
073<script type="text/javascript">
074 
075/*in this init() function you fill find the draggable sortable implementation by Jason, to see the full commented code address to his site the link is above in this article*/
076function init()
077{
078  var list = $('ul');
079  list.isotope({ 
080    transformsEnabled: true,
081    animationEngine:'jquery'/*enable animation with jquery*/
082    , itemSelector: '.isotopey'
083    , onLayout: function() {
084      list.css('overflow', 'visible');
085    
086  });
087  list.sortable({
088    cursor: 'move'
089 
090    , start: function(event, ui) {                       
091 
092      ui.item.addClass('grabbing moving').removeClass('isotopey');
093 
094      ui.placeholder
095        .addClass('starting')
096        .removeClass('moving')
097        .css({
098          top: ui.originalPosition.top
099          , left: ui.originalPosition.left
100        })
101        ;
102      list.isotope('reloadItems');                   
103    }               
104    , change: function(event, ui) {
105      ui.placeholder.removeClass('starting');
106 
107      list
108        .isotope('reloadItems')
109        .isotope({ sortBy: 'original-order'})
110      ;
111    }
112    , beforeStop: function(event, ui) {
113      ui.placeholder.after(ui.item);                   
114    }
115    , stop: function(event, ui) {     
116      ui.item.removeClass('grabbing').addClass('isotopey');
117      list
118        .isotope('reloadItems')
119        .isotope({ sortBy: 'original-order' }, function(){
120          console.log(ui.item.is('.grabbing'));
121          if (!ui.item.is('.grabbing')) {
122            ui.item.removeClass('moving');                       
123          }
124        })
125        ;
126    }
127  });
128}
129  </script>
130</head>
131<body onload="init()">
132 
133<ul class="container">
134  <li class="isotopey ">1</li>
135  <li class="isotopey ">2</li>
136  <li class="isotopey ">3</li>
137  <li class="isotopey ">4</li>
138  <li class="isotopey ">5</li>
139  <li class="isotopey ">6</li>
140  <li class="isotopey ">7</li>
141  <li class="isotopey ">8</li>
142  <li class="isotopey ">9</li>
143  <li class="isotopey ">10</li>
144 
145</ul>
146 
147</body>
148</html>

Making the grid sortable

The thing in the code, is that the ul list, implements the jquery ui sortable widget, and when you drag any list element, it will be reordered, and it is possible to get any element’s index, information, etc, using the ui’s methods, as for isotope, what it does is basically the animation and responsive reorder of the grid, however if you wish to add items to the grid, you may use isotope’s functions and the won’t crash with jquery ui.
It is also important that the containers used are not div containers, they must be li elements since those are the ones that jquery ui use.