Move layout positioning logic to its own file.

pull/111/head
Glen Cheney 8 years ago
parent fd330bd800
commit 7aa6461b4d

@ -7,14 +7,11 @@
// Define globals exposed by modern browsers.
"browser": true,
// Define globals exposed by jQuery.
"jquery": false,
// Define globals exposed by Node.js.
"node": true,
// Allow ES6.
"esnext": true,
"esversion": 6,
/*
* ENFORCING OPTIONS

279
dist/shuffle.js vendored

@ -98,6 +98,8 @@ return /******/ (function(modules) { // webpackBootstrap
var _onTransitionEnd = __webpack_require__(13);
var _layout2 = __webpack_require__(14);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@ -110,10 +112,6 @@ return /******/ (function(modules) { // webpackBootstrap
return Math.max.apply(Math, array);
}
function arrayMin(array) {
return Math.min.apply(Math, array);
}
function arrayIncludes(array, obj) {
if (arguments.length === 2) {
return arrayIncludes(array)(obj);
@ -718,123 +716,14 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: '_getItemPosition',
value: function _getItemPosition(itemSize) {
var columnSpan = this._getColumnSpan(itemSize.width, this.colWidth, this.cols);
var setY = this._getColumnSet(columnSpan, this.cols);
// Finds the index of the smallest number in the set.
var shortColumnIndex = this._getShortColumn(setY, this.options.buffer);
// Position the item
var point = new _point2.default(Math.round(this.colWidth * shortColumnIndex), Math.round(setY[shortColumnIndex]));
// Update the columns array with the new values for each column.
// e.g. before the update the columns could be [250, 0, 0, 0] for an item
// which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].
var setHeight = setY[shortColumnIndex] + itemSize.height;
var setSpan = this.cols + 1 - setY.length;
for (var i = 0; i < setSpan; i++) {
this.positions[shortColumnIndex + i] = setHeight;
}
return point;
}
/**
* Determine the number of columns an items spans.
* @param {number} itemWidth Width of the item.
* @param {number} columnWidth Width of the column (includes gutter).
* @param {number} columns Total number of columns
* @return {number}
* @private
*/
}, {
key: '_getColumnSpan',
value: function _getColumnSpan(itemWidth, columnWidth, columns) {
var columnSpan = itemWidth / columnWidth;
// If the difference between the rounded column span number and the
// calculated column span number is really small, round the number to
// make it fit.
if (Math.abs(Math.round(columnSpan) - columnSpan) < this.options.columnThreshold) {
// e.g. columnSpan = 4.0089945390298745
columnSpan = Math.round(columnSpan);
}
// Ensure the column span is not more than the amount of columns in the whole layout.
return Math.min(Math.ceil(columnSpan), columns);
}
/**
* Retrieves the column set to use for placement.
* @param {number} columnSpan The number of columns this current item spans.
* @param {number} columns The total columns in the grid.
* @return {Array.<number>} An array of numbers represeting the column set.
* @private
*/
}, {
key: '_getColumnSet',
value: function _getColumnSet(columnSpan, columns) {
// The item spans only one column.
if (columnSpan === 1) {
return this.positions;
// The item spans more than one column, figure out how many different
// places it could fit horizontally.
// The group count is the number of places within the positions this block
// could fit, ignoring the current positions of items.
// Imagine a 2 column brick as the second item in a 4 column grid with
// 10px height each. Find the places it would fit:
// [10, 0, 0, 0]
// | | |
// * * *
//
// Then take the places which fit and get the bigger of the two:
// max([10, 0]), max([0, 0]), max([0, 0]) = [10, 0, 0]
//
// Next, find the first smallest number (the short column).
// [10, 0, 0]
// |
// *
//
// And that's where it should be placed!
} else {
var groupCount = columns + 1 - columnSpan;
var groupY = [];
// For how many possible positions for this item there are.
for (var i = 0; i < groupCount; i++) {
// Find the bigger value for each place it could fit.
groupY[i] = arrayMax(this.positions.slice(i, i + columnSpan));
}
return groupY;
}
}
/**
* Find index of short column, the first from the left where this item will go.
*
* @param {Array.<number>} positions The array to search for the smallest number.
* @param {number} buffer Optional buffer which is very useful when the height
* is a percentage of the width.
* @return {number} Index of the short column.
* @private
*/
}, {
key: '_getShortColumn',
value: function _getShortColumn(positions, buffer) {
var minPosition = arrayMin(positions);
for (var i = 0, len = positions.length; i < len; i++) {
if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {
return i;
}
}
return 0;
return (0, _layout2.getItemPosition)({
itemSize: itemSize,
positions: this.positions,
gridSize: this.colWidth,
total: this.cols,
threshold: this.options.columnThreshold,
buffer: this.options.buffer
});
}
/**
@ -2102,6 +1991,154 @@ return /******/ (function(modules) { // webpackBootstrap
return false;
}
/***/ },
/* 14 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getItemPosition = getItemPosition;
var _point = __webpack_require__(6);
var _point2 = _interopRequireDefault(_point);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function arrayMax(array) {
return Math.max.apply(Math, array);
}
function arrayMin(array) {
return Math.min.apply(Math, array);
}
/**
* Determine the location of the next item, based on its size.
* @param {Object} itemSize Object with width and height.
* @param {Array.<number>} positions Positions of the other current items.
* @param {number} gridSize The column width or row height.
* @param {number} total The total number of columns or rows.
* @param {number} threshold Buffer value for the column to fit.
* @param {number} buffer Vertical buffer for the height of items.
* @return {Point}
*/
function getItemPosition(_ref) {
var itemSize = _ref.itemSize;
var positions = _ref.positions;
var gridSize = _ref.gridSize;
var total = _ref.total;
var threshold = _ref.threshold;
var buffer = _ref.buffer;
var span = getColumnSpan(itemSize.width, gridSize, total, threshold);
var setY = getAvailablePositions(positions, span, total);
var shortColumnIndex = getShortColumn(setY, buffer);
// Position the item
var point = new _point2.default(Math.round(gridSize * shortColumnIndex), Math.round(setY[shortColumnIndex]));
// Update the columns array with the new values for each column.
// e.g. before the update the columns could be [250, 0, 0, 0] for an item
// which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].
var setHeight = setY[shortColumnIndex] + itemSize.height;
for (var i = 0; i < span; i++) {
positions[shortColumnIndex + i] = setHeight;
}
return point;
}
/**
* Determine the number of columns an items spans.
* @param {number} itemWidth Width of the item.
* @param {number} columnWidth Width of the column (includes gutter).
* @param {number} columns Total number of columns
* @param {number} threshold A buffer value for the size of the column to fit.
* @return {number}
*/
function getColumnSpan(itemWidth, columnWidth, columns, threshold) {
var columnSpan = itemWidth / columnWidth;
// If the difference between the rounded column span number and the
// calculated column span number is really small, round the number to
// make it fit.
if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {
// e.g. columnSpan = 4.0089945390298745
columnSpan = Math.round(columnSpan);
}
// Ensure the column span is not more than the amount of columns in the whole layout.
return Math.min(Math.ceil(columnSpan), columns);
}
/**
* Retrieves the column set to use for placement.
* @param {number} columnSpan The number of columns this current item spans.
* @param {number} columns The total columns in the grid.
* @return {Array.<number>} An array of numbers represeting the column set.
*/
function getAvailablePositions(positions, columnSpan, columns) {
// The item spans only one column.
if (columnSpan === 1) {
return positions;
}
// The item spans more than one column, figure out how many different
// places it could fit horizontally.
// The group count is the number of places within the positions this block
// could fit, ignoring the current positions of items.
// Imagine a 2 column brick as the second item in a 4 column grid with
// 10px height each. Find the places it would fit:
// [20, 10, 10, 0]
// | | |
// * * *
//
// Then take the places which fit and get the bigger of the two:
// max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0]
//
// Next, find the first smallest number (the short column).
// [20, 10, 0]
// |
// *
//
// And that's where it should be placed!
//
// Another example where the second column's item extends past the first:
// [10, 20, 10, 0] => [20, 20, 10] => 10
var available = [];
// For how many possible positions for this item there are.
for (var i = 0; i <= columns - columnSpan; i++) {
// Find the bigger value for each place it could fit.
available.push(arrayMax(positions.slice(i, i + columnSpan)));
}
return available;
}
/**
* Find index of short column, the first from the left where this item will go.
*
* @param {Array.<number>} positions The array to search for the smallest number.
* @param {number} buffer Optional buffer which is very useful when the height
* is a percentage of the width.
* @return {number} Index of the short column.
*/
function getShortColumn(positions, buffer) {
var minPosition = arrayMin(positions);
for (var i = 0, len = positions.length; i < len; i++) {
if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {
return i;
}
}
return 0;
}
/***/ }
/******/ ])
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,129 @@
'use strict';
import Point from './point';
function arrayMax(array) {
return Math.max.apply(Math, array);
}
function arrayMin(array) {
return Math.min.apply(Math, array);
}
/**
* Determine the location of the next item, based on its size.
* @param {Object} itemSize Object with width and height.
* @param {Array.<number>} positions Positions of the other current items.
* @param {number} gridSize The column width or row height.
* @param {number} total The total number of columns or rows.
* @param {number} threshold Buffer value for the column to fit.
* @param {number} buffer Vertical buffer for the height of items.
* @return {Point}
*/
export function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {
var span = getColumnSpan(itemSize.width, gridSize, total, threshold);
var setY = getAvailablePositions(positions, span, total);
var shortColumnIndex = getShortColumn(setY, buffer);
// Position the item
var point = new Point(
Math.round(gridSize * shortColumnIndex),
Math.round(setY[shortColumnIndex]));
// Update the columns array with the new values for each column.
// e.g. before the update the columns could be [250, 0, 0, 0] for an item
// which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].
var setHeight = setY[shortColumnIndex] + itemSize.height;
for (var i = 0; i < span; i++) {
positions[shortColumnIndex + i] = setHeight;
}
return point;
}
/**
* Determine the number of columns an items spans.
* @param {number} itemWidth Width of the item.
* @param {number} columnWidth Width of the column (includes gutter).
* @param {number} columns Total number of columns
* @param {number} threshold A buffer value for the size of the column to fit.
* @return {number}
*/
function getColumnSpan(itemWidth, columnWidth, columns, threshold) {
var columnSpan = itemWidth / columnWidth;
// If the difference between the rounded column span number and the
// calculated column span number is really small, round the number to
// make it fit.
if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {
// e.g. columnSpan = 4.0089945390298745
columnSpan = Math.round(columnSpan);
}
// Ensure the column span is not more than the amount of columns in the whole layout.
return Math.min(Math.ceil(columnSpan), columns);
}
/**
* Retrieves the column set to use for placement.
* @param {number} columnSpan The number of columns this current item spans.
* @param {number} columns The total columns in the grid.
* @return {Array.<number>} An array of numbers represeting the column set.
*/
function getAvailablePositions(positions, columnSpan, columns) {
// The item spans only one column.
if (columnSpan === 1) {
return positions;
}
// The item spans more than one column, figure out how many different
// places it could fit horizontally.
// The group count is the number of places within the positions this block
// could fit, ignoring the current positions of items.
// Imagine a 2 column brick as the second item in a 4 column grid with
// 10px height each. Find the places it would fit:
// [20, 10, 10, 0]
// | | |
// * * *
//
// Then take the places which fit and get the bigger of the two:
// max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0]
//
// Next, find the first smallest number (the short column).
// [20, 10, 0]
// |
// *
//
// And that's where it should be placed!
//
// Another example where the second column's item extends past the first:
// [10, 20, 10, 0] => [20, 20, 10] => 10
var available = [];
// For how many possible positions for this item there are.
for (var i = 0; i <= columns - columnSpan; i++) {
// Find the bigger value for each place it could fit.
available.push(arrayMax(positions.slice(i, i + columnSpan)));
}
return available;
}
/**
* Find index of short column, the first from the left where this item will go.
*
* @param {Array.<number>} positions The array to search for the smallest number.
* @param {number} buffer Optional buffer which is very useful when the height
* is a percentage of the width.
* @return {number} Index of the short column.
*/
function getShortColumn(positions, buffer) {
var minPosition = arrayMin(positions);
for (var i = 0, len = positions.length; i < len; i++) {
if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {
return i;
}
}
return 0;
}

@ -11,6 +11,7 @@ import Classes from './classes';
import getNumberStyle from './get-number-style';
import sorter from './sorter';
import { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';
import { getItemPosition } from './layout';
function toArray(arrayLike) {
return Array.prototype.slice.call(arrayLike);
@ -20,10 +21,6 @@ function arrayMax(array) {
return Math.max.apply(Math, array);
}
function arrayMin(array) {
return Math.min.apply(Math, array);
}
function arrayIncludes(array, obj) {
if (arguments.length === 2) {
return arrayIncludes(array)(obj);
@ -532,116 +529,14 @@ class Shuffle {
* @private
*/
_getItemPosition(itemSize) {
var columnSpan = this._getColumnSpan(itemSize.width, this.colWidth, this.cols);
var setY = this._getColumnSet(columnSpan, this.cols);
// Finds the index of the smallest number in the set.
var shortColumnIndex = this._getShortColumn(setY, this.options.buffer);
// Position the item
var point = new Point(
Math.round(this.colWidth * shortColumnIndex),
Math.round(setY[shortColumnIndex]));
// Update the columns array with the new values for each column.
// e.g. before the update the columns could be [250, 0, 0, 0] for an item
// which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].
var setHeight = setY[shortColumnIndex] + itemSize.height;
var setSpan = this.cols + 1 - setY.length;
for (var i = 0; i < setSpan; i++) {
this.positions[shortColumnIndex + i] = setHeight;
}
return point;
}
/**
* Determine the number of columns an items spans.
* @param {number} itemWidth Width of the item.
* @param {number} columnWidth Width of the column (includes gutter).
* @param {number} columns Total number of columns
* @return {number}
* @private
*/
_getColumnSpan(itemWidth, columnWidth, columns) {
var columnSpan = itemWidth / columnWidth;
// If the difference between the rounded column span number and the
// calculated column span number is really small, round the number to
// make it fit.
if (Math.abs(Math.round(columnSpan) - columnSpan) < this.options.columnThreshold) {
// e.g. columnSpan = 4.0089945390298745
columnSpan = Math.round(columnSpan);
}
// Ensure the column span is not more than the amount of columns in the whole layout.
return Math.min(Math.ceil(columnSpan), columns);
}
/**
* Retrieves the column set to use for placement.
* @param {number} columnSpan The number of columns this current item spans.
* @param {number} columns The total columns in the grid.
* @return {Array.<number>} An array of numbers represeting the column set.
* @private
*/
_getColumnSet(columnSpan, columns) {
// The item spans only one column.
if (columnSpan === 1) {
return this.positions;
// The item spans more than one column, figure out how many different
// places it could fit horizontally.
// The group count is the number of places within the positions this block
// could fit, ignoring the current positions of items.
// Imagine a 2 column brick as the second item in a 4 column grid with
// 10px height each. Find the places it would fit:
// [10, 0, 0, 0]
// | | |
// * * *
//
// Then take the places which fit and get the bigger of the two:
// max([10, 0]), max([0, 0]), max([0, 0]) = [10, 0, 0]
//
// Next, find the first smallest number (the short column).
// [10, 0, 0]
// |
// *
//
// And that's where it should be placed!
} else {
var groupCount = columns + 1 - columnSpan;
var groupY = [];
// For how many possible positions for this item there are.
for (var i = 0; i < groupCount; i++) {
// Find the bigger value for each place it could fit.
groupY[i] = arrayMax(this.positions.slice(i, i + columnSpan));
}
return groupY;
}
}
/**
* Find index of short column, the first from the left where this item will go.
*
* @param {Array.<number>} positions The array to search for the smallest number.
* @param {number} buffer Optional buffer which is very useful when the height
* is a percentage of the width.
* @return {number} Index of the short column.
* @private
*/
_getShortColumn(positions, buffer) {
var minPosition = arrayMin(positions);
for (var i = 0, len = positions.length; i < len; i++) {
if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {
return i;
}
}
return 0;
return getItemPosition({
itemSize,
positions: this.positions,
gridSize: this.colWidth,
total: this.cols,
threshold: this.options.columnThreshold,
buffer: this.options.buffer,
});
}
/**

Loading…
Cancel
Save