[MERGE]: survey: fixed a bug in warning message when users exceed maximal number...
[odoo/odoo.git] / addons / web / static / src / js / core.js
index f63c975..0584c49 100644 (file)
@@ -160,6 +160,12 @@ openerp.web.callback = function(obj, method) {
             position: "last"
         });
     };
+    callback.remove = function(f) {
+        callback.callback_chain = _.difference(callback.callback_chain, _.filter(callback.callback_chain, function(el) {
+            return el.callback === f;
+        }));
+        return callback;
+    };
 
     return callback.add({
         callback: method,
@@ -342,6 +348,31 @@ openerp.web.CallbackEnabled = openerp.web.Class.extend(/** @lends openerp.web.Ca
                 }
             }
         }
+    },
+    /**
+     * Proxies a method of the object, in order to keep the right ``this`` on
+     * method invocations.
+     *
+     * This method is similar to ``Function.prototype.bind`` or ``_.bind``, and
+     * even more so to ``jQuery.proxy`` with a fundamental difference: its
+     * resolution of the method being called is lazy, meaning it will use the
+     * method as it is when the proxy is called, not when the proxy is created.
+     *
+     * Other methods will fix the bound method to what it is when creating the
+     * binding/proxy, which is fine in most javascript code but problematic in
+     * OpenERP Web where developers may want to replace existing callbacks with
+     * theirs.
+     *
+     * The semantics of this precisely replace closing over the method call.
+     *
+     * @param {String} method_name name of the method to invoke
+     * @returns {Function} proxied method
+     */
+    proxy: function (method_name) {
+        var self = this;
+        return function () {
+            return self[method_name].apply(self, arguments);
+        }
     }
 });
 
@@ -359,6 +390,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
         this.debug = ($.deparam($.param.querystring()).debug != undefined);
         // TODO: session store in cookie should be optional
         this.name = openerp._session_id;
+        this.qweb_mutex = new $.Mutex();
     },
     bind: function(origin) {
         var window_origin = location.protocol+"//"+location.host;
@@ -372,12 +404,12 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
         this.username = false;
         this.user_context= {};
         this.db = false;
+        this.openerp_entreprise = false;
         this.module_list = [];
         this.module_loaded = {"web": true};
         this.context = {};
         this.shortcuts = [];
         this.active_id = null;
-        this.ready = $.Deferred();
         return this.session_init();
     },
     /**
@@ -461,6 +493,8 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
             data: JSON.stringify(payload),
             processData: false,
         }, url);
+        if (this.synch)
+               ajax.async = false;
         return $.ajax(ajax);
     },
     rpc_jsonp: function(url, payload) {
@@ -478,9 +512,11 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
             cache: false,
             data: data
         }, url);
+        if (this.synch)
+               ajax.async = false;
         var payload_str = JSON.stringify(payload);
         var payload_url = $.param({r:payload_str});
-        if(playload_url.length < 2000) {
+        if(payload_url.length < 2000) {
             // Direct jsonp request
             ajax.data.r = payload_str;
             return $.ajax(ajax);
@@ -536,7 +572,24 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
         var self = this;
         // TODO: session store in cookie should be optional
         this.session_id = this.get_cookie('session_id');
-        return this.rpc("/web/session/get_session_info", {}).pipe(function(result) {
+        return this.session_reload().pipe(function(result) {
+            var modules = openerp._modules.join(',');
+            var deferred = self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb);
+            if(self.session_is_valid()) {
+                return deferred.pipe(function() { return self.load_modules(); });
+            }
+            return deferred;
+        });
+    },
+    /**
+     * (re)loads the content of a session: db name, username, user id, session
+     * context and status of the support contract
+     *
+     * @returns {$.Deferred} deferred indicating the session is done reloading
+     */
+    session_reload: function () {
+        var self = this;
+        return this.rpc("/web/session/get_session_info", {}).then(function(result) {
             // If immediately follows a login (triggered by trying to restore
             // an invalid session or no session at all), refresh session data
             // (should not change, but just in case...)
@@ -544,13 +597,9 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
                 db: result.db,
                 username: result.login,
                 uid: result.uid,
-                user_context: result.context
+                user_context: result.context,
+                openerp_entreprise: result.openerp_entreprise
             });
-            var deferred = self.do_load_qweb(['/web/webclient/qweb']);
-            if(self.uid) {
-                return deferred.then(self.load_modules());
-            }
-            return deferred;
         });
     },
     session_is_valid: function() {
@@ -559,7 +608,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
     /**
      * The session is validated either by login or by restoration of a previous session
      */
-    session_authenticate: function(db, login, password) {
+    session_authenticate: function(db, login, password, _volatile) {
         var self = this;
         var base_location = document.location.protocol + '//' + document.location.host;
         var params = { db: db, login: login, password: password, base_location: base_location };
@@ -569,16 +618,19 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
                 db: result.db,
                 username: result.login,
                 uid: result.uid,
-                user_context: result.context
+                user_context: result.context,
+                openerp_entreprise: result.openerp_entreprise
             });
-            // TODO: session store in cookie should be optional
-            self.set_cookie('session_id', self.session_id);
+            if (!_volatile) {
+                self.set_cookie('session_id', self.session_id);
+            }
             return self.load_modules();
         });
     },
     session_logout: function() {
         this.set_cookie('session_id', '');
-        window.location.reload();
+    },
+    on_session_valid: function() {
     },
     /**
      * Called when a rpc call fail due to an invalid session.
@@ -627,28 +679,24 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
      */
     load_modules: function() {
         var self = this;
-        if(openerp._modules_loaded) {
-            return $.when();
-        }
-        this.rpc('/web/session/modules', {}, function(result) {
+        return this.rpc('/web/session/modules', {}).pipe(function(result) {
             self.module_list = result;
             var lang = self.user_context.lang;
             var params = { mods: ["web"].concat(result), lang: lang};
-            self.rpc('/web/webclient/translations',params).pipe(function(transs) {
-                openerp.web._t.database.set_bundle(transs);
-                var modules = self.module_list.join(',');
-                var file_list = ["/web/static/lib/datejs/globalization/" +
-                    self.user_context.lang.replace("_", "-") + ".js"
-                ];
-                return $.when(
-                    self.rpc('/web/webclient/csslist', {mods: modules}, self.do_load_css),
-                    self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb),
-                    self.rpc('/web/webclient/jslist', {mods: modules}).pipe(function(files) {
+            var modules = self.module_list.join(',');
+            return $.when(
+                self.rpc('/web/webclient/csslist', {mods: modules}, self.do_load_css),
+                self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb),
+                self.rpc('/web/webclient/translations', params).pipe(function(trans) {
+                    openerp.web._t.database.set_bundle(trans);
+                    var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"];
+                    return self.rpc('/web/webclient/jslist', {mods: modules}).pipe(function(files) {
                         return self.do_load_js(file_list.concat(files)); 
-                    })
-                ).then(function() {
-                    self.ready.resolve();
-                });
+                    });
+                })
+            ).then(function() {
+                self.on_modules_loaded();
+                self.on_session_valid();
             });
         });
     },
@@ -681,22 +729,20 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
             var head = document.head || document.getElementsByTagName('head')[0];
             head.appendChild(tag);
         } else {
-            self.on_modules_loaded();
             d.resolve();
         }
         return d;
     },
     do_load_qweb: function(files) {
         var self = this;
-        if (files.length != 0) {
-            var file = files.shift();
-            return self.rpc('/web/proxy/load', {path: file}).pipe(function(xml) {
-                openerp.web.qweb.add_template(_.str.trim(xml));
-                return self.do_load_qweb(files);
+        _.each(files, function(file) {
+            self.qweb_mutex.exec(function() {
+                return self.rpc('/web/proxy/load', {path: file}).pipe(function(xml) {
+                    openerp.web.qweb.add_template(_.str.trim(xml));
+                });
             });
-        } else {
-            return $.when();
-        }
+        });
+        return self.qweb_mutex.def;
     },
     on_modules_loaded: function() {
         for(var j=0; j<this.module_list.length; j++) {
@@ -804,7 +850,16 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
             }
         };
         timer = setTimeout(waitLoop, CHECK_INTERVAL);
-    }
+    },
+    synchronized_mode: function(to_execute) {
+       var synch = this.synch;
+       this.synch = true;
+       try {
+               return to_execute();
+       } finally {
+               this.synch = synch;
+       }
+    },
 });
 
 /**
@@ -1171,10 +1226,6 @@ openerp.web.qweb.format_text_node = function(s) {
     return tr === ts ? s : tr;
 }
 
-/** Setup default connection */
-openerp.connection = new openerp.web.Connection();
-openerp.web.qweb.default_dict['__debug__'] = openerp.connection.debug;
-
 /** Jquery extentions */
 $.Mutex = (function() {
     function Mutex() {
@@ -1192,6 +1243,11 @@ $.Mutex = (function() {
     return Mutex;
 })();
 
+/** Setup default connection */
+openerp.connection = new openerp.web.Connection();
+openerp.web.qweb.default_dict['__debug__'] = openerp.connection.debug;
+
+
 $.async_when = function() {
     var async = false;
     var def = $.Deferred();
@@ -1218,6 +1274,15 @@ $.async_when = function() {
     return def;
 };
 
+// special tweak for the web client
+var old_async_when = $.async_when;
+$.async_when = function() {
+       if (openerp.connection.synch)
+               return $.when.apply(this, arguments);
+       else
+               return old_async_when.apply(this, arguments);
+};
+
 };
 
 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: