Responsive, Draggable, Filterable Grid Layout – muuri

Category: Javascript , Layout , Recommended | July 10, 2021
Author:haltu
Views Total:973 views
Official Page:Go to website
Last Update:July 10, 2021
License:MIT

Preview:

Responsive, Draggable, Filterable Grid Layout – muuri

Description:

muuri is a versatile JavaScript library that helps you create responsive, draggable, filterable, searchable grid layouts with smooth web animations.

Install it via package managers:

# Yarn
yarn add muuri
# NPM
$ npm install muuri
# Bower
$ bower install muuri

Basic usage:

1. Include the main JavaScript file ‘muuri.js’ on the webpage.

<script src="muuri.min.js"></script>

2. Include the Web Animations Polyfill if needed.

<script src="https://cdn.jsdelivr.net/npm/[email protected]/web-animations.min.js"></script>

3. Add your own grid items to the layout.

<div class="grid">
  <div class="item">
    <div class="item-content">
      Item 1
    </div>
  </div>
  <div class="item">
    <div class="item-content">
      Item 2
    </div>
  </div>
  <div class="item">
    <div class="item-content">
      Item 3
    </div>
  </div>
  ...
</div>

4. Initialize the grid layout:

var grid = new Muuri('.grid');

5. Apply your own CSS styles to the layout & grid items:

.grid {
  position: relative;
}
.item {
  display: block;
  position: absolute;
  width: 100px;
  height: 100px;
  margin: 5px;
  z-index: 1;
  background: #000;
  color: #fff;
}
.item.muuri-item-dragging {
  z-index: 3;
}
.item.muuri-item-releasing {
  z-index: 2;
}
.item.muuri-item-hidden {
  z-index: 0;
}
.item-content {
  position: relative;
  width: 100%;
  height: 100%;
}

6. Config the grid layout with the following options.

var grid = new Muuri('.grid',{
    // Initial item elements
    items: '*',
    // Default show animation
    showDuration: 300,
    showEasing: 'ease',
    // Default hide animation
    hideDuration: 300,
    hideEasing: 'ease',
    // Item's visible/hidden state styles
    visibleStyles: {
      opacity: '1',
      transform: 'scale(1)'
    },
    hiddenStyles: {
      opacity: '0',
      transform: 'scale(0.5)'
    },
    // Layout
    layout: {
      fillGaps: false,
      horizontal: false,
      alignRight: false,
      alignBottom: false,
      rounding: false
    },
    layoutOnResize: 150,
    layoutOnInit: true,
    layoutDuration: 300,
    layoutEasing: 'ease',
    /* e.g.
    sortData: {
      foo: function (item, element) {
        return parseFloat(element.getAttribute('data-foo'));
      },
      bar: function (item, element) {
        return element.getAttribute('data-bar').toUpperCase();
      },
    },
    */
    sortData: null,
    // Drag & Drop Options
    dragEnabled: false,
    dragContainer: null,
    dragHandle: null,
    dragStartPredicate: {
      distance: 0,
      delay: 0
    },
    dragAxis: 'xy', // 'x', 'y'
    dragSort: true,
    dragSortHeuristics: {
      sortInterval: 100,
      minDragDistance: 10,
      minBounceBackAngle: 1
    },
    dragSortPredicate: {
      threshold: 50,
      action: 'move',
      migrateAction: 'move'
    },
    dragRelease: {
      duration: 300,
      easing: 'ease',
      useDragContainer: true
    },
    dragCssProps: {
      touchAction: 'none',
      userSelect: 'none',
      userDrag: 'none',
      tapHighlightColor: 'rgba(0, 0, 0, 0)',
      touchCallout: 'none',
      contentZooming: 'none'
    },
    dragPlaceholder: {
      enabled: false,
      createElement: null,
      onCreate: null,
      onRemove: null
    },
    dragAutoScroll: {
      targets: [],
      handle: null,
      threshold: 50,
      safeZone: 0.2,
      speed: Muuri.AutoScroller.smoothSpeed(1000, 2000, 2500),
      sortDuringScroll: true,
      smoothStop: false,
      onStart: null,
      onStop: null
    },
    // Classnames
    containerClass: 'muuri',
    itemClass: 'muuri-item',
    itemVisibleClass: 'muuri-item-shown',
    itemHiddenClass: 'muuri-item-hidden',
    itemPositioningClass: 'muuri-item-positioning',
    itemDraggingClass: 'muuri-item-dragging',
    itemReleasingClass: 'muuri-item-releasing',
    itemPlaceholderClass: 'muuri-item-placeholder'
});

7. You can also set options globally.

Muuri.defaultOptions.showDuration = 400;
Muuri.defaultOptions.dragSortPredicate.action = 'swap';

8. Grid methods.

// get the grid element
grid.getElement();
// get a specific grid element
grid.getElement(target);
// get a single grid item
grid.getItem(target);
// get all items
grid.getItems();
// get all items in an array of item instances/elements/indices.
grid.refreshItems([target]);
// refresh the sort data of the grid's items.
grid.refreshSortData();
// synchronize the item elements in the DOM to match the order of the items in the grid
grid.synchronize();
// calculate item positions and move items to their calculated positions
grid.layout([instant], [callback]);
// add new items
// options.active — boolean / undefined
// options.index — number
// options.layout — boolean / function / string
grid.add(elements, [options]);
// remove items
// options.removeElements — boolean
// options.layout — boolean / function / string
grid.remove(elements, [options]);
// show the selected items
// options.instant — boolean
// options.syncWithLayout — boolean
// options.onFinish — function
// options.layout — boolean / function / string
grid.show(items, [options]);
// hide the selected items
// options.instant — boolean
// options.syncWithLayout — boolean
// options.onFinish — function
// options.layout — boolean / function / string
grid.hide(items, [options]);
// filter items.
// predicate — function / string
// options.instant — boolean
// options.syncWithLayout — boolean
// options.onFinish — function
// options.layout — boolean / function / string
grid.filter(predicate, [options]);
// sort items
// comparer — array / function / string
// options.descending — boolean
// options.layout — boolean / function / string
grid.sort(comparer, [options]);
// move an item to another position in the grid
// item — element / Muuri.Item / number
// position — element / Muuri.Item / number
// options.action — string
// options.layout — boolean / function / string
grid.move(item, position, [options]);
// move an item into another grid
// item — element / Muuri.Item / number
// grid — Muuri
// position — element / Muuri.Item / number
// options.appendTo — element
// options.layoutSender — boolean / function / string
// options.layoutReceiver — boolean / function / string
grid.send(item, grid, position, [options]);
// bind/unbind an event listener.
grid.on(event, listener);
grid.off(event, listener);
// destroy the grid and remove the items or not
grid.destroy([removeElements]);

8. Item methods.

// get the grid instance the item belongs to
item.getGrid();
// get the item element.
item.getElement();
// get item element's cached width
item.getWidth();
// get item element's cached height
item.getHeight();
// get item element's cached margins
item.getMargin();
// get item element's cached position
item.getPosition();
// check if the item is currently active
item.isActive();
// check if the item is currently visibl
item.isVisible();
// check if the item is currently animating to visible.
item.isShowing();
// check if the item is currently animating to hidden.
item.isHiding();
// check if the item is currently being positioned.
item.isPositioning();
// check if the item is currently being dragged.
item.isDragging();
// check if the item is currently being released.
item.isReleasing();
// check if the item is destroyed.
item.isDestroyed();

9. Event handlers.

grid.on('synchronize', function () {
  console.log('Synced!');
});
grid.on('layoutStart', function (items, isInstant) {
  console.log(items, isInstant);
});
grid.on('layoutEnd', function (items) {
  console.log(items);
  // For good measure you might want to filter out all the non-active items,
  // because it's techniclly possible that some of the items are
  // destroyed/hidden when we receive this event.
  var activeItems = items.filter(function (item) {
    return item.isActive();
  });
});
grid.on('layoutAbort', function (items) {
  console.log(items);
  // For good measure you might want to filter out all the non-active items,
  // because it's techniclly possible that some of the items are destroyed or
  // hidden when we receive this event.
  var activeItems = items.filter(function (item) {
    return item.isActive();
  });
});
grid.on('add', function (items) {
  console.log(items);
});
grid.on('remove', function (items, indices) {
  console.log(items, indices);
});
grid.on('showStart', function (items) {
  console.log(items);
});
grid.on('showEnd', function (items) {
  console.log(items);
});
grid.on('hideStart', function (items) {
  console.log(items);
});
grid.on('hideEnd', function (items) {
  console.log(items);
});
grid.on('filter', function (shownItems, hiddenItems) {
  console.log(shownItems);
  console.log(hiddenItems);
});
grid.on('sort', function (currentOrder, previousOrder) {
  console.log(currentOrder);
  console.log(previousOrder);
});
grid.on('move', function (data) {
  console.log(data);
});
grid.on('send', function (data) {
  console.log(data);
});
grid.on('beforeSend', function (data) {
  console.log(data);
});
grid.on('receive', function (data) {
  console.log(data);
});
grid.on('beforeReceive', function (data) {
  console.log(data);
});
grid.on('dragInit', function (item, event) {
  console.log(event);
  console.log(item);
});
grid.on('dragStart', function (item, event) {
  console.log(event);
  console.log(item);
});
grid.on('dragMove', function (item, event) {
  console.log(event);
  console.log(item);
});
grid.on('dragScroll', function (item, event) {
  console.log(event);
  console.log(item);
});
grid.on('dragEnd', function (item, event) {
  console.log(event);
  console.log(item);
});
grid.on('dragReleaseStart', function (item) {
  console.log(item);
});
grid.on('dragReleaseEnd', function (item) {
  console.log(item);
});
grid.on('destroy', function () {
  console.log('Muuri is no more...');
});

Changelog:

v0.9.5 (07/10/2021)

  • update

You Might Be Interested In:


Leave a Reply