JAVASCRIPT   55

Masonry

Guest on 13th July 2022 06:53:24 AM

  1. /*!
  2.  * Masonry v4.2.2
  3.  * Cascading grid layout library
  4.  * https://masonry.desandro.com
  5.  * MIT License
  6.  * by David DeSandro
  7.  */
  8.  
  9. ( function( window, factory ) {
  10.   // universal module definition
  11.   /* jshint strict: false */ /*globals define, module, require */
  12.   if ( typeof define == 'function' && define.amd ) {
  13.     // AMD
  14.     define( [
  15.         'outlayer/outlayer',
  16.         'get-size/get-size'
  17.       ],
  18.       factory );
  19.   } else if ( typeof module == 'object' && module.exports ) {
  20.     // CommonJS
  21.     module.exports = factory(
  22.       require('outlayer'),
  23.       require('get-size')
  24.     );
  25.   } else {
  26.     // browser global
  27.     window.Masonry = factory(
  28.       window.Outlayer,
  29.       window.getSize
  30.     );
  31.   }
  32.  
  33. }( window, function factory( Outlayer, getSize ) {
  34.  
  35. 'use strict';
  36.  
  37. // -------------------------- masonryDefinition -------------------------- //
  38.  
  39.   // create an Outlayer layout class
  40.   var Masonry = Outlayer.create('masonry');
  41.   // isFitWidth -> fitWidth
  42.   Masonry.compatOptions.fitWidth = 'isFitWidth';
  43.  
  44.   var proto = Masonry.prototype;
  45.  
  46.   proto._resetLayout = function() {
  47.     this.getSize();
  48.     this._getMeasurement( 'columnWidth', 'outerWidth' );
  49.     this._getMeasurement( 'gutter', 'outerWidth' );
  50.     this.measureColumns();
  51.  
  52.     // reset column Y
  53.     this.colYs = [];
  54.     for ( var i=0; i < this.cols; i++ ) {
  55.       this.colYs.push( 0 );
  56.     }
  57.  
  58.     this.maxY = 0;
  59.     this.horizontalColIndex = 0;
  60.   };
  61.  
  62.   proto.measureColumns = function() {
  63.     this.getContainerWidth();
  64.     // if columnWidth is 0, default to outerWidth of first item
  65.     if ( !this.columnWidth ) {
  66.       var firstItem = this.items[0];
  67.       var firstItemElem = firstItem && firstItem.element;
  68.       // columnWidth fall back to item of first element
  69.       this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
  70.         // if first elem has no width, default to size of container
  71.         this.containerWidth;
  72.     }
  73.  
  74.     var columnWidth = this.columnWidth += this.gutter;
  75.  
  76.     // calculate columns
  77.     var containerWidth = this.containerWidth + this.gutter;
  78.     var cols = containerWidth / columnWidth;
  79.     // fix rounding errors, typically with gutters
  80.     var excess = columnWidth - containerWidth % columnWidth;
  81.     // if overshoot is less than a pixel, round up, otherwise floor it
  82.     var mathMethod = excess && excess < 1 ? 'round' : 'floor';
  83.     cols = Math[ mathMethod ]( cols );
  84.     this.cols = Math.max( cols, 1 );
  85.   };
  86.  
  87.   proto.getContainerWidth = function() {
  88.     // container is parent if fit width
  89.     var isFitWidth = this._getOption('fitWidth');
  90.     var container = isFitWidth ? this.element.parentNode : this.element;
  91.     // check that this.size and size are there
  92.     // IE8 triggers resize on body size change, so they might not be
  93.     var size = getSize( container );
  94.     this.containerWidth = size && size.innerWidth;
  95.   };
  96.  
  97.   proto._getItemLayoutPosition = function( item ) {
  98.     item.getSize();
  99.     // how many columns does this brick span
  100.     var remainder = item.size.outerWidth % this.columnWidth;
  101.     var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
  102.     // round if off by 1 pixel, otherwise use ceil
  103.     var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
  104.     colSpan = Math.min( colSpan, this.cols );
  105.     // use horizontal or top column position
  106.     var colPosMethod = this.options.horizontalOrder ?
  107.       '_getHorizontalColPosition' : '_getTopColPosition';
  108.     var colPosition = this[ colPosMethod ]( colSpan, item );
  109.     // position the brick
  110.     var position = {
  111.       x: this.columnWidth * colPosition.col,
  112.       y: colPosition.y
  113.     };
  114.     // apply setHeight to necessary columns
  115.     var setHeight = colPosition.y + item.size.outerHeight;
  116.     var setMax = colSpan + colPosition.col;
  117.     for ( var i = colPosition.col; i < setMax; i++ ) {
  118.       this.colYs[i] = setHeight;
  119.     }
  120.  
  121.     return position;
  122.   };
  123.  
  124.   proto._getTopColPosition = function( colSpan ) {
  125.     var colGroup = this._getTopColGroup( colSpan );
  126.     // get the minimum Y value from the columns
  127.     var minimumY = Math.min.apply( Math, colGroup );
  128.  
  129.     return {
  130.       col: colGroup.indexOf( minimumY ),
  131.       y: minimumY,
  132.     };
  133.   };
  134.  
  135.   /**
  136.    * @param {Number} colSpan - number of columns the element spans
  137.    * @returns {Array} colGroup
  138.    */
  139.   proto._getTopColGroup = function( colSpan ) {
  140.     if ( colSpan < 2 ) {
  141.       // if brick spans only one column, use all the column Ys
  142.       return this.colYs;
  143.     }
  144.  
  145.     var colGroup = [];
  146.     // how many different places could this brick fit horizontally
  147.     var groupCount = this.cols + 1 - colSpan;
  148.     // for each group potential horizontal position
  149.     for ( var i = 0; i < groupCount; i++ ) {
  150.       colGroup[i] = this._getColGroupY( i, colSpan );
  151.     }
  152.     return colGroup;
  153.   };
  154.  
  155.   proto._getColGroupY = function( col, colSpan ) {
  156.     if ( colSpan < 2 ) {
  157.       return this.colYs[ col ];
  158.     }
  159.     // make an array of colY values for that one group
  160.     var groupColYs = this.colYs.slice( col, col + colSpan );
  161.     // and get the max value of the array
  162.     return Math.max.apply( Math, groupColYs );
  163.   };
  164.  
  165.   // get column position based on horizontal index. #873
  166.   proto._getHorizontalColPosition = function( colSpan, item ) {
  167.     var col = this.horizontalColIndex % this.cols;
  168.     var isOver = colSpan > 1 && col + colSpan > this.cols;
  169.     // shift to next row if item can't fit on current row
  170.     col = isOver ? 0 : col;
  171.     // don't let zero-size items take up space
  172.     var hasSize = item.size.outerWidth && item.size.outerHeight;
  173.     this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
  174.  
  175.     return {
  176.       col: col,
  177.       y: this._getColGroupY( col, colSpan ),
  178.     };
  179.   };
  180.  
  181.   proto._manageStamp = function( stamp ) {
  182.     var stampSize = getSize( stamp );
  183.     var offset = this._getElementOffset( stamp );
  184.     // get the columns that this stamp affects
  185.     var isOriginLeft = this._getOption('originLeft');
  186.     var firstX = isOriginLeft ? offset.left : offset.right;
  187.     var lastX = firstX + stampSize.outerWidth;
  188.     var firstCol = Math.floor( firstX / this.columnWidth );
  189.     firstCol = Math.max( 0, firstCol );
  190.     var lastCol = Math.floor( lastX / this.columnWidth );
  191.     // lastCol should not go over if multiple of columnWidth #425
  192.     lastCol -= lastX % this.columnWidth ? 0 : 1;
  193.     lastCol = Math.min( this.cols - 1, lastCol );
  194.     // set colYs to bottom of the stamp
  195.  
  196.     var isOriginTop = this._getOption('originTop');
  197.     var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
  198.       stampSize.outerHeight;
  199.     for ( var i = firstCol; i <= lastCol; i++ ) {
  200.       this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
  201.     }
  202.   };
  203.  
  204.   proto._getContainerSize = function() {
  205.     this.maxY = Math.max.apply( Math, this.colYs );
  206.     var size = {
  207.       height: this.maxY
  208.     };
  209.  
  210.     if ( this._getOption('fitWidth') ) {
  211.       size.width = this._getContainerFitWidth();
  212.     }
  213.  
  214.     return size;
  215.   };
  216.  
  217.   proto._getContainerFitWidth = function() {
  218.     var unusedCols = 0;
  219.     // count unused columns
  220.     var i = this.cols;
  221.     while ( --i ) {
  222.       if ( this.colYs[i] !== 0 ) {
  223.         break;
  224.       }
  225.       unusedCols++;
  226.     }
  227.     // fit container to columns that have been used
  228.     return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
  229.   };
  230.  
  231.   proto.needsResizeLayout = function() {
  232.     var previousWidth = this.containerWidth;
  233.     this.getContainerWidth();
  234.     return previousWidth != this.containerWidth;
  235.   };
  236.  
  237.   return Masonry;
  238.  
  239. }));

Raw Paste


Login or Register to edit or fork this paste. It's free.