/**
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* <p>This widget is the base to be used when constructing menus. Typically this widget should be configured with
* a combination of [menu bar items]{@link module:alfresco/menus/AlfMenuBarItem} and
* [popup menus]{@link module:alfresco/menus/AlfMenuBarPopup} (although custom menu widgets could also be included).
* This widget supports keyboard navigation using the cursor keys and enter or space for selection (please note that
* using the tab key will jump to the next widget - tab is not used to navigate items within the menu bar).</p>
* <p>The default menu bar behaviour is for all [popup menus]{@link module:alfresco/menus/AlfMenuBarPopup} to appear
* below the menu bar, however it is possible to configure this widget so that they appear above the menu bar by
* configuring the [popupMenusAbove]{@link module:alfresco/menus/AlfMenuBar#popupMenusAbove} attribute to be true.</p>
*
* @example <caption>Typical menu bar configuration</caption>
* {
* name: "alfresco/menus/AlfMenuBar",
* config: {
* widgets: [
* {
* name: "alfresco/menus/AlfMenuBarItem",
* config: {
* label: "Do something",
* publishTopic: "DO_SOMETHING",
* publishPayload: {
* data: "INFO_ABOUT_WHAT_TO_DO"
* }
* }
* }
* ]
* }
* }
*
* @example <caption>Configuring a menu bar with popups above</caption>
* {
* name: "alfresco/menus/AlfMenuBar",
* config: {
* popupMenusAbove: true,
* widgets: [
* {
* name: "alfresco/menus/AlfMenuBarPopup",
* config: {
* label: "More options...",
* widgets: [
* {
* name: "alfresco/menus/AlfMenuItem",
* config: {
* label: "Do something",
* publishTopic: "DO_SOMETHING",
* publishPayload: {
* data: "INFO_ABOUT_WHAT_TO_DO"
* }
* }
* }
* ]
* }
* }
* ]
* }
* }
*
* @module alfresco/menus/AlfMenuBar
* @extends external:dijit/_WidgetBase
* @mixes external:dojo/_TemplatedMixin
* @mixes module:alfresco/core/Core
* @mixes module:alfresco/core/CoreWidgetProcessing
* @author Dave Draper
*/
define(["dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!./templates/AlfMenuBar.html",
"alfresco/core/Core",
"alfresco/core/CoreWidgetProcessing",
"dojo/_base/array",
"dijit/MenuBar"],
function(declare, _WidgetBase, _TemplatedMixin, template, AlfCore, CoreWidgetProcessing, array, MenuBar) {
/**
* This is a customization of the default dijit/MenuBar implementation to allow menu popups to be locked.
* The reason that this feature was implemented was because it was observed that including the dijit/form/Textarea
* widget (and presumably other widgets) within a popup menu resulted in focus issues occurring following
* user input that would cause the popups to close inappropriately. This customization is something of a hack
* as a "proper" solution could not be found to control the focus stack and associated events adequately. This
* problem was found specifically when implementing the alfresco/header/UserStatus widget.
*/
var CustomMenuBar = declare([MenuBar, AlfCore], {
/**
* This boolean attribute is used as an indicator of whether or not the MenuBar popups should
* be locked in the open state.
*
* @instance
* @type {boolean}
*/
_lockPopupsOpen: false,
/**
* Overriden to only allow the default implementation to execute if the _lockPopupsOpen attribute
* is set to false.
*
* @instance
*/
_closeChild: function alfresco_menus_AlfMenuBar_CustomMenuBar___closeChild(){
this.alfLog("log", "Custom MenuBar _closeChild");
if (this._lockPopupsOpen)
{
// No action required.
}
else
{
this.inherited(arguments);
}
}
});
return declare([_WidgetBase, _TemplatedMixin, AlfCore, CoreWidgetProcessing], {
/**
* The scope to use for i18n messages.
*
* @instance
* @type {String}
*/
i18nScope: "org.alfresco.Menus",
/**
* An array of the CSS files to use with this widget.
*
* @instance
* @type {Array}
*/
cssRequirements: [{cssFile:"./css/AlfMenuBar.css"}],
/**
* An array of the i18n files to use with this widget.
*
* @instance
* @type {Array}
*/
i18nRequirements: [{i18nFile: "./i18n/AlfMenuBar.properties"}],
/**
* The HTML template to use for the widget.
* @instance
* @type {String}
*/
templateString: template,
/**
* In some circumstances it may be required to have the [popup menus]{@link module:alfresco/menus/AlfMenuBarPopup}
* appear above the menu bar (e.g. if the menu bar is at the bottom of a page or layout control). This attribute
* can be configured to be true in order to support that requirement. The default value is false which will result
* in [popup menus]{@link module:alfresco/menus/AlfMenuBarPopup} being displayed below the menu bar.
*
* @instance
* @type {boolean}
* @default
*/
popupMenusAbove: false,
/**
* A reference to the MenuBar
*
* @instance
* @type {Object}
*/
_menuBar: null,
/**
* This function has been provided to set the _lockPopupsOpen attribute in the custom MenuBar implementation
* (declared above) to prevent the _closeChild function from executing. This function (and the associated
* custom MenuBar) has been implemented to handle calls from the alfresco/header/UserStatus widget which
* needs to prevent the MenuBar from closing popups when the dijit/form/Textarea used for capturing user
* status has focus.
*
* @instance
* @param b {boolean}
*/
lockPopupsOpen: function alfresco_menus_AlfMenuBar__lockPopupsOpen(b) {
this._menuBar._lockPopupsOpen = b;
},
/**
* Instantiates the MenuBar (a custom declared implementation) and processes the widgets assigned to ensure
* that the labels are localized before being sent for processing.
*
* @instance
*/
postCreate: function alfresco_menus_AlfMenuBar__postCreate() {
this._menuBar = new CustomMenuBar({
_orient: this.popupMenusAbove === true ? ["above"] : ["below"]
});
this._menuBar.placeAt(this.containerNode);
if (this.widgets && this.widgets instanceof Array)
{
// Convert any i18n keys into the translated labels...
array.forEach(this.widgets, function(entry) {
if (entry.config && entry.config.label)
{
entry.config.label = this.message(entry.config.label);
}
}, this);
// Process all the widgets, when complete the allWidgetsProcessed function will be called
// with all the instantiated menu widgets passed as an argument. These will then be added
// to the menu bar to complete the creation process.
this.processWidgets(this.widgets);
}
},
/**
* Implements the callback to add all of the widgets into the MenuBar.
*
* @instance
* @param widgets The widgets that have been successfully instantiated.
*/
allWidgetsProcessed: function alfresco_menus_AlfMenuBar__allWidgetsProcessed(widgets) {
array.forEach(widgets, function(entry) {
this._menuBar.addChild(entry);
}, this);
}
});
});