diff options
| author | Antony Lesuisse <al@openerp.com> | 2011-12-16 02:53:58 +0100 |
|---|---|---|
| committer | Antony Lesuisse <al@openerp.com> | 2011-12-16 02:53:58 +0100 |
| commit | fc4faa599beeb239ca941cd0e72b47c83bec4f48 (patch) | |
| tree | fb20d6ec7f56a87e39a0c8a4eb7812e5afef0a00 /addons/web/static/src/js/core.js | |
| parent | b98867779a20d3836069dee5dd84001ae266362d (diff) | |
| parent | 28715cfaab85970c3bbabf49bc12a5dfa2efc200 (diff) | |
[MERGE] jsonp branch by chs,
deferrization and cleanup of Connection,
simple jsonp (not fully tested),
url (push_state) is broken
(+395/-262) 8 files modified
bzr revid: al@openerp.com-20111216015358-e8p5bi8pl86onlbz
Diffstat (limited to 'addons/web/static/src/js/core.js')
| -rw-r--r-- | addons/web/static/src/js/core.js | 312 |
1 files changed, 181 insertions, 131 deletions
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index d3734d29278..3d66c4f4ccf 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -350,11 +350,19 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. * @param {String} [server] JSON-RPC endpoint hostname * @param {String} [port] JSON-RPC endpoint port */ - init: function(server, port) { + init: function() { this._super(); - this.server = (server == undefined) ? location.hostname : server; - this.port = (port == undefined) ? location.port : port; - this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp"; + // TODO: session store in cookie should be optional + this.name = openerp._session_id; + }, + bind: function(host, protocol) { + var self = this; + this.host = (host == undefined) ? location.host : host; + this.protocol = (protocol == undefined) ? location.protocol : protocol; + this.prefix = this.protocol + '//' + this.host; + openerp.web.qweb.default_dict['_s'] = this.prefix + this.rpc_mode = (this.host == location.host) ? "json" : "jsonp"; + this.rpc_function = (this.host == location.host) ? this.rpc_json : this.rpc_jsonp; this.debug = (window.location.search.indexOf('?debug') !== -1); this.session_id = false; this.uid = false; @@ -366,14 +374,8 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. this.context = {}; this.shortcuts = []; this.active_id = null; - // TODO: session should have an optional name indicating that they'll - // be saved to (and revived from) cookies - this.name = 'session'; - this.do_load_qweb(['/web/webclient/qweb']); - }, - - start: function() { - this.session_restore(); + this.ready = $.Deferred(); + return this.session_init(); }, /** * Executes an RPC call, registering the provided callbacks. @@ -390,82 +392,133 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. */ rpc: function(url, params, success_callback, error_callback) { var self = this; + // url can be an $.ajax option object + if (_.isString(url)) { + url = { url: url }; + } // Construct a JSON-RPC2 request, method is currently unused params.session_id = this.session_id; if (this.debug) params.debug = 1; - - // Call using the rpc_mode - var deferred = $.Deferred(); - this.rpc_ajax(url, { - jsonrpc: "2.0", - method: "call", + var payload = { + jsonrpc: '2.0', + method: 'call', params: params, - id: _.uniqueId('browser-client-') - }).then(function () {deferred.resolve.apply(deferred, arguments);}, - function(error) {deferred.reject(error, $.Event());}); - return deferred.fail(function() { + id: _.uniqueId('r') + }; + var deferred = $.Deferred(); + this.on_rpc_request(); + this.rpc_function(url, payload).then( + function (response, textStatus, jqXHR) { + self.on_rpc_response(); + if (!response.error) { + deferred.resolve(response["result"], textStatus, jqXHR); + } else if (response.error.data.type === "session_invalid") { + self.uid = false; + // TODO deprecate or use a deferred on login.do_ask_login() + self.on_session_invalid(function() { + self.rpc(url, payload.params, + function() { deferred.resolve.apply(deferred, arguments); }, + function() { deferred.reject.apply(deferred, arguments); }); + }); + } else { + deferred.reject(response.error, $.Event()); + } + }, + function(jqXHR, textStatus, errorThrown) { + self.on_rpc_response(); + var error = { + code: -32098, + message: "XmlHttpRequestError " + errorThrown, + data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] } + }; + deferred.reject(error, $.Event()); + }); + // Allow deferred user to disable on_rpc_error in fail + deferred.fail(function() { deferred.fail(function(error, event) { if (!event.isDefaultPrevented()) { self.on_rpc_error(error, event); } }); }).then(success_callback, error_callback).promise(); + return deferred; }, /** * Raw JSON-RPC call * * @returns {jQuery.Deferred} ajax-webd deferred object */ - rpc_ajax: function(url, payload) { + rpc_json: function(url, payload) { var self = this; - this.on_rpc_request(); - // url can be an $.ajax option object - if (_.isString(url)) { - url = { - url: url - } - } var ajax = _.extend({ type: "POST", - url: url, dataType: 'json', contentType: 'application/json', data: JSON.stringify(payload), - processData: false + processData: false, }, url); - var deferred = $.Deferred(); - $.ajax(ajax).done(function(response, textStatus, jqXHR) { - self.on_rpc_response(); - if (!response.error) { - deferred.resolve(response["result"], textStatus, jqXHR); - return; - } - if (response.error.data.type !== "session_invalid") { - deferred.reject(response.error); - return; - } - self.uid = false; - self.on_session_invalid(function() { - self.rpc(url, payload.params, - function() { - deferred.resolve.apply(deferred, arguments); - }, - function(error, event) { - event.preventDefault(); - deferred.reject.apply(deferred, arguments); - }); - }); - }).fail(function(jqXHR, textStatus, errorThrown) { - self.on_rpc_response(); - var error = { - code: -32098, - message: "XmlHttpRequestError " + errorThrown, - data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] } + return $.ajax(ajax); + }, + rpc_jsonp: function(url, payload) { + var self = this; + // extracted from payload to set on the url + var data = { + session_id: this.session_id, + id: payload.id, + }; + url.url = this.get_url(url.url); + var ajax = _.extend({ + type: "GET", + dataType: 'jsonp', + jsonp: 'jsonp', + cache: false, + data: data + }, url); + var payload_str = JSON.stringify(payload); + var payload_url = $.param({r:payload_str}); + if(playload_url.length < 2000) { + // Direct jsonp request + ajax.data.r = payload_str; + return $.ajax(ajax); + } else { + // Indirect jsonp request + var ifid = _.uniqueId('oe_rpc_iframe'); + var display = options.openerp.debug ? 'block' : 'none'; + var $iframe = $(_.str.sprintf("<iframe src='javascript:false;' name='%s' id='%s' style='display:%s'></iframe>", ifid, ifid, display)); + var $form = $('<form>') + .attr('method', 'POST') + .attr('target', ifid) + .attr('enctype', "multipart/form-data") + .attr('action', ajax.url + '?' + $.param(data)) + .append($('<input type="hidden" name="r" />').attr('value', payload_str)) + .hide() + .appendTo($('body')); + var cleanUp = function() { + if ($iframe) { + $iframe.unbind("load").attr("src", "javascript:false;").remove(); + } + $form.remove(); }; - deferred.reject(error); - }); - return deferred.promise(); + var deferred = $.Deferred(); + // the first bind is fired up when the iframe is added to the DOM + $iframe.bind('load', function() { + // the second bind is fired up when the result of the form submission is received + $iframe.unbind('load').bind('load', function() { + $.ajax(ajax).always(function() { + cleanUp(); + }).then( + function() { deferred.resolve.apply(deferred, arguments); }, + function() { deferred.reject.apply(deferred, arguments); } + ); + }); + // now that the iframe can receive data, we fill and submit the form + $form.submit(); + }); + // append the iframe to the DOM (will trigger the first load) + $form.after($iframe); + return deferred; + } }, on_rpc_request: function() { }, @@ -474,75 +527,51 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. on_rpc_error: function(error) { }, /** - * The session is validated either by login or by restoration of a previous session - */ - on_session_valid: function() { - if(!openerp._modules_loaded) - this.load_modules(); - }, - on_session_invalid: function(contination) { - }, - session_is_valid: function() { - return this.uid; - }, - session_authenticate: function(db, login, password, success_callback) { - var self = this; - var base_location = document.location.protocol + '//' + document.location.host; - var params = { db: db, login: login, password: password, base_location: base_location }; - return this.rpc("/web/session/authenticate", params, function(result) { - _.extend(self, { - session_id: result.session_id, - uid: result.uid, - user_context: result.context, - db: result.db, - username: result.login - }); - self.session_save(); - self.on_session_valid(); - return true; - }).then(success_callback); - }, - login: function() { this.session_authenticate.apply(this, arguments); }, - /** - * Reloads uid and session_id from local storage, if they exist + * Init a session, reloads from cookie, if it exists */ - session_restore: function () { + session_init: function () { 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", {}).then(function(result) { + return this.rpc("/web/session/get_session_info", {}).pipe(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...) but should not call - // on_session_valid again as it triggers reloading the menu - var already_logged = self.uid; + // (should not change, but just in case...) _.extend(self, { - uid: result.uid, - user_context: result.context, db: result.db, - username: result.login + username: result.login, + uid: result.uid, + user_context: result.context }); - if (!already_logged) { - if (self.uid) { - self.on_session_valid(); - } else { - self.on_session_invalid(); - } + var deferred = self.do_load_qweb(['/web/webclient/qweb']); + if(self.uid) { + return deferred.then(self.load_modules()); } - }, function() { - self.on_session_invalid(); + return deferred; }); }, /** - * Saves the session id and uid locally + * The session is validated either by login or by restoration of a previous session */ - session_save: function () { - this.set_cookie('session_id', this.session_id); + session_authenticate: function(db, login, password) { + var self = this; + var base_location = document.location.protocol + '//' + document.location.host; + var params = { db: db, login: login, password: password, base_location: base_location }; + return this.rpc("/web/session/authenticate", params).pipe(function(result) { + _.extend(self, { + session_id: result.session_id, + db: result.db, + username: result.login, + uid: result.uid, + user_context: result.context + }); + // TODO: session store in cookie should be optional + self.set_cookie('session_id', self.session_id); + return self.load_modules(); + }); }, - logout: function() { + session_logout: function() { this.set_cookie('session_id', ''); - this.reload_client(); - }, - reload_client: function() { window.location.reload(); }, /** @@ -586,23 +615,28 @@ 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) { self.module_list = result; var lang = self.user_context.lang; var params = { mods: ["web"].concat(result), lang: lang}; - self.rpc('/web/webclient/translations',params).then(function(transs) { + 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" ]; - - self.rpc('/web/webclient/csslist', {"mods": modules}, self.do_load_css); - self.rpc('/web/webclient/jslist', {"mods": modules}, function(files) { - self.do_load_js(file_list.concat(files)); + 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) { + return self.do_load_js(file_list.concat(files)); + }) + ).then(function() { + self.ready.resolve(); }); - self.rpc('/web/webclient/qweblist', {"mods": modules}, self.do_load_qweb); - openerp._modules_loaded = true; }); }); }, @@ -610,7 +644,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; _.each(files, function (file) { $('head').append($('<link>', { - 'href': file, + 'href': self.get_url(file), 'rel': 'stylesheet', 'type': 'text/css' })); @@ -618,28 +652,39 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. }, do_load_js: function(files) { var self = this; + var d = $.Deferred(); if(files.length != 0) { var file = files.shift(); var tag = document.createElement('script'); tag.type = 'text/javascript'; - tag.src = file; + tag.src = self.get_url(file); tag.onload = tag.onreadystatechange = function() { if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done ) return; tag.onload_done = true; - self.do_load_js(files); + self.do_load_js(files).then(function () { + d.resolve(); + }); }; var head = document.head || document.getElementsByTagName('head')[0]; head.appendChild(tag); } else { - this.on_modules_loaded(); + self.on_modules_loaded(); + d.resolve(); } + return d; }, do_load_qweb: function(files) { var self = this; - _.each(files, function(file) { - openerp.web.qweb.add_template(file); - }); + 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); + }); + } else { + return $.when(); + } }, on_modules_loaded: function() { for(var j=0; j<this.module_list.length; j++) { @@ -654,6 +699,9 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. } } }, + get_url: function (file) { + return this.prefix + file; + }, /** * Cooperative file download implementation, for ajaxy APIs. * @@ -1069,6 +1117,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we } }); +/** Configure blockui */ if ($.blockUI) { $.blockUI.defaults.baseZ = 1100; $.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">'; @@ -1100,6 +1149,7 @@ openerp.web.qweb.format_text_node = function(s) { openerp.connection = new openerp.web.Connection(); openerp.web.qweb.default_dict['__debug__'] = openerp.connection.debug; +/** Jquery extentions */ $.Mutex = (function() { function Mutex() { this.def = $.Deferred().resolve(); |
