/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Logan Byam
*/
/**
* @module bajaux/util/CommandButtonGroup
*/
define([ 'jquery',
'Promise',
'bajaux/events',
'bajaux/Widget',
'bajaux/commands/Command',
'bajaux/commands/CommandGroup',
'bajaux/util/CommandButton' ], function (
$,
Promise,
events,
Widget,
Command,
CommandGroup,
CommandButton) {
'use strict';
var ENABLE_DISABLE = events.ENABLE_EVENT + ' ' + events.DISABLE_EVENT;
function widgetDefaults() {
return {
properties: {
toolbar: false,
onDisabled: { value: 'none', hidden: true, transient: true }
}
};
}
/**
* A widget for displaying and invoking Commands in a `CommandGroup`.
*
* @class
* @extends module:bajaux/Widget
* @alias module:bajaux/util/CommandButtonGroup
*
* @param {Object} [params]
* @param {String} [params.properties.onDisabled] specify a policy for handling
* enabling/disabling of Commands. By default, the `CommandButton` itself
* will be responsible for updating its own DOM. A value of `hide` will
* cause the entire element to be hidden when the command is disabled.
* @param {Boolean} [params.properties.toolbar=false] Set to true to
* cause the group to render a toolbar button group instead of a group of
* normal buttons.
*/
var CommandButtonGroup = function CommandButtonGroup(params) {
Widget.call(this, { params: params, defaults: widgetDefaults() });
};
CommandButtonGroup.prototype = Object.create(Widget.prototype);
CommandButtonGroup.prototype.constructor = CommandButtonGroup;
/**
* @private
* @returns {Array.<module:bajaux/util/CommandButtonGroup>}
*/
CommandButtonGroup.prototype.$getButtons = function () {
return this.jq().children().map(function () {
return $(this).data('widget');
}).get();
};
/**
* When a button is enabled or disabled, the group should update its DOM.
* This will perform the hiding/showing of the element, according to the
* `onDisabled` parameter passed to the constructor.
*
* @private
* @param {module:bajaux/util/CommandButton} btn the widget
* that has just been enabled/disabled
*/
CommandButtonGroup.prototype.$updateButtonDom = function (btn) {
var jq = btn.jq(),
enabled = btn.canInvokeCommand();
switch (this.properties().getValue('onDisabled')) {
case 'hide':
jq.toggle(enabled);
break;
}
};
/**
* Return true if this group is in toolbar mode.
*
* @private
* @returns {*}
*/
CommandButtonGroup.prototype.$isToolbar = function () {
return this.properties().getValue('toolbar');
};
/**
* Return true if this group is a toggle group.
*
* @private
* @returns {*}
*/
CommandButtonGroup.prototype.$isToggleGroup = function (params) {
return params && params.toggleGroup;
};
/**
* Creates a DOM element in which to initialize a new `CommandButton`.
* By default gives a `button` element with a class of `ux-btn-tb`, to turn
* this group into a toolbar button group. Override if needed (ensure the
* element gets appended to `this.jq()`).
*
* @private
* @param {module:bajaux/commands/Command} cmd
* @returns {JQuery}
*/
CommandButtonGroup.prototype.$createButtonDom = function (cmd) {
var button = $('<button type="button"></button>');
button.addClass(this.$isToolbar() ? 'ux-btn-tb' : 'ux-btn');
return button.appendTo(this.jq());
};
/**
* Create a CommandButton for the given command. Override if your
* CommandButtonGroup subclass needs more control over what kind of
* CommandButtons get instantiated.
*
* @private
* @param {module:bajaux/commands/Command} cmd
* @returns {module:bajaux/util/CommandButton}
*/
CommandButtonGroup.prototype.$createCommandButton = function (cmd) {
return new CommandButton();
};
/**
* Adds the `ux-btn-tb-group` class to the DOM to turn this into a toolbar
* button group.
*
* @param {JQuery} dom
*/
CommandButtonGroup.prototype.doInitialize = function (dom) {
var that = this;
dom.addClass('CommandButtonGroup');
if (that.$isToolbar()) {
dom.addClass('ux-btn-tb-group');
}
if (that.$isToggleGroup(arguments && arguments[1])) {
dom.addClass('ux-toggle-btn-group');
}
dom.on(ENABLE_DISABLE, '.CommandButton', function (e, cmdButton) {
that.$updateButtonDom(cmdButton);
});
};
//TODO: how should this handle subgroups? flatten, or make multiple toolbars?
/**
* Loads a `CommandGroup`, creating `CommandButton` widgets for each
* command in the group. Arms event handlers to hide elements for
* disabled buttons, as specified by the `onDisabled` parameter.
*
* @param {module:bajaux/commands/CommandGroup} group
* @returns {Promise} promise to be resolved when the group is fully
* loaded and all elements initialized, or rejected if no `CommandGroup`
* given
*/
CommandButtonGroup.prototype.doLoad = function (group) {
if (!(group instanceof CommandGroup)) {
throw new Error('CommandGroup required');
}
var that = this;
return this.getChildWidgets().destroyAll()
.then(() => {
that.jq().empty();
return Promise.all(group.getChildren().map((kid) => {
if (!(kid instanceof Command)) {
return; //skip groups
}
return this.$buildFor(kid);
}));
});
};
/**
* @private
* @param {module:bajaux/commands/Command} cmd
* @returns {Promise} to be resolved after the child button has been
* initialized and loaded
*/
CommandButtonGroup.prototype.$buildFor = function (cmd) {
const cmdButton = this.$createCommandButton(cmd);
const dom = this.$createButtonDom(cmd);
return cmdButton.initialize(dom)
.then(() => {
this.$updateButtonDom(cmdButton);
return cmdButton.load(cmd);
});
};
/**
* Removes the `ux-btn-tb-group` class and destroys all child buttons.
*
* @returns {Promise}
*/
CommandButtonGroup.prototype.doDestroy = function () {
var jq = this.jq();
jq.removeClass('CommandButtonGroup ux-btn-tb-group');
var buttons = jq.children().map(function () {
return $(this).data('widget');
}).get();
return Promise.all(buttons.map(function (button) {
var jq = button.jq();
if (jq) {
jq.removeData('prev').removeData('parent');
}
return button.destroy();
}));
};
return CommandButtonGroup;
});