Created
October 24, 2014 12:45
-
-
Save KraigWalker/f3a879c02b41daff0b9f to your computer and use it in GitHub Desktop.
Famo.us FlexGrid Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey, Thanks for the post! Have you gotten this to work yet?