UNPKG

packery

Version:

bin-packing layout library

185 lines (155 loc) 4.94 kB
/** * Packery Item Element **/ ( function( window ) { 'use strict'; // -------------------------- Item -------------------------- // function itemDefinition( getStyleProperty, Outlayer, Rect ) { var transformProperty = getStyleProperty('transform'); // sub-class Item var Item = function PackeryItem() { Outlayer.Item.apply( this, arguments ); }; Item.prototype = new Outlayer.Item(); var protoCreate = Item.prototype._create; Item.prototype._create = function() { // call default _create logic protoCreate.call( this ); this.rect = new Rect(); // rect used for placing, in drag or Packery.fit() this.placeRect = new Rect(); }; // -------------------------- drag -------------------------- // Item.prototype.dragStart = function() { this.getPosition(); this.removeTransitionStyles(); // remove transform property from transition if ( this.isTransitioning && transformProperty ) { this.element.style[ transformProperty ] = 'none'; } this.getSize(); // create place rect, used for position when dragged then dropped // or when positioning this.isPlacing = true; this.needsPositioning = false; this.positionPlaceRect( this.position.x, this.position.y ); this.isTransitioning = false; this.didDrag = false; }; /** * handle item when it is dragged * @param {Number} x - horizontal position of dragged item * @param {Number} y - vertical position of dragged item */ Item.prototype.dragMove = function( x, y ) { this.didDrag = true; var packerySize = this.layout.size; x -= packerySize.paddingLeft; y -= packerySize.paddingTop; this.positionPlaceRect( x, y ); }; Item.prototype.dragStop = function() { this.getPosition(); var isDiffX = this.position.x !== this.placeRect.x; var isDiffY = this.position.y !== this.placeRect.y; // set post-drag positioning flag this.needsPositioning = isDiffX || isDiffY; // reset flag this.didDrag = false; }; // -------------------------- placing -------------------------- // /** * position a rect that will occupy space in the packer * @param {Number} x * @param {Number} y * @param {Boolean} isMaxYContained */ Item.prototype.positionPlaceRect = function( x, y, isMaxYOpen ) { this.placeRect.x = this.getPlaceRectCoord( x, true ); this.placeRect.y = this.getPlaceRectCoord( y, false, isMaxYOpen ); }; /** * get x/y coordinate for place rect * @param {Number} coord - x or y * @param {Boolean} isX * @param {Boolean} isMaxOpen - does not limit value to outer bound * @returns {Number} coord - processed x or y */ Item.prototype.getPlaceRectCoord = function( coord, isX, isMaxOpen ) { var measure = isX ? 'Width' : 'Height'; var size = this.size[ 'outer' + measure ]; var segment = this.layout[ isX ? 'columnWidth' : 'rowHeight' ]; var parentSize = this.layout.size[ 'inner' + measure ]; // additional parentSize calculations for Y if ( !isX ) { parentSize = Math.max( parentSize, this.layout.maxY ); // prevent gutter from bumping up height when non-vertical grid if ( !this.layout.rowHeight ) { parentSize -= this.layout.gutter; } } var max; if ( segment ) { segment += this.layout.gutter; // allow for last column to reach the edge parentSize += isX ? this.layout.gutter : 0; // snap to closest segment coord = Math.round( coord / segment ); // contain to outer bound // contain non-growing bound, allow growing bound to grow var mathMethod; if ( this.layout.options.isHorizontal ) { mathMethod = !isX ? 'floor' : 'ceil'; } else { mathMethod = isX ? 'floor' : 'ceil'; } var maxSegments = Math[ mathMethod ]( parentSize / segment ); maxSegments -= Math.ceil( size / segment ); max = maxSegments; } else { max = parentSize - size; } coord = isMaxOpen ? coord : Math.min( coord, max ); coord *= segment || 1; return Math.max( 0, coord ); }; Item.prototype.copyPlaceRectPosition = function() { this.rect.x = this.placeRect.x; this.rect.y = this.placeRect.y; }; // ----- ----- // // remove element from DOM Item.prototype.removeElem = function() { this.element.parentNode.removeChild( this.element ); // add space back to packer this.layout.packer.addSpace( this.rect ); this.emitEvent( 'remove', [ this ] ); }; // ----- ----- // return Item; } // -------------------------- transport -------------------------- // if ( typeof define === 'function' && define.amd ) { // AMD define( [ 'get-style-property/get-style-property', 'outlayer/outlayer', './rect' ], itemDefinition ); } else if ( typeof exports === 'object' ) { // CommonJS module.exports = itemDefinition( require('desandro-get-style-property'), require('outlayer'), require('./rect') ); } else { // browser global window.Packery.Item = itemDefinition( window.getStyleProperty, window.Outlayer, window.Packery.Rect ); } })( window );