maniajs
Version:
ManiaPlanet (Dedicated) Server Controller.
470 lines (382 loc) • 12.9 kB
JavaScript
/**
* List View
*/
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _events = require('events');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* List View
*
* @class ListView
* @type {ListView}
*
* @property {App} app
* @property {string} title Title of list.
* @property {Player} player Player Login (single login!).
* @property {[{name: {string}, field: {string}, width: {number}, [level]: {number}, [event]: {string}}]} columns Columns to define.
* @property {[{}]} data Array with objects. Give a custom manialink with the 'custom' key. This will be injected into the row!
*/
var ListView = function (_EventEmitter) {
_inherits(ListView, _EventEmitter);
/**
* Construct List View
* @param {App} app
* @param {string} title
* @param {Player} player
* @param {[{name: {string}, field: {string}, width: {number}, [level]: {number}, [event]: {string}}]} columns Columns to define.
* @param {[{}]} data Array with objects. Give a custom manialink with the 'custom' key. This will be injected into the row!
*/
function ListView(app, title, player, columns, data) {
_classCallCheck(this, ListView);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ListView).call(this));
_this.setMaxListeners(0);
_this.app = app;
_this.title = title;
_this.player = player;
_this.columns = columns;
_this.data = data;
_this.ui = _this.app.uiFacade.build(_this.app, 'list', 2, '|' + _this.player.login);
_this.range = {
start: 0,
stop: 15
};
return _this;
}
/**
* Parse Data and Columns and Prepare the UI. Must be called before the display or update command!
*/
_createClass(ListView, [{
key: 'parse',
value: function parse() {
var _this2 = this;
this.width = 210;
this.totalWidth = 0;
this.page = 0; // Current Page NR.
this.numRows = this.data.length; // Total Rows data
this.numCols = this.columns.length; // Total Columns.
this.header = []; // Contains Headers, ready for view.
this.body = []; // Contains Body, ready for view.
this.events = []; // Possible events, we use a | to separate from the index of the record!
this.send = {}; // Will be the data to send to the view.
// Create header for player.
var left = 0; // Current left position
this.columns.forEach(function (raw) {
if (raw.hasOwnProperty('level') && _this2.player.level < raw.level) {
return; // Skip, the player has no rights for this col!
}
if (raw.hasOwnProperty('event')) {
_this2.events.push(raw.event);
}
if (raw.hasOwnProperty('sort') && typeof raw.sort === 'function') {
raw.sortEvent = 'action="_sort|' + _this2.header.length + '"';
if (_this2.events.indexOf('_sort') === -1) {
_this2.events.push('_sort');
}
} else {
raw.sort = null;
raw.sortEvent = '';
}
_this2.totalWidth += raw.width;
raw.colStyle = raw.sort ? 'TextRaceChat' : '';
raw.left = left + 2;
left += raw.width;
raw.sepLeft = left; // TODO: ? separator?
_this2.header.push(raw);
});
// Update number of cols.
this.numCols = this.header.length;
if (this.totalWidth > this.width) {
throw new Error('Total Column Width is greater than the maximum of ' + width + '!');
}
// Current page, items.
var pageItems = 0;
// Make body!
this.data.forEach(function (rawRow, rowIdx) {
// Current left position
var left = 0;
// Reset page items if on new page.
if (pageItems === 15) {
pageItems = 0;
}
// Row data.
var row = { data: [], top: pageItems * 6, even: pageItems % 2 === 1 };
_this2.header.forEach(function (rawCol, colIdx) {
if (rawCol.field && !rawRow.hasOwnProperty(rawCol.field)) {
_this2.app.log.info('List View: Data has no field as defined in column! Will be skipped!');
return;
}
var col = {};
// Text/ManiaLink/button
col.text = '';
var text = rawRow.hasOwnProperty(rawCol.field) ? rawRow[rawCol.field] : '';
if (rawCol.hasOwnProperty('custom') && rawCol.custom) {
// Custom MANIALINK!;
col.text = false;
col.button = false;
col.custom = text;
} else if (rawCol.hasOwnProperty('button') && rawCol.button) {
col.custom = false;
col.text = false;
col.button = true;
col.style = rawCol.style || 'Icons64x64_1';
col.substyle = rawCol.substyle || 'LvlRed';
} else {
col.text = text;
col.style = rawCol.style || '';
col.custom = false;
col.button = false;
}
// Event
if (rawCol.hasOwnProperty('event') && rawCol.event) {
col.event = 'action="' + rawCol.event + '|' + rowIdx + '"';
if (col.style === '') {
col.style = 'TextCardSmallScores2';
}
} else {
col.event = '';
}
// Width and height
col.width = rawCol.width;
col.height = 5;
// Position
col.left = left + 2;
col.top = pageItems * 6;
left += col.width;
// Add to row
row.data.push(col);
});
// Add to body
_this2.body.push(row);
// Page Items
pageItems++;
});
// Calculate total pages.
this.numRows = this.body.length;
this.pages = Math.ceil(this.numRows / 15);
// Prepare the UI.
this.prepare();
}
/**
* Prepare the UI.
*/
}, {
key: 'prepare',
value: function prepare() {
var _this3 = this;
this.ui.timeout = 0;
this.ui.hideClick = false;
this.ui.global({
title: this.title,
header: this.header,
body: this.body.slice(this.range.start, this.range.stop),
page: this.page + 1,
pages: this.pages,
total: this.numRows,
range: {
start: this.range.start + 1,
stop: this.range.stop
},
next: this.page + 1 < this.pages,
prev: this.page > 0
});
this.ui.player(this.player.login);
// Callbacks on every event that we have.
this.events.forEach(function (event) {
_this3.ui.on(event, function (params) {
_this3.handle(event, params);
});
});
// View Handlers.
this.ui.on('close', function (params) {
return _this3.handleClose(params.login);
});
this.on('_sort', function (params) {
return _this3.handleSort(params.login, params.idx);
});
this.ui.on('first', function (params) {
return _this3.handleFirst(params.login);
});
this.ui.on('prev_10', function (params) {
return _this3.handlePrev(params.login, 10);
});
this.ui.on('prev', function (params) {
return _this3.handlePrev(params.login, 1);
});
this.ui.on('next', function (params) {
return _this3.handleNext(params.login, 1);
});
this.ui.on('next_10', function (params) {
return _this3.handleNext(params.login, 10);
});
this.ui.on('last', function (params) {
return _this3.handleLast(params.login);
});
}
/**
* Handle Sorting Action
* @todo:
*/
}, {
key: 'handleSort',
value: function handleSort(login, column) {
if (this.header.length <= column) {
return;
}
var col = this.header[column];
this.body.sort(function (a, b) {
return col.sort(a.data[column].text, b.data[column].text);
});
this.handleFirst(login);
}
/**
* Handle Close Button.
*/
}, {
key: 'handleClose',
value: function handleClose(login) {
if (this.player.login === login) {
this.close();
this.emit('close', login);
}
}
}, {
key: 'handleLast',
value: function handleLast(login) {
if (this.player.login !== login) {
return;
}
this.page = this.pages - 1;
this.range.start = 15 * this.pages - 15;
this.range.stop = 15 * this.pages;
this._pageUpdate();
this.emit('last', login);
}
}, {
key: 'handleFirst',
value: function handleFirst(login) {
if (this.player.login !== login) {
return;
}
this.page = 0;
this.range.start = 0;
this.range.stop = 15;
this._pageUpdate();
this.emit('first', login);
}
}, {
key: 'handleNext',
value: function handleNext(login, skip) {
if (this.player.login !== login) {
return;
}
if (this.page + skip > this.pages) {
return false;
}
this.range.start += 15 * skip;
this.range.stop += 15 * skip;
this.page += skip;
this._pageUpdate();
this.emit('next', login);
}
}, {
key: 'handlePrev',
value: function handlePrev(login, skip) {
if (this.player.login !== login) {
return;
}
if (this.page - skip < 0) {
return false;
}
this.range.start -= 15 * skip;
this.range.stop -= 15 * skip;
this.page -= skip;
this._pageUpdate();
this.emit('prev', login);
}
/**
* Update Page, send new slice to client!
* @returns {Promise}
* @private
*/
}, {
key: '_pageUpdate',
value: function _pageUpdate() {
// Change page, change the slice!
return this.ui.global({
title: this.title,
header: this.header,
body: this.body.slice(this.range.start, this.range.stop),
page: this.page + 1,
pages: this.pages,
total: this.numRows,
range: {
start: this.range.start + 1,
stop: this.range.stop
},
next: this.page + 1 < this.pages,
prev: this.page > 0
}).update();
}
/**
* List Event Handler.
*
* @param {string} event
* @param {{}} params
*/
}, {
key: 'handle',
value: function handle(event, params) {
if (params.answer.indexOf('|') === -1) {
return false;
}
if (params.login !== this.player.login) {
return false;
}
// Parse
var idx = parseInt(params.answer.substr(params.answer.indexOf('|') + 1));
if (!isNaN(idx)) {
var row = this.data[idx] || false;
// Emit
this.emit(event, { login: params.login, idx: idx, entry: row });
}
}
/**
* Start displaying to player.
*
* @returns {Promise}
*/
}, {
key: 'display',
value: function display() {
return this.ui.display();
}
/**
* Stop displaying to player.
*
* @returns {Promise}
*/
}, {
key: 'close',
value: function close() {
// Send empty manialink to the player with the same ID.
return this.ui.destroy();
}
/**
* Get UI instance.
* @returns {InterfaceBuilder}
*/
}, {
key: 'toUI',
value: function toUI() {
return this.ui;
}
}]);
return ListView;
}(_events.EventEmitter);
exports.default = ListView;