+(function (global, factory) {
if (typeof exports === 'undefined') {
factory(global.webduino || {});
} else {
module.exports = factory;
}
}(this, function (scope) {
'use strict';
var PinEvent = scope.PinEvent,
Pin = scope.Pin,
Module = scope.Module;
var ButtonEvent = {
/**
* Fires when a button is pressed.
*
* @event ButtonEvent.PRESS
*/
PRESS: 'pressed',
/**
* Fires when a button is released.
*
* @event ButtonEvent.RELEASE
*/
RELEASE: 'released',
/**
* Fires when a button is long-pressed.
*
* @event ButtonEvent.LONG_PRESS
*/
LONG_PRESS: 'longPress',
/**
* Fires when a button is sustained-pressed.
*
* @event ButtonEvent.SUSTAINED_PRESS
*/
SUSTAINED_PRESS: 'sustainedPress'
};
/**
* The Button Class.
*
* @namespace webduino.module
* @class Button
* @constructor
* @param {webduino.Board} board The board the button is attached to.
* @param {webduino.pin} pin The pin the button is connected to.
* @param {Number} [buttonMode] Type of resistor the button is connected to, either Button.PULL_DOWN or Button.PULL_UP.
* @param {Number} [sustainedPressInterval] A period of time when the button is pressed and hold for that long, it would be considered a "sustained press." Measured in ms.
* @extends webduino.Module
*/
function Button(board, pin, buttonMode, sustainedPressInterval) {
Module.call(this);
this._board = board;
this._pin = pin;
this._repeatCount = 0;
this._timer = null;
this._timeout = null;
this._buttonMode = buttonMode || Button.PULL_DOWN;
this._sustainedPressInterval = sustainedPressInterval || 1000;
this._debounceInterval = 20;
this._pressHandler = onPress.bind(this);
this._releaseHandler = onRelease.bind(this);
this._sustainedPressHandler = onSustainedPress.bind(this);
board.setDigitalPinMode(pin.number, Pin.DIN);
if (this._buttonMode === Button.INTERNAL_PULL_UP) {
board.enablePullUp(pin.number);
this._pin.value = Pin.HIGH;
} else if (this._buttonMode === Button.PULL_UP) {
this._pin.value = Pin.HIGH;
}
this._pin.on(PinEvent.CHANGE, onPinChange.bind(this));
}
function onPinChange(pin) {
var btnVal = pin.value;
var stateHandler;
if (this._buttonMode === Button.PULL_DOWN) {
if (btnVal === 1) {
stateHandler = this._pressHandler;
} else {
stateHandler = this._releaseHandler;
}
} else if (this._buttonMode === Button.PULL_UP || this._buttonMode === Button.INTERNAL_PULL_UP) {
if (btnVal === 1) {
stateHandler = this._releaseHandler;
} else {
stateHandler = this._pressHandler;
}
}
if (this._timeout) {
clearTimeout(this._timeout);
}
this._timeout = setTimeout(stateHandler, this._debounceInterval);
}
function onPress() {
this.emit(ButtonEvent.PRESS);
if (this._timer) {
clearInterval(this._timer);
delete this._timer;
}
this._timer = setInterval(this._sustainedPressHandler, this._sustainedPressInterval);
}
function onRelease() {
this.emit(ButtonEvent.RELEASE);
if (this._timer) {
clearInterval(this._timer);
delete this._timer;
}
this._repeatCount = 0;
}
function onSustainedPress() {
if (this._repeatCount > 0) {
this.emit(ButtonEvent.SUSTAINED_PRESS);
} else {
this.emit(ButtonEvent.LONG_PRESS);
}
this._repeatCount++;
}
Button.prototype = Object.create(Module.prototype, {
constructor: {
value: Button
},
/**
* Return the button mode.
*
* @attribute buttonMode
* @type {Number} buttonMode
* @readOnly
*/
buttonMode: {
get: function () {
return this._buttonMode;
}
},
/**
* Return the sustained-press interval.
*
* @attribute sustainedPressInterval
* @type {Number}
*/
sustainedPressInterval: {
get: function () {
return this._sustainedPressInterval;
},
set: function (intervalTime) {
this._sustainedPressInterval = intervalTime;
}
}
});
/**
* Indicates the pull-down resistor type.
*
* @property PULL_DOWN
* @type {Number}
* @static
* @final
*/
Button.PULL_DOWN = 0;
/**
* Indicates the pull-up resistor type.
*
* @property PULL_UP
* @type {Number}
* @static
* @final
*/
Button.PULL_UP = 1;
/**
* Indicates the internal-pull-up resistor type.
*
* @property INTERNAL_PULL_UP
* @type {Number}
* @static
* @final
*/
Button.INTERNAL_PULL_UP = 2;
scope.module.ButtonEvent = ButtonEvent;
scope.module.Button = Button;
}));