summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/core/dom.js
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2018-07-02 16:49:41 +0200
committerqsm-odoo <qsm@odoo.com>2018-07-27 12:36:54 +0200
commit6dc37ee461c967bc2180fddaa0910007b4552054 (patch)
treec2b9bd05cfeaa538ef04be862926598b950bd823 /addons/web/static/src/js/core/dom.js
parent76f714dca8957233ba3bbca73f340fa21244f5f2 (diff)
[REF] web, *: share and adapt code for auto "more" buttons for navbars
* portal, web_tour, website, base Before this commit, there were 3 different implementations for the same feature: the "more" button in the community navbar, the "+" button for the website menu and the "+" button in the enterprise navbar. As those implementation were now broken with BS4, it was a good time to share the code of those 3 features.
Diffstat (limited to 'addons/web/static/src/js/core/dom.js')
-rw-r--r--addons/web/static/src/js/core/dom.js113
1 files changed, 113 insertions, 0 deletions
diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js
index d695cf18296..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');
/**
@@ -315,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);
+ }
+ },
};
});