286 lines
7.5 KiB
JavaScript
286 lines
7.5 KiB
JavaScript
/*
|
|
* Axelor Business Solutions
|
|
*
|
|
* Copyright (C) 2005-2019 Axelor (<http://axelor.com>).
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program 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 Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
(function() {
|
|
|
|
"use strict";
|
|
|
|
var ui = angular.module('axelor.ui');
|
|
|
|
MenuBarCtrl.$inject = ['$scope', '$element'];
|
|
function MenuBarCtrl($scope, $element) {
|
|
|
|
this.isDivider = function(item) {
|
|
return !item.title && !item.icon;
|
|
};
|
|
|
|
this.isSubMenu = function(item) {
|
|
return item && item.items && item.items.length > 0;
|
|
};
|
|
|
|
$scope.isImage = function (menu) {
|
|
return menu.icon && menu.icon.indexOf('fa-') !== 0;
|
|
};
|
|
|
|
$scope.isIcon = function (menu) {
|
|
return menu.icon && menu.icon.indexOf('fa-') === 0;
|
|
};
|
|
|
|
$scope.canShowTitle = function(menu) {
|
|
return menu.showTitle === null || menu.showTitle === undefined || menu.showTitle;
|
|
};
|
|
}
|
|
|
|
ui.directive('uiMenuBar', function() {
|
|
|
|
return {
|
|
replace: true,
|
|
controller: MenuBarCtrl,
|
|
scope: {
|
|
menus: '=',
|
|
handler: '='
|
|
},
|
|
link: function(scope, element, attrs, ctrl) {
|
|
|
|
ctrl.handler = scope.handler;
|
|
|
|
scope.onMenuClick = _.once(function onMenuClick(e) {
|
|
element.find('.dropdown-toggle').dropdown();
|
|
$(e.currentTarget).dropdown('toggle');
|
|
});
|
|
},
|
|
|
|
template:
|
|
"<ul class='nav menu-bar'>" +
|
|
"<li class='menu dropdown button-menu' ng-class='::{\"button-menu\": menu.isButton, \"has-icon\": menu.icon}' ng-repeat='menu in ::menus'>" +
|
|
"<a href='' class='dropdown-toggle btn' ng-class='::{\"btn\": menu.isButton}' data-toggle='dropdown' ng-click='onMenuClick($event)'>" +
|
|
"<img ng-if='::isImage(menu)' ng-src='{{menu.icon}}'> " +
|
|
"<i class='fa {{::menu.icon}}' ng-if='::isIcon(menu)'></i> " +
|
|
"<span class='menu-title' ng-show='::canShowTitle(menu)'>{{::menu.title}}</span> " +
|
|
"<b class='caret'></b>" +
|
|
"</a>" +
|
|
"<ul ui-menu='menu'></ul>" +
|
|
"</li>" +
|
|
"</ul>"
|
|
};
|
|
});
|
|
|
|
ui.directive('uiMenu', function() {
|
|
|
|
return {
|
|
replace: true,
|
|
require: '^uiMenuBar',
|
|
scope: {
|
|
menu: '=uiMenu'
|
|
},
|
|
link: function(scope, element, attrs, ctrl) {
|
|
|
|
},
|
|
template:
|
|
"<ul class='dropdown-menu'>" +
|
|
"<li ng-repeat='item in ::menu.items' ui-menu-item='item'>" +
|
|
"</ul>"
|
|
};
|
|
});
|
|
|
|
ui.directive('uiMenuItem', ['$compile', 'ActionService', function($compile, ActionService) {
|
|
|
|
return {
|
|
replace: true,
|
|
require: '^uiMenuBar',
|
|
scope: {
|
|
item: '=uiMenuItem'
|
|
},
|
|
link: function(scope, element, attrs, ctrl) {
|
|
|
|
var item = scope.item;
|
|
var handler = null;
|
|
|
|
scope.field = item;
|
|
scope.isDivider = ctrl.isDivider(item);
|
|
scope.isSubMenu = ctrl.isSubMenu(item);
|
|
|
|
if (item.action) {
|
|
handler = ActionService.handler(ctrl.handler, element, {
|
|
action: item.action,
|
|
prompt: item.prompt
|
|
});
|
|
element.addClass("action-item").attr("x-name", item.name);
|
|
}
|
|
|
|
scope.isRequired = function(){};
|
|
scope.isValid = function(){};
|
|
|
|
attrs = {
|
|
hidden: !!item.hidden,
|
|
readonly: !!item.readonly
|
|
};
|
|
|
|
scope.attr = function(name, value) {
|
|
attrs[name] = value;
|
|
};
|
|
|
|
scope.isReadonly = function(){
|
|
if (attrs.readonly) return true;
|
|
if (_.isFunction(item.active)) {
|
|
return !item.active();
|
|
}
|
|
return false;
|
|
};
|
|
|
|
scope.isHidden = function(){
|
|
if (attrs.hidden) return true;
|
|
if (_.isFunction(item.visible)) {
|
|
return !item.visible();
|
|
}
|
|
return false;
|
|
};
|
|
|
|
var form = element.parents('.form-view:first');
|
|
var formScope = form.data('$scope');
|
|
|
|
if (formScope) {
|
|
formScope.$watch('record', function menubarRecordWatch(rec) {
|
|
scope.record = rec;
|
|
});
|
|
}
|
|
|
|
scope.onClick = function(e) {
|
|
element.parents('.dropdown').dropdown('toggle');
|
|
if (scope.isSubMenu) return;
|
|
if (item.action) {
|
|
return handler.onClick();
|
|
}
|
|
if (_.isFunction(item.click)) {
|
|
return item.click(e);
|
|
}
|
|
};
|
|
|
|
scope.cssClass = function() {
|
|
if (scope.isDivider) {
|
|
return 'divider';
|
|
}
|
|
if (scope.isSubMenu) {
|
|
return 'dropdown-submenu';
|
|
}
|
|
};
|
|
|
|
|
|
if (scope.isSubMenu) {
|
|
$compile('<ul ui-menu="item"></ul>')(scope, function(cloned, scope) {
|
|
element.append(cloned);
|
|
});
|
|
}
|
|
},
|
|
template:
|
|
"<li ng-class='cssClass()' ui-widget-states ng-show='!isHidden()'>" +
|
|
"<a href='' ng-show='isReadonly()' class='disabled'>{{item.title}}</a>" +
|
|
"<a href='' ng-show='!isDivider && !isReadonly()' ng-click='onClick($event)'>{{item.title}}</a>" +
|
|
"</li>"
|
|
};
|
|
}]);
|
|
|
|
ui.directive('uiToolbarAdjust', function() {
|
|
|
|
return function (scope, element, attrs) {
|
|
|
|
var elemMenubar = null;
|
|
var elemToolbar = null;
|
|
var elemSiblings = null;
|
|
|
|
var elemToolbarMobile = null;
|
|
|
|
function setup() {
|
|
elemMenubar = element.children('.view-menubar');
|
|
elemToolbar = element.children('.view-toolbar');
|
|
elemSiblings = element.children(':not(.view-menubar,.view-toolbar,.view-toolbar-mobile)');
|
|
|
|
elemToolbarMobile = element.children('.view-toolbar-mobile').hide();
|
|
|
|
var running = false;
|
|
scope.$onAdjust(function () {
|
|
if (running) {
|
|
return;
|
|
}
|
|
running = true;
|
|
try {
|
|
adjust();
|
|
} finally {
|
|
running = false;
|
|
}
|
|
});
|
|
|
|
scope.$callWhen(adjust, function () {
|
|
return element.is(':visible');
|
|
});
|
|
}
|
|
|
|
function hideAndShow(first, second, visibility) {
|
|
[elemMenubar, elemToolbar, elemToolbarMobile].forEach(function (elem) {
|
|
elem.hide().css('visibility', 'hidden');
|
|
});
|
|
[first, second].forEach(function (elem) {
|
|
if (elem && element.is(':visible')) {
|
|
elem.show().css('visibility', visibility || '');
|
|
}
|
|
});
|
|
}
|
|
|
|
function adjust() {
|
|
|
|
if (elemMenubar === null) {
|
|
return;
|
|
}
|
|
|
|
var width = element.width() - 8;
|
|
elemSiblings.each(function (i) {
|
|
width -= $(this).width();
|
|
});
|
|
|
|
if (axelor.device.small) {
|
|
if (width > elemToolbarMobile.width() + elemMenubar.width()) {
|
|
hideAndShow(elemToolbarMobile, elemMenubar);
|
|
} else if (width > elemToolbarMobile.width()) {
|
|
hideAndShow(elemToolbarMobile);
|
|
} else if (width > elemMenubar.width()) {
|
|
hideAndShow(elemMenubar);
|
|
}
|
|
return;
|
|
}
|
|
|
|
function canShow(first, second) {
|
|
hideAndShow(first, second, 'hidden');
|
|
if (width > first.width() + second.width()) {
|
|
first.css('visibility', '');
|
|
second.css('visibility', '');
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
canShow(elemToolbar, elemMenubar) ||
|
|
canShow(elemToolbarMobile, elemMenubar) ||
|
|
canShow(elemToolbar, $()) ||
|
|
canShow(elemToolbarMobile, $());
|
|
}
|
|
|
|
scope.waitForActions(setup, 100);
|
|
};
|
|
});
|
|
|
|
})();
|