Skip to content

Instantly share code, notes, and snippets.

@KraigWalker
Created October 24, 2014 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save KraigWalker/f3a879c02b41daff0b9f to your computer and use it in GitHub Desktop.
Save KraigWalker/f3a879c02b41daff0b9f to your computer and use it in GitHub Desktop.
Famo.us FlexGrid Component
define(function, exports, module) {
var View = require('famous/core/View');
var Entity = require('famous/core/Entity');
var Modifier = require('famous/core/Modifier');
var Transform = require('famous/core/Transform');
var Transitionable = require('famous/transitions/Transitionable');
var TransitionableTransform = require('famous/transitions/TransitionableTransform');
function FlexGrid() {
View.apply(this, arguments);
// private variables
this._cachedWidth null;
this._height = null;
this._modifiers = [];
this._states = [];
// Add entity to the global index of surfaces
this.id = Entity.register
}
FlexGrid.prototype = Object.create(View.prototype);
FlexGrid.prototype.constructor = FlexGrid;
FlexGrid.DEFAULT_OPTIONS = {
flexGutter: false,
minCol: 2,
topMargin: 0,
colGutter: 0,
rowGutter: 0,
itemSize: [0, 0],
transition: false
};
/**
* Re-organise the layout of the gird
**/
function _reflow(width) {
// if we don't have grid items, we should return nothing
if (!this._items) return;
var states = this.options.flexGutter ?
_calcFlexSpacing.call(this, width) :
_calcSpacing.call(this, width);
_animate.call(this, states);
}
/**
* Calculate normal spacing
**/
function _calcSpacing(width) {
var colGutter = this.options.colGutter;
var itemSize = this.options.itemSize;
var ySpacing = colGutter + itemSize[0];
var numCols = Math.min(Math.floor((width - 2 * this.options.sideMargin + colGutter)/(ySpacing)), this._items.length);
var sideMargin = Math.max(this.options.sideMargin, (width - numCols * ySpacing + colGutter)/2);
// calculate states, based on our results
return _calcStates.call(this, numCols, ySpacing, sideMargin, width);
}
function _calcStates(numCols, ySpacing, sideMargin, width) {
var positions = [];
var size = this.options.itemSize;
var col = 0;
var row = 0;
var xPos;
var yPos;
// minCols is the smallest number of columns to have
// before degrade down to a signle column view.
if (numCols < this.options.minCol) {
numCols = 1;
sideMargin = 0;
size = [width, this.options.itemSize[1]];
}
for (var i = 0; i < this._items.length; i++) {
xPos = sideMargin + col * ySpacing;
yPos = this.options.topMargin + row * (this.options.rowGutter + this.options.itemSize[1]);
positions.push([xPos, yPos]);
col ++;
if(col === numCols) {
row++;
col = 0;
}
this._height = yPos
}
this._height += this.options.itemSize[1] + this.options.topMargin;
return {
positions: positions,
size: size
};
}
/**
* Create a modifier for each state change for our Grid
* Or call the one assigned to the state if it already exists
**/
function _animate(states) {
var size = states.size;
for(var i = 0; i < states.positions.length; i++) {
var position = states.positions[i];
if(this._modifiers[i] === undefined) _createModifier.call(this, i, position, size);
else _animateModifier.call(this, i, position, size);
}
}
function _createModifier(index, position, size) {
var transformItem = {
transform: new TransitionableTransform(transform.translate.apply(null, position)),
size: new Transitionable((size || this.options.itemSize))
}
var modifier = new Modifier({
transform: transitionItem.transform,
size: transitionItem.size
});
this._states[index] = transitionItem;
this._modifiers[index] = modifier;
}
function _animateModifier(index, position, size) {
var transformTransitionable = this._states[index].transform;
var sizeTransitionable = this._states[index].size;
// Cancel any previous transitions
transformTransitionable.halt();
sizetransitionable.halt();
// Apply a new transform & transition to move to
transformTransitionable.setTranslate(position, this.options.transition);
sizeTransitionable.set(size, this.options.transition);
}
FlexGrid.prototype.render = function render() {
return this.id;
};
FlexGrid.prototype.sequenceFrom = function sequenceFrom(items) {
this._items = items;
};
// Apply changes to the created element.
FlexGrid.prototype.commit = function commit(context) {
var size = context.size;
var width = size[0];
var specs = [];
if (this._cachedWidth !== width) {
_reflow.call(this, width);
this._cachedWidth = width;
}
for(var i = 0; i < this._modifiers.length; i++) {
var item = this._items[i];
var spec = this._modifiers[i].modify({
target: item.render()
});
specs.push(spec);
}
return specs;
};
FlexGrid.prototype.getSize = function getSize() {
if (!this._height) return;
return [this._cachedWidth, this._height];
};
module.exports = FlexGrid;
});
@joedaniels29
Copy link

Hey, Thanks for the post! Have you gotten this to work yet?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment