Last active
August 29, 2015 14:02
-
-
Save markmarijnissen/62c810e70f308affd5d6 to your computer and use it in GitHub Desktop.
Famo.us SidepanelLayout
This file contains 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
var View = require('famous/core/View'); | |
var Engine = require('famous/core/Engine'); | |
var Modifier = require('famous/core/Modifier'); | |
var Transform = require('famous/core/Transform'); | |
var StateModifier = require('famous/modifiers/StateModifier'); | |
var Easing = require('famous/transitions/Easing'); | |
var Transitionable = require('famous/transitions/Transitionable'); | |
var GenericSync = require('famous/inputs/GenericSync'); | |
/** | |
A typical sidepanel that swipes from the left. | |
emits: | |
'sidepanel': true (opened) | false (closed) | |
'opening' | |
'closing' | |
listens to & public API: | |
open(<boolean> value): true (open) | false (close) | null (toggle) | |
**/ | |
function SidepanelLayout(options) { | |
View.apply(this, arguments); | |
Engine.emit('created',this); | |
// show sidepanel or not... | |
this._busy = false; | |
this.opened = false; | |
// position content X | |
this.contentPos = new Transitionable(0); | |
window.contentPos = this.contentPos; | |
// Add sidepanel and content | |
if(!!options.sidepanel) { | |
_addSidepanel.call(this,options.sidepanel); | |
} else { | |
Engine.emit('error',{target:this,message:'No sidepanel!'}); | |
} | |
if(!!options.content) { | |
_addContent.call(this,options.content); | |
} else { | |
Engine.emit('error',{target:this,message:'No content!'}); | |
} | |
// handle Swipe | |
_handleSwipe.call(this); | |
// handle events | |
this._eventInput.on('open',this.open); | |
} | |
SidepanelLayout.prototype = Object.create(View.prototype); | |
SidepanelLayout.prototype.constructor = SidepanelLayout; | |
SidepanelLayout.DEFAULT_OPTIONS = { | |
sidepanel: null, //RenderNode for sidepanel | |
content: null, //Rendernode for content | |
background: null, | |
maxPos: 1e4, | |
width: 225, //How much should content move? | |
transition: { | |
duration: 300, | |
curve: 'easeOut' | |
}, | |
posThreshold: 138, //When should sidepanel open? | |
velThreshold: 0.75 //When should sidepanel open? | |
}; | |
SidepanelLayout.prototype.open = function(value) { | |
if(value !== false && value !== true) value = !this.opened; | |
if(value !== this.opened) { | |
if(value) { | |
_open.call(this); | |
} else { | |
_close.call(this); | |
} | |
} | |
}; | |
function _open() { | |
this._eventOutput.emit('opening'); | |
this._busy = true; | |
this.contentPos.set(this.options.width, this.options.transition, function() { | |
this.opened = true; | |
this._busy = false; | |
this._eventOutput.emit('sidepanel',true); | |
}.bind(this)); | |
} | |
function _close() { | |
this._eventOutput.emit('closing'); | |
this._busy = true; | |
this.contentPos.set(0, this.options.transition, function() { | |
this.opened = false; | |
this._busy = false; | |
this._eventOutput.emit('sidepanel',false); | |
}.bind(this)); | |
} | |
function _handleSwipe() { | |
var sync = new GenericSync( | |
['mouse', 'touch'], | |
{direction : GenericSync.DIRECTION_X} | |
); | |
// Listen to touch events from CONTENT to swipe to Sidepanel! | |
this.content.pipe(sync); | |
sync.on('update', function(data) { | |
if(this._busy) return; | |
var currentPosition = this.contentPos.get(); | |
var position = Math.max(0, currentPosition + data.delta); | |
position = Math.min(this.options.maxPos,position); | |
this.contentPos.set(position); | |
}.bind(this)); | |
sync.on('end', (function(data) { | |
if(this._busy) return; | |
var velocity = data.velocity; | |
var position = this.contentPos.get(); | |
if(this.contentPos.get() > this.options.posThreshold) { | |
if(velocity < -this.options.velThreshold) { | |
_close.call(this); | |
} else { | |
_open.call(this); | |
} | |
} else { | |
if(velocity > this.options.velThreshold) { | |
_open.call(this); | |
} else { | |
_close.call(this); | |
} | |
} | |
}).bind(this)); | |
} | |
function _addContent(content) { | |
this.content = content; | |
this.contentMod = new Modifier({ | |
transform: function() { | |
return Transform.translate(this.contentPos.get(), 0, 0); | |
}.bind(this) | |
}); | |
this.add(this.contentMod).add(content); | |
} | |
function _addSidepanel(sidepanel) { | |
this.sidepanel = sidepanel; | |
this.sidepanelMod = new StateModifier({ | |
transform: Transform.translate(0,0,-1000), | |
size: [undefined,undefined] | |
}); | |
this.add(this.sidepanelMod).add(sidepanel); | |
} | |
module.exports = SidepanelLayout; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment