summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2018-07-27 12:42:10 +0200
committerqsm-odoo <qsm@odoo.com>2018-07-27 12:42:10 +0200
commit2b3017974bc7cd4b3a74f83c956224cfe4e5a918 (patch)
treeff6aab8dc6bfa7afbe9ef714ca157ebc0185d2fd /addons/web/static/src/js
parent8ed8b46f6434a2a3adea69e0134317e30bf9b936 (diff)
parent519594e9cab9a6362ef7c3e911605e4507a0a008 (diff)
[MERGE] *: migrate Bootstrap 3.3.7 to 4.1.3
See sub-commits for details. task-49280 Closes https://github.com/odoo/odoo/pull/25045
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/chrome/control_panel.js7
-rw-r--r--addons/web/static/src/js/chrome/menu.js61
-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/chrome/web_client.js6
-rw-r--r--addons/web/static/src/js/core/dialog.js4
-rw-r--r--addons/web/static/src/js/core/dom.js164
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js12
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js37
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js6
-rw-r--r--addons/web/static/src/js/fields/upgrade_fields.js2
-rw-r--r--addons/web/static/src/js/libs/bootstrap.js28
-rw-r--r--addons/web/static/src/js/services/config.js15
-rw-r--r--addons/web/static/src/js/services/crash_manager.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js1
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_renderer.js2
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js52
-rw-r--r--addons/web/static/src/js/views/graph/graph_controller.js10
-rw-r--r--addons/web/static/src/js/views/graph/graph_renderer.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column_progressbar.js10
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column_quick_create.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_controller.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_record.js7
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js2
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_controller.js13
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_renderer.js6
-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.js8
-rw-r--r--addons/web/static/src/js/views/search/search_inputs.js8
-rw-r--r--addons/web/static/src/js/views/search/search_view.js2
-rw-r--r--addons/web/static/src/js/views/search/search_view_mobile.js2
-rw-r--r--addons/web/static/src/js/views/view_dialogs.js4
-rw-r--r--addons/web/static/src/js/widgets/data_export.js20
-rw-r--r--addons/web/static/src/js/widgets/date_picker.js103
-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/model_field_selector.js6
-rw-r--r--addons/web/static/src/js/widgets/switch_company_menu.js6
41 files changed, 391 insertions, 287 deletions
diff --git a/addons/web/static/src/js/chrome/control_panel.js b/addons/web/static/src/js/chrome/control_panel.js
index 0913b574a3d..fb265390f51 100644
--- a/addons/web/static/src/js/chrome/control_panel.js
+++ b/addons/web/static/src/js/chrome/control_panel.js
@@ -245,11 +245,12 @@ var ControlPanel = Widget.extend({
var self = this;
var is_last = (index === length-1);
var li_content = bc.title && _.escape(bc.title.trim()) || data.noDisplayContent;
- var $bc = $('<li>')
- .append(is_last ? li_content : $('<a>').html(li_content))
+ var $bc = $('<li>', {class: 'breadcrumb-item'})
+ .append(is_last ? li_content : $('<a>', {href: '#'}).html(li_content))
.toggleClass('active', is_last);
if (!is_last) {
- $bc.click(function () {
+ $bc.click(function (ev) {
+ ev.preventDefault();
self.trigger_up('breadcrumb_clicked', {controllerID: bc.controllerID});
});
}
diff --git a/addons/web/static/src/js/chrome/menu.js b/addons/web/static/src/js/chrome/menu.js
index 1e253ba54f7..c96d4b17f8c 100644
--- a/addons/web/static/src/js/chrome/menu.js
+++ b/addons/web/static/src/js/chrome/menu.js
@@ -2,6 +2,7 @@ odoo.define('web.Menu', function (require) {
"use strict";
var core = require('web.core');
+var dom = require('web.dom');
var session = require('web.session');
var Widget = require('web.Widget');
@@ -37,66 +38,10 @@ var Menu = Widget.extend({
}
this.trigger('menu_bound');
- var lazyreflow = _.debounce(this.reflow.bind(this), 200);
- core.bus.on('resize', this, function() {
- if ($(window).width() < 768 ) {
- lazyreflow('all_outside');
- } else {
- lazyreflow();
- }
- });
- core.bus.trigger('resize');
+ dom.initAutoMoreMenu(this.$el);
this.is_bound.resolve();
},
-
- /**
- * Reflow the menu items and dock overflowing items into a "More" menu item.
- * Automatically called when 'menu_bound' event is triggered and on window resizing.
- *
- * @param {string} behavior If set to 'all_outside', all the items are displayed.
- * If not set, only the overflowing items are hidden.
- */
- reflow: function(behavior) {
- var self = this;
- var $more_container = this.$('#menu_more_container').hide();
- var $more = this.$('#menu_more');
- var $systray = this.$el.parents().find('.oe_systray');
-
- $more.children('li').insertBefore($more_container); // Pull all the items out of the more menu
-
- // 'all_outside' beahavior should display all the items, so hide the more menu and exit
- if (behavior === 'all_outside') {
- // Show list of menu items
- self.$el.show();
- this.$el.find('li').show();
- $more_container.hide();
- return;
- }
-
- // Hide all menu items
- var $toplevel_items = this.$el.find('li').not($more_container).not($systray.find('li')).hide();
- // Show list of menu items (which is empty for now since all menu items are hidden)
- self.$el.show();
- $toplevel_items.each(function() {
- var remaining_space = self.$el.parent().width() - $more_container.outerWidth();
- self.$el.parent().children(':visible').each(function() {
- remaining_space -= $(this).outerWidth();
- });
-
- if ($(this).width() >= remaining_space) {
- return false; // the current item will be appended in more_container
- }
- $(this).show(); // show the current item in menu bar
- });
- $more.append($toplevel_items.filter(':hidden').show());
- $more_container.toggle(!!$more.children().length);
- // Hide toplevel item if there is only one
- var $toplevel = self.$el.children("li:visible");
- if ($toplevel.length === 1) {
- $toplevel.hide();
- }
- },
/**
* Opens a given menu by id, as if a user had browsed to that menu by hand
* except does not trigger any event on the way
@@ -143,7 +88,7 @@ var Menu = Widget.extend({
}
// add a tooltip to cropped menu items
this.$secondary_menus.find('.oe_secondary_submenu li a span').each(function() {
- $(this).tooltip(this.scrollWidth > this.clientWidth ? {title: $(this).text().trim(), placement: 'right'} :'destroy');
+ $(this).tooltip(this.scrollWidth > this.clientWidth ? {title: $(this).text().trim(), placement: 'right'} : 'dispose');
});
},
/**
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/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js
index c4886cd0e89..d3ebabfab1e 100644
--- a/addons/web/static/src/js/chrome/web_client.js
+++ b/addons/web/static/src/js/chrome/web_client.js
@@ -3,6 +3,7 @@ odoo.define('web.WebClient', function (require) {
var AbstractWebClient = require('web.AbstractWebClient');
var config = require('web.config');
+var core = require('web.core');
var data_manager = require('web.data_manager');
var dom = require('web.dom');
var framework = require('web.framework');
@@ -48,6 +49,9 @@ return AbstractWebClient.extend({
return $.when(systray_menu_loaded, user_menu_loaded).then(function() {
self.menu.start();
self.bind_hashchange();
+ setTimeout(function () {
+ self.menu.$el.removeClass('d-none');
+ }, 200)
});
},
@@ -165,7 +169,7 @@ return AbstractWebClient.extend({
toggle_fullscreen: function(fullscreen) {
this._super(fullscreen);
if (!fullscreen) {
- this.menu.reflow();
+ core.bus.trigger('resize');
}
},
diff --git a/addons/web/static/src/js/core/dialog.js b/addons/web/static/src/js/core/dialog.js
index 847845ae17e..9cca9c1127a 100644
--- a/addons/web/static/src/js/core/dialog.js
+++ b/addons/web/static/src/js/core/dialog.js
@@ -40,7 +40,7 @@ var Dialog = Widget.extend({
* button is added to allow closing the dialog
* @param {string} [options.buttons[].text]
* @param {string} [options.buttons[].classes]
- * Default to 'btn-primary' if only one button, 'btn-default'
+ * Default to 'btn-primary' if only one button, 'btn-secondary'
* otherwise
* @param {boolean} [options.buttons[].close=false]
* @param {function} [options.buttons[].click]
@@ -123,7 +123,7 @@ var Dialog = Widget.extend({
_.each(buttons, function (buttonData) {
var $button = dom.renderButton({
attrs: {
- class: buttonData.classes || (buttons.length > 1 ? 'btn-default' : 'btn-primary'),
+ class: buttonData.classes || (buttons.length > 1 ? 'btn-secondary' : 'btn-primary'),
disabled: buttonData.disabled,
},
icon: buttonData.icon,
diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js
index e82db818bb5..a34a207fda8 100644
--- a/addons/web/static/src/js/core/dom.js
+++ b/addons/web/static/src/js/core/dom.js
@@ -20,6 +20,7 @@ odoo.define('web.dom', function (require) {
* something happens in the DOM.
*/
+var config = require('web.config');
var core = require('web.core');
/**
@@ -208,11 +209,10 @@ return {
* @param {Object} options
* @param {Object} [options.attrs] - Attributes to put on the button element
* @param {string} [options.attrs.type='button']
- * @param {string} [options.attrs.class='btn-default']
+ * @param {string} [options.attrs.class='btn-secondary']
* Note: automatically completed with "btn btn-X"
* (@see options.size for the value of X)
- * @param {string} [options.size='sm'] - @see options.attrs.class
- * Note: use 'md' for no sizing class
+ * @param {string} [options.size] - @see options.attrs.class
* @param {string} [options.icon]
* The specific fa icon class (for example "fa-home") or an URL for
* an image to use as icon.
@@ -235,10 +235,10 @@ return {
}
jQueryParams.class = 'btn';
- if (options.size !== 'md') {
- jQueryParams.class += (' btn-' + (options.size || 'sm'));
+ if (options.size) {
+ jQueryParams.class += (' btn-' + options.size);
}
- jQueryParams.class += (' ' + (extraClasses || 'btn-default'));
+ jQueryParams.class += (' ' + (extraClasses || 'btn-secondary'));
var $button = $('<button/>', jQueryParams);
@@ -262,33 +262,41 @@ return {
return $button;
},
/**
- * Renders a checkbox with standard odoo template. This does not use any xml
- * template to avoid forcing the frontend part to lazy load a xml file for
- * each widget which might want to create a simple checkbox.
+ * Renders a checkbox with standard odoo/BS template. This does not use any
+ * xml template to avoid forcing the frontend part to lazy load a xml file
+ * for each widget which might want to create a simple checkbox.
*
* @param {Object} [options]
* @param {Object} [options.prop]
* Allows to set the input properties (disabled and checked states).
* @param {string} [options.text]
* The checkbox's associated text. If none is given then a simple
- * checkbox without label structure is rendered.
+ * checkbox is rendered.
* @returns {jQuery}
*/
renderCheckbox: function (options) {
- var $container = $('<div class="o_checkbox"><input type="checkbox"/><span/></div>');
- if (options && options.prop) {
- $container.children('input').prop(options.prop);
+ var id = _.uniqueId('checkbox-');
+ var $container = $('<div/>', {
+ class: 'custom-control custom-checkbox',
+ });
+ var $input = $('<input/>', {
+ type: 'checkbox',
+ id: id,
+ class: 'custom-control-input',
+ });
+ var $label = $('<label/>', {
+ for: id,
+ class: 'custom-control-label',
+ text: options && options.text || '',
+ });
+ if (!options || !options.text) {
+ $label.html('&#8203;'); // BS checkboxes need some label content (so
+ // add a zero-width space when there is no text)
}
- if (options && options.text) {
- $container = $('<label/>').append(
- $container,
- $('<span/>', {
- class: 'ml8',
- text: options.text,
- })
- );
+ if (options && options.prop) {
+ $input.prop(options.prop);
}
- return $container;
+ return $container.append($input, $label);
},
/**
* Sets the selection range of a given input or textarea
@@ -308,5 +316,117 @@ return {
.select();
}
},
+ /**
+ * Creates an automatic 'more' dropdown-menu for a set of navbar items.
+ *
+ * @param {jQuery} $el
+ * @param {Object} [options]
+ * @param {string} [options.unfoldable='none']
+ * @param {function} [options.maxWidth]
+ * @param {string} [options.sizeClass='SM']
+ */
+ initAutoMoreMenu: function ($el, options) {
+ options = _.extend({
+ unfoldable: 'none',
+ maxWidth: false,
+ sizeClass: 'SM',
+ }, options || {});
+
+ var $extraItemsToggle = null;
+
+ var debouncedAdapt = _.debounce(_adapt, 250);
+ core.bus.on('resize', null, debouncedAdapt);
+ _adapt();
+
+ $el.data('dom:autoMoreMenu:destroy', function () {
+ _restore();
+ core.bus.off('resize', null, debouncedAdapt);
+ $el.removeData('dom:autoMoreMenu:destroy');
+ });
+
+ function _restore() {
+ if ($extraItemsToggle === null) {
+ return;
+ }
+ var $items = $extraItemsToggle.children('.dropdown-menu').children();
+ $items.addClass('nav-item');
+ $items.children().removeClass('dropdown-item').addClass('nav-link');
+ $items.insertBefore($extraItemsToggle);
+ $extraItemsToggle.remove();
+ $extraItemsToggle = null;
+ }
+
+ function _adapt() {
+ if (!$el.is(':visible')) {
+ return;
+ }
+
+ _restore();
+ if (config.device.size_class <= config.device.SIZES[options.sizeClass]) {
+ return;
+ }
+
+ var $allItems = $el.children();
+ var $unfoldableItems = $allItems.filter(options.unfoldable);
+ var $items = $allItems.not($unfoldableItems);
+
+ var maxWidth = 0;
+ if (options.maxWidth) {
+ maxWidth = options.maxWidth();
+ } else {
+ var rect = $el[0].getBoundingClientRect();
+ var style = window.getComputedStyle($el[0]);
+ maxWidth = (rect.right - rect.left);
+ maxWidth -= (parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth));
+ maxWidth -= _.reduce($unfoldableItems, function (sum, el) {
+ return sum + computeFloatOuterWidthWithMargins(el);
+ }, 0);
+ }
+
+ var nbItems = $items.length;
+ var menuItemsWidth = _.reduce($items, function (sum, el) {
+ return sum + computeFloatOuterWidthWithMargins(el);
+ }, 0);
+
+ if (maxWidth - menuItemsWidth >= -0.001) {
+ return
+ }
+
+ var $dropdownMenu = $('<ul/>', {class: 'dropdown-menu'});
+ $extraItemsToggle = $('<li/>', {class: 'nav-item dropdown o_extra_menu_items'})
+ .append($('<a/>', {href: '#', class: 'nav-link dropdown-toggle o-no-caret', 'data-toggle': 'dropdown'})
+ .append($('<i/>', {class: 'fa fa-plus'})))
+ .append($dropdownMenu);
+ $extraItemsToggle.insertAfter($items.last());
+
+ menuItemsWidth += computeFloatOuterWidthWithMargins($extraItemsToggle[0]);
+ do {
+ menuItemsWidth -= computeFloatOuterWidthWithMargins($items.eq(--nbItems)[0]);
+ } while (menuItemsWidth > maxWidth);
+
+ var $extraItems = $items.slice(nbItems).detach();
+ $extraItems.removeClass('nav-item');
+ $extraItems.children().removeClass('nav-link').addClass('dropdown-item');
+ $dropdownMenu.append($extraItems);
+ $extraItemsToggle.find('.nav-link').toggleClass('active', $extraItems.children().hasClass('active'));
+ }
+
+ function computeFloatOuterWidthWithMargins(el) {
+ var rect = el.getBoundingClientRect();
+ var style = window.getComputedStyle(el);
+ return rect.right - rect.left + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
+ }
+ },
+ /**
+ * Cleans what has been done by `initAutoMoreMenu'.
+ *
+ * @param {jQuery} $el
+ */
+ destroyAutoMoreMenu: function ($el) {
+ var destroyFunc = $el.data('dom:autoMoreMenu:destroy');
+ if (destroyFunc) {
+ destroyFunc.call(null);
+ }
+ },
};
});
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js
index eab0093ed50..7cf72791be5 100644
--- a/addons/web/static/src/js/fields/abstract_field.js
+++ b/addons/web/static/src/js/fields/abstract_field.js
@@ -304,7 +304,6 @@ var AbstractField = Widget.extend({
this._reset(record, event);
return this._render() || $.when();
},
-
/**
* Remove the invalid class on a field
*/
@@ -312,7 +311,15 @@ var AbstractField = Widget.extend({
this.$el.removeClass('o_field_invalid');
this.$el.removeAttr('aria-invalid');
},
-
+ /**
+ * Sets the given id on the focusable element of the field and as 'for'
+ * attribute of potential internal labels.
+ *
+ * @param {string} id
+ */
+ setIDForLabel: function (id) {
+ this.getFocusableElement().attr('id', id);
+ },
/**
* add the invalid class on a field
*/
@@ -320,7 +327,6 @@ var AbstractField = Widget.extend({
this.$el.addClass('o_field_invalid');
this.$el.attr('aria-invalid', 'true');
},
-
/**
* Update the modifiers with the newest value.
* Now this.attrs.modifiersValue can be used consistantly even with
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 51816220c9f..bd13305df0c 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -701,8 +701,8 @@ var FieldBoolean = AbstractField.extend({
// The formatValue of boolean fields renders HTML elements similar to
// the one rendered by the widget itself. Even though the event might
// have been fired on the non-widget version of this field, we can still
- // test the presence of its o_checkbox class.
- if (activated && options && options.event && $(options.event.target).parents('.o_checkbox').length) {
+ // test the presence of its custom class.
+ if (activated && options && options.event && $(options.event.target).closest('.custom-control.custom-checkbox').length) {
this._setValue(!this.value); // Toggle the checkbox
}
return activated;
@@ -737,6 +737,15 @@ var FieldBoolean = AbstractField.extend({
}
return rendered;
},
+ /**
+ * Associates the 'for' attribute of the internal label.
+ *
+ * @override
+ */
+ setIDForLabel: function (id) {
+ this._super.apply(this, arguments);
+ this.$('.custom-control-label').attr('for', id);
+ },
//--------------------------------------------------------------------------
// Private
@@ -1612,10 +1621,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 +1702,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();
}
},
});
@@ -1778,7 +1783,7 @@ var LabelSelection = AbstractField.extend({
_render: function () {
this.classes = this.nodeOptions && this.nodeOptions.classes || {};
var labelClass = this.classes[this.value] || 'primary';
- this.$el.addClass('label label-' + labelClass).text(this._formatValue(this.value));
+ this.$el.addClass('badge badge-' + labelClass).text(this._formatValue(this.value));
},
});
@@ -2693,9 +2698,9 @@ var ImageSelection = AbstractField.extend({
var self = this;
this.$el.empty();
_.each(this.nodeOptions, function (val, key) {
- var $container = $('<div>').addClass('col-xs-3 text-center');
+ var $container = $('<div>').addClass('col-3 text-center');
var $img = $('<img>')
- .addClass('img img-responsive img-thumbnail ml16')
+ .addClass('img img-fluid img-thumbnail ml16')
.toggleClass('btn-info', key === self.value)
.attr('src', val.image_link)
.data('key', key);
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index c1c458d1935..ba83de415e7 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -968,7 +968,7 @@ var FieldX2Many = AbstractField.extend({
_renderButtons: function () {
if (!this.isReadonly && this.view.arch.tag === 'kanban') {
this.$buttons = $(qweb.render('KanbanView.buttons', {
- btnClass: 'btn-default',
+ btnClass: 'btn-secondary',
create_text: this.nodeOptions.create_text,
}));
this.$buttons.on('click', 'button.o-kanban-button-new', this._onAddRecord.bind(this));
@@ -1887,7 +1887,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
this.$color_picker.dropdown('toggle');
this.$color_picker.attr("tabindex", 1).focus();
if (!tagColor) {
- this.$('.o_checkbox input').prop('checked', true);
+ this.$('.custom-checkbox input').prop('checked', true);
}
}
},
@@ -1909,7 +1909,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
var changes = {};
if ($target.is('.o_hide_in_kanban')) {
- var $checkbox = $('.o_hide_in_kanban .o_checkbox input');
+ var $checkbox = $('.o_hide_in_kanban .custom-checkbox input');
$checkbox.prop('checked', !$checkbox.prop('checked')); // toggle checkbox
this.prevColors = this.prevColors ? this.prevColors : {};
if ($checkbox.is(':checked')) {
diff --git a/addons/web/static/src/js/fields/upgrade_fields.js b/addons/web/static/src/js/fields/upgrade_fields.js
index 119a64881e3..dd91ca2efc2 100644
--- a/addons/web/static/src/js/fields/upgrade_fields.js
+++ b/addons/web/static/src/js/fields/upgrade_fields.js
@@ -94,7 +94,7 @@ var AbstractFieldUpgrade = {
this._super.apply(this, arguments);
this._insertEnterpriseLabel($("<span>", {
text: "Enterprise",
- 'class': "label label-primary oe_inline o_enterprise_label"
+ 'class': "badge badge-primary oe_inline o_enterprise_label"
}));
},
/**
diff --git a/addons/web/static/src/js/libs/bootstrap.js b/addons/web/static/src/js/libs/bootstrap.js
index 04ca2381d7d..135a6b65df6 100644
--- a/addons/web/static/src/js/libs/bootstrap.js
+++ b/addons/web/static/src/js/libs/bootstrap.js
@@ -7,23 +7,19 @@ odoo.define('web.bootstrap.extensions', function () {
*/
/* Bootstrap defaults overwrite */
-$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
-$.fn.tooltip.Constructor.DEFAULTS.html = true;
-$.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover focus click';
-$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
-$.fn.tooltip.Constructor.DEFAULTS.delay = { show: 1000, hide: 0 };
-//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
-var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
-$.fn.modal.Constructor.prototype.enforceFocus = function () { };
+$.fn.tooltip.Constructor.Default.placement = 'top';
+$.fn.tooltip.Constructor.Default.fallbackPlacement = ['bottom', 'right', 'left', 'top'];
+$.fn.tooltip.Constructor.Default.html = true;
+$.fn.tooltip.Constructor.Default.trigger = 'hover focus click';
+$.fn.tooltip.Constructor.Default.container = 'body';
+$.fn.tooltip.Constructor.Default.delay = { show: 1000, hide: 0 };
+
+var bootstrapShowFunction = $.fn.tooltip.Constructor.prototype.show;
$.fn.tooltip.Constructor.prototype.show = function () {
+ // Overwrite bootstrap tooltip method to prevent showing 2 tooltip at the
+ // same time
$('.tooltip').remove();
- //the following fix the bug when using placement
- //auto and the parent element does not exist anymore resulting in
- //an error. This should be remove once we updade bootstrap to a version that fix the bug
- //edit: bug has been fixed here : https://github.com/twbs/bootstrap/pull/13752
- var e = $.Event('show.bs.' + this.type);
- var inDom = $.contains(document.documentElement, this.$element[0]);
- if (e.isDefaultPrevented() || !inDom) return;
- return bootstrap_show_function.call(this);
+
+ return bootstrapShowFunction.call(this);
};
});
diff --git a/addons/web/static/src/js/services/config.js b/addons/web/static/src/js/services/config.js
index d05a263ef4e..946f7d39f55 100644
--- a/addons/web/static/src/js/services/config.js
+++ b/addons/web/static/src/js/services/config.js
@@ -41,22 +41,23 @@ var config = {
/**
* A frequent use case is to have a different render in 'mobile' mode,
* meaning when the screen is small. This flag (boolean) is true when
- * the size is XXS or XS. It is also updated dynamically.
+ * the size is XS/VSM/SM. It is also updated dynamically.
*
* @type Boolean
*/
isMobile: null,
/**
- * Mapping between the numbers 0,1,2,3,4,5 and some descriptions
+ * Mapping between the numbers 0,1,2,3,4,5,6 and some descriptions
*/
- SIZES: { XXS: 0, XS: 1, SM: 2, MD: 3, LG: 4, XL: 5 },
+ SIZES: { XS: 0, VSM: 1, SM: 2, MD: 3, LG: 4, XL: 5, XXL: 6 },
},
};
var medias = [
window.matchMedia('(max-width: 474px)'),
- window.matchMedia('(min-width: 475px) and (max-width: 767px)'),
+ window.matchMedia('(min-width: 475px) and (max-width: 575px)'),
+ window.matchMedia('(min-width: 576px) and (max-width: 767px)'),
window.matchMedia('(min-width: 768px) and (max-width: 991px)'),
window.matchMedia('(min-width: 992px) and (max-width: 1199px)'),
window.matchMedia('(min-width: 1200px) and (max-width: 1533px)'),
@@ -69,8 +70,8 @@ var medias = [
* @returns {integer} a number between 0 and 5, included
*/
function _getSizeClass() {
- for(var i = 0 ; i < medias.length ; i++) {
- if(medias[i].matches) {
+ for (var i = 0 ; i < medias.length ; i++) {
+ if (medias[i].matches) {
return i;
}
}
@@ -83,7 +84,7 @@ function _updateSizeProps() {
var sc = _getSizeClass();
if (sc !== config.device.size_class) {
config.device.size_class = sc;
- config.device.isMobile = config.device.size_class <= config.device.SIZES.SM;
+ config.device.isMobile = config.device.size_class <= config.device.SIZES.MD;
}
}
diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js
index a5b8cb32c13..b105913464e 100644
--- a/addons/web/static/src/js/services/crash_manager.js
+++ b/addons/web/static/src/js/services/crash_manager.js
@@ -142,7 +142,7 @@ var CrashManager = core.Class.extend({
});
});
dialog.on("closed", this, function () {
- $clipboardBtn.tooltip("destroy");
+ $clipboardBtn.tooltip('dispose');
clipboard.destroy();
});
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js
index 13a00dda046..197892f3361 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -152,7 +152,6 @@ var BasicRenderer = AbstractRenderer.extend({
// widget's $el
$node = $node.length ? $node : widget.$el;
$node.tooltip({
- delay: { show: 1000, hide: 0 },
title: function () {
return qweb.render('WidgetLabel.tooltip', {
debug: config.debug,
diff --git a/addons/web/static/src/js/views/calendar/calendar_renderer.js b/addons/web/static/src/js/views/calendar/calendar_renderer.js
index 4b4050b67cc..ffb4f41ad6b 100644
--- a/addons/web/static/src/js/views/calendar/calendar_renderer.js
+++ b/addons/web/static/src/js/views/calendar/calendar_renderer.js
@@ -98,7 +98,7 @@ var SidebarFilter = Widget.extend(FieldManagerMixin, {
this.many2one.filter_ids = _.without(_.pluck(this.filters, 'value'), 'all');
}
this.$el.on('click', '.o_remove', this._onFilterRemove.bind(this));
- this.$el.on('click', '.o_checkbox input', this._onFilterActive.bind(this));
+ this.$el.on('click', '.custom-checkbox input', this._onFilterActive.bind(this));
},
//--------------------------------------------------------------------------
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 646dfdd8c40..276173c6f9a 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -35,7 +35,7 @@ var FormRenderer = BasicRenderer.extend({
* @override
*/
start: function () {
- if (config.device.size_class <= config.device.SIZES.XXS) {
+ if (config.device.size_class <= config.device.SIZES.XS) {
this.$el.addClass('o_xxs_form_view');
}
return this._super.apply(this, arguments);
@@ -159,9 +159,9 @@ var FormRenderer = BasicRenderer.extend({
.removeAttr('disabled');
},
/**
- * Put the focus on the last activated widget.
+ * Put the focus on the last activated widget.
* This function is used when closing a dialog to give the focus back to the
- * form that has opened it and ensures that the focus is in the correct
+ * form that has opened it and ensures that the focus is in the correct
* field.
*/
focusLastActivatedWidget: function () {
@@ -181,7 +181,7 @@ var FormRenderer = BasicRenderer.extend({
var $notebook = $(this);
var name = $notebook.data('name');
var index = -1;
- $notebook.find('li').each(function (i) {
+ $notebook.find('.nav-link').each(function (i) {
if ($(this).hasClass('active')) {
index = i;
}
@@ -265,7 +265,6 @@ var FormRenderer = BasicRenderer.extend({
_addButtonTooltip: function (node, $button) {
var self = this;
$button.tooltip({
- delay: { show: 1000, hide: 0 },
title: function () {
return qweb.render('WidgetButton.tooltip', {
debug: config.debug,
@@ -364,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);
@@ -397,12 +396,13 @@ var FormRenderer = BasicRenderer.extend({
// Current API of odoo for rendering buttons is "if classes are given
// use those on top of the 'btn' and 'btn-{size}' classes, otherwise act
- // as if 'btn-default' class was given". The problem is that, for header
- // buttons only, we allowed users to only indicate their custom classes
- // without having to explicitely ask for the 'btn-default' class to be
- // added. We force it so here when no bootstrap btn type class is found.
- if ($button.not('.btn-primary, .btn-default, .btn-link, .btn-success, .btn-info, .btn-warning, .btn-danger').length) {
- $button.addClass('btn-default');
+ // as if 'btn-secondary' class was given". The problem is that, for
+ // header buttons only, we allowed users to only indicate their custom
+ // classes without having to explicitely ask for the 'btn-secondary'
+ // class to be added. We force it so here when no bootstrap btn type
+ // class is found.
+ if ($button.not('.btn-primary, .btn-secondary, .btn-link, .btn-success, .btn-info, .btn-warning, .btn-danger').length) {
+ $button.addClass('btn-secondary');
}
this._addOnClickAction($button, node);
@@ -612,10 +612,11 @@ var FormRenderer = BasicRenderer.extend({
'data-toggle': 'tab',
disable_anchor: 'true',
href: '#' + page_id,
+ class: 'nav-link',
role: 'tab',
text: page.attrs.string,
});
- return $('<li>').append($a);
+ return $('<li>', {class: 'nav-item'}).append($a);
},
/**
* @private
@@ -761,7 +762,7 @@ var FormRenderer = BasicRenderer.extend({
_renderTagNotebook: function (node) {
var self = this;
var $headers = $('<ul class="nav nav-tabs">');
- var $pages = $('<div class="tab-content nav nav-tabs">');
+ var $pages = $('<div class="tab-content">');
var autofocusTab = -1;
// renderedTabs is used to aggregate the generated $headers and $pages
// alongside their node, so that their modifiers can be registered once
@@ -785,7 +786,7 @@ var FormRenderer = BasicRenderer.extend({
});
if (renderedTabs.length) {
var tabToFocus = renderedTabs[Math.max(0, autofocusTab)];
- tabToFocus.$header.addClass('active');
+ tabToFocus.$header.find('.nav-link').addClass('active');
tabToFocus.$page.addClass('active');
}
// register the modifiers for each tab
@@ -793,12 +794,13 @@ var FormRenderer = BasicRenderer.extend({
self._registerModifiers(tab.node, self.state, tab.$header, {
callback: function (element, modifiers) {
// if the active tab is invisible, activate the first visible tab instead
- if (modifiers.invisible && element.$el.hasClass('active')) {
- element.$el.removeClass('active');
+ var $link = element.$el.find('.nav-link');
+ if (modifiers.invisible && $link.hasClass('active')) {
+ $link.removeClass('active');
tab.$page.removeClass('active');
- var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first()');
+ var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first() > a');
$firstVisibleTab.addClass('active');
- $pages.find($firstVisibleTab.find('a').attr('href')).addClass('active');
+ $pages.find($firstVisibleTab.attr('href')).addClass('active');
}
},
});
@@ -859,7 +861,7 @@ var FormRenderer = BasicRenderer.extend({
this.defs = defs;
var $form = this._renderNode(this.arch).addClass(this.className);
delete this.defs;
-
+
return $.when.apply($, defs).then(function () {
self._updateView($form.contents());
}, function () {
@@ -867,7 +869,7 @@ var FormRenderer = BasicRenderer.extend({
}).then(function(){
if (self.lastActivatedFieldIndex >= 0) {
self._activateNextFieldWidget(self.state, self.lastActivatedFieldIndex);
- }
+ }
});
},
/**
@@ -900,7 +902,7 @@ var FormRenderer = BasicRenderer.extend({
// enterprise label will be displayed as many times as the field
// exists on settings.
var $widgets = self.$('.o_field_widget[name=' + widget.name + ']');
- var $label = idForLabel ? self.$('label[for=' + idForLabel + ']') : $();
+ var $label = idForLabel ? self.$('.o_form_label[for=' + idForLabel + ']') : $();
$label = $label.eq($widgets.index(widget.$el));
if (config.debug || widget.attrs.help || widget.field.help) {
self._addFieldTooltip(widget, $label);
@@ -920,7 +922,7 @@ var FormRenderer = BasicRenderer.extend({
* @param {idForLabel} string
*/
_setIDForLabel: function (widget, idForLabel) {
- widget.getFocusableElement().attr('id', idForLabel);
+ widget.setIDForLabel(idForLabel);
},
//--------------------------------------------------------------------------
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 e7f25c23fdd..b6a1c121f0f 100644
--- a/addons/web/static/src/js/views/graph/graph_controller.js
+++ b/addons/web/static/src/js/views/graph/graph_controller.js
@@ -45,7 +45,7 @@ var GraphController = AbstractController.extend(GroupByMenuInterfaceMixin,{
destroy: function () {
if (this.$buttons) {
// remove jquery's tooltip() handlers
- this.$buttons.find('button').off().tooltip('destroy');
+ this.$buttons.find('button').off().tooltip('dispose');
}
this._super.apply(this, arguments);
},
@@ -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/graph/graph_renderer.js b/addons/web/static/src/js/views/graph/graph_renderer.js
index 1fbd6572a9a..686bbaee842 100644
--- a/addons/web/static/src/js/views/graph/graph_renderer.js
+++ b/addons/web/static/src/js/views/graph/graph_renderer.js
@@ -243,7 +243,7 @@ return AbstractRenderer.extend({
svg.transition().duration(100);
- var legend_right = config.device.size_class > config.device.SIZES.XS;
+ var legend_right = config.device.size_class > config.device.SIZES.VSM;
var chart = nv.models.pieChart().labelType('percent');
chart.options({
diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js
index 95e3f1e85b1..a1c7e415470 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column.js
@@ -153,7 +153,7 @@ var KanbanColumn = Widget.extend({
this.$el.toggleClass('o_column_folded', this.folded && !config.device.isMobile);
var tooltip = this.data.count + _t(' records');
tooltip = '<p>' + tooltip + '</p>' + this.tooltipInfo;
- this.$header.find('.o_kanban_header_title').tooltip({html: true}).attr('data-original-title', tooltip);
+ this.$header.find('.o_kanban_header_title').tooltip({}).attr('data-original-title', tooltip);
if (!this.remaining) {
this.$('.o_kanban_load_more').remove();
} else {
diff --git a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
index 7af6b677dcf..0bfe5027876 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
@@ -133,9 +133,8 @@ var KanbanColumnProgressBar = Widget.extend({
});
if (this.progressBarHelp && _.every(this.subgroupCounts, function (val) { return val === 0; })) {
this.$el.tooltip({
- delay: '0',
- trigger:'hover',
- placement: 'top',
+ delay: 0,
+ trigger: 'hover',
title: this.progressBarHelp,
});
}
@@ -152,9 +151,8 @@ var KanbanColumnProgressBar = Widget.extend({
// Adapt tooltip
$bar.attr('data-original-title', count + ' ' + key);
$bar.tooltip({
- delay: '0',
- trigger:'hover',
- placement: 'top'
+ delay: 0,
+ trigger: 'hover',
});
// Adapt active state
diff --git a/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js b/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js
index 170b950a49d..b2a38d4e53e 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js
@@ -184,7 +184,7 @@ var ColumnQuickCreate = Widget.extend({
examples: this.examples,
})),
buttons: [{
- classes: 'btn-primary pull-right',
+ classes: 'btn-primary float-right',
close: true,
text: _t('Got it'),
}],
diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js
index 26846e2c511..ab05fabd517 100644
--- a/addons/web/static/src/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/js/views/kanban/kanban_controller.js
@@ -119,7 +119,7 @@ var KanbanController = BasicController.extend({
return this._super.apply(this, arguments);
},
/**
- * In grouped mode, set 'Create' button as btn-default if there is no column
+ * In grouped mode, set 'Create' button as btn-secondary if there is no column
* (except if we can't create new columns)
*
* @private
diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js
index 247f8eca90f..627543b3422 100644
--- a/addons/web/static/src/js/views/kanban/kanban_record.js
+++ b/addons/web/static/src/js/views/kanban/kanban_record.js
@@ -99,8 +99,7 @@ var KanbanRecord = Widget.extend({
var tooltip = $el.attr('tooltip');
if (tooltip) {
$el.tooltip({
- 'html': true,
- 'title': self.qweb.render(tooltip, self.qweb_context)
+ title: self.qweb.render(tooltip, self.qweb_context)
});
}
});
@@ -350,7 +349,7 @@ var KanbanRecord = Widget.extend({
_setFieldDisplay: function ($el, fieldName) {
// attribute display
if (this.fieldsInfo[fieldName].display === 'right') {
- $el.addClass('pull-right');
+ $el.addClass('float-right');
} else if (this.fieldsInfo[fieldName].display === 'full') {
$el.addClass('o_text_block');
}
@@ -490,7 +489,7 @@ var KanbanRecord = Widget.extend({
if (elem === event.currentTarget) {
ischild = false;
}
- var test_event = events && events.click && (events.click.length > 1 || events.click[0].namespace !== "tooltip");
+ var test_event = events && events.click && (events.click.length > 1 || events.click[0].namespace !== 'bs.tooltip');
if (ischild) {
children.push(elem);
if (test_event) {
diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index 82a08b3b27f..20d68744f6a 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -653,7 +653,7 @@ var ListRenderer = BasicRenderer.extend({
return this._super();
}
- var $table = $('<table>').addClass('o_list_view table table-condensed table-hover table-striped');
+ var $table = $('<table>').addClass('o_list_view table table-sm table-hover table-striped');
this.$el
.addClass('table-responsive')
.append($table);
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/pivot/pivot_renderer.js b/addons/web/static/src/js/views/pivot/pivot_renderer.js
index b3953076161..9312b27f1ef 100644
--- a/addons/web/static/src/js/views/pivot/pivot_renderer.js
+++ b/addons/web/static/src/js/views/pivot/pivot_renderer.js
@@ -9,7 +9,7 @@ var QWeb = core.qweb;
var PivotRenderer = AbstractRenderer.extend({
tagName: 'table',
- className: 'table-hover table-condensed table-bordered',
+ className: 'table-hover table-sm table-bordered',
events: _.extend({}, AbstractRenderer.prototype.events, {
'hover td': '_onTdHover',
}),
@@ -105,7 +105,7 @@ var PivotRenderer = AbstractRenderer.extend({
}
$row.append($cell);
- $cell.toggleClass('hidden-xs', (cell.expanded !== undefined) || (cell.measure !== undefined && j < headers[i].length - this.state.measures.length));
+ $cell.toggleClass('d-none d-md-table-cell', (cell.expanded !== undefined) || (cell.measure !== undefined && j < headers[i].length - this.state.measures.length));
if (cell.height > 1) {
$cell.css('padding', 0);
}
@@ -159,7 +159,7 @@ var PivotRenderer = AbstractRenderer.extend({
}
$row.append($cell);
- $cell.toggleClass('hidden-xs', j < length - nbrMeasures);
+ $cell.toggleClass('d-none d-md-table-cell', j < length - nbrMeasures);
}
$tbody.append($row);
}
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..af5425ec2d7 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 float-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 7b3b8e31fef..d686a4d55cb 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',
}),
@@ -78,14 +78,14 @@ var GroupByMenu = DropdownMenu.extend({
if (options && options.headerStyle === 'primary') {
style = {
el: {class: 'btn-group o_graph_groupbys_menu o_dropdown', attrs: {'role': 'group'}},
- mainButton: {class: 'btn btn-primary btn-sm dropdown-toggle'},
+ mainButton: {class: 'btn btn-primary dropdown-toggle'},
};
}
var dropdownHeader = {
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 float-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/views/search/search_view.js b/addons/web/static/src/js/views/search/search_view.js
index 9e1f70fec22..2bac31ed27f 100644
--- a/addons/web/static/src/js/views/search/search_view.js
+++ b/addons/web/static/src/js/views/search/search_view.js
@@ -535,7 +535,7 @@ var SearchView = Widget.extend({
* puts the focus on the search input
*/
_focusInput: function () {
- if (!config.device.touch && config.device.size_class >= config.device.SIZES.SM) {
+ if (!config.device.touch && config.device.size_class >= config.device.SIZES.MD) {
this.$('input').focus();
}
},
diff --git a/addons/web/static/src/js/views/search/search_view_mobile.js b/addons/web/static/src/js/views/search/search_view_mobile.js
index 852a65c0a37..ea7fe33ad81 100644
--- a/addons/web/static/src/js/views/search/search_view_mobile.js
+++ b/addons/web/static/src/js/views/search/search_view_mobile.js
@@ -54,7 +54,7 @@ SearchView.include({
* @private
*/
_toggleMobileSearchView: function () {
- this.$('.o_enable_searchview').toggleClass('btn-default', !!this.query.length);
+ this.$('.o_enable_searchview').toggleClass('btn-secondary', !!this.query.length);
this.$('.o_mobile_search').toggleClass('o_hidden');
},
diff --git a/addons/web/static/src/js/views/view_dialogs.js b/addons/web/static/src/js/views/view_dialogs.js
index ed0adf0ff3b..e99f81ccb08 100644
--- a/addons/web/static/src/js/views/view_dialogs.js
+++ b/addons/web/static/src/js/views/view_dialogs.js
@@ -109,7 +109,7 @@ var FormViewDialog = ViewDialog.extend({
options = options || {};
options.buttons = [{
text: (readonly ? _t("Close") : _t("Discard")),
- classes: "btn-default o_form_button_cancel",
+ classes: "btn-secondary o_form_button_cancel",
close: true,
click: function () {
if (!readonly) {
@@ -360,7 +360,7 @@ var SelectCreateDialog = ViewDialog.extend({
// Set the dialog's buttons
self.__buttons = [{
text: _t("Cancel"),
- classes: "btn-default o_form_button_cancel",
+ classes: "btn-secondary o_form_button_cancel",
close: true,
}];
if (!self.options.no_create) {
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/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js
index 8f87b36c874..9d47e79f6a7 100644
--- a/addons/web/static/src/js/widgets/date_picker.js
+++ b/addons/web/static/src/js/widgets/date_picker.js
@@ -1,69 +1,74 @@
odoo.define('web.datepicker', function (require) {
"use strict";
-var core = require('web.core');
var field_utils = require('web.field_utils');
var time = require('web.time');
var Widget = require('web.Widget');
-var _t = core._t;
-
var DateWidget = Widget.extend({
template: "web.datepicker",
type_of_date: "date",
events: {
- 'dp.change': 'changeDatetime',
- 'dp.show': '_onShow',
+ 'change.datetimepicker': 'changeDatetime',
+ 'show.datetimepicker': '_onShow',
+ 'click input.o_datepicker_input': '_onClick',
'change .o_datepicker_input': 'changeDatetime',
+ 'input input': '_onInput',
},
/**
* @override
*/
- init: function(parent, options) {
+ init: function (parent, options) {
this._super.apply(this, arguments);
- var l10n = _t.database.parameters;
-
this.name = parent.name;
- this.options = _.defaults(options || {}, {
+ this.options = _.extend({
format : this.type_of_date === 'datetime' ? time.getLangDatetimeFormat() : time.getLangDateFormat(),
minDate: moment({ y: 1900 }),
maxDate: moment().add(200, "y"),
- calendarWeeks: true,
+ useCurrent: false,
icons: {
time: 'fa fa-clock-o',
date: 'fa fa-calendar',
- next: 'fa fa-chevron-right',
- previous: 'fa fa-chevron-left',
up: 'fa fa-chevron-up',
down: 'fa fa-chevron-down',
- close: 'fa fa-times',
+ previous: 'fa fa-chevron-left',
+ next: 'fa fa-chevron-right',
+ today: 'fa fa-calendar-check-o',
+ clear: 'fa fa-delete',
+ close: 'fa fa-times'
+ },
+ calendarWeeks: true,
+ buttons: {
+ showToday: false,
+ showClear: false,
+ showClose: false,
},
- locale : moment.locale(),
- allowInputToggle: true,
- keyBinds: null,
widgetParent: 'body',
- useCurrent: false,
- });
+ keyBinds: null,
+ allowInputToggle: true,
+ }, options || {});
},
/**
* @override
*/
- start: function() {
+ start: function () {
this.$input = this.$('input.o_datepicker_input');
- this.$input.focus(function(e) {
+ this.$input.focus(function (e) {
e.stopImmediatePropagation();
});
+ this.__libInput = true;
this.$input.datetimepicker(this.options);
- this.picker = this.$input.data('DateTimePicker');
- this.$input.click(this.picker.toggle.bind(this.picker));
+ this.__libInput = false;
this._setReadonly(false);
},
/**
* @override
*/
- destroy: function() {
- this.picker.destroy();
+ destroy: function () {
+ this.__libInput = true;
+ this.$input.datetimepicker('destroy');
+ this.__libInput = false;
this._super.apply(this, arguments);
},
@@ -82,7 +87,7 @@ var DateWidget = Widget.extend({
var hasChanged = !oldValue !== !newValue;
if (oldValue && newValue) {
var formattedOldValue = oldValue.format(time.getLangDatetimeFormat());
- var formattedNewValue = newValue.format(time.getLangDatetimeFormat())
+ var formattedNewValue = newValue.format(time.getLangDatetimeFormat());
if (formattedNewValue !== formattedOldValue) {
hasChanged = true;
}
@@ -106,13 +111,13 @@ var DateWidget = Widget.extend({
*/
isValid: function () {
var value = this.$input.val();
- if(value === "") {
+ if (value === "") {
return true;
} else {
try {
this._parseClient(value);
return true;
- } catch(e) {
+ } catch (e) {
return false;
}
}
@@ -124,9 +129,9 @@ var DateWidget = Widget.extend({
this.set({'value': value});
var formatted_value = value ? this._formatClient(value) : null;
this.$input.val(formatted_value);
- if (this.picker) {
- this.picker.date(value || null);
- }
+ this.__libInput = true;
+ this.$input.datetimepicker('date', value || null);
+ this.__libInput = false;
},
//--------------------------------------------------------------------------
@@ -162,7 +167,7 @@ var DateWidget = Widget.extend({
*
* @private
*/
- _setValueFromUi: function() {
+ _setValueFromUi: function () {
var value = this.$input.val() || false;
this.setValue(this._parseClient(value));
},
@@ -172,6 +177,23 @@ var DateWidget = Widget.extend({
//--------------------------------------------------------------------------
/**
+ * @private
+ */
+ _onClick: function () {
+ this.__libInput = true;
+ this.$input.datetimepicker('toggle');
+ this.__libInput = false;
+ },
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onInput: function (ev) {
+ if (this.__libInput) {
+ ev.stopImmediatePropagation();
+ }
+ },
+ /**
* set the date of the picker by the current date or the today date
*
* @private
@@ -179,9 +201,11 @@ var DateWidget = Widget.extend({
_onShow: function () {
//when opening datetimepicker the date and time by default should be the one from
//the input field if any or the current day otherwise
- if(this.$input.val().length !== 0 && this.isValid()) {
+ if (this.$input.val().length !== 0 && this.isValid()) {
var value = this._parseClient(this.$input.val());
- this.picker.date(value);
+ this.__libInput = true;
+ this.$input.datetimepicker('date', value);
+ this.__libInput = false;
this.$input.select();
}
},
@@ -189,11 +213,14 @@ var DateWidget = Widget.extend({
var DateTimeWidget = DateWidget.extend({
type_of_date: "datetime",
- init: function() {
- this._super.apply(this, arguments);
- this.options = _.defaults(this.options, {
- showClose: true,
- });
+ init: function (parent, options) {
+ this._super(parent, _.extend({
+ buttons: {
+ showToday: false,
+ showClear: false,
+ showClose: true,
+ },
+ }, options || {}));
},
});
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 a3a83519678..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-sm btn-default 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/model_field_selector.js b/addons/web/static/src/js/widgets/model_field_selector.js
index 81abfbe0d6c..e9990ac5105 100644
--- a/addons/web/static/src/js/widgets/model_field_selector.js
+++ b/addons/web/static/src/js/widgets/model_field_selector.js
@@ -253,7 +253,7 @@ var ModelFieldSelector = Widget.extend({
if (!this._isOpen) return;
this._isOpen = false;
- this.$popover.addClass("hidden");
+ this.$popover.addClass('d-none');
if (this.dirty) {
this.dirty = false;
@@ -332,7 +332,7 @@ var ModelFieldSelector = Widget.extend({
}));
// Toggle the warning message
- this.$valid.toggleClass("hidden", !!this.isValid());
+ this.$valid.toggleClass('d-none', !!this.isValid());
// Adapt the popover content
var page = _.last(this.pages);
@@ -376,7 +376,7 @@ var ModelFieldSelector = Widget.extend({
if (this._isOpen) return;
this._isOpen = true;
- this.$popover.removeClass("hidden");
+ this.$popover.removeClass('d-none');
},
/**
* Toggles the valid status of the widget and display the error message if
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();