summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
authorAntony Lesuisse <al@openerp.com>2011-12-16 02:53:58 +0100
committerAntony Lesuisse <al@openerp.com>2011-12-16 02:53:58 +0100
commitfc4faa599beeb239ca941cd0e72b47c83bec4f48 (patch)
treefb20d6ec7f56a87e39a0c8a4eb7812e5afef0a00 /addons/web/static
parentb98867779a20d3836069dee5dd84001ae266362d (diff)
parent28715cfaab85970c3bbabf49bc12a5dfa2efc200 (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')
-rw-r--r--addons/web/static/src/js/chrome.js125
-rw-r--r--addons/web/static/src/js/core.js312
-rw-r--r--addons/web/static/src/js/formats.js2
-rw-r--r--addons/web/static/src/xml/base.xml60
4 files changed, 289 insertions, 210 deletions
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index e27dc343961..50fb8018918 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -629,9 +629,6 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
callback: continuation || function() {}
});
},
- on_logout: function() {
- this.session.logout();
- }
});
openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# */{
@@ -995,47 +992,52 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
this._super(null, element_id);
openerp.webclient = this;
- var params = {};
- if (jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
- this.$element.addClass("kitten-mode-activated");
- this.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) {
- self.$element.toggleClass('clark-gable');
- });
- }
- this.$element.html(QWeb.render("Interface", params));
-
this.notification = new openerp.web.Notification(this);
this.loading = new openerp.web.Loading(this);
this.crashmanager = new openerp.web.CrashManager();
this.header = new openerp.web.Header(this);
this.login = new openerp.web.Login(this);
- this.header.on_logout.add(this.login.on_logout);
+ this.header.on_logout.add(this.on_logout);
this.header.on_action.add(this.on_menu_action);
- this.session.on_session_invalid.add(this.login.do_ask_login);
- this.session.on_session_valid.add_last(this.header.do_update);
- this.session.on_session_invalid.add_last(this.header.do_update);
- this.session.on_session_valid.add_last(this.on_logged);
- this.session.on_session_invalid.add_last(this.on_logged_out);
-
- this.menu = new openerp.web.Menu(this, "oe_menu", "oe_secondary_menu");
- this.menu.on_action.add(this.on_menu_action);
-
this._current_state = null;
-
},
start: function() {
this._super.apply(this, arguments);
- this.notification.prependTo(this.$element);
- this.loading.appendTo($('#oe_loading'));
- this.header.appendTo($("#oe_header"));
- this.session.start();
- this.login.appendTo($('#oe_login'));
- this.menu.start();
+ var self = this;
+ this.session.bind().then(function() {
+ var params = {};
+ if (jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
+ this.$element.addClass("kitten-mode-activated");
+ this.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) {
+ self.$element.toggleClass('clark-gable');
+ });
+ }
+ self.$element.html(QWeb.render("Interface", params));
+ self.menu = new openerp.web.Menu(self, "oe_menu", "oe_secondary_menu");
+ self.menu.on_action.add(self.on_menu_action);
+
+ self.notification.prependTo(self.$element);
+ self.loading.appendTo($('#oe_loading'));
+ self.header.appendTo($("#oe_header"));
+ self.login.appendTo($('#oe_login'));
+ self.menu.start();
+ self.login.on_login_invalid();
+ });
+ this.session.ready.then(function() {
+ self.login.on_login_valid();
+ self.header.do_update();
+ self.menu.do_reload();
+ if(self.action_manager)
+ self.action_manager.stop();
+ self.action_manager = new openerp.web.ActionManager(this);
+ self.action_manager.appendTo($("#oe_app"));
+ self.bind_hashchange();
+ });
},
do_reload: function() {
- return $.when(this.session.session_restore(),this.menu.do_reload());
+ return $.when(this.session.session_init(),this.menu.do_reload());
},
do_notify: function() {
var n = this.notification;
@@ -1045,24 +1047,10 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
var n = this.notification;
n.warn.apply(n, arguments);
},
- on_logged: function() {
- this.menu.do_reload();
- if(this.action_manager)
- this.action_manager.stop();
- this.action_manager = new openerp.web.ActionManager(this);
- this.action_manager.appendTo($("#oe_app"));
-
- if (openerp._modules_loaded) { // TODO: find better option than this
- this.bind_hashchange();
- } else {
- this.session.on_modules_loaded.add({ // XXX what about a $.Deferred ?
- callback: $.proxy(this, 'bind_hashchange'),
- unique: true,
- position: 'last'
- })
- }
- },
- on_logged_out: function() {
+ on_logout: function() {
+ this.session.session_logout();
+ this.login.on_login_invalid();
+ this.header.do_update();
$(window).unbind('hashchange', this.on_hashchange);
this.do_push_state({});
if(this.action_manager)
@@ -1105,6 +1093,47 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
},
});
+openerp.currentScript = function() {
+ var currentScript = document.currentScript;
+ if (!currentScript) {
+ var sc = document.getElementsByTagName('script');
+ currentScript = sc[sc.length-1];
+ }
+ return currentScript;
+};
+
+openerp.web.EmbeddedClient = openerp.web.Widget.extend({
+ template: 'EmptyComponent',
+ init: function(action_id, options) {
+ this._super();
+ // TODO take the xmlid of a action instead of its id
+ this.action_id = action_id;
+ this.options = options || {};
+ this.am = new openerp.web.ActionManager(this);
+ },
+
+ start: function() {
+ var self = this;
+
+ this.am.appendTo(this.$element.addClass('openerp'));
+
+ return this.rpc("/web/action/load", { action_id: this.action_id }, function(result) {
+ var action = result.result;
+ action.flags = _.extend({
+ //views_switcher : false,
+ search_view : false,
+ action_buttons : false,
+ sidebar : false
+ //pager : false
+ }, self.options, action.flags || {});
+
+ self.am.do_action(action);
+ });
+ },
+
+});
+
+
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
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();
diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js
index 2df651158eb..264cc836e2d 100644
--- a/addons/web/static/src/js/formats.js
+++ b/addons/web/static/src/js/formats.js
@@ -254,7 +254,7 @@ openerp.web.format_cell = function (row_data, column, value_if_empty, process_mo
if (column.tag === 'button') {
return [
'<button type="button" title="', column.string || '', '">',
- '<img src="/web/static/src/img/icons/', column.icon, '.png"',
+ '<img src="', openerp.connection.prefix, '/web/static/src/img/icons/', column.icon, '.png"',
' alt="', column.string || '', '"/>',
'</button>'
].join('')
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 600d1c0b78b..ff21856aeff 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -266,7 +266,7 @@
<form class="oe_forms">
<fieldset>
<legend style="">
- <img src="/web/static/src/img/stock_person.png" alt="" />
+ <img t-att-src='_s + "/web/static/src/img/stock_person.png"' alt="" />
</legend>
<div class="oe_box2">
<table align="center" cellspacing="2px" cellpadding="0">
@@ -306,7 +306,7 @@
<tbody>
<tr>
<td>
- <img src="/web/static/src/img/product.png"/>
+ <img t-att-src='_s + "/web/static/src/img/product.png"'/>
</td>
<td>
<strong>Full featured</strong><br />
@@ -315,7 +315,7 @@
</tr>
<tr>
<td>
- <img src="/web/static/src/img/accessories-archiver.png"/>
+ <img t-att-src='_s + "/web/static/src/img/accessories-archiver.png"'/>
</td>
<td>
<strong>Open Source</strong><br />
@@ -324,7 +324,7 @@
</tr>
<tr>
<td>
- <img src="/web/static/src/img/partner.png" />
+ <img t-att-src='_s + "/web/static/src/img/partner.png"' />
</td>
<td>
<strong>User Friendly</strong><br />
@@ -352,13 +352,13 @@
<div class="header_corner">
<ul class="block">
<li>
- <a t-att-href="'/' + widget.qs" title="Home" class="home"><img src="/web/static/src/img/header-home.png" width="16" height="16" border="0"/></a>
+ <a t-att-href="'/' + widget.qs" title="Home" class="home"><img t-att-src='_s + "/web/static/src/img/header-home.png"' width="16" height="16" border="0"/></a>
</li>
<li class="preferences">
- <a href="javascript:void(0)" title="Preferences" class="preferences"><img src="/web/static/src/img/header-preferences.png" width="16" height="16" border="0"/></a>
+ <a href="javascript:void(0)" title="Preferences" class="preferences"><img t-att-src='_s + "/web/static/src/img/header-preferences.png"' width="16" height="16" border="0"/></a>
</li>
<li>
- <a href="javascript:void(0)" title="About" class="about"><img src="/web/static/src/img/header-about.png" width="16" height="16" border="0"/></a>
+ <a href="javascript:void(0)" title="About" class="about"><img t-att-src='_s + "/web/static/src/img/header-about.png"' width="16" height="16" border="0"/></a>
</li>
</ul>
<div class="block">
@@ -724,7 +724,7 @@
<input type="hidden" name="model" t-att-value="view.dataset.model"/>
<input type="hidden" name="id" t-att-value="view.datarecord.id"/>
<button class="button" type="button">
- <img src="/web/static/src/img/throbber.gif" width="16" height="16" style="display: none"/>
+ <img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16" style="display: none"/>
<span>Add</span>
</button>
<input type="file" class="oe-binary-file" name="ufile" title="Add attachment"
@@ -736,14 +736,14 @@
<br style="clear: both"/>
<ul class="oe-sidebar-attachments-items">
<li t-foreach="attachments" t-as="attachment">
- <t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/web/binary/saveas?session_id='
+ <t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="_s + '/web/binary/saveas?session_id='
+ session.session_id + '&amp;model=ir.attachment&amp;id=' + attachment.id
+ '&amp;field=datas&amp;fieldname=name&amp;t=' + (new Date().getTime())"/>
<a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank">
<t t-esc="attachment.name"/>
</a>
<a href="#" class="oe-sidebar-attachment-delete" t-att-data-id="attachment.id" t-attf-title="Delete the attachment #{attachment.name}">
- <img src="/web/static/src/img/attachments-close.png" width="15" height="15" border="0"/>
+ <img t-att-src='_s + "/web/static/src/img/attachments-close.png"' width="15" height="15" border="0"/>
</a>
</li>
</ul>
@@ -895,7 +895,7 @@
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type} #{_(['integer', 'float', 'float_time']).contains(widget.type) ? 'oe-number' : ''}"
style="width: 100%"
- /><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
+ /><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" t-att-src='_s + "/web/static/src/img/icons/terp-translate.png"' width="16" height="16" border="0"/>
</t>
<t t-name="FieldChar.readonly">
<div
@@ -914,7 +914,7 @@
</td>
<td width="16">
<button type="button" class="button" title="Send an e-mail with your default e-mail client">
- <img src="/web/static/src/img/icons/terp-mail-message-new.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/terp-mail-message-new.png"'/>
</button>
</td>
</tr>
@@ -928,7 +928,7 @@
</td>
<td width="16">
<button type="button" class="button" title="Open this resource">
- <img src="/web/static/src/img/icons/gtk-ok.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/gtk-ok.png"'/>
</button>
</td>
</tr>
@@ -940,7 +940,7 @@
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"
style="width: 100%"
- ></textarea><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
+ ></textarea><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" t-att-src='_s + "/web/static/src/img/icons/terp-translate.png"' width="16" height="16" border="0"/>
</t>
<t t-name="web.datetimepicker">
<div class="oe_datepicker_root">
@@ -948,7 +948,7 @@
<input type="text" size="1" style="width: 100%"
t-att-name="widget.name"
t-attf-class="oe_datepicker_master field_#{widget.type_of_date}"
- /><img class="oe_input_icon oe_datepicker_trigger" src="/web/static/src/img/ui/field_calendar.png"
+ /><img class="oe_input_icon oe_datepicker_trigger" t-att-src='_s + "/web/static/src/img/ui/field_calendar.png"'
title="Select date" width="16" height="16" border="0"/>
</div>
</t>
@@ -968,9 +968,9 @@
<input type="text" size="1" style="width: 100%;"
t-att-id="widget.element_id"/>
<span class="oe-m2o-drop-down-button">
- <img src="/web/static/src/img/down-arrow.png" /></span>
+ <img t-att-src='_s + "/web/static/src/img/down-arrow.png"' /></span>
<span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'">
- <img src="/web/static/src/img/icons/gtk-index.png"/></span>
+ <img t-att-src='_s + "/web/static/src/img/icons/gtk-index.png"'/></span>
<div t-att-id="widget.cm_id" class="contextMenu" style="display:none">
</div>
</div>
@@ -1021,7 +1021,7 @@
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
- <img src="/web/static/src/img/placeholder.png" class="oe-binary-image"
+ <img t-att-src='_s + "/web/static/src/img/placeholder.png"' class="oe-binary-image"
t-att-border="widget.readonly ? 0 : 1"
t-att-id="widget.element_id + '_field'"
t-att-name="widget.name"
@@ -1043,7 +1043,7 @@
<input type="hidden" name="session_id" value=""/>
<input type="hidden" name="callback" t-att-value="widget.iframe"/>
<button class="button" type="button" title="Set Image">
- <img src="/web/static/src/img/icons/STOCK_DIRECTORY.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/>
</button>
<input type="file" class="oe-binary-file" name="ufile"/>
</form>
@@ -1051,14 +1051,14 @@
</td>
<td>
<button class="button oe-binary-file-clear" type="button" title="Clear">
- <img src="/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"'/>
</button>
</td>
</tr>
</table>
</div>
<div class="oe-binary-progress" style="display: none">
- <img src="/web/static/src/img/throbber.gif" width="16" height="16"/>
+ <img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16"/>
<b>Uploading ...</b>
</div>
<iframe t-att-id="widget.iframe" t-att-name="widget.iframe" style="display: none"> </iframe>
@@ -1086,7 +1086,7 @@
<input type="hidden" name="session_id" value=""/>
<input type="hidden" name="callback" t-att-value="widget.iframe"/>
<button class="button" type="button" title="Set Image">
- <img src="/web/static/src/img/icons/STOCK_DIRECTORY.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/>
<span>Select</span>
</button>
<input type="file" class="oe-binary-file" name="ufile"/>
@@ -1095,13 +1095,13 @@
</td>
<td>
<button class="button oe-binary-file-save" type="button" title="Save As">
- <img src="/web/static/src/img/icons/gtk-save.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/gtk-save.png"'/>
<span>Save As</span>
</button>
</td>
<td>
<button class="button oe-binary-file-clear" type="button" title="Clear">
- <img src="/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"'/>
<span>Clear</span>
</button>
</td>
@@ -1109,7 +1109,7 @@
</table>
</td>
<td class="oe-binary-progress" style="display: none" nowrap="true">
- <img src="/web/static/src/img/throbber.gif" width="16" height="16"/>
+ <img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16"/>
<b>Uploading ...</b>
<iframe t-att-id="widget.iframe" t-att-name="widget.iframe" style="display: none"> </iframe>
</td>
@@ -1118,7 +1118,7 @@
</t>
<t t-name="WidgetButton">
<button type="button" class="oe_button">
- <img t-if="widget.node.attrs.icon" t-att-src="'/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
+ <img t-if="widget.node.attrs.icon" t-att-src="_s + '/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
<span t-if="widget.string"><t t-esc="widget.string"/></span>
</button>
</t>
@@ -1211,7 +1211,7 @@
t-att-title="attrs.help"
t-att-class="classes.join(' ')"
t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined">
- <img t-att-src="'/web/static/src/img/icons/' + (attrs.icon || 'gtk-home') + '.png'" width="16" height="16"/>
+ <img t-att-src="_s + '/web/static/src/img/icons/' + (attrs.icon || 'gtk-home') + '.png'" width="16" height="16"/>
<br t-if="attrs.string"/>
<t t-esc="attrs.string"/>
</button>
@@ -1358,7 +1358,7 @@
<t t-name="DialogWarning">
<table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning">
<tr>
- <td><img src="/web/static/src/img/warning.png" class="oe-dialog-icon"/></td>
+ <td><img t-att-src='_s + "/web/static/src/img/warning.png"' class="oe-dialog-icon"/></td>
<td>
<p>
<t t-js="d">
@@ -1586,7 +1586,7 @@
<td valign="top" align="left" style="cursor: pointer;" width="18">
<t t-if="field.children">
<t t-if="(field.id).split('/').length != 3">
- <img t-att-id="'parentimg-' + field.id" src="/web/static/src/img/expand.gif" width="16" height="16" border="0"/>
+ <img t-att-id="'parentimg-' + field.id" t-att-src='_s + "/web/static/src/img/expand.gif"' width="16" height="16" border="0"/>
</t>
</t>
</td>
@@ -1702,7 +1702,7 @@
<tr>
<td t-foreach="records[0]" t-as="column">
<input class="sel_fields" placeholder="--- Don't Import ---"/><span class="oe-m2o-drop-down-button">
- <img src="/web/static/src/img/down-arrow.png" /></span>
+ <img t-att-src='_s + "/web/static/src/img/down-arrow.png"' /></span>
</td>
</tr>
<tr t-foreach="records" t-as="record" class="oe_import_grid-row">