define([
'jquery',
'ui/component',
'ui/utils',
'jqueryui'
], function (
$,
Component,
Utils
) {
'use strict';
var MenuButton = Component.extend({
init: function () {
this.element = MenuButton.makeMenuButton(this);
}
});
// static functions
/**
* @param props button properties:
* click - if provided will generate a split button,
* otherwise just a normal select button.
* menu - array of props for nested buttons
* text - button text
* html - button html
* iconUrl - button icon url
* siblingContainer
* - a $ object that will be searched for other split buttons.
* If a split button is expanded, all the other split buttons in
* this container will be closed.
*/
MenuButton.makeMenuButton = function (props) {
var wrapper = $('
' , {'class': 'aloha-ui-menubutton-container'});
var expand = Utils.makeButtonElement({'class': 'aloha-ui-menubutton-expand'});
var menu = $('
' , {'class': 'aloha-ui-menubutton-menu'});
var action = null;
var buttonset = null;
if ($.browser.msie) {
wrapper.addClass('aloha-ui-menubutton-iehack');
}
if (props.click) {
action = Utils.makeButton(Utils.makeButtonElement({'class': 'aloha-ui-menubutton-action'}), props)
.click(props.click);
Utils.makeButton(expand, {}, true);
buttonset = $('')
.buttonset()
.append(action)
.append(expand);
} else {
Utils.makeButton(expand, props, true)
.addClass('aloha-ui-menubutton-single');
}
if (!props.menu) {
return wrapper.append(action);
}
function hideMenu(menu) {
menu.hide().parent().removeClass('aloha-ui-menubutton-pressed');
}
expand
.click(function (){
wrapper.addClass('aloha-ui-menubutton-pressed');
if (props.siblingContainer) {
props.siblingContainer
.find('.aloha-ui-menubutton-menu')
.each(function (){
if (this !== menu[0]) {
hideMenu($(this));
}
});
}
if (menu.is(':visible')) {
hideMenu(menu);
return;
}
menu.show().position({
my: 'left top',
at: 'left bottom',
of: action || expand
});
// In order to prevent the floating menu from being partially
// covered by the ribbon, we use "position: relative" and an
// invisible border to pad the top of the document. This
// throws off the offset to the menu button so we need to
// compensate in ordet to ensure that the menu is placed
// underneatht the menubutton.
// NB: For the time being we are not using the above fix.
/*
var target = action || expand;
var bodyOffset = parseInt($('body').css('border-top-width'), 10) || 0;
menu.css('top', target.height() + target.offset().top + bodyOffset);
*/
$(document).bind('click', function (event){
$(this).unbind(event);
menu.hide();
wrapper.removeClass('aloha-ui-menubutton-pressed');
});
return false;
});
wrapper.append(buttonset || expand).append(menu);
menu.append(makeNestedMenus(makeCloseHandler(menu), props.menu));
menu.hide().menu({
'select': onSelect
});
return wrapper;
};
function makeNestedMenus(parentCloseHandler, menu){
var elems = [];
$.each(menu, function (_, item) {
var elem = $('
- ');
elem.append($('', {'href': 'javascript:void 0', 'html': Utils.makeButtonLabelWithIcon(item)}));
if (item.click) {
elem.data('aloha-ui-menubutton-select', function (){
parentCloseHandler();
item.click();
});
}
if (item.menu) {
var nestedMenu = $('
').appendTo(elem);
nestedMenu.append(
makeNestedMenus(makeCloseHandler(nestedMenu, parentCloseHandler),
item.menu));
}
elems.push(elem[0]);
});
return elems;
}
function makeCloseHandler(menu, parentCloseHandler) {
parentCloseHandler = parentCloseHandler || $.noop;
return function (){
// We must blur the parent menu otherwise it will remain in
// focused state and not expand the next time it is hovered over
// after the user has selected an item.
menu.blur().hide();
menu.parent().removeClass('aloha-ui-menubutton-pressed');
parentCloseHandler();
};
}
function onSelect(event, ui) {
var clickHandler = ui.item.data('aloha-ui-menubutton-select');
clickHandler && clickHandler(event, ui);
// We use preventDefault() to keep a click on a menu item from
// scrolling to the top of the page.
event.preventDefault();
}
return MenuButton;
});