/**
* @module stb/stack
* @author Stanislav Kalashnik <sk@infomir.eu>
* @license GNU GENERAL PUBLIC LICENSE Version 3
*/
'use strict';
var Emitter = require('./emitter');
/**
* Simple observable stack implementation.
*
* @constructor
* @extends Emitter
*
* @param {Object} [data={}] init attributes
*
* @example
* var stack1 = new Stack(),
* stack2 = new Stack([1, 2, 3]);
*/
function Stack ( data ) {
/**
* Current top stack element.
*
* @readonly
* @type {Object}
*/
this.current = null;
/**
* List of all stack elements.
*
* @readonly
* @type {Object[]}
*/
this.data = data || [];
if ( DEBUG ) {
if ( !Array.isArray(this.data) ) { throw 'wrong data type'; }
}
// parent init
Emitter.call(this);
}
// inheritance
Stack.prototype = Object.create(Emitter.prototype);
Stack.prototype.constructor = Stack;
/**
* Add new element to the stack event.
*
* @event module:stb/stack~Stack#push
*
* @type {Object}
* @property {*} prev previous top element
* @property {*} curr current top element
*/
/**
* Add new element to the stack.
*
* @param {Object} data new element
*
* @fires module:stb/stack~Stack#push
*
* @example
* stack.push(123);
* stack.push('abc');
* stack.push({foo: 'bar'});
*/
Stack.prototype.push = function ( data ) {
var prev = this.current;
// apply
this.data.push(data);
// link
this.current = data;
// there are some listeners
if ( this.events['push'] !== undefined ) {
// notify listeners
this.emit('push', {prev: prev, curr: this.current});
}
};
/**
* Remove current top element from the stack event.
*
* @event module:stb/stack~Stack#pop
*
* @type {Object}
* @property {*} prev previous top element
* @property {*} curr current top element
*/
/**
* Remove current top element from the stack.
*
* @return {*} removed element
*
* @fires module:stb/stack~Stack#pop
*
* @example
* var item = stack.pop();
*/
Stack.prototype.pop = function () {
var prev = null;
// there are some pages in the stack
if ( this.data.length > 0 ) {
// remove the current
prev = this.data.pop();
// set top element
this.current = this.data.length > 0 ? this.data[this.data.length - 1] : null;
// there are some listeners
if ( this.events['pop'] !== undefined ) {
// notify listeners
this.emit('pop', {prev: prev, curr: this.current});
}
}
return prev;
};
// public
module.exports = Stack;