Skip to content

Commit

Permalink
Merge branch 'horizontal-order'
Browse files Browse the repository at this point in the history
  • Loading branch information
desandro committed Apr 20, 2017
2 parents 7f17538 + cd5739f commit 389863a
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 26 deletions.
86 changes: 60 additions & 26 deletions masonry.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
// isFitWidth -> fitWidth
Masonry.compatOptions.fitWidth = 'isFitWidth';

Masonry.prototype._resetLayout = function() {
var proto = Masonry.prototype;

proto._resetLayout = function() {
this.getSize();
this._getMeasurement( 'columnWidth', 'outerWidth' );
this._getMeasurement( 'gutter', 'outerWidth' );
Expand All @@ -54,9 +56,10 @@
}

this.maxY = 0;
this.horizontalColIndex = 0;
};

Masonry.prototype.measureColumns = function() {
proto.measureColumns = function() {
this.getContainerWidth();
// if columnWidth is 0, default to outerWidth of first item
if ( !this.columnWidth ) {
Expand All @@ -81,7 +84,7 @@
this.cols = Math.max( cols, 1 );
};

Masonry.prototype.getContainerWidth = function() {
proto.getContainerWidth = function() {
// container is parent if fit width
var isFitWidth = this._getOption('fitWidth');
var container = isFitWidth ? this.element.parentNode : this.element;
Expand All @@ -91,41 +94,49 @@
this.containerWidth = size && size.innerWidth;
};

Masonry.prototype._getItemLayoutPosition = function( item ) {
proto._getItemLayoutPosition = function( item ) {
item.getSize();
// how many columns does this brick span
var remainder = item.size.outerWidth % this.columnWidth;
var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
// round if off by 1 pixel, otherwise use ceil
var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
colSpan = Math.min( colSpan, this.cols );

var colGroup = this._getColGroup( colSpan );
// get the minimum Y value from the columns
var minimumY = Math.min.apply( Math, colGroup );
var shortColIndex = colGroup.indexOf( minimumY );

// use horizontal or top column position
var colPosMethod = this.options.horizontalOrder ?
'_getHorizontalColPosition' : '_getTopColPosition';
var colPosition = this[ colPosMethod ]( colSpan, item );
// position the brick
var position = {
x: this.columnWidth * shortColIndex,
y: minimumY
x: this.columnWidth * colPosition.col,
y: colPosition.y
};

// apply setHeight to necessary columns
var setHeight = minimumY + item.size.outerHeight;
var setSpan = this.cols + 1 - colGroup.length;
for ( var i = 0; i < setSpan; i++ ) {
this.colYs[ shortColIndex + i ] = setHeight;
var setHeight = colPosition.y + item.size.outerHeight;
var setMax = colSpan + colPosition.col;
for ( var i = colPosition.col; i < setMax; i++ ) {
this.colYs[i] = setHeight;
}

return position;
};

proto._getTopColPosition = function( colSpan ) {
var colGroup = this._getTopColGroup( colSpan );
// get the minimum Y value from the columns
var minimumY = Math.min.apply( Math, colGroup );

return {
col: colGroup.indexOf( minimumY ),
y: minimumY,
};
};

/**
* @param {Number} colSpan - number of columns the element spans
* @returns {Array} colGroup
*/
Masonry.prototype._getColGroup = function( colSpan ) {
proto._getTopColGroup = function( colSpan ) {
if ( colSpan < 2 ) {
// if brick spans only one column, use all the column Ys
return this.colYs;
Expand All @@ -136,15 +147,38 @@
var groupCount = this.cols + 1 - colSpan;
// for each group potential horizontal position
for ( var i = 0; i < groupCount; i++ ) {
// make an array of colY values for that one group
var groupColYs = this.colYs.slice( i, i + colSpan );
// and get the max value of the array
colGroup[i] = Math.max.apply( Math, groupColYs );
colGroup[i] = this._getColGroupY( i, colSpan );
}
return colGroup;
};

Masonry.prototype._manageStamp = function( stamp ) {
proto._getColGroupY = function( col, colSpan ) {
if ( colSpan < 2 ) {
return this.colYs[ col ];
}
// make an array of colY values for that one group
var groupColYs = this.colYs.slice( col, col + colSpan );
// and get the max value of the array
return Math.max.apply( Math, groupColYs );
};

// get column position based on horizontal index. #873
proto._getHorizontalColPosition = function( colSpan, item ) {
var col = this.horizontalColIndex % this.cols;
var isOver = colSpan > 1 && col + colSpan > this.cols;
// shift to next row if item can't fit on current row
col = isOver ? 0 : col;
// don't let zero-size items take up space
var hasSize = item.size.outerWidth && item.size.outerHeight;
this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;

return {
col: col,
y: this._getColGroupY( col, colSpan ),
};
};

proto._manageStamp = function( stamp ) {
var stampSize = getSize( stamp );
var offset = this._getElementOffset( stamp );
// get the columns that this stamp affects
Expand All @@ -167,7 +201,7 @@
}
};

Masonry.prototype._getContainerSize = function() {
proto._getContainerSize = function() {
this.maxY = Math.max.apply( Math, this.colYs );
var size = {
height: this.maxY
Expand All @@ -180,7 +214,7 @@
return size;
};

Masonry.prototype._getContainerFitWidth = function() {
proto._getContainerFitWidth = function() {
var unusedCols = 0;
// count unused columns
var i = this.cols;
Expand All @@ -194,7 +228,7 @@
return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
};

Masonry.prototype.needsResizeLayout = function() {
proto.needsResizeLayout = function() {
var previousWidth = this.containerWidth;
this.getContainerWidth();
return previousWidth != this.containerWidth;
Expand Down
152 changes: 152 additions & 0 deletions sandbox/horizontal-order.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />

<title>horizontal order</title>

<style>
* { box-sizing: border-box; }

body { font-family: sans-serif; }

.grid {
background: #DDD;
max-width: 900px;
margin-bottom: 60px;
}

.grid-item {
float: left;
width: 150px;
height: 150px;
border: 1px solid #333;
color: white;
font-size: 20px;
background: #19F;
counter-increment: grid-item;
}

.grid-item:before {
content: counter(grid-item);
padding: 10px;
}

.grid-item--width2 { width: 300px; }
.grid-item--width3 { width: 450px; }

.grid-item--height2 { height: 200px; }
.grid-item--height3 { height: 250px; }

.grid-item.is-zero { height: 0; border: none; }

.stamp {
border: 1px solid #333;
background: #E21;
position: absolute;
}

.stamp--1 {
width: 300px;
height: 200px;
right: 0;
top: 0;
}
</style>

</head>
<body>

<h1>horizontal order</h1>

<div class="grid grid--1">
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item is-zero"></div>
<div class="grid-item grid-item--width2"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item grid-item--width3"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--width3"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
</div>

<div class="grid grid--2">
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
</div>

<div class="grid grid--3">
<div class="stamp stamp--1"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height2"></div>
<div class="grid-item"></div>
<div class="grid-item grid-item--height3"></div>
<div class="grid-item"></div>
</div>

<script src="../bower_components/ev-emitter/ev-emitter.js"></script>
<script src="../bower_components/get-size/get-size.js"></script>
<script src="../bower_components/desandro-matches-selector/matches-selector.js"></script>
<script src="../bower_components/fizzy-ui-utils/utils.js"></script>
<script src="../bower_components/outlayer/item.js"></script>
<script src="../bower_components/outlayer/outlayer.js"></script>

<script src="../masonry.js"></script>

<script>
new Masonry( '.grid--1', {
itemSelector: '.grid-item',
horizontalOrder: true,
});

new Masonry( '.grid--2', {
itemSelector: '.grid-item',
horizontalOrder: true,
});

new Masonry( '.grid--3', {
itemSelector: '.grid-item',
horizontalOrder: true,
stamp: '.stamp',
})
</script>

</body>
</html>
15 changes: 15 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<script src="unit/zero-column-width.js"></script>
<script src="unit/element-sizing.js"></script>
<script src="unit/pixel-rounding.js"></script>
<script src="unit/horizontal-order.js"></script>

</head>
<body>
Expand Down Expand Up @@ -147,5 +148,19 @@ <h2>Pixel rounding</h2>
<div class="item"></div>
</div>

<h2>Horizontal order</h2>
<div id="horizontal-order" class="container">
<div class="item h3">1</div>
<div class="item h2">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item h3">5</div>
<div class="item h2">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>


</body>
</html>
18 changes: 18 additions & 0 deletions test/unit/horizontal-order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
QUnit.test( 'horizontal order', function( assert ) {

var grid = document.querySelector('#horizontal-order');
var itemElems = grid.querySelectorAll('.item');
new Masonry( grid, {
horizontalOrder: true,
});

// items should match %3 column
for ( var i=0; i < itemElems.length; i++ ) {
var itemElem = itemElems[i];
var col = i % 3;
var left = col * 60 + 'px';
var message = 'item ' + (i+1) + ', column' + (col + 1);
assert.equal( itemElem.style.left, left, message );
}

});

0 comments on commit 389863a

Please sign in to comment.