odoo.define('web.AbstractWebClient', function (require) { "use strict"; var ActionManager = require('web.ActionManager'); var core = require('web.core'); var crash_manager = require('web.crash_manager'); var Loading = require('web.Loading'); var NotificationManager = require('web.notification').NotificationManager; var session = require('web.session'); var utils = require('web.utils'); var Widget = require('web.Widget'); var _t = core._t; var WebClient = Widget.extend({ custom_events: { notification: function (e) { if(this.notification_manager) { this.notification_manager.notify(e.data.title, e.data.message, e.data.sticky); } }, warning: function (e) { if(this.notification_manager) { this.notification_manager.warn(e.data.title, e.data.message, e.data.sticky); } }, clear_uncommitted_changes: function (e) { this.clear_uncommitted_changes().then(e.data.callback); }, toggle_fullscreen: function (event) { this.toggle_fullscreen(event.data.fullscreen); }, current_action_updated: function (e) { this.current_action_updated(e.data.action); }, perform_rpc: function(event) { if (event.data.on_fail) { event.data.on_fail(); } }, perform_model_rpc: function(event) { if (event.data.on_fail) { event.data.on_fail(); } }, }, init: function(parent) { this.client_options = {}; this._super(parent); this.origin = undefined; this._current_state = null; this.menu_dm = new utils.DropMisordered(); this.action_mutex = new utils.Mutex(); this.set('title_part', {"zopenerp": "Odoo"}); }, start: function() { var self = this; this.on("change:title_part", this, this._title_changed); this._title_changed(); return session.is_bound .then(function () { self.bind_events(); return $.when( self.set_action_manager(), self.set_notification_manager(), self.set_loading() ); }).then(function () { if (session.session_is_valid()) { return self.show_application(); } else { // database manager needs the webclient to keep going even // though it has no valid session return $.when(); } }).then(function () { // Listen to 'scroll' event and propagate it on main bus self.action_manager.$el.on('scroll', core.bus.trigger.bind(core.bus, 'scroll')); core.bus.trigger('web_client_ready'); }); }, bind_events: function() { var self = this; $('.oe_systray').show(); this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function() { $(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter'); }); this.$el.on('click', '.oe_dropdown_toggle', function(ev) { ev.preventDefault(); var $toggle = $(this); var doc_width = $(document).width(); var $menu = $toggle.siblings('.oe_dropdown_menu'); $menu = $menu.size() >= 1 ? $menu : $toggle.find('.oe_dropdown_menu'); var state = $menu.is('.oe_opened'); setTimeout(function() { // Do not alter propagation $toggle.add($menu).toggleClass('oe_opened', !state); if (!state) { // Move $menu if outside window's edge var offset = $menu.offset(); var menu_width = $menu.width(); var x = doc_width - offset.left - menu_width - 2; if (x < 0) { $menu.offset({ left: offset.left + x }).width(menu_width); } } }, 0); }); core.bus.on('click', this, function(ev) { $('.tooltip').remove(); if (!$(ev.target).is('input[type=file]')) { self.$('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened'); } }); core.bus.on('connection_lost', this, this.on_connection_lost); core.bus.on('connection_restored', this, this.on_connection_restored); // crash manager integration session.on('error', crash_manager, crash_manager.rpc_error); window.onerror = function (message, file, line, col, error) { // Scripts injected in DOM (eg: google API's js files) won't return a clean error on window.onerror. // The browser will just give you a 'Script error.' as message and nothing else for security issue. // To enable onerror to work properly with CORS file, you should: // 1. add crossorigin="anonymous" to your