195 lines
5.9 KiB
JavaScript
195 lines
5.9 KiB
JavaScript
/*jshint browser:true */
|
|
/*globals React, App */
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
/**
|
|
* Displays a noteboard from given notes
|
|
*
|
|
* @prop {notes: array} Array of notes to show
|
|
* @prop {channels: array} Array of configured channels
|
|
* @prop {time: int} Playback time
|
|
* @prop {length: int} Playback length
|
|
* @prop {speed: int} Playback speed
|
|
* @prop {opened: bool} Whether a file is opened
|
|
* @prop {startWheel: function} Called when wheeling starts
|
|
* @prop {setTime: function} Called to change time
|
|
* @prop {open: function} Called to load a file
|
|
* @child Note
|
|
*/
|
|
App.components.create('Note', {
|
|
displayName: 'Board',
|
|
mixins: [React.addons.PureRenderMixin],
|
|
|
|
statics: {
|
|
/**
|
|
* List of black keys
|
|
*/
|
|
black: [22, 25, 27, 30, 32, 34, 37, 39, 42, 44,
|
|
46, 49, 51, 54, 56, 58, 61, 63, 66, 68,
|
|
70, 73, 75, 78, 80, 82, 85, 87, 90, 92,
|
|
94, 97, 99, 102, 104, 106]
|
|
},
|
|
|
|
/**
|
|
* State and props config
|
|
*/
|
|
propTypes: {
|
|
notes: React.PropTypes.array,
|
|
channels: React.PropTypes.array,
|
|
|
|
time: React.PropTypes.number,
|
|
length: React.PropTypes.number,
|
|
speed: React.PropTypes.number,
|
|
opened: React.PropTypes.bool,
|
|
|
|
startWheel: React.PropTypes.func,
|
|
setTime: React.PropTypes.func,
|
|
open: React.PropTypes.func,
|
|
create: React.PropTypes.func
|
|
},
|
|
|
|
getDefaultProps: function () {
|
|
return {
|
|
notes: [],
|
|
channels: [],
|
|
playing: false,
|
|
time: 0,
|
|
length: 0,
|
|
speed: 1,
|
|
opened: false,
|
|
|
|
startWheel: function () {},
|
|
setTime: function () {},
|
|
open: function () {},
|
|
create: function () {}
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Events
|
|
*/
|
|
componentDidMount: function () {
|
|
window.addEventListener('keyup', this.keyUp);
|
|
window.addEventListener('keydown', this.keyDown);
|
|
},
|
|
|
|
componentWillUnmount: function () {
|
|
window.removeEventListener('keyup', this.keyUp);
|
|
window.removeEventListener('keydown', this.keyDown);
|
|
},
|
|
|
|
/* keyboard shortcuts */
|
|
keyDown: function (e) {
|
|
var code = e.keyCode;
|
|
|
|
// top arrow: scroll top
|
|
if (code === 38) {
|
|
this.scroll(-0.5);
|
|
e.preventDefault();
|
|
}
|
|
|
|
// bottom arrow: scroll bottom
|
|
if (code === 40) {
|
|
this.scroll(0.5);
|
|
e.preventDefault();
|
|
}
|
|
},
|
|
|
|
keyUp: function (e) {
|
|
var code = e.keyCode;
|
|
|
|
// home: go to start
|
|
if (code === 36) {
|
|
this.props.setTime(0);
|
|
e.preventDefault();
|
|
}
|
|
|
|
// end: go to end
|
|
if (code === 35) {
|
|
this.props.setTime(this.props.length - 1);
|
|
e.preventDefault();
|
|
}
|
|
},
|
|
|
|
/* scroll noteboard */
|
|
scroll: function (delta) {
|
|
var nextValue = this.props.time - delta;
|
|
|
|
if (nextValue < 0) {
|
|
nextValue = 0;
|
|
}
|
|
|
|
if (nextValue > this.props.length) {
|
|
nextValue = this.props.length;
|
|
}
|
|
|
|
this.props.setTime(nextValue);
|
|
},
|
|
|
|
/* reduce wheel amplitude */
|
|
wheel: function (e) {
|
|
this.props.startWheel();
|
|
this.scroll(e.deltaY * 0.01);
|
|
},
|
|
|
|
/* trigger opening window */
|
|
open: function () {
|
|
this.props.open('', true);
|
|
},
|
|
|
|
/**
|
|
* Render noteboard
|
|
*/
|
|
render: function () {
|
|
var children, notes,
|
|
controls = [], id = -1, className = 'noteboard';
|
|
|
|
if (this.props.opened) {
|
|
className += ' opened';
|
|
|
|
children = App.components.Note.Score({
|
|
key: 'score',
|
|
className: 'score',
|
|
|
|
notes: this.props.notes,
|
|
channels: this.props.channels,
|
|
time: this.props.time
|
|
});
|
|
} else {
|
|
className += ' closed';
|
|
|
|
// add opening controls
|
|
controls.push(React.DOM.button({
|
|
key: 'create',
|
|
className: 'bt primary',
|
|
onClick: this.props.create
|
|
}, 'Composer'));
|
|
|
|
controls.push(React.DOM.button({
|
|
key: 'open',
|
|
className: 'bt primary',
|
|
onClick: this.open
|
|
}, 'Ouvrir un fichier'));
|
|
|
|
children = React.DOM.p({
|
|
key: 'controls',
|
|
className: 'controls'
|
|
}, [
|
|
React.DOM.img({
|
|
key: 'image',
|
|
src: 'images/logos/logo_u128.png',
|
|
alt: 'Aucun fichier ouvert'
|
|
})
|
|
].concat(controls));
|
|
}
|
|
|
|
return React.DOM.div({
|
|
className: className,
|
|
onWheel: this.wheel,
|
|
onClick: this.click
|
|
}, children);
|
|
}
|
|
});
|
|
}()); |