summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2018-03-14 16:21:14 +0100
committerqsm-odoo <qsm@odoo.com>2018-07-27 12:36:54 +0200
commit1c1c0897e8eca607c7f1b96b68a06c026c543e6a (patch)
tree1f667224be28146cbcbe602892094046052ea93b /addons/web/static/src
parent220e49f9d66f2e2ea875143c2da0c20919ec0b3e (diff)
[REF] *: BS4, adapt dropdowns and carets
- The dropdown structure was simplified, allowing to get rid of the 3-levels structure induced by <ul/> elements and dropdowns can now contain anything. The class 'dropdown-item' is now mandatory for each dropdown clickable element. The class 'dropdown-item-text' can be used to add same padding and style but without making the element have a clickable look. - Dividers now use the class 'dropdown-divider' - The way dropdowns are opened and hidden also changed (before the 'open' class was added on the `.dropdown-menu` parent, now the 'show' class is added on both the `.dropdown-menu` parent and the `.dropdown-menu` itself). - JS-wise, no click event handlers can be put on `.dropdown-toggle` elements anymore (instead, use handlers for dropdown events). - Carets are automatically put on `.dropdown-toggle` elements, so this commit replaces the `.caret` elements with this. This feature was possible to disable but would prevent us from adding a caret with scss. Also, this simplifies the DOM. The 'o-no-caret' class was also introduced to allow using the 'dropdown-toggle' class on non-caret elements. - Also adapt the scss to use $caret-width instead of $caret-width-base
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/chrome/sidebar.js9
-rw-r--r--addons/web/static/src/js/chrome/user_menu.js2
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js18
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js6
-rw-r--r--addons/web/static/src/js/views/graph/graph_controller.js8
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_controller.js13
-rw-r--r--addons/web/static/src/js/views/search/favorites_menu.js25
-rw-r--r--addons/web/static/src/js/views/search/filters_menu.js4
-rw-r--r--addons/web/static/src/js/views/search/groupby_menu.js6
-rw-r--r--addons/web/static/src/js/views/search/search_inputs.js8
-rw-r--r--addons/web/static/src/js/widgets/data_export.js20
-rw-r--r--addons/web/static/src/js/widgets/debug_manager.js8
-rw-r--r--addons/web/static/src/js/widgets/domain_selector.js2
-rw-r--r--addons/web/static/src/js/widgets/dropdown_menu.js14
-rw-r--r--addons/web/static/src/js/widgets/switch_company_menu.js6
-rw-r--r--addons/web/static/src/scss/dropdown.scss15
-rw-r--r--addons/web/static/src/scss/dropdown_menu.scss29
-rw-r--r--addons/web/static/src/scss/form_view.scss2
-rw-r--r--addons/web/static/src/scss/kanban_view.scss6
-rw-r--r--addons/web/static/src/scss/navbar.scss34
-rw-r--r--addons/web/static/src/scss/search_groupby_menu.scss16
-rw-r--r--addons/web/static/src/scss/search_view.scss17
-rw-r--r--addons/web/static/src/scss/ui.scss6
-rw-r--r--addons/web/static/src/scss/utils.scss37
-rw-r--r--addons/web/static/src/xml/base.xml276
-rw-r--r--addons/web/static/src/xml/kanban.xml16
26 files changed, 282 insertions, 321 deletions
diff --git a/addons/web/static/src/js/chrome/sidebar.js b/addons/web/static/src/js/chrome/sidebar.js
index 47d598aaeb8..d02c936f470 100644
--- a/addons/web/static/src/js/chrome/sidebar.js
+++ b/addons/web/static/src/js/chrome/sidebar.js
@@ -11,7 +11,7 @@ var _t = core._t;
var Sidebar = Widget.extend({
events: {
- "click .dropdown-menu li a": "_onDropdownClicked"
+ "click .dropdown-item": "_onDropdownClicked"
},
/**
* @override
@@ -177,9 +177,10 @@ var Sidebar = Widget.extend({
this.$el.html(QWeb.render('Sidebar', {widget: this}));
// Hides Sidebar sections when item list is empty
- this.$('.o_dropdown').each(function () {
- if (!$(this).find('li').length) {
- $(this).hide();
+ _.each(this.$('.o_dropdown'), function (el) {
+ var $dropdown = $(el);
+ if (!$dropdown.find('.dropdown-item').length) {
+ $dropdown.hide();
}
});
this.$("[title]").tooltip({
diff --git a/addons/web/static/src/js/chrome/user_menu.js b/addons/web/static/src/js/chrome/user_menu.js
index 84c16b51f82..1251c9b6b5b 100644
--- a/addons/web/static/src/js/chrome/user_menu.js
+++ b/addons/web/static/src/js/chrome/user_menu.js
@@ -23,7 +23,7 @@ var UserMenu = Widget.extend({
start: function () {
var self = this;
var session = this.getSession();
- this.$el.on('click', 'li a[data-menu]', function (ev) {
+ this.$el.on('click', '[data-menu]', function (ev) {
ev.preventDefault();
var menu = $(this).data('menu');
self['_onMenu' + menu.charAt(0).toUpperCase() + menu.slice(1)]();
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 51816220c9f..00092073d6a 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -1612,10 +1612,7 @@ var AttachmentImage = AbstractField.extend({
var StateSelectionWidget = AbstractField.extend({
template: 'FormSelection',
events: {
- 'click a': function (e) {
- e.preventDefault();
- },
- 'click li': '_setSelection'
+ 'click .dropdown-item': '_setSelection',
},
supportedFieldTypes: ['selection'],
@@ -1696,13 +1693,12 @@ var StateSelectionWidget = AbstractField.extend({
* @param {MouseEvent} ev
*/
_setSelection: function (ev) {
- var li = $(ev.target).closest('li');
- if (li.length) {
- var value = String(li.data('value'));
- this._setValue(value);
- if (this.mode === 'edit') {
- this._render();
- }
+ ev.preventDefault();
+ var $item = $(ev.currentTarget);
+ var value = String($item.data('value'));
+ this._setValue(value);
+ if (this.mode === 'edit') {
+ this._render();
}
},
});
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index 5d4e2ad4cb5..a0bb82d569f 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -363,11 +363,11 @@ var FormRenderer = BasicRenderer.extend({
text: _t("More"),
}));
- var $ul = $("<ul>", {'class': "dropdown-menu o_dropdown_more", role: "menu"});
+ var $dropdown = $("<div>", {'class': "dropdown-menu o_dropdown_more", role: "menu"});
_.each(folded_buttons, function ($button) {
- $('<li>').appendTo($ul).append($button);
+ $button.addClass('dropdown-item').appendTo($dropdown);
});
- $ul.appendTo($result);
+ $dropdown.appendTo($result);
}
this._handleAttributes($result, node);
diff --git a/addons/web/static/src/js/views/graph/graph_controller.js b/addons/web/static/src/js/views/graph/graph_controller.js
index 36a05af7653..b6a1c121f0f 100644
--- a/addons/web/static/src/js/views/graph/graph_controller.js
+++ b/addons/web/static/src/js/views/graph/graph_controller.js
@@ -161,8 +161,9 @@ var GraphController = AbstractController.extend(GroupByMenuInterfaceMixin,{
this.$buttons
.find('.o_graph_button[data-mode="' + state.mode + '"]')
.addClass('active');
- this.$measureList.find('li').each(function (index, li) {
- $(li).toggleClass('selected', $(li).data('field') === state.measure);
+ _.each(this.$measureList.find('.dropdown-item'), function (item) {
+ var $item = $(item);
+ $item.toggleClass('selected', $item.data('field') === state.measure);
});
},
@@ -185,8 +186,7 @@ var GraphController = AbstractController.extend(GroupByMenuInterfaceMixin,{
} else if ($target.parents('.o_graph_measures_list').length) {
event.preventDefault();
event.stopPropagation();
- parent = $target.parent();
- field = parent.data('field');
+ field = $target.data('field');
this._setMeasure(field);
}
},
diff --git a/addons/web/static/src/js/views/pivot/pivot_controller.js b/addons/web/static/src/js/views/pivot/pivot_controller.js
index f0976c9a8b4..945cc132b03 100644
--- a/addons/web/static/src/js/views/pivot/pivot_controller.js
+++ b/addons/web/static/src/js/views/pivot/pivot_controller.js
@@ -164,9 +164,9 @@ var PivotController = AbstractController.extend({
fields: fields
}));
- this.$fieldSelection.find('ul').first()
+ this.$fieldSelection.find('.dropdown-menu').first()
.css({top: top, left: left})
- .show();
+ .addClass('show');
},
/**
* @private
@@ -186,7 +186,7 @@ var PivotController = AbstractController.extend({
var state = this.model.get({raw: true});
_.each(this.measures, function (measure, name) {
var isSelected = _.contains(state.measures, name);
- self.$buttons.find('li[data-field="' + name + '"]')
+ self.$buttons.find('.dropdown-item[data-field="' + name + '"]')
.toggleClass('selected', isSelected);
});
},
@@ -215,8 +215,7 @@ var PivotController = AbstractController.extend({
.then(this.update.bind(this, {}, {reload: false}));
}
if ($target.parents('.o_pivot_measures_list').length) {
- var parent = $target.parent();
- var field = parent.data('field');
+ var field = $target.data('field');
event.preventDefault();
event.stopPropagation();
this.model
@@ -298,11 +297,11 @@ var PivotController = AbstractController.extend({
_onFieldMenuSelection: function (event) {
event.preventDefault();
var $target = $(event.target);
- if ($target.parent().hasClass('disabled')) {
+ if ($target.hasClass('disabled')) {
event.stopPropagation();
return;
}
- var field = $target.parent().data('field');
+ var field = $target.data('field');
var interval = $target.data('interval');
var header = this.model.getHeader(this.lastHeaderSelected);
if (interval) {
diff --git a/addons/web/static/src/js/views/search/favorites_menu.js b/addons/web/static/src/js/views/search/favorites_menu.js
index 1e62ffb5ce3..47e99aec573 100644
--- a/addons/web/static/src/js/views/search/favorites_menu.js
+++ b/addons/web/static/src/js/views/search/favorites_menu.js
@@ -14,14 +14,11 @@ var _t = core._t;
return Widget.extend({
template: 'SearchView.FavoriteMenu',
events: {
- 'click li': function (event) {
- event.stopImmediatePropagation();
+ 'click .dropdown-item': function (ev) {
+ ev.preventDefault();
},
- 'click li a': function (event) {
- event.preventDefault();
- },
- 'click .o_save_search a': function (event) {
- event.preventDefault();
+ 'click .o_save_search': function (ev) {
+ ev.preventDefault();
this.toggle_save_menu();
},
'click .o_save_name button': 'save_favorite',
@@ -49,8 +46,8 @@ return Widget.extend({
this.$save_search = this.$('.o_save_search');
this.$save_name = this.$('.o_save_name');
this.$inputs = this.$save_name.find('input');
- this.$user_divider = this.$('.divider.user_filter');
- this.$shared_divider = this.$('.divider.shared_filter');
+ this.$user_divider = this.$('.dropdown-divider.user_filter');
+ this.$shared_divider = this.$('.dropdown-divider.shared_filter');
this.$inputs.eq(0).val(this.searchview.get_title());
var $shared_filter = this.$inputs.eq(1),
$default_filter = this.$inputs.eq(2);
@@ -207,7 +204,7 @@ return Widget.extend({
};
},
clear_selection: function () {
- this.$('li.selected').removeClass('selected');
+ this.$('.selected').removeClass('selected');
},
/**
* Adds a filter description to the filters dict
@@ -230,10 +227,10 @@ return Widget.extend({
this.$shared_divider.show();
}
if (!(key in this.$filters)) {
- var $filter = $('<li>')
+ var $filter = $('<div>', {class: 'position-relative'})
.addClass(filter.user_id ? 'o-searchview-custom-private'
: 'o-searchview-custom-public')
- .append($('<a>', {'href': '#'}).text(filter.name))
+ .append($('<a>', {href: '#', class: 'dropdown-item'}).text(filter.name))
.append($('<span>', {
class: 'fa fa-trash-o o-remove-filter',
on: {
@@ -256,7 +253,7 @@ return Widget.extend({
});
if (current) {
this.query.remove(current);
- this.$filters[this.key_for(filter)].removeClass('selected');
+ this.$filters[this.key_for(filter)].find('.dropdown-item').removeClass('selected');
return;
}
this.query.reset([this.facet_for(filter)], {
@@ -268,7 +265,7 @@ return Widget.extend({
this.searchview.dataset.set_sort(sort_items);
}
- this.$filters[this.key_for(filter)].addClass('selected');
+ this.$filters[this.key_for(filter)].find('.dropdown-item').addClass('selected');
},
remove_filter: function (filter, $filter, key) {
var self = this;
diff --git a/addons/web/static/src/js/views/search/filters_menu.js b/addons/web/static/src/js/views/search/filters_menu.js
index 221f98faa97..cf79bec2640 100644
--- a/addons/web/static/src/js/views/search/filters_menu.js
+++ b/addons/web/static/src/js/views/search/filters_menu.js
@@ -76,7 +76,7 @@ var FiltersMenu = DropdownMenu.extend({
category: 'filterCategory',
title: 'Filters',
icon: 'fa fa-filter',
- symbol: this.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'
+ symbol: this.isMobile ? 'fa fa-chevron-right pull-right mt4' : false,
};
this._super(parent, dropdownHeader, filters, this.fields);
},
@@ -88,7 +88,7 @@ var FiltersMenu = DropdownMenu.extend({
* @private
*/
start: function () {
- this.$menu = this.$('ul.o_dropdown_menu');
+ this.$menu = this.$('.o_dropdown_menu');
this.$menu.addClass('o_filters_menu');
var generatorMenu = QWeb.render('FiltersMenuGenerator', {widget: this});
this.$menu.append(generatorMenu);
diff --git a/addons/web/static/src/js/views/search/groupby_menu.js b/addons/web/static/src/js/views/search/groupby_menu.js
index 7be61ae6606..8540e702589 100644
--- a/addons/web/static/src/js/views/search/groupby_menu.js
+++ b/addons/web/static/src/js/views/search/groupby_menu.js
@@ -14,7 +14,7 @@ var DEFAULT_INTERVAL = 'month';
var GroupByMenu = DropdownMenu.extend({
events: _.extend({}, DropdownMenu.prototype.events,
{
- 'click .o_add_custom_group a': '_onAddCustomGroupClick',
+ 'click .o_add_custom_group': '_onAddCustomGroupClick',
'click button.o_apply_group': '_onButtonApplyClick',
'click .o_group_selector': '_onGroupSelectorClick',
}),
@@ -85,7 +85,7 @@ var GroupByMenu = DropdownMenu.extend({
category: 'groupByCategory',
title: 'Group By',
icon: 'fa fa-bars',
- symbol: this.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret',
+ symbol: this.isMobile ? 'fa fa-chevron-right pull-right mt4' : false,
style: style,
};
this._super(parent, dropdownHeader, groupbys, options);
@@ -98,7 +98,7 @@ var GroupByMenu = DropdownMenu.extend({
* @private
*/
start: function () {
- this.$menu = this.$('ul.o_dropdown_menu');
+ this.$menu = this.$('.o_dropdown_menu');
this.$menu.addClass('o_group_by_menu');
var $generatorMenu = QWeb.render('GroupbyMenuGenerator', {widget: this});
this.$menu.append($generatorMenu);
diff --git a/addons/web/static/src/js/views/search/search_inputs.js b/addons/web/static/src/js/views/search/search_inputs.js
index ee179d7da74..81f53ee4053 100644
--- a/addons/web/static/src/js/views/search/search_inputs.js
+++ b/addons/web/static/src/js/views/search/search_inputs.js
@@ -503,8 +503,13 @@ var ManyToOneField = CharField.extend({
var FilterGroup = Input.extend(/** @lends instance.web.search.FilterGroup# */{
template: 'SearchView.filters',
+ events: {
+ click: 'toggle_filter',
+ },
+
icon: "fa-filter",
completion_label: _lt("Filter on: %s"),
+
/**
* Inclusive group of filters, creates a continuous "button" with clickable
* sections (the normal display for filters is to be a self-contained button)
@@ -536,7 +541,6 @@ var FilterGroup = Input.extend(/** @lends instance.web.search.FilterGroup# */{
this.searchview.query.on('add remove change reset', this.proxy('search_change'));
},
start: function () {
- this.$el.on('click', 'a', this.proxy('toggle_filter'));
return $.when(null);
},
/**
@@ -684,7 +688,7 @@ var FilterGroup = Input.extend(/** @lends instance.web.search.FilterGroup# */{
toggle_filter: function (e) {
e.preventDefault();
e.stopPropagation();
- this.toggle(this.filters[Number($(e.target).parent().data('index'))]);
+ this.toggle(this.filters[Number($(e.currentTarget).data('index'))]);
},
toggle: function (filter, options) {
this.searchview.query.toggle(this.make_facet([this.make_value(filter)]), options);
diff --git a/addons/web/static/src/js/widgets/data_export.js b/addons/web/static/src/js/widgets/data_export.js
index 30e17604077..d05bf2d33fc 100644
--- a/addons/web/static/src/js/widgets/data_export.js
+++ b/addons/web/static/src/js/widgets/data_export.js
@@ -49,7 +49,7 @@ var DataExport = Dialog.extend({
function process_children() {
var $this = $(this);
- if($this.hasClass('open')) {
+ if($this.hasClass('show')) {
$this.children('.o_export_tree_item')
.addClass('o_selected')
.each(process_children);
@@ -77,19 +77,19 @@ var DataExport = Dialog.extend({
switch(e.keyCode || e.which) {
case $.ui.keyCode.LEFT:
- if ($elem.hasClass('open')) {
+ if ($elem.hasClass('show')) {
this.on_expand_action(record);
}
break;
case $.ui.keyCode.RIGHT:
- if (!$elem.hasClass('open')) {
+ if (!$elem.hasClass('show')) {
this.on_expand_action(record);
}
break;
case $.ui.keyCode.UP:
var $prev = $elem.prev('.o_export_tree_item');
if($prev.length === 1) {
- while($prev.hasClass('open')) {
+ while($prev.hasClass('show')) {
$prev = $prev.children('.o_export_tree_item').last();
}
} else {
@@ -104,7 +104,7 @@ var DataExport = Dialog.extend({
break;
case $.ui.keyCode.DOWN:
var $next;
- if($elem.hasClass('open')) {
+ if($elem.hasClass('show')) {
$next = $elem.children('.o_export_tree_item').first();
} else {
$next = $elem.next('.o_export_tree_item');
@@ -408,7 +408,7 @@ var DataExport = Dialog.extend({
var self = this;
if(expansion) {
this.$('.o_export_tree_item[data-id="' + expansion + '"]')
- .addClass('open')
+ .addClass('show')
.find('.o_expand_parent')
.toggleClass('fa-chevron-right fa-chevron-down')
.next()
@@ -429,8 +429,8 @@ var DataExport = Dialog.extend({
},
show_content: function(id) {
var $this = this.$('.o_export_tree_item[data-id="' + id + '"]');
- $this.toggleClass('open');
- var is_open = $this.hasClass('open');
+ $this.toggleClass('show');
+ var is_open = $this.hasClass('show');
$this.children('.o_expand_parent').toggleClass('fa-chevron-down', !!is_open).toggleClass('fa-chevron-right', !is_open);
@@ -441,8 +441,8 @@ var DataExport = Dialog.extend({
if(!is_open) {
$child.hide();
} else if(child_len === $child_field.eq(i).data('id').split("/").length) {
- if ($child.hasClass('open')) {
- $child.removeClass('open');
+ if ($child.hasClass('show')) {
+ $child.removeClass('show');
$child.children('.o_expand_parent').removeClass('fa-chevron-down').addClass('fa-chevron-right');
}
$child.show();
diff --git a/addons/web/static/src/js/widgets/debug_manager.js b/addons/web/static/src/js/widgets/debug_manager.js
index 4eee9266594..d553387f153 100644
--- a/addons/web/static/src/js/widgets/debug_manager.js
+++ b/addons/web/static/src/js/widgets/debug_manager.js
@@ -23,12 +23,12 @@ var DebugManager = Widget.extend({
template: "WebClient.DebugManager",
events: {
"click a[data-action]": "perform_callback",
- "mouseover .o_debug_dropdowns > li:not(.open)": function(e) {
+ "mouseover .o_debug_dropdowns > li:not(.show)": function(e) {
// Open other dropdowns on mouseover
- var $opened = this.$('.o_debug_dropdowns > li.open');
+ var $opened = this.$('.o_debug_dropdowns > li.show');
if($opened.length) {
- $opened.removeClass('open');
- $(e.currentTarget).addClass('open').find('> a').focus();
+ $opened.removeClass('show');
+ $(e.currentTarget).addClass('show').find('> a').focus();
}
},
},
diff --git a/addons/web/static/src/js/widgets/domain_selector.js b/addons/web/static/src/js/widgets/domain_selector.js
index c5a561b1b77..dab0c97108b 100644
--- a/addons/web/static/src/js/widgets/domain_selector.js
+++ b/addons/web/static/src/js/widgets/domain_selector.js
@@ -161,7 +161,7 @@ var DomainNode = Widget.extend({
var DomainTree = DomainNode.extend({
template: "DomainTree",
events: _.extend({}, DomainNode.prototype.events, {
- "click .o_domain_tree_operator_selector > ul > li > a": "_onOperatorChange",
+ "click .o_domain_tree_operator_selector .dropdown-item": "_onOperatorChange",
}),
custom_events: {
// If a domain child sends a request to add a child or remove one, call
diff --git a/addons/web/static/src/js/widgets/dropdown_menu.js b/addons/web/static/src/js/widgets/dropdown_menu.js
index 410d915dc9a..6f8f78a13d5 100644
--- a/addons/web/static/src/js/widgets/dropdown_menu.js
+++ b/addons/web/static/src/js/widgets/dropdown_menu.js
@@ -11,8 +11,8 @@ var QWeb = core.qweb;
var DropdownMenu = Widget.extend({
template: 'web.DropdownMenu',
events: {
- 'click li.o_menu_item': '_onItemClick',
- 'click li.o_item_option': '_onOptionClick',
+ 'click .o_menu_item': '_onItemClick',
+ 'click .o_item_option': '_onOptionClick',
'click span.o_trash_button': '_onTrashClick',
'hidden.bs.dropdown': '_onBootstrapClose',
},
@@ -44,12 +44,12 @@ var DropdownMenu = Widget.extend({
this.dropdownCategory = dropdownHeader.category;
this.dropdownTitle = dropdownHeader.title;
this.dropdownIcon = dropdownHeader.icon;
- this.dropdownSymbol = dropdownHeader.symbol || 'caret';
+ this.dropdownSymbol = dropdownHeader.symbol || false;
// this parameter fixes the menu style. By default,
// the style used is the one used in the search view
this.dropdownStyle = dropdownHeader.style || {
el: {class: 'btn-group o_dropdown', attrs: {}},
- mainButton: {class: 'o_dropdown_toggler_btn btn btn-secondary dropdown-toggle'},
+ mainButton: {class: 'o_dropdown_toggler_btn btn btn-secondary dropdown-toggle' + (this.dropdownSymbol ? ' o-no-caret' : '')},
};
this.items = items;
_.each(this.items, this._prepareItem.bind(this));
@@ -105,8 +105,8 @@ var DropdownMenu = Widget.extend({
*/
_renderMenuItems: function () {
var newMenuItems = QWeb.render('DropdownMenu.MenuItems', {widget: this});
- this.$el.find('.o_menu_item,.divider[data-removable="1"]').remove();
- this.$('ul.o_dropdown_menu').prepend($(newMenuItems));
+ this.$el.find('.o_menu_item, .dropdown-divider[data-removable="1"]').remove();
+ this.$('.o_dropdown_menu').prepend($(newMenuItems));
},
/**
* this function computes some default values for some of the item keys
@@ -189,7 +189,7 @@ var DropdownMenu = Widget.extend({
* @param {jQueryEvent} event
*/
_onBootstrapClose: function () {
- _.each(this.items, function(item) {
+ _.each(this.items, function (item) {
item.isOpen = false;
});
this._renderMenuItems();
diff --git a/addons/web/static/src/js/widgets/switch_company_menu.js b/addons/web/static/src/js/widgets/switch_company_menu.js
index 01c224370d2..c9498950a04 100644
--- a/addons/web/static/src/js/widgets/switch_company_menu.js
+++ b/addons/web/static/src/js/widgets/switch_company_menu.js
@@ -18,7 +18,7 @@ var _t = core._t;
var SwitchCompanyMenu = Widget.extend({
template: 'SwitchCompanyMenu',
events: {
- 'click .dropdown-menu li a[data-menu]': '_onClick',
+ 'click .dropdown-item[data-menu]': '_onClick',
},
/**
* @override
@@ -53,8 +53,8 @@ var SwitchCompanyMenu = Widget.extend({
} else {
a = '<span style="margin-right: 24px;"/>';
}
- companiesList += '<li><a href="#" data-menu="company" data-company-id="' +
- company[0] + '">' + a + company[1] + '</a></li>';
+ companiesList += '<a href="#" class="dropdown-item" data-menu="company" data-company-id="' +
+ company[0] + '">' + a + company[1] + '</a>';
});
this.$('.dropdown-menu').html(companiesList);
return this._super();
diff --git a/addons/web/static/src/scss/dropdown.scss b/addons/web/static/src/scss/dropdown.scss
index 9a60d78d9d3..8287e098b32 100644
--- a/addons/web/static/src/scss/dropdown.scss
+++ b/addons/web/static/src/scss/dropdown.scss
@@ -5,7 +5,7 @@
.ui-autocomplete { // Copy style of bootstrap dropdown
background-image: none;
background-color: $dropdown-bg;
- border: 1px solid $dropdown-border;
+ border: $dropdown-border-width solid $dropdown-border-color;
font-size: $font-size-base;
padding: 5px 0px;
box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176);
@@ -41,7 +41,7 @@
.o_inline_dropdown {
position: relative;
- &> .dropdown-menu {
+ & > .dropdown-menu {
top: 0;
left: 100%;
}
@@ -52,9 +52,12 @@
}
@mixin dropdown-menu-mixin {
- .open .dropdown-menu > li {
- position: relative; // to allow absolute positionning inside the li
- > a {
+ .show .dropdown-menu {
+ > * {
+ position: relative; // to allow absolute positionning inside the items
+ }
+
+ .dropdown-item {
&:focus, &:active, &:focus:active {
outline: none;
}
@@ -62,7 +65,7 @@
@extend %dropdown-li-a-padding;
}
- &.dropdown-header {
+ .dropdown-header {
@extend %dropdown-li-a-padding;
color: $o-main-text-color;
diff --git a/addons/web/static/src/scss/dropdown_menu.scss b/addons/web/static/src/scss/dropdown_menu.scss
index 8024783d3c2..8f5b0c1f00a 100644
--- a/addons/web/static/src/scss/dropdown_menu.scss
+++ b/addons/web/static/src/scss/dropdown_menu.scss
@@ -1,38 +1,23 @@
.o_dropdown_menu {
- > li.divider:first-child {
+ > .dropdown-divider:first-child {
display: none;
}
- max-height: calc(100vh - 125px);
+ max-height: calc(100vh - 125px); // FIXME
overflow: auto;
- .o_submenu_switcher {
- float:right;
- width: 25px;
- text-align: center;
- }
- .o_trash_button {
- float:right;
- + .o_submenu_switcher {
- margin-right: 6px;
- }
- }
- ul {
- list-style-type: none;
- padding-left: 20px;
- }
- li.o_menu_item {
+ .o_menu_item {
position: relative;
- > a {
+ > .dropdown-item {
color: $o-main-text-color;
- padding-right: 25px;
+
&:hover {
color: darken($o-main-text-color, 10%);
}
}
&.selected {
- > a {
+ > .dropdown-item {
color: darken($o-main-text-color, 10%);
font-weight: bold;
&:before {
@@ -43,7 +28,7 @@
}
}
}
- li.divider:first-child {
+ .dropdown-divider:first-child {
display: none;
}
.o_item_option {
diff --git a/addons/web/static/src/scss/form_view.scss b/addons/web/static/src/scss/form_view.scss
index f6537e8cd07..51c584c916e 100644
--- a/addons/web/static/src/scss/form_view.scss
+++ b/addons/web/static/src/scss/form_view.scss
@@ -274,7 +274,7 @@
padding: 5px 0 2px 0;
min-width: 100px;
- > li > .btn {
+ .dropdown-item.btn {
min-width: 100%;
margin-bottom: 3px;
}
diff --git a/addons/web/static/src/scss/kanban_view.scss b/addons/web/static/src/scss/kanban_view.scss
index b377a93a0eb..bd595243d84 100644
--- a/addons/web/static/src/scss/kanban_view.scss
+++ b/addons/web/static/src/scss/kanban_view.scss
@@ -150,7 +150,7 @@
@include o-kanban-dropdown;
margin: (-$o-kanban-inside-vgutter - 1px) (-$o-kanban-inside-hgutter - 1px) 0 0;
}
- &.open .dropdown-toggle {
+ &.show .dropdown-toggle {
@include o-kanban-dropdown-open;
}
.dropdown-menu {
@@ -159,7 +159,7 @@
}
}
- &:hover .o_dropdown_kanban, .o_dropdown_kanban.open {
+ &:hover .o_dropdown_kanban, .o_dropdown_kanban.show {
visibility: visible;
}
@@ -342,7 +342,7 @@
margin-left: $o-kanban-inside-hgutter*2;
}
- &:hover .o_kanban_config, .o_kanban_config.open {
+ &:hover .o_kanban_config, .o_kanban_config.show {
visibility: visible;
margin-left: $o-kanban-inside-hgutter;
}
diff --git a/addons/web/static/src/scss/navbar.scss b/addons/web/static/src/scss/navbar.scss
index 9a3f3d9a718..66a080cf1bd 100644
--- a/addons/web/static/src/scss/navbar.scss
+++ b/addons/web/static/src/scss/navbar.scss
@@ -86,7 +86,7 @@
width: $o-navbar-height;
text-align: center;
}
- &.open > ul {
+ &.show > ul {
padding: 0;
> li {
@@ -115,27 +115,23 @@
&.o_menu_systray {
float: right;
- .open .dropdown-menu {
- left: auto;
- right: 0;
- }
}
}
- .open .dropdown-menu {
+ .dropdown-menu.show {
max-height: 90vh; // the dropdown should not overstep the viewport
min-width: 100%;
overflow: auto;
margin-top: 0;
@for $index from 3 through 5 {
- > li.o_menu_header_lvl_#{$index}, > li .o_menu_entry_lvl_#{$index} {
+ .o_menu_header_lvl_#{$index}, .o_menu_entry_lvl_#{$index} {
padding-left: $o-dropdown-hpadding + ($index - 2)*12px;
}
}
}
- .open .dropdown-toggle {
+ .show .dropdown-toggle {
background-color: $o-navbar-inverse-link-hover-bg;
}
.o_user_menu {
@@ -165,7 +161,7 @@
display: none;
}
- &.open .dropdown-menu {
+ .dropdown-menu.show {
max-height: none;
}
}
@@ -173,7 +169,7 @@
&.o_menu_sections {
width: 100%;
- > li.open .dropdown-menu {
+ .dropdown-menu.show {
position: static;
float: none;
background-color: transparent;
@@ -181,7 +177,7 @@
border: none;
overflow: visible;
- > li > a {
+ > .dropdown-item {
background-color: transparent;
color: inherit;
}
@@ -196,7 +192,7 @@
> li {
display: inline-block;
- &.open .dropdown-menu {
+ .dropdown-menu.show {
@include o-position-absolute($o-navbar-height, 0, 0, 0);
position: fixed;
width: auto;
@@ -225,10 +221,10 @@
}
@include media-breakpoint-down(md) {
- .o_switch_company_menu > .dropdown-menu {
- padding-top: 0px;
- li.bg-info {
- padding: 10px;
- }
- }
- }
+ .o_switch_company_menu > .dropdown-menu {
+ padding-top: 0px;
+ .bg-info {
+ padding: 10px;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/search_groupby_menu.scss b/addons/web/static/src/scss/search_groupby_menu.scss
deleted file mode 100644
index 4092b4b5fb7..00000000000
--- a/addons/web/static/src/scss/search_groupby_menu.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-// Group By
-.o_group_by_menu {
- @include o-selected-li;
-
- max-height: calc(100vh - 125px);
- overflow: auto;
-
- .o_add_group { // add button
- @include o-search-options-dropdown-custom-li;
- }
-
- .o_submenu_switcher {
- position: absolute;
- right: 0px;
- }
-}
diff --git a/addons/web/static/src/scss/search_view.scss b/addons/web/static/src/scss/search_view.scss
index 0ad27f5c391..700c13f7e84 100644
--- a/addons/web/static/src/scss/search_view.scss
+++ b/addons/web/static/src/scss/search_view.scss
@@ -1,5 +1,4 @@
-@mixin o-search-options-dropdown-custom-li {
- margin: 3px 25px;
+@mixin o-search-options-dropdown-custom-item {
width: auto;
max-width: 250px;
}
@@ -116,7 +115,7 @@
color: darken($o-main-text-color, 10%);
}
}
- &.open > a {
+ &.show > a {
font-weight: bold;
color: darken($o-main-text-color, 10%);
}
@@ -130,7 +129,7 @@
a:before {
@include o-caret-right;
@include o-position-absolute($top: 50%, $left: 10px);
- margin-top: (-$caret-width-base);
+ margin-top: (-$caret-width);
}
}
.o_open_menu {
@@ -138,7 +137,7 @@
a:before {
@include o-caret-down;
@include o-position-absolute($top: 50%, $left: 10px);
- margin-top: (-$caret-width-base);
+ margin-top: (-$caret-width);
}
}
@@ -150,7 +149,7 @@
overflow: auto;
.o_filter_condition {
- @include o-search-options-dropdown-custom-li;
+ @include o-search-options-dropdown-custom-item;
margin-bottom: 8px;
.o_or_filter { // or between conditions
display: none; // hidden for the first condition
@@ -177,7 +176,7 @@
}
.o_add_filter_menu { // apply and add buttons
display: none; // Needed by the webclient
- @include o-search-options-dropdown-custom-li;
+ @include o-search-options-dropdown-custom-item;
}
.o_submenu_switcher {
position: absolute;
@@ -196,7 +195,7 @@
max-height: calc(100vh - 125px);
overflow: auto;
- .divider {display: none;} // hide the divider by default (no favorite)
+ .dropdown-divider {display: none;} // hide the divider by default (no favorite)
.o-searchview-custom-private, .o-searchview-custom-public {
.o-remove-filter {
@include o-position-absolute(50%, 12px);
@@ -212,6 +211,6 @@
}
.o_save_name { // save button
display: none; // hidden by default
- @include o-search-options-dropdown-custom-li;
+ @include o-search-options-dropdown-custom-item;
}
}
diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss
index d88f21f83a1..e30a3d59d20 100644
--- a/addons/web/static/src/scss/ui.scss
+++ b/addons/web/static/src/scss/ui.scss
@@ -13,3 +13,9 @@
[aria-hidden="true"], [aria-hidden="1"] {
display: none!important;
}
+
+.dropdown-toggle.o-no-caret {
+ &::before, &::after {
+ content: normal;
+ }
+}
diff --git a/addons/web/static/src/scss/utils.scss b/addons/web/static/src/scss/utils.scss
index 4b76f10b1d2..a01ba14f5a4 100644
--- a/addons/web/static/src/scss/utils.scss
+++ b/addons/web/static/src/scss/utils.scss
@@ -72,7 +72,7 @@
// ------------------------------------------------------------------
// Caret
// ------------------------------------------------------------------
-@mixin o-caret-down($caret-width: $caret-width-base) {
+@mixin o-caret-down($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: 0;
border-left: $caret-width solid transparent;
@@ -80,7 +80,7 @@
border-top: $caret-width solid;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
-@mixin o-caret-up($caret-width: $caret-width-base) {
+@mixin o-caret-up($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: $caret-width solid;
border-left: $caret-width solid transparent;
@@ -88,7 +88,7 @@
border-top: 0;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
-@mixin o-caret-left($caret-width: $caret-width-base) {
+@mixin o-caret-left($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: $caret-width solid transparent;
border-left: 0;
@@ -96,7 +96,7 @@
border-top: $caret-width solid transparent;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
-@mixin o-caret-right($caret-width: $caret-width-base) {
+@mixin o-caret-right($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: $caret-width solid transparent;
border-left: $caret-width solid;
@@ -108,25 +108,22 @@
// ------------------------------------------------------------------
// Dropdowns
// ------------------------------------------------------------------
-@mixin o-selected-li {
- li {
+@mixin o-selected-li { // FIXME use active ?
+ .dropdown-item {
position: relative;
- > a {
- color: $o-main-text-color;
- &:hover {
- color: darken($o-main-text-color, 10%);
- }
+ color: $o-main-text-color;
+ &:hover {
+ color: darken($o-main-text-color, 10%);
}
+
&.selected {
- > a {
- color: darken($o-main-text-color, 10%);
- font-weight: bold;
- &:before {
- font-family: FontAwesome;
- position: absolute;
- left: 6px;
- content: "\f00c";
- }
+ color: darken($o-main-text-color, 10%);
+ font-weight: bold;
+ &:before {
+ font-family: FontAwesome;
+ position: absolute;
+ left: 6px;
+ content: "\f00c";
}
}
}
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 376aeb58e41..1eaa2e59b84 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -231,31 +231,31 @@
<a href="#" title="Open Developer Tools" aria-label="Open Developer Tools" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
<span class="fa fa-bug"/>
</a>
- <ul class="dropdown-menu o_debug_dropdown" role="menu"/>
+ <div class="dropdown-menu dropdown-menu-right o_debug_dropdown" role="menu"/>
</li>
</t>
<t t-name="WebClient.DebugManager.Global">
- <li><a role="menuitem" href="#" data-action="perform_js_tests">Run JS Tests</a></li>
- <li><a role="menuitem" href="#" data-action="perform_js_mobile_tests">Run JS Mobile Tests</a></li>
- <li><a role="menuitem" href="#" data-action="select_view">Open View</a></li>
+ <a role="menuitem" href="#" data-action="perform_js_tests" class="dropdown-item">Run JS Tests</a>
+ <a role="menuitem" href="#" data-action="perform_js_mobile_tests" class="dropdown-item">Run JS Mobile Tests</a>
+ <a role="menuitem" href="#" data-action="select_view" class="dropdown-item">Open View</a>
<t t-if="manager._events">
- <li class="divider" role="separator"/>
- <li><a role="menuitem" href="#" data-action="show_timelines">Toggle Timelines</a></li>
- <li><a role="menuitem" href="#" data-action="requests_clear">Clear Events</a></li>
+ <div class="dropdown-divider" role="separator"/>
+ <a role="menuitem" href="#" data-action="show_timelines" class="dropdown-item">Toggle Timelines</a>
+ <a role="menuitem" href="#" data-action="requests_clear" class="dropdown-item">Clear Events</a>
</t>
- <li class="divider o_debug_leave_section" role="separator"/>
- <li><a role="menuitem" href="#" data-action="split_assets">Activate Assets Debugging</a></li>
- <li><a role="menuitem" href="#" data-action="regenerateAssets">Regenerate Assets Bundles</a></li>
- <li><a role="menuitem" href="#" data-action="leave_debug_mode">Leave the Developer Tools</a></li>
+ <div class="dropdown-divider o_debug_leave_section" role="separator"/>
+ <a role="menuitem" href="#" data-action="split_assets" class="dropdown-item">Activate Assets Debugging</a>
+ <a role="menuitem" href="#" data-action="regenerateAssets" class="dropdown-item">Regenerate Assets Bundles</a>
+ <a role="menuitem" href="#" data-action="leave_debug_mode" class="dropdown-item">Leave the Developer Tools</a>
</t>
<t t-name="WebClient.DebugManager.Action">
<t t-if="action">
- <li class="divider" role="separator"/>
- <li><a role="menuitem" href="#" data-action="edit" t-att-data-model="action.type" t-att-data-id="action.id">Edit Action</a></li>
+ <div class="dropdown-divider" role="separator"/>
+ <a role="menuitem" href="#" data-action="edit" t-att-data-model="action.type" t-att-data-id="action.id" class="dropdown-item">Edit Action</a>
<t t-if="action.res_model">
- <li><a role="menuitem" href="#" data-action="get_view_fields">View Fields</a></li>
- <li><a role="menuitem" href="#" data-action="manage_filters">Manage Filters</a></li>
- <li><a role="menuitem" href="#" data-action="translate">Technical Translation</a></li>
+ <a role="menuitem" href="#" data-action="get_view_fields" class="dropdown-item">View Fields</a>
+ <a role="menuitem" href="#" data-action="manage_filters" class="dropdown-item">Manage Filters</a>
+ <a role="menuitem" href="#" data-action="translate" class="dropdown-item">Technical Translation</a>
</t>
</t>
</t>
@@ -272,21 +272,19 @@
</t>
<t t-name="WebClient.DebugManager.View">
<t t-if="view">
- <li role="separator" class="divider"/>
+ <div role="separator" class="dropdown-divider"/>
<t t-if="view.type === 'form'">
- <li><a role="menuitem" href="#" data-action="set_defaults">Set Defaults</a></li>
+ <a role="menuitem" href="#" data-action="set_defaults" class="dropdown-item">Set Defaults</a>
<t t-if="controller.getSelectedIds().length === 1">
- <li><a role="menuitem" href="#" data-action="get_metadata">View Metadata</a></li>
+ <a role="menuitem" href="#" data-action="get_metadata" class="dropdown-item">View Metadata</a>
</t>
</t>
- <li><a role="menuitem" href="#" data-action="fvg">Fields View Get</a></li>
+ <a role="menuitem" href="#" data-action="fvg" class="dropdown-item">Fields View Get</a>
<t t-if="can_edit">
- <li>
- <a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="view.fieldsView.view_id">
+ <a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="view.fieldsView.view_id" class="dropdown-item">
Edit View: <t t-esc="_.str.capitalize(view.type)"/>
- </a>
- </li>
- <li t-if="searchview and searchview.$el.is(':visible')"><a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="action.searchFieldsView.view_id">Edit SearchView</a></li>
+ </a>
+ <a t-if="searchview and searchview.$el.is(':visible')" role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="action.searchFieldsView.view_id" class="dropdown-item">Edit SearchView</a>
</t>
</t>
</t>
@@ -344,15 +342,15 @@
<div class="btn-group o_dropdown">
<button t-if="section.name != 'buttons'" class="o_dropdown_toggler_btn btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<t t-if="section.name == 'files'" t-raw="widget.items[section.name].length || ''"/>
- <t t-esc="section.label"/> <span class="caret"/>
+ <t t-esc="section.label"/>
</button>
<t t-if="section.name == 'buttons'" t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
<a t-att-title="item.title or None" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url or '#'" target="_blank">
<t t-raw="item.label"/>
</a>
</t>
- <ul class="dropdown-menu" role="menu">
- <li role="menuitem" t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
+ <div class="dropdown-menu" role="menu">
+ <t t-foreach="widget.items[section.name]" t-as="item">
<t t-if="section.name == 'files'">
<t t-set="item.title">
<b>Attachment : </b><br/>
@@ -369,12 +367,12 @@
<t t-raw="item.write_uid[1]"/> <t t-esc="item.write_date_string"/>
</t>
</t>
- <a t-att-title="item.title or None" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url or '#'">
+ <a t-attf-class="dropdown-item #{item.classname}" role="menuitem" t-att-title="item.title or None" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url or '#'">
<t t-raw="item.label"/>
<span t-if="section.name == 'files' and widget.options.editable and !item.callback" class="fa fa-trash-o o_sidebar_delete_attachment" t-att-data-id="item.id" title="Delete this attachment" role="img" aria-label="Delete this attachment"/>
</a>
- </li>
- <li role="menuitem" t-if="section.name == 'files' and widget.options.editable" class="o_sidebar_add_attachment">
+ </t>
+ <div role="menuitem" t-if="section.name == 'files' and widget.options.editable" class="dropdown-item o_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileuploadId"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
@@ -384,8 +382,8 @@
<input type="hidden" name="session_id" t-att-value="widget.getSession().session_id" t-if="widget.getSession().override_session"/>
<span>Add...</span>
</t>
- </li>
- </ul>
+ </div>
+ </div>
</div>
</t>
</t>
@@ -511,15 +509,15 @@
<t t-name="GraphView.buttons">
<div class="btn-group" role="toolbar" aria-label="Main actions">
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- Measures <span class="caret"/>
+ Measures
</button>
- <ul class="dropdown-menu o_graph_measures_list" role="menu">
- <li t-foreach="measures" t-as="measure" t-att-data-field="measure[0]">
- <a role="menuitem" href="#"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
- </li>
- <li role="separator" class="divider"></li>
- <li data-field="__count__"><a role="menuitem" href="#">Count</a></li>
- </ul>
+ <div class="dropdown-menu o_graph_measures_list" role="menu">
+ <t t-foreach="measures" t-as="measure">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-field="measure[0]"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
+ </t>
+ <div role="separator" class="dropdown-divider"/>
+ <a role="menuitem" href="#" class="dropdown-item" data-field="__count__">Count</a>
+ </div>
</div>
<div class="btn-group" role="toolbar" aria-label="Change graph">
<button class="btn btn-secondary fa fa-bar-chart-o o_graph_button" title="Bar Chart" aria-label="Bar Chart" data-mode="bar"/>
@@ -540,15 +538,15 @@
<t t-name="PivotView.buttons">
<div class="btn-group" role="toolbar" aria-label="Main actions">
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- Measures <span class="caret"/>
+ Measures
</button>
- <ul class="dropdown-menu o_pivot_measures_list" role="menu">
- <li t-foreach="measures" t-as="measure" t-att-data-field="measure[0]">
- <a role="menuitem" href="#"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
- </li>
- <li role="separator" class="divider"></li>
- <li data-field="__count"><a role="menuitem" href="#">Count</a></li>
- </ul>
+ <div class="dropdown-menu o_pivot_measures_list" role="menu">
+ <t t-foreach="measures" t-as="measure">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-field="measure[0]"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
+ </t>
+ <div role="separator" class="dropdown-divider"/>
+ <a role="menuitem" href="#" class="dropdown-item" data-field="__count">Count</a>
+ </div>
</div>
<div class="btn-group" role="toolbar" aria-label="Pivot settings">
<button class="btn btn-secondary fa fa-expand o_pivot_flip_button" title="Flip axis" aria-label="Flip axis"/>
@@ -557,29 +555,27 @@
</div>
</t>
<t t-name="PivotView.FieldSelection">
- <ul class="dropdown-menu o_pivot_field_menu" role="menu">
+ <div class="dropdown-menu o_pivot_field_menu" role="menu">
<t t-foreach="fields" t-as="field">
<t t-if="(field[1].type === 'date') || (field[1].type === 'datetime')">
- <li role="menuitem" aria-haspopup="true" t-att-data-field="field[0]" t-attf-class="o_inline_dropdown#{field[2] ? ' disabled' : ''}">
- <a href="#" class="o_pivot_field_selection">
+ <div role="menuitem" aria-haspopup="true" class="o_inline_dropdown">
+ <a href="#" t-att-data-field="field[0]" t-attf-class="dropdown-item o_pivot_field_selection#{field[2] ? ' disabled' : ''}">
<t t-esc="field[1].string"/>
</a>
- <ul class="dropdown-menu" role="menu">
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'day'">Day</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'week'">Week</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'month'">Month</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'quarter'">Quarter</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'year'">Year</a></li>
- </ul>
- </li>
+ <div class="dropdown-menu" role="menu">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'day'" t-att-data-field="field[0]">Day</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'week'" t-att-data-field="field[0]">Week</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'month'" t-att-data-field="field[0]">Month</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'quarter'" t-att-data-field="field[0]">Quarter</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'year'" t-att-data-field="field[0]">Year</a>
+ </div>
+ </div>
</t>
<t t-else="">
- <li t-att-data-field="field[0]" t-att-class="(field[2] ? 'disabled' : '')">
- <a role="menuitem" href="#"><t t-esc="field[1].string"/></a>
- </li>
+ <a href="#" role="menuitem" t-att-data-field="field[0]" t-attf-class="dropdown-item#{field[2] ? ' disabled' : ''}"><t t-esc="field[1].string"/></a>
</t>
</t>
- </ul>
+ </div>
</t>
<div t-name="PivotView.nodata">
<div class="o_view_nocontent" role="alert">
@@ -597,17 +593,16 @@
<t t-name="FormSelection">
<div class="btn-group o_selection" aria-atomic="true">
<a href="#" data-toggle="dropdown" aria-label="Dropdown menu" title="Dropdown menu"><span class="o_status"/></a>
- <ul class="dropdown-menu state" role="menu">
- </ul>
+ <div class="dropdown-menu state" role="menu"/>
</div>
</t>
<t t-name="FormSelection.items">
- <li t-foreach="states" t-as="rec" t-att-data-value="rec.name">
- <a role="menuitem" href="#">
+ <t t-foreach="states" t-as="rec">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-value="rec.name">
<span t-att-class="'o_status ' + (rec.state_class &amp;&amp; rec.state_class || '')"/>
<t t-raw="rec.state_name"/>
</a>
- </li>
+ </t>
</t>
<t t-name="FieldDomain.content">
<div t-if="hasModel" class="o_field_domain_panel">
@@ -636,10 +631,10 @@
<t t-if="widget.operator === '|'">Any</t>
<t t-if="widget.operator === '!'">None</t>
</button>
- <ul class="dropdown-menu" role="menu">
- <li><a role="menuitem" href="#" data-operator="&amp;">All</a></li>
- <li><a role="menuitem" href="#" data-operator="|">Any</a></li>
- </ul>
+ <div class="dropdown-menu" role="menu">
+ <a role="menuitem" href="#" class="dropdown-item" data-operator="&amp;">All</a>
+ <a role="menuitem" href="#" class="dropdown-item" data-operator="|">Any</a>
+ </div>
</div>
<strong t-else="">
<t t-if="widget.operator === '&amp;'">ALL</t>
@@ -901,12 +896,12 @@
</t>
<t t-name="FieldStatus.content">
<t t-if="selection_folded.length">
- <button type="button" class="btn o_arrow_button btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">More <span class="caret"/></button>
- <ul class="dropdown-menu o-status-more" role="menu">
- <li t-foreach="selection_folded" t-as="i">
+ <button type="button" class="btn o_arrow_button btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">More</button>
+ <div class="dropdown-menu o-status-more" role="menu">
+ <t t-foreach="selection_folded" t-as="i">
<t t-call="FieldStatus.content.button"/>
- </li>
- </ul>
+ </t>
+ </div>
</t>
<t t-foreach="selection_unfolded.reverse()" t-as="i">
<t t-call="FieldStatus.content.button"/>
@@ -1069,71 +1064,67 @@
<t t-if="widget.items.length !== 0">
<t t-set="group" t-value="0"/>
<t t-foreach="widget.items" t-as="item">
- <li t-if="group !== item.groupId" class="divider" data-removable="1"/>
- <li t-att-class="'o_menu_item ' + (item.isActive ? 'selected ' : '')"
+ <div t-if="group !== item.groupId" class="dropdown-divider" data-removable="1"/>
+ <div t-attf-class="o_menu_item#{item.isActive ? ' selected ' : ''}"
t-att-data-id="item.itemId">
- <a href="#">
+ <a href="#" class="dropdown-item">
<t t-esc="item.description"/>
<span t-if="item.isRemovable" t-att-data-id="item.itemId" class="o_trash_button" > <span class="fa fa-trash-o"></span> </span>
<span t-if="item.hasOptions" t-att-data-id="item.itemId" class="o_submenu_switcher">
<span t-att-class="item.isOpen ? 'fa fa-caret-down' : 'fa fa-caret-right'"></span>
</span>
</a>
- <ul t-if="item.hasOptions &amp;&amp; item.isOpen">
+ <ul t-if="item.hasOptions &amp;&amp; item.isOpen" class="list-unstyled">
<t t-set="subgroup" t-value="0"/>
<t t-foreach="_.values(item.options)" t-as="option">
- <li t-if="subgroup !== option.groupId" class="divider" data-removable="1"/>
- <li t-att-class="'o_item_option ' + (item.currentOptionId === option.optionId ? 'selected': '')"
+ <li t-if="subgroup !== option.groupId" class="dropdown-divider" data-removable="1"/>
+ <li t-attf-class="o_item_option#{item.currentOptionId === option.optionId ? ' selected': ''}"
t-att-data-item_id="item.itemId" t-att-data-option_id="option.optionId">
- <a href="#"><t t-esc="option.description"/></a>
+ <a href="#" class="dropdown-item pl-5"><t t-esc="option.description"/></a>
</li>
<t t-set="subgroup" t-value="option.groupId"/>
</t>
</ul>
- </li>
+ </div>
<t t-set="group" t-value="item.groupId"/>
</t>
</t>
</t>
-<div t-name="web.DropdownMenu" t-att-class="widget.dropdownStyle.el.class" t-att="widget.dropdownStyle.el.attrs" >
+<div t-name="web.DropdownMenu" t-att-class="widget.dropdownStyle.el.class" t-att="widget.dropdownStyle.el.attrs">
<button t-att-class="widget.dropdownStyle.mainButton.class" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
- <span t-att-class="widget.dropdownIcon"/> <t t-esc="widget.dropdownTitle"/> <span t-att-class="widget.dropdownSymbol"/>
+ <span t-att-class="widget.dropdownIcon"/> <t t-esc="widget.dropdownTitle"/> <span t-if="widget.dropdownSymbol" t-att-class="widget.dropdownSymbol"/>
</button>
- <ul class="dropdown-menu o_dropdown_menu" role="menu">
+ <div class="dropdown-menu o_dropdown_menu" role="menu">
<t t-call="DropdownMenu.MenuItems"/>
- </ul>
+ </div>
</div>
<t t-name="GroupbyMenuGenerator">
- <li t-if="Object.keys(widget.presentedFields).length !== 0 &amp;&amp; widget.items.length !== 0" class="o_generator_menu divider"/>
- <li t-if="Object.keys(widget.presentedFields).length !== 0" class="o_generator_menu o_add_custom_group ">
- <a href="#">Add Custom Group</a>
- </li>
- <li t-if="widget.generatorMenuIsOpen" class="o_generator_menu">
- <select class="o_input o_group_selector o_add_group">
+ <div t-if="Object.keys(widget.presentedFields).length !== 0 &amp;&amp; widget.items.length !== 0" class="dropdown-divider o_generator_menu"/>
+ <button t-if="Object.keys(widget.presentedFields).length !== 0" type="button" class="dropdown-item o_generator_menu o_add_custom_group">Add Custom Group</button>
+ <div t-if="widget.generatorMenuIsOpen" class="dropdown-item-text o_generator_menu">
+ <select class="w-auto o_input o_group_selector o_add_group">
<t t-foreach="widget.presentedFields" t-as="field">
<option t-att-value="field.name"><t t-esc="field.string"/></option>
</t>
</select>
- </li>
- <li t-if="widget.generatorMenuIsOpen" class="o_generator_menu">
+ </div>
+ <div t-if="widget.generatorMenuIsOpen" class="dropdown-item-text o_generator_menu">
<button type="button" class="btn btn-primary o_apply_group o_add_group" tabindex="-1">Apply</button>
- </li>
+ </div>
</t>
<t t-name="FiltersMenuGenerator">
- <li class="divider"/>
- <li t-if="Object.keys(widget.fields).length !== 0" class="o_add_custom_filter o_closed_menu">
- <a href="#">Add Custom Filter</a>
- </li>
- <li class="o_add_filter_menu">
+ <div class="dropdown-divider"/>
+ <button t-if="Object.keys(widget.fields).length !== 0" type="button" class="dropdown-item o_add_custom_filter o_closed_menu">Add Custom Filter</button>
+ <div class="dropdown-item-text o_add_filter_menu">
<button class="btn btn-primary o_apply_filter" type="button">Apply</button>
<button class="btn btn-secondary o_add_condition" type="button">
<span class="fa fa-plus-circle"/>
Add a condition
</button>
- </li>
+ </div>
</t>
@@ -1173,15 +1164,20 @@
<t t-esc="widget.model.get('label') + (widget.optionLabel ? (': ' + widget.optionLabel) : '')"/>
</span>
<t t-name="SearchView.autocomplete">
- <ul class="dropdown-menu o_searchview_autocomplete" role="menu"></ul>
+ <div class="dropdown-menu o_searchview_autocomplete" role="menu"/>
</t>
<t t-name="SearchView.filters">
- <li t-foreach="widget.filters" t-as="filter" t-if="!filter.visible || filter.visible()"
- t-att-title="filter.attrs.string ? filter.attrs.help : undefined"
- t-att-data-index="filter_index">
- <a role="menuitem" href="#"><t t-esc="filter.attrs.string or filter.attrs.help or filter.attrs.name or 'Ω'"/></a>
- </li>
+ <t t-foreach="widget.filters" t-as="filter">
+ <a t-if="!filter.visible || filter.visible()"
+ href="#"
+ class="dropdown-item"
+ t-att-title="filter.attrs.string ? filter.attrs.help : undefined"
+ t-att-data-index="filter_index"
+ role="menuitem">
+ <t t-esc="filter.attrs.string or filter.attrs.help or filter.attrs.name or 'Ω'"/>
+ </a>
+ </t>
</t>
<t t-name="SearchView.field">
<label t-att-class="'oe_label' + (attrs.help ? '_help' : '')"
@@ -1243,7 +1239,7 @@
</div>
</t>
<t t-name="SearchView.extended_search.proposition">
- <li role="menuitem" class="o_filter_condition">
+ <div role="menuitem" class="dropdown-item-text o_filter_condition">
<span class="o_or_filter">or</span>
<span>
<select class="o_input o_searchview_extended_prop_field">
@@ -1258,7 +1254,7 @@
</span>
<select class="o_input o_searchview_extended_prop_op"/>
<span class="o_searchview_extended_prop_value"/>
- </li>
+ </div>
</t>
<t t-name="SearchView.extended_search.proposition.float">
<input class="o_input"
@@ -1276,28 +1272,26 @@
</t>
<div t-name="SearchView.FavoriteMenu" class="btn-group o_dropdown">
- <button class="o_dropdown_toggler_btn btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1" aria-label="Favorites" title="Favorites">
- <span class="fa fa-star"/> Favorites <span t-attf-class="#{widget.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'}"/>
+ <button t-attf-class="o_dropdown_toggler_btn btn btn-secondary dropdown-toggle#{widget.isMobile ? ' o-no-caret' : ''}" data-toggle="dropdown" aria-expanded="false" tabindex="-1" aria-label="Favorites" title="Favorites">
+ <span class="fa fa-star"/> Favorites <span t-if="widget.isMobile" class="fa fa-chevron-right pull-right mt4"/>
</button>
- <ul class="dropdown-menu o_favorites_menu" role="menu">
- <li class="divider user_filter"/>
- <li class="divider shared_filter"/>
- <li class="o_save_search o_closed_menu">
- <a role="menuitem" href="#">Save current search</a>
- </li>
- <li role="menuitem" class="o_save_name">
- <input type="text"></input>
- </li>
- <li role="menuitem" class="o_save_name">
+ <div class="dropdown-menu o_favorites_menu" role="menu">
+ <div class="dropdown-divider user_filter"/>
+ <div class="dropdown-divider shared_filter"/>
+ <a role="menuitem" href="#" class="dropdown-item o_save_search o_closed_menu">Save current search</a>
+ <div role="menuitem" class="dropdown-item-text o_save_name">
+ <input type="text" class="o_input"></input>
+ </div>
+ <div role="menuitem" class="dropdown-item-text o_save_name">
<span><div class="o_checkbox"><input type="checkbox"/><span/></div> Use by default</span>
- </li>
- <li role="menuitem" class="o_save_name">
+ </div>
+ <div role="menuitem" class="dropdown-item-text o_save_name">
<span><div class="o_checkbox"><input type="checkbox"/><span/></div> Share with all users </span><span class="fa fa-users" role="img" aria-label="Users" title="Users"/>
- </li>
- <li class="o_save_name">
+ </div>
+ <div class="dropdown-item-text o_save_name">
<button role="menuitem" type="button" class="btn btn-primary">Save</button>
- </li>
- </ul>
+ </div>
+ </div>
</div>
<div t-name="ExportDialog" class="o_export">
@@ -1460,27 +1454,27 @@
<img class="img-circle oe_topbar_avatar" t-att-src="_s + '/web/static/src/img/user_menu_avatar.png'" alt="Avatar"/>
<span class="oe_topbar_name"/>
</a>
- <ul class="dropdown-menu" role="menu">
+ <div class="dropdown-menu dropdown-menu-right" role="menu">
<t t-call="UserMenu.Actions"/>
- </ul>
+ </div>
</li>
</t>
<t t-name="UserMenu.Actions">
- <li><a role="menuitem" href="#" data-menu="documentation">Documentation</a></li>
- <li><a role="menuitem" href="#" data-menu="support">Support</a></li>
- <li role="separator" class="divider"/>
- <li><a role="menuitem" href="#" data-menu="settings">Preferences</a></li>
- <li><a role="menuitem" href="#" data-menu="account">My Odoo.com account</a></li>
- <li><a role="menuitem" href="#" data-menu="logout">Log out</a></li>
+ <a role="menuitem" href="#" data-menu="documentation" class="dropdown-item">Documentation</a>
+ <a role="menuitem" href="#" data-menu="support" class="dropdown-item">Support</a>
+ <div role="separator" class="dropdown-divider"/>
+ <a role="menuitem" href="#" data-menu="settings" class="dropdown-item">Preferences</a>
+ <a role="menuitem" href="#" data-menu="account" class="dropdown-item">My Odoo.com account</a>
+ <a role="menuitem" href="#" data-menu="logout" class="dropdown-item">Log out</a>
</t>
<t t-name="SwitchCompanyMenu">
<li class="o_switch_company_menu">
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" href="#" aria-label="Dropdown menu" title="Dropdown menu">
- <span t-attf-class="#{widget.isMobile ? 'fa fa-building-o' : 'oe_topbar_name'}"/> <span class="caret"/>
+ <span t-attf-class="#{widget.isMobile ? 'fa fa-building-o' : 'oe_topbar_name'}"/>
</a>
- <ul class="dropdown-menu" role="menu"/>
+ <div class="dropdown-menu dropdown-menu-right" role="menu"/>
</li>
</t>
diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml
index a6d5ecc4ff4..4fc71cd6074 100644
--- a/addons/web/static/src/xml/kanban.xml
+++ b/addons/web/static/src/xml/kanban.xml
@@ -16,18 +16,18 @@
<span t-attf-id="#kanban_header_#{widget.id or widget.db_id}" class="o_column_title"><t t-esc="widget.title"/></span>
<span class="o_column_unfold"><i class="fa fa-arrows-h" role="img" aria-label="Unfold" title="Unfold"/></span>
<span class="o_kanban_config dropdown">
- <a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-gear" role="img" aria-label="Settings" title="Settings"/></a>
- <ul class="dropdown-menu" role="menu">
- <li><a role="menuitem" class="o_kanban_toggle_fold" href="#">Fold</a></li>
+ <a class="dropdown-toggle o-no-caret" data-toggle="dropdown" href="#"><i class="fa fa-gear" role="img" aria-label="Settings" title="Settings"/></a>
+ <div class="dropdown-menu" role="menu">
+ <a role="menuitem" class="dropdown-item o_kanban_toggle_fold" href="#">Fold</a>
<t t-if="widget.grouped_by_m2o">
- <li t-if="widget.editable and widget.id"><a role="menuitem" class="o_column_edit" href="#">Edit Stage</a></li>
- <li t-if="widget.deletable and widget.id"><a role="menuitem" class="o_column_delete" href="#">Delete</a></li>
+ <a t-if="widget.editable and widget.id" role="menuitem" class="dropdown-item o_column_edit" href="#">Edit Stage</a>
+ <a t-if="widget.deletable and widget.id" role="menuitem" class="dropdown-item o_column_delete" href="#">Delete</a>
</t>
<t t-if="widget.has_active_field">
- <li><a class="o_column_archive_records" href="#">Archive All</a></li>
- <li><a class="o_column_unarchive_records" href="#">Unarchive All</a></li>
+ <a href="#" class="dropdown-item o_column_archive_records">Archive All</a>
+ <a href="#" class="dropdown-item o_column_unarchive_records">Unarchive All</a>
</t>
- </ul>
+ </div>
</span>
<span t-if="widget.quick_create" class="o_kanban_quick_add"><i class="fa fa-plus" role="img" aria-label="Quick add" title="Quick add"/></span>
</div>