/**
* 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/>.
*/
/**
* @module alfresco/menus/_AlfMenuItemMixin
* @extends module:alfresco/core/Core
* @mixes module:alfresco/core/CoreRwd
* @mixes module:alfresco/menus/_AlfPopupCloseMixin
* @mixes module:alfresco/services/_NavigationServiceTopicMixin
* @mixes module:alfresco/renderers/_PublishPayloadMixin
* @mixes module:alfresco/navigation/_HtmlAnchorMixin
* @author Dave Draper
* @author Richard Smith
*/
define(["dojo/_base/declare",
"alfresco/core/Core",
"alfresco/core/CoreRwd",
"alfresco/enums/urlTypes",
"alfresco/menus/_AlfPopupCloseMixin",
"alfresco/services/_NavigationServiceTopicMixin",
"alfresco/renderers/_PublishPayloadMixin",
"alfresco/navigation/_HtmlAnchorMixin",
"service/constants/Default",
"dojo/dom-class",
"dojo/dom-style",
"dojo/dom-construct",
"dojo/on",
"dojo/_base/lang",
"dojo/_base/event",
"dojo/has"],
function(declare, AlfCore, AlfCoreRwd, urlTypes, _AlfPopupCloseMixin, _NavigationServiceTopicMixin, _PublishPayloadMixin,
_HtmlAnchorMixin, AlfConstants, domClass, domStyle, domConstruct, on, lang, event, has) {
return declare([AlfCore, AlfCoreRwd, _AlfPopupCloseMixin, _NavigationServiceTopicMixin, _PublishPayloadMixin, _HtmlAnchorMixin], {
/**
* An array of the CSS files to use with this widget.
*
* @instance
* @type {object[]}
* @default [{cssFile:"./css/_AlfMenuItemMixin.css"},{cssFile: "./css/AlfMenuItemIconMixin.css"},{cssFile: "../core/css/Icons.css"}]
*/
cssRequirements: [{cssFile: "./css/_AlfMenuItemMixin.css"},
{cssFile: "./css/AlfMenuItemIconMixin.css"},
{cssFile: "../core/css/Icons.css"}],
/**
* Defines the image width for the menu item icon. An image is only used if no explicit CSS class is set.
*
* @instance
* @type {string}
* @default
*/
iconImageWidth: "16px",
/**
* Defines the image height for the menu item icon. An image is only used if no explicit CSS class is set.
*
* @instance
* @type {string}
* @default
*/
iconImageHeight: "16px",
/**
* @instance
* @type {string}
* @default
*/
iconAltText: "",
/**
* If a 'targetUrl' attribute is provided the value will be passed as a publication event to the NavigationService
* to reload the page to the URL defined.
*
* @instance
* @type {string}
* @default
*/
targetUrl: null,
/**
* Indicates how the target URL should be handled.
*
* @instance
* @type {string}
* @default [PAGE_RELATIVE]{@link module:alfresco/enums/urlTypes#PAGE_RELATIVE}
*/
targetUrlType: urlTypes.PAGE_RELATIVE,
/**
* Indicates whether or not the URL should be opened in the current window/tab or in a new window.
*
* @instance
* @type {string}
* @default
*/
targetUrlLocation: "CURRENT",
/**
* Should we publish the publishTopic when we initially render the item?
*
* @instance
* @type {Boolean}
* @default
*/
publishOnRender: false,
/**
* The topic whose publication should trigger disablement/enablement function
*
* @instance
* @type {string}
* @default
*/
disablementTopic: null,
/**
* The topic that the widget will listen to.
*
* @instance
* @type {string}
* @default
*/
selectionTopic: null,
/**
* It's important to perform label encoding before buildRendering occurs (e.g. before postCreate)
* to ensure that an unencoded label isn't set and then replaced.
*
* @instance
*/
postMixInProperties: function alfresco_menus__AlfMenuItemMixin__postMixInProperties() {
// We need to keep a copy of the unencoded label, in case it needs to be used for the
// title (which must remain unencoded, to prevent double-encoding)...
var originalLabel = this.label;
if (this.label)
{
this.params.label = this.label = this.encodeHTML(this.message(this.label));
}
if (!this.title && originalLabel)
{
this.title = this.message(originalLabel);
}
else if (this.title)
{
this.title = this.message(this.title);
}
if (!this.iconAltText && this.title)
{
this.iconAltText = this.message(originalLabel);
}
else if (this.iconAltText)
{
this.iconAltText = this.message(this.iconAltText);
}
this.params.title = this.title;
this.inherited(arguments);
},
/**
* Ensures that the supplied menu item label is translated.
* @instance
*/
postCreate: function alfresco_menus__AlfMenuItemMixin__postCreate() {
this.set("label", this.label);
this.inherited(arguments);
domClass.add(this.domNode, "alfresco-menus-_AlfMenuItemMixin");
// Set up a handler for onContextMenu actions (e.g. right-clicks), although by default this will perform no action...
on(this.domNode, "contextmenu", lang.hitch(this, "onContextMenu"));
this.makeAnchor(this.targetUrl, this.targetUrlType);
if (this.disablementTopic)
{
this.alfSubscribe(this.disablementTopic, lang.hitch(this, "disable"));
}
if (this.selectionTopic)
{
this.alfSubscribe(this.selectionTopic, lang.hitch(this, "handleSelection"));
}
},
/**
* Returns an array containing the selector that identifies the span to wrap in an anchor.
* This overrides the [mixed in function]{@link module:alfresco/navigation/_HtmlAnchorMixin}
* that just returns an empty array.
*
* @instance
*/
getAnchorTargetSelectors: function alfresco_renderers_SearchResultPropertyLink__getAnchorTargetSelectors() {
return ["td.dijitMenuItemLabel","span.alf-menu-bar-label-node"];
},
/**
* Extension point for handling context click events. By default this performs no action.
*
* @instance
* @param {event} evt The context menu event
*/
onContextMenu: function(evt) {
// jshint unused:false
// No action by default.
},
/**
* @instance
*/
setupIconNode: function alfresco_menus__AlfMenuItemMixin__setupIconNode() {
if (this.iconClass && this.iconClass !== "dijitNoIcon" && this.iconNode)
{
var iconNodeParent = this.iconNode.parentNode;
domConstruct.destroy(this.iconNode);
this.iconNode = domConstruct.create("img", {
role:"button",
className: "dijitInline dijitIcon dijitMenuItemIcon alfresco-menus-_AlfMenuItemMixin__icon alfresco-menus-AlfMenuItemIconMixin " + this.iconClass,
src: require.toUrl("alfresco/menus/css/images/transparent-20.png"),
title: this.iconAltText,
alt: this.iconAltText,
tabIndex: 0
}, iconNodeParent, "first");
}
else if (this.iconImage && this.iconNode)
{
/* The Dojo CSS class "dijitNoIcon" will automatically have been applied to a menu item
* if it is not overridden. Therefore in order to ensure that the icon is displayed it
* is necessary to set the height and width and to ensure that the display is set to
* block. Because the style is being explicitly set it will take precedence over the
* Dojo CSS class.
*/
if (has("ie") === 8)
{
if (location.protocol.indexOf("https") !== -1)
{
//It is ssl in IE8, so we use full URL. see MNT-10867
this.iconImage = location.protocol + "//" + location.host + this.iconImage;
}
}
domStyle.set(this.iconNode, { backgroundImage: "url(" + this.iconImage + ")",
width: this.iconImageWidth,
height: this.iconImageHeight,
display: "inline-block",
verticalAlign: "middle" });
}
else if (this.iconNode)
{
// If there is no iconClass or iconImage then we need to explicitly set the
// parent element of the icon node to have an inherited width. This is because there
// is a CSS selector that fixes the width of menu items with icons to ensure that
// they are all aligned. This means that there would be a space for an icon even if
// one was not available.
domStyle.set(this.iconNode.parentNode, {
width: "auto"
});
}
},
/**
* Overrides the default onClick function. Currently only supports page navigation.
*
* @instance
* @param {object} evt The click event
*/
onClick: function alfresco_menus__AlfMenuItemMixin__onClick(evt) {
// jshint maxcomplexity:false
var targetUrlLocation = this.targetUrlLocation;
var middleButton = evt.button === 1;
var leftButton = evt.button === 0;
var ctrlKey = has("mac") ? evt.metaKey : evt.ctrlKey;
if (middleButton || (leftButton && ctrlKey))
{
targetUrlLocation = "NEW";
}
else if (this.publishPayload && leftButton && this.publishPayload.target !== this.currentTarget)
{
this.publishPayload.target = this.defaultNavigationTarget || this.currentTarget;
}
// Emit the event to close popups in the stack...
this.emitClosePopupEvent();
if (this.targetUrl)
{
// Stop the event (to prevent the browser processing <a> elements
event.stop(evt);
// Handle URLs...
this.alfPublish("ALF_NAVIGATE_TO_PAGE", { url: this.targetUrl,
type: this.targetUrlType,
target: targetUrlLocation});
}
else if (this.publishTopic)
{
// Handle publish requests...
//var payload = (this.publishPayload) ? this.publishPayload : {};
var publishGlobal = this.publishGlobal || false;
var publishToParent = this.publishToParent || false;
// TODO: DD: Not keen on the fact that somehow this "document" specific stuff has crept in here...
// Ideally it shouldn't be there...
var payload = this.generatePayload((this.publishPayload) ? this.publishPayload : {document: this.currentItem}, this.currentItem, null, this.publishPayloadType, this.publishPayloadItemMixin, this.publishPayloadModifiers);
this.alfPublish(this.publishTopic, payload, publishGlobal, publishToParent);
}
else
{
this.alfLog("error", "An AlfMenuBarItem was clicked but did not define a 'targetUrl' or 'publishTopic' attribute", evt);
}
},
/**
* This function enables or disables the menu item based upon parameter 'payload.value'.
*
* @instance
* @param {object} payload
*/
disable: function alfresco_menus__AlfMenuItemMixin__disable(payload) {
if(payload && typeof payload.value === "boolean" && typeof this.set === "function")
{
this.set("disabled", payload.value);
}
else
{
this.alfLog("warn", "Attempt made to disable or enable AlfMenuItem but mixed inappropariately or triggered with inapproriate payload", this);
}
},
/**
* @instance
* @param {object} payload The payload from the publication on the selection topic
*/
handleSelection: function alfresco_menus__AlfMenuItemMixin__handleSelection(payload) {
this.alfLog("log", "Selection detected", payload);
if (payload)
{
// Update the label with the selection...
if (payload.label)
{
this.set("label", this.message(payload.label));
}
else if (payload.value || payload.value === false || payload.value === 0)
{
this.set("label", payload.value.toString());
}
}
}
});
});