diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/chrome/menu.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/chrome/menu.js')
| -rw-r--r-- | addons/web/static/src/js/chrome/menu.js | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/addons/web/static/src/js/chrome/menu.js b/addons/web/static/src/js/chrome/menu.js new file mode 100644 index 00000000..28585aa1 --- /dev/null +++ b/addons/web/static/src/js/chrome/menu.js @@ -0,0 +1,243 @@ +odoo.define('web.Menu', function (require) { +"use strict"; + +var AppsMenu = require('web.AppsMenu'); +var config = require('web.config'); +var core = require('web.core'); +var dom = require('web.dom'); +var SystrayMenu = require('web.SystrayMenu'); +var UserMenu = require('web.UserMenu'); +var Widget = require('web.Widget'); + +UserMenu.prototype.sequence = 0; // force UserMenu to be the right-most item in the systray +SystrayMenu.Items.push(UserMenu); + +var QWeb = core.qweb; + +var Menu = Widget.extend({ + template: 'Menu', + menusTemplate: 'Menu.sections', + events: { + 'mouseover .o_menu_sections > li:not(.show)': '_onMouseOverMenu', + 'click .o_menu_brand': '_onAppNameClicked', + }, + + init: function (parent, menu_data) { + var self = this; + this._super.apply(this, arguments); + + this.$menu_sections = {}; + this.menu_data = menu_data; + + // Prepare navbar's menus + var $menu_sections = $(QWeb.render(this.menusTemplate, { + menu_data: this.menu_data, + })); + $menu_sections.filter('section').each(function () { + self.$menu_sections[parseInt(this.className, 10)] = $(this).children('li'); + }); + + // Bus event + core.bus.on('change_menu_section', this, this.change_menu_section); + }, + start: function () { + var self = this; + + this.$menu_apps = this.$('.o_menu_apps'); + this.$menu_brand_placeholder = this.$('.o_menu_brand'); + this.$section_placeholder = this.$('.o_menu_sections'); + this._updateMenuBrand(); + + // Navbar's menus event handlers + var on_secondary_menu_click = function (ev) { + ev.preventDefault(); + var menu_id = $(ev.currentTarget).data('menu'); + var action_id = $(ev.currentTarget).data('action-id'); + self._on_secondary_menu_click(menu_id, action_id); + }; + var menu_ids = _.keys(this.$menu_sections); + var primary_menu_id, $section; + for (var i = 0; i < menu_ids.length; i++) { + primary_menu_id = menu_ids[i]; + $section = this.$menu_sections[primary_menu_id]; + $section.on('click', 'a[data-menu]', self, on_secondary_menu_click.bind(this)); + } + + // Apps Menu + this._appsMenu = new AppsMenu(self, this.menu_data); + var appsMenuProm = this._appsMenu.appendTo(this.$menu_apps); + + // Systray Menu + this.systray_menu = new SystrayMenu(this); + var systrayMenuProm = this.systray_menu.attachTo(this.$('.o_menu_systray')).then(function() { + self.systray_menu.on_attach_callback(); // At this point, we know we are in the DOM + dom.initAutoMoreMenu(self.$section_placeholder, { + maxWidth: function () { + return self.$el.width() - (self.$menu_apps.outerWidth(true) + self.$menu_brand_placeholder.outerWidth(true) + self.systray_menu.$el.outerWidth(true)); + }, + sizeClass: 'SM', + }); + }); + + + + return Promise.all([this._super.apply(this, arguments), appsMenuProm, systrayMenuProm]); + }, + change_menu_section: function (primary_menu_id) { + if (!this.$menu_sections[primary_menu_id]) { + this._updateMenuBrand(); + return; // unknown menu_id + } + + if (this.current_primary_menu === primary_menu_id) { + return; // already in that menu + } + + if (this.current_primary_menu) { + this.$menu_sections[this.current_primary_menu].detach(); + } + + // Get back the application name + for (var i = 0; i < this.menu_data.children.length; i++) { + if (this.menu_data.children[i].id === primary_menu_id) { + this._updateMenuBrand(this.menu_data.children[i].name); + break; + } + } + + this.$menu_sections[primary_menu_id].appendTo(this.$section_placeholder); + this.current_primary_menu = primary_menu_id; + + core.bus.trigger('resize'); + }, + _trigger_menu_clicked: function (menu_id, action_id) { + this.trigger_up('menu_clicked', { + id: menu_id, + action_id: action_id, + previous_menu_id: this.current_secondary_menu || this.current_primary_menu, + }); + }, + /** + * Updates the name of the app in the menu to the value of brandName. + * If brandName is falsy, hides the menu and its sections. + * + * @private + * @param {brandName} string + */ + _updateMenuBrand: function (brandName) { + if (brandName) { + this.$menu_brand_placeholder.text(brandName).show(); + this.$section_placeholder.show(); + } else { + this.$menu_brand_placeholder.hide() + this.$section_placeholder.hide(); + } + }, + _on_secondary_menu_click: function (menu_id, action_id) { + var self = this; + + // It is still possible that we don't have an action_id (for example, menu toggler) + if (action_id) { + self._trigger_menu_clicked(menu_id, action_id); + this.current_secondary_menu = menu_id; + } + }, + /** + * Helpers used by web_client in order to restore the state from + * an url (by restore, read re-synchronize menu and action manager) + */ + action_id_to_primary_menu_id: function (action_id) { + var primary_menu_id, found; + for (var i = 0; i < this.menu_data.children.length && !primary_menu_id; i++) { + found = this._action_id_in_subtree(this.menu_data.children[i], action_id); + if (found) { + primary_menu_id = this.menu_data.children[i].id; + } + } + return primary_menu_id; + }, + _action_id_in_subtree: function (root, action_id) { + // action_id can be a string or an integer + if (root.action && root.action.split(',')[1] === String(action_id)) { + return true; + } + var found; + for (var i = 0; i < root.children.length && !found; i++) { + found = this._action_id_in_subtree(root.children[i], action_id); + } + return found; + }, + menu_id_to_action_id: function (menu_id, root) { + if (!root) { + root = $.extend(true, {}, this.menu_data); + } + + if (root.id === menu_id) { + return root.action.split(',')[1] ; + } + for (var i = 0; i < root.children.length; i++) { + var action_id = this.menu_id_to_action_id(menu_id, root.children[i]); + if (action_id !== undefined) { + return action_id; + } + } + return undefined; + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Returns the id of the current primary (first level) menu. + * + * @returns {integer} + */ + getCurrentPrimaryMenu: function () { + return this.current_primary_menu; + }, + /** + * Open the first app, returns whether an application was found. + * + * @returns {Boolean} + */ + openFirstApp: function () { + return this._appsMenu.openFirstApp(); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * When clicking on app name, opens the first action of the app + * + * @private + * @param {MouseEvent} ev + */ + _onAppNameClicked: function (ev) { + var actionID = parseInt(this.menu_id_to_action_id(this.current_primary_menu)); + this._trigger_menu_clicked(this.current_primary_menu, actionID); + }, + /** + * @private + * @param {MouseEvent} ev + */ + _onMouseOverMenu: function (ev) { + if (config.device.isMobile) { + return; + } + var $target = $(ev.currentTarget); + var $opened = $target.siblings('.show'); + if ($opened.length) { + $opened.find('[data-toggle="dropdown"]:first').dropdown('toggle'); + $opened.removeClass('show'); + $target.find('[data-toggle="dropdown"]:first').dropdown('toggle'); + $target.addClass('show'); + } + }, +}); + +return Menu; + +}); |
