# Quicksand

Reorder and filter items with a nice shuffling animation.

Examples

## Advanced: Sorting one set of HTML (cloning)

Filter by type Everything Applications Utilities
Sort by Size Name

- Activity Monitor 348 KB
- Address Book 1904 KB
- Finder 1337 KB
- Front Row 401 KB
- Google Pokémon 12875 KB
- iCal 5273 KB
- iChat 5437 KB
- Interface Builder 2764 KB
- iTuna 17612 KB
- Keychain Access 972 KB
- Network Utility 245 KB
- Sync 3788 KB
- TextEdit 1669 KB

## JavaScript

    // Custom sorting plugin
    (function($) {
      $.fn.sorted = function(customOptions) {
        var options = {
          reversed: false,
          by: function(a) { return a.text(); }
        };
        $.extend(options, customOptions);
        $data = $(this);
        arr = $data.get();
        arr.sort(function(a, b) {
          var valA = options.by($(a));
          var valB = options.by($(b));
          if (options.reversed) {
            return (valA < valB) ? 1 : (valA > valB) ? -1 : 0;
          } else {
            return (valA < valB) ? -1 : (valA > valB) ? 1 : 0;
          }
        });
        return $(arr);
      };
    })(jQuery);

    // DOMContentLoaded
    $(function() {

      // bind radiobuttons in the form
      var $filterType = $('#filter input[name="type"]');
      var $filterSort = $('#filter input[name="sort"]');

      // get the first collection
      var $applications = $('#applications');

      // clone applications to get a second collection
      var $data = $applications.clone();

      // attempt to call Quicksand on every form change
      $filterType.add($filterSort).change(function(e) {
        if ($($filterType+':checked').val() == 'all') {
          var $filteredData = $data.find('li');
        } else {
          var $filteredData = $data.find('li[data-type=' + $($filterType+":checked").val() + ']');
        }

        // if sorted by size
        if ($('#filter input[name="sort"]:checked').val() == "size") {
          var $sortedData = $filteredData.sorted({
            by: function(v) {
              return parseFloat($(v).find('span[data-type=size]').text());
            }
          });
        } else {
          // if sorted by name
          var $sortedData = $filteredData.sorted({
            by: function(v) {
              return $(v).find('strong').text().toLowerCase();
            }
          });
        }

        // finally, call quicksand
        $applications.quicksand($sortedData, {
          duration: 800,
          easing: 'easeInOutQuad'
        });

      });

    });

## HTML

    <form id="filter">
      <fieldset>
        <legend>Filter by type</legend>
        <label><input type="radio" name="type" value="all" checked="checked">Everything</label>
        <label><input type="radio" name="type" value="app">Applications</label>
        <label><input type="radio" name="type" value="util">Utilities</label>
      </fieldset>
      <fieldset>
        <legend>Sort by</legend>
        <label><input type="radio" name="sort" value="size" checked="checked">Size</label>
        <label><input type="radio" name="sort" value="name">Name</label>
      </fieldset>
    </form>

    <ul id="applications" class="image-grid">
      <li data-id="id-1" data-type="util">
        <img src="activity-monitor.png" width="128" height="128" alt="" />
        <strong>Activity Monitor</strong>
        <span data-type="size">348 KB</span>
      </li>
      <li data-id="id-2" data-type="app">
        <img src="address-book.png" width="128" height="128" alt="" />
        <strong>Address Book</strong>
        <span data-type="size">1904 KB</span>
      </li>
      <li data-id="id-3" data-type="app">
        <img src="finder.png" width="128" height="128" alt="" />
        <strong>Finder</strong>
        <span data-type="size">1337 KB</span>
      </li>
      <li data-id="id-4" data-type="app">
        <img src="front-row.png" width="128" height="128" alt="" />
        <strong>Front Row</strong>
        <span data-type="size">401 KB</span>
      </li>
      <li data-id="id-5" data-type="app">
        <img src="google-pokemon.png" width="128" height="128" alt="" />
        <strong>Google Pokémon</strong>
        <span data-type="size">12875 KB</span>
      </li>
      <li data-id="id-6" data-type="app">
        <img src="ical.png" width="128" height="128" alt="" />
        <strong>iCal</strong>
        <span data-type="size">5273 KB</span>
      </li>
      <li data-id="id-7" data-type="app">
        <img src="ichat.png" width="128" height="128" alt="" />
        <strong>iChat</strong>
        <span data-type="size">5437 KB</span>
      </li>
      <li data-id="id-8" data-type="app">
        <img src="interface-builder.png" width="128" height="128" alt="" />
        <strong>Interface Builder</strong>
        <span data-type="size">2764 KB</span>
      </li>
      <li data-id="id-9" data-type="app">
        <img src="ituna.png" width="128" height="128" alt="" />
        <strong>iTuna</strong>
        <span data-type="size">17612 KB</span>
      </li>
      <li data-id="id-10" data-type="util">
        <img src="keychain-access.png" width="128" height="128" alt="" />
        <strong>Keychain Access</strong>
        <span data-type="size">972 KB</span>
      </li>
      <li data-id="id-11" data-type="util">
        <img src="network-utility.png" width="128" height="128" alt="" />
        <strong>Network Utility</strong>
        <span data-type="size">245 KB</span>
      </li>
      <li data-id="id-12" data-type="util">
        <img src="sync.png" width="128" height="128" alt="" />
        <strong>Sync</strong>
        <span data-type="size">3788 KB</span>
      </li>
      <li data-id="id-13" data-type="app">
        <img src="textedit.png" width="128" height="128" alt="" />
        <strong>TextEdit</strong>
        <span data-type="size">1669 KB</span>
      </li>
    </ul>