summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
authorVo Minh Thu <vmt@openerp.com>2012-01-18 11:12:52 +0100
committerVo Minh Thu <vmt@openerp.com>2012-01-18 11:12:52 +0100
commit75b3fc0907ee873c6e16d1fa8e8bfe58d4f520c1 (patch)
tree3e7f7bbe9110eeae766b46bb9c16a867579b6452 /addons/web
parent3203d264aecd751a8c261cea4f72fa323a3098be (diff)
parent152f92916bc36d00c0e59fbc49fb655a4fd85908 (diff)
[MERGE] merged trunk.
bzr revid: vmt@openerp.com-20120118101252-e81nlyzym2nkebf4
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/__init__.py1
-rw-r--r--addons/web/common/http.py4
-rw-r--r--addons/web/common/nonliterals.py2
-rw-r--r--addons/web/common/xml2json.py52
-rw-r--r--addons/web/controllers/main.py6
-rw-r--r--addons/web/po/pt_BR.po36
-rw-r--r--addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch58
-rw-r--r--addons/web/static/lib/jquery.tipTip/jquery.tipTip.js519
-rw-r--r--addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js191
-rw-r--r--addons/web/static/lib/jquery.tipTip/tipTip.css27
-rw-r--r--addons/web/static/lib/qweb/qweb-benchmark.html16
-rw-r--r--addons/web/static/lib/qweb/qweb-test-call.xml2
-rw-r--r--addons/web/static/lib/qweb/qweb2.js10
-rw-r--r--addons/web/static/src/css/base.css28
-rw-r--r--addons/web/static/src/js/chrome.js17
-rw-r--r--addons/web/static/src/js/core.js6
-rw-r--r--addons/web/static/src/js/data.js4
-rw-r--r--addons/web/static/src/js/data_export.js3
-rw-r--r--addons/web/static/src/js/view_editor.js12
-rw-r--r--addons/web/static/src/js/view_form.js36
-rw-r--r--addons/web/static/src/js/view_list.js31
-rw-r--r--addons/web/static/src/js/view_page.js1
-rw-r--r--addons/web/static/src/xml/base.xml38
23 files changed, 520 insertions, 580 deletions
diff --git a/addons/web/__init__.py b/addons/web/__init__.py
index b09c8c213bc..36dead8ab74 100644
--- a/addons/web/__init__.py
+++ b/addons/web/__init__.py
@@ -1,7 +1,6 @@
import common
import controllers
import logging
-import optparse
_logger = logging.getLogger(__name__)
diff --git a/addons/web/common/http.py b/addons/web/common/http.py
index 17ccfb63d8a..434edf5e3a7 100644
--- a/addons/web/common/http.py
+++ b/addons/web/common/http.py
@@ -328,6 +328,7 @@ def session_context(request, storage_path, session_cookie='sessionid'):
# Remove all OpenERPSession instances with no uid, they're generated
# either by login process or by HTTP requests without an OpenERP
# session id, and are generally noise
+ removed_sessions = []
for key, value in request.session.items():
if (isinstance(value, session.OpenERPSession)
and not value._uid
@@ -335,6 +336,7 @@ def session_context(request, storage_path, session_cookie='sessionid'):
and value._creation_time + (60*5) < time.time() # FIXME do not use a fixed value
):
_logger.debug('remove session %s', key)
+ removed_sessions.append(key)
del request.session[key]
with session_lock:
@@ -364,7 +366,7 @@ def session_context(request, storage_path, session_cookie='sessionid'):
# add missing keys
for k, v in in_store.iteritems():
- if k not in request.session:
+ if k not in request.session and k not in removed_sessions:
request.session[k] = v
session_store.save(request.session)
diff --git a/addons/web/common/nonliterals.py b/addons/web/common/nonliterals.py
index f6e81894a4c..0f5248edf33 100644
--- a/addons/web/common/nonliterals.py
+++ b/addons/web/common/nonliterals.py
@@ -8,7 +8,7 @@ import binascii
import hashlib
import simplejson.encoder
-__all__ = ['Domain', 'Context', 'NonLiteralEncoder, non_literal_decoder', 'CompoundDomain', 'CompoundContext']
+__all__ = ['Domain', 'Context', 'NonLiteralEncoder', 'non_literal_decoder', 'CompoundDomain', 'CompoundContext']
#: 48 bits should be sufficient to have almost no chance of collision
#: with a million hashes, according to hg@67081329d49a
diff --git a/addons/web/common/xml2json.py b/addons/web/common/xml2json.py
index 1f2e74691b9..df3aad67fa5 100644
--- a/addons/web/common/xml2json.py
+++ b/addons/web/common/xml2json.py
@@ -4,35 +4,23 @@
#
# URL: http://code.google.com/p/xml2json-direct/
-class Xml2Json(object):
- @staticmethod
- def convert_to_json(s):
- return simplejson.dumps(
- Xml2Json.convert_to_structure(s), sort_keys=True, indent=4)
-
- @staticmethod
- def convert_to_structure(s):
- root = ElementTree.fromstring(s)
- return Xml2Json.convert_element(root)
-
- @staticmethod
- def convert_element(el, preserve_whitespaces=False):
- res = {}
- if el.tag[0] == "{":
- ns, name = el.tag.rsplit("}", 1)
- res["tag"] = name
- res["namespace"] = ns[1:]
- else:
- res["tag"] = el.tag
- res["attrs"] = {}
- for k, v in el.items():
- res["attrs"][k] = v
- kids = []
- if el.text and (preserve_whitespaces or el.text.strip() != ''):
- kids.append(el.text)
- for kid in el:
- kids.append(Xml2Json.convert_element(kid, preserve_whitespaces))
- if kid.tail and (preserve_whitespaces or kid.tail.strip() != ''):
- kids.append(kid.tail)
- res["children"] = kids
- return res
+def from_elementtree(el, preserve_whitespaces=False):
+ res = {}
+ if el.tag[0] == "{":
+ ns, name = el.tag.rsplit("}", 1)
+ res["tag"] = name
+ res["namespace"] = ns[1:]
+ else:
+ res["tag"] = el.tag
+ res["attrs"] = {}
+ for k, v in el.items():
+ res["attrs"][k] = v
+ kids = []
+ if el.text and (preserve_whitespaces or el.text.strip() != ''):
+ kids.append(el.text)
+ for kid in el:
+ kids.append(from_elementtree(kid, preserve_whitespaces))
+ if kid.tail and (preserve_whitespaces or kid.tail.strip() != ''):
+ kids.append(kid.tail)
+ res["children"] = kids
+ return res
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 3a23556794a..a514cafb6c8 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -99,7 +99,7 @@ html_template = """<!DOCTYPE html>
});
</script>
</head>
- <body></body>
+ <body class="openerp" id="oe"></body>
</html>
"""
@@ -207,7 +207,7 @@ class WebClient(openerpweb.Controller):
'js': js,
'css': css,
'modules': simplejson.dumps(self.server_wide_modules(req)),
- 'init': 'new s.web.WebClient().replace($("body"));',
+ 'init': 'new s.web.WebClient().start();',
}
return r
@@ -933,7 +933,7 @@ class View(openerpweb.Controller):
xml = self.transform_view(arch, session, evaluation_context)
else:
xml = ElementTree.fromstring(arch)
- fvg['arch'] = common.xml2json.Xml2Json.convert_element(xml, preserve_whitespaces)
+ fvg['arch'] = common.xml2json.from_elementtree(xml, preserve_whitespaces)
for field in fvg['fields'].itervalues():
if field.get('views'):
diff --git a/addons/web/po/pt_BR.po b/addons/web/po/pt_BR.po
index 4be0c66826c..eb3e427a769 100644
--- a/addons/web/po/pt_BR.po
+++ b/addons/web/po/pt_BR.po
@@ -8,15 +8,14 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-12-20 18:48+0100\n"
-"PO-Revision-Date: 2012-01-15 02:47+0000\n"
-"Last-Translator: Renato Lima - http://www.akretion.com "
-"<renatonlima@gmail.com>\n"
+"PO-Revision-Date: 2012-01-16 13:38+0000\n"
+"Last-Translator: Rafael Sales <Unknown>\n"
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2012-01-16 05:27+0000\n"
-"X-Generator: Launchpad (build 14664)\n"
+"X-Launchpad-Export-Date: 2012-01-17 05:08+0000\n"
+"X-Generator: Launchpad (build 14676)\n"
#: addons/web/static/src/js/chrome.js:162
#: addons/web/static/src/js/chrome.js:175
@@ -626,7 +625,7 @@ msgstr "Visão de Depuração#"
#: addons/web/static/src/xml/base.xml:0
msgid "- Fields View Get"
-msgstr ""
+msgstr "- Fields View Get"
#: addons/web/static/src/xml/base.xml:0
msgid "- Edit"
@@ -786,7 +785,7 @@ msgstr "Botão"
#: addons/web/static/src/xml/base.xml:0
msgid "(no string)"
-msgstr ""
+msgstr "(sem string)"
#: addons/web/static/src/xml/base.xml:0
msgid "Special:"
@@ -875,6 +874,10 @@ msgid ""
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
+"Este assistente irá exportar todos os dados que corresponda aos critérios de "
+"pesquisa atual em um arquivo CSV.\n"
+" Você pode exportar todos os dados ou apenas os campos que podem "
+"ser reimportados após a modificação."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
@@ -945,6 +948,10 @@ msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
+"Selecionar um arquivo .CSV para importar. Se você precisar de uma amostra do "
+"arquivo para importação,\n"
+" você deve usar a ferramenta de exportação com a opção \"Importação "
+"Compatível\"."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
@@ -1039,6 +1046,13 @@ msgid ""
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
+"é um sistema de software livre de escala empresarial que é projetado para "
+"aumentar\n"
+" produtividade e lucro através da integração de dados. Ele se "
+"conecta, melhora e\n"
+" gerencia os processos de negócio em áreas como vendas, "
+"finanças, supply chain,\n"
+" gerenciamento de projetos, produção, serviços, CRM, etc .."
#: addons/web/static/src/xml/base.xml:0
msgid ""
@@ -1051,6 +1065,14 @@ msgid ""
" production system and migration to a new version to be "
"straightforward."
msgstr ""
+"É um sistema independente de plataforma, onde pode ser instalado em "
+"ambientes Windows, Mac OS X,\n"
+" e várias distribuições Linux ou baseadas em Unix. Sua "
+"arquitetura permite que\n"
+" novas funcionalidades sejam criadas rapidamente, e modificações "
+"possam ser realizadas em um\n"
+" sistema de produção e sua migração para uma nova versão de "
+"forma simples."
#: addons/web/static/src/xml/base.xml:0
msgid ""
diff --git a/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch
deleted file mode 100644
index 1a62870a6b0..00000000000
--- a/addons/web/static/lib/jquery.tipTip/jquery.tipTip.fme.patch
+++ /dev/null
@@ -1,58 +0,0 @@
---- jquery.tipTip_old.js 2011-12-01 14:15:35.000000000 +0100
-+++ jquery.tipTip.js 2011-12-07 12:32:32.000000000 +0100
-@@ -20,6 +20,9 @@
- */
-
- (function($){
-+ $.tipTipClear = function() {
-+ $("#tiptip_holder").remove();
-+ }
- $.fn.tipTip = function(options) {
- var defaults = {
- activation: "hover",
-@@ -31,7 +34,7 @@
- fadeIn: 200,
- fadeOut: 200,
- attribute: "title",
-- content: false, // HTML or String to fill TipTIp with
-+ content: false, // HTML String or function to fill TipTIp with
- enter: function(){},
- exit: function(){}
- };
-@@ -51,12 +54,7 @@
-
- return this.each(function(){
- var org_elem = $(this);
-- if(opts.content){
-- var org_title = opts.content;
-- } else {
-- var org_title = org_elem.attr(opts.attribute);
-- }
-- if(org_title != ""){
-+ if(opts.content || org_elem.attr(opts.attribute)){
- if(!opts.content){
- org_elem.removeAttr(opts.attribute); //remove original Attribute
- }
-@@ -99,6 +97,8 @@
-
- function active_tiptip(){
- opts.enter.call(this);
-+ var org_title = typeof opts.content === 'function' ? opts.content.call(org_elem, opts) : opts.content;
-+ org_title = org_title || org_elem.attr(opts.attribute);
- tiptip_content.html(org_title);
- tiptip_holder.hide().removeAttr("class").css("margin","0");
- tiptip_arrow.removeAttr("style");
-@@ -177,7 +177,12 @@
- tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
-
- if (timeout){ clearTimeout(timeout); }
-- timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
-+ timeout = setTimeout(function() {
-+ tiptip_holder.stop(true,true);
-+ if ($.contains(document.documentElement, org_elem[0])) {
-+ tiptip_holder.fadeIn(opts.fadeIn);
-+ }
-+ }, opts.delay);
- }
-
- function deactive_tiptip(){
diff --git a/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js
index 522df828003..ff8cc1b0ba6 100644
--- a/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js
+++ b/addons/web/static/lib/jquery.tipTip/jquery.tipTip.js
@@ -1,196 +1,325 @@
- /*
- * TipTip
- * Copyright 2010 Drew Wilson
- * www.drewwilson.com
- * code.drewwilson.com/entry/tiptip-jquery-plugin
- *
- * Version 1.3 - Updated: Mar. 23, 2010
- *
- * This Plug-In will create a custom tooltip to replace the default
- * browser tooltip. It is extremely lightweight and very smart in
- * that it detects the edges of the browser window and will make sure
- * the tooltip stays within the current window size. As a result the
- * tooltip will adjust itself to be displayed above, below, to the left
- * or to the right depending on what is necessary to stay within the
- * browser window. It is completely customizable as well via CSS.
- *
- * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
-
-(function($){
- $.tipTipClear = function() {
- $("#tiptip_holder").remove();
+/*
+* TipTip
+* Copyright 2010 Drew Wilson
+* www.drewwilson.com
+* code.drewwilson.com/entry/tiptip-jquery-plugin
+*
+* Version 1.3 - Updated: Mar. 23, 2010
+*
+* This Plug-In will create a custom tooltip to replace the default
+* browser tooltip. It is extremely lightweight and very smart in
+* that it detects the edges of the browser window and will make sure
+* the tooltip stays within the current window size. As a result the
+* tooltip will adjust itself to be displayed above, below, to the left
+* or to the right depending on what is necessary to stay within the
+* browser window. It is completely customizable as well via CSS.
+*
+* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
+* http://www.opensource.org/licenses/mit-license.php
+* http://www.gnu.org/licenses/gpl.html
+*/
+
+(function ($) {
+ $.fn.tipTip = function (options) {
+
+ var defaults = {
+ activation: 'hover', // How to show (and hide) the tooltip. Can be: hover, focus, click and manual.
+ keepAlive: false, // When true the tooltip won't disapper when the mouse moves away from the element. Instead it will be hidden when it leaves the tooltip.
+ maxWidth: '200px', // The max-width to set on the tooltip. You may also use the option cssClass to set this.
+ edgeOffset: 0, // The offset between the tooltip arrow edge and the element that has the tooltip.
+ defaultPosition: 'bottom', // The position of the tooltip. Can be: top, right, bottom and left.
+ delay: 400, // The delay in msec to show a tooltip.
+ fadeIn: 200, // The length in msec of the fade in.
+ fadeOut: 200, // The length in msec of the fade out.
+ attribute: 'title', // The attribute to fetch the tooltip text if the option content is false.
+ content: false, // HTML or String or Function (that returns HTML or String) to fill TipTIp with
+ enter: function () { }, // Callback function before a tooltip is shown.
+ afterEnter: function () { }, // Callback function after a tooltip is shown.
+ exit: function () { }, // Callback function before a tooltip is hidden.
+ afterExit: function () { }, // Callback function after a tooltip is hidden.
+ cssClass: '', // CSS class that will be applied on the tooltip before showing only for this instance of tooltip.
+ detectTextDir: true // When false auto-detection for right-to-left text will be disable (When true affects a bit the performance).
+ };
+
+ // Setup tip tip elements and render them to the DOM
+ if ($('#tiptip_holder').length <= 0) {
+ var tiptip_inner_arrow = $('<div>', { id: 'tiptip_arrow_inner' }),
+ tiptip_arrow = $('<div>', { id: 'tiptip_arrow' }).append(tiptip_inner_arrow),
+ tiptip_content = $('<div>', { id: 'tiptip_content' }),
+ tiptip_holder = $('<div>', { id: 'tiptip_holder' }).append(tiptip_arrow).append(tiptip_content);
+ $('body').append(tiptip_holder);
+ } else {
+ var tiptip_holder = $('#tiptip_holder'),
+ tiptip_content = $('#tiptip_content'),
+ tiptip_arrow = $('#tiptip_arrow');
+ }
+
+ return this.each(function () {
+ var org_elem = $(this),
+ data = org_elem.data('tipTip'),
+ opts = data && data.options || $.extend({}, defaults, options),
+ callback_data = {
+ holder: tiptip_holder,
+ content: tiptip_content,
+ arrow: tiptip_arrow,
+ options: opts
+ };
+
+ if (data) {
+ switch (options) {
+ case 'show':
+ activate();
+ break;
+ case 'hide':
+ deactivate();
+ break;
+ case 'destroy':
+ org_elem.unbind('.tipTip').removeData('tipTip');
+ break;
+ case 'position':
+ position_tiptip();
+ }
+ } else {
+ var timeout = false;
+
+ org_elem.data('tipTip', { options: opts });
+
+ if (opts.activation == 'hover') {
+ org_elem.bind('mouseenter.tipTip', function () {
+ activate();
+ }).bind('mouseleave.tipTip', function () {
+ if (!opts.keepAlive) {
+ deactivate();
+ } else {
+ tiptip_holder.one('mouseleave.tipTip', function () {
+ deactivate();
+ });
+ }
+ });
+ } else if (opts.activation == 'focus') {
+ org_elem.bind('focus.tipTip', function () {
+ activate();
+ }).bind('blur.tipTip', function () {
+ deactivate();
+ });
+ } else if (opts.activation == 'click') {
+ org_elem.bind('click.tipTip', function (e) {
+ e.preventDefault();
+ activate();
+ return false;
+ }).bind('mouseleave.tipTip', function () {
+ if (!opts.keepAlive) {
+ deactivate();
+ } else {
+ tiptip_holder.one('mouseleave.tipTip', function () {
+ deactivate();
+ });
+ }
+ });
+ } else if (opts.activation == 'manual') {
+ // Nothing to register actually. We decide when to show or hide.
+ }
+ }
+
+ function activate() {
+ if (opts.enter.call(org_elem, callback_data) === false) {
+ return;
+ }
+
+ // Get the text and append it in the tiptip_content.
+ var org_title;
+ if (opts.content) {
+ org_title = $.isFunction(opts.content) ? opts.content.call(org_elem, callback_data) : opts.content;
+ } else {
+ org_title = opts.content = org_elem.attr(opts.attribute);
+ org_elem.removeAttr(opts.attribute); //remove original Attribute
+ }
+ if (!org_title) {
+ return; // don't show tip when no content.
+ }
+
+ tiptip_content.html(org_title);
+ tiptip_holder.hide().removeAttr('class').css({ 'max-width': opts.maxWidth });
+ if (opts.cssClass) {
+ tiptip_holder.addClass(opts.cssClass);
+ }
+
+ // Calculate the position of the tooltip.
+ position_tiptip();
+
+ // Show the tooltip.
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+
+ timeout = setTimeout(function () {
+ tiptip_holder.stop(true, true).fadeIn(opts.fadeIn);
+ }, opts.delay);
+
+ $(window).bind('resize.tipTip scroll.tipTip', position_tiptip);
+
+ // Ensure clicking on anything makes tipTip deactivate
+ $(document).unbind("click.tipTip dblclick.tipTip").bind("click.tiptip dblclick.tiptip", deactivate);
+
+
+ org_elem.addClass('tiptip_visible'); // Add marker class to easily find the target element with visible tooltip. It will be remove later on deactivate().
+
+ opts.afterEnter.call(org_elem, callback_data);
+ }
+
+ function deactivate() {
+ if (opts.exit.call(org_elem, callback_data) === false) {
+ return;
+ }
+
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+
+ tiptip_holder.fadeOut(opts.fadeOut);
+
+ $(window).unbind('resize.tipTip scroll.tipTip');
+ $(document).unbind("click.tipTip").unbind("dblclick.tipTip");
+
+ org_elem.removeClass('tiptip_visible');
+
+ opts.afterExit.call(org_elem, callback_data);
+ }
+
+ function position_tiptip() {
+ var org_offset = org_elem.offset(),
+ org_top = org_offset.top,
+ org_left = org_offset.left,
+ org_width = org_elem.outerWidth(),
+ org_height = org_elem.outerHeight(),
+ tip_top,
+ tip_left,
+ tip_width = tiptip_holder.outerWidth(),
+ tip_height = tiptip_holder.outerHeight(),
+ tip_class,
+ tip_classes = { top: 'tip_top', bottom: 'tip_bottom', left: 'tip_left', right: 'tip_right' },
+ arrow_top,
+ arrow_left,
+ arrow_width = 12, // tiptip_arrow.outerHeight() and tiptip_arrow.outerWidth() don't work because they need the element to be visible.
+ arrow_height = 12,
+ win = $(window),
+ win_top = win.scrollTop(),
+ win_left = win.scrollLeft(),
+ win_width = win.width(),
+ win_height = win.height(),
+ is_rtl = opts.detectTextDir && isRtlText(tiptip_content.text());
+
+ function moveTop() {
+ tip_class = tip_classes.top;
+ tip_top = org_top - tip_height - opts.edgeOffset - (arrow_height / 2);
+ tip_left = org_left + ((org_width - tip_width) / 2);
+ }
+
+ function moveBottom() {
+ tip_class = tip_classes.bottom;
+ tip_top = org_top + org_height + opts.edgeOffset + (arrow_height / 2);
+ tip_left = org_left + ((org_width - tip_width) / 2);
+ }
+
+ function moveLeft() {
+ tip_class = tip_classes.left;
+ tip_top = org_top + ((org_height - tip_height) / 2);
+ tip_left = org_left - tip_width - opts.edgeOffset - (arrow_width / 2);
+ }
+
+ function moveRight() {
+ tip_class = tip_classes.right;
+ tip_top = org_top + ((org_height - tip_height) / 2);
+ tip_left = org_left + org_width + opts.edgeOffset + (arrow_width / 2);
+ }
+
+ // Calculate the position of the tooltip.
+ if (opts.defaultPosition == 'bottom') {
+ moveBottom();
+ } else if (opts.defaultPosition == 'top') {
+ moveTop();
+ } else if (opts.defaultPosition == 'left' && !is_rtl) {
+ moveLeft();
+ } else if (opts.defaultPosition == 'left' && is_rtl) {
+ moveRight();
+ } else if (opts.defaultPosition == 'right' && !is_rtl) {
+ moveRight();
+ } else if (opts.defaultPosition == 'right' && is_rtl) {
+ moveLeft();
+ } else {
+ moveBottom();
+ }
+
+ // Flip the tooltip if off the window's viewport. (left <-> right and top <-> bottom).
+ if (tip_class == tip_classes.left && !is_rtl && tip_left < win_left) {
+ moveRight();
+ } else if (tip_class == tip_classes.left && is_rtl && tip_left - tip_width < win_left) {
+ moveRight();
+ } else if (tip_class == tip_classes.right && !is_rtl && tip_left > win_left + win_width) {
+ moveLeft();
+ } else if (tip_class == tip_classes.right && is_rtl && tip_left + tip_width > win_left + win_width) {
+ moveLeft();
+ } else if (tip_class == tip_classes.top && tip_top < win_top) {
+ moveBottom();
+ } else if (tip_class == tip_classes.bottom && tip_top > win_top + win_height) {
+ moveTop();
+ }
+
+ // Fix the vertical position if the tooltip is off the top or bottom sides of the window's viewport.
+ if (tip_class == tip_classes.left || tip_class == tip_classes.right) { // If positioned left or right check if the tooltip is off the top or bottom window's viewport.
+ if (tip_top + tip_height > win_height + win_top) { // If the bottom edge of the tooltip is off the bottom side of the window's viewport.
+ tip_top = org_top + org_height > win_height + win_top ? org_top + org_height - tip_height : win_height + win_top - tip_height; // Make 'bottom edge of the tooltip' == 'bottom side of the window's viewport'.
+ } else if (tip_top < win_top) { // If the top edge of the tooltip if off the top side of the window's viewport.
+ tip_top = org_top < win_top ? org_top : win_top; // Make 'top edge of the tooltip' == 'top side of the window's viewport'.
+ }
+ }
+
+ // Fix the horizontal position if the tooltip is off the right or left sides of the window's viewport.
+ if (tip_class == tip_classes.top || tip_class == tip_classes.bottom) {
+ if (tip_left + tip_width > win_width + win_left) { // If the right edge of the tooltip is off the right side of the window's viewport.
+ tip_left = org_left + org_width > win_width + win_left ? org_left + org_width - tip_width : win_width + win_left - tip_width; // Make 'right edge of the tooltip' == 'right side of the window's viewport'.
+ } else if (tip_left < win_left) { // If the left edge of the tooltip if off the left side of the window's viewport.
+ tip_left = org_left < win_left ? org_left : win_left; // Make 'left edge of the tooltip' == 'left side of the window's viewport'.
+ }
+ }
+
+ // Apply the new position.
+ tiptip_holder
+ .css({ left: Math.round(tip_left), top: Math.round(tip_top) })
+ .removeClass(tip_classes.top)
+ .removeClass(tip_classes.bottom)
+ .removeClass(tip_classes.left)
+ .removeClass(tip_classes.right)
+ .addClass(tip_class);
+
+ // Position the arrow
+ if (tip_class == tip_classes.top) {
+ arrow_top = tip_height; // Position the arrow vertically on the top of the tooltip.
+ arrow_left = org_left - tip_left + ((org_width - arrow_width) / 2); // Center the arrow horizontally on the center of the target element.
+ } else if (tip_class == tip_classes.bottom) {
+ arrow_top = -arrow_height; // Position the arrow vertically on the bottom of the tooltip.
+ arrow_left = org_left - tip_left + ((org_width - arrow_width) / 2); // Center the arrow horizontally on the center of the target element.
+ } else if (tip_class == tip_classes.left) {
+ arrow_top = org_top - tip_top + ((org_height - arrow_height) / 2); // Center the arrow vertically on the center of the target element.
+ arrow_left = tip_width; // Position the arrow vertically on the left of the tooltip.
+ } else if (tip_class == tip_classes.right) {
+ arrow_top = org_top - tip_top + ((org_height - arrow_height) / 2); // Center the arrow vertically on the center of the target element.
+ arrow_left = -arrow_width; // Position the arrow vertically on the right of the tooltip.
+ }
+
+ tiptip_arrow
+ .css({ left: Math.round(arrow_left), top: Math.round(arrow_top) });
+ }
+ });
}
- $.fn.tipTip = function(options) {
- var defaults = {
- activation: "hover",
- keepAlive: false,
- maxWidth: "200px",
- edgeOffset: 3,
- defaultPosition: "bottom",
- delay: 400,
- fadeIn: 200,
- fadeOut: 200,
- attribute: "title",
- content: false, // HTML String or function to fill TipTIp with
- enter: function(){},
- exit: function(){}
- };
- var opts = $.extend(defaults, options);
-
- // Setup tip tip elements and render them to the DOM
- if($("#tiptip_holder").length <= 0){
- var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
- var tiptip_content = $('<div id="tiptip_content"></div>');
- var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
- $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
- } else {
- var tiptip_holder = $("#tiptip_holder");
- var tiptip_content = $("#tiptip_content");
- var tiptip_arrow = $("#tiptip_arrow");
- }
-
- return this.each(function(){
- var org_elem = $(this);
- if(opts.content || org_elem.attr(opts.attribute)){
- if(!opts.content){
- org_elem.removeAttr(opts.attribute); //remove original Attribute
- }
- var timeout = false;
-
- if(opts.activation == "hover"){
- org_elem.hover(function(){
- active_tiptip();
- }, function(){
- if(!opts.keepAlive){
- deactive_tiptip();
- }
- });
- if(opts.keepAlive){
- tiptip_holder.hover(function(){}, function(){
- deactive_tiptip();
- });
- }
- } else if(opts.activation == "focus"){
- org_elem.focus(function(){
- active_tiptip();
- }).blur(function(){
- deactive_tiptip();
- });
- } else if(opts.activation == "click"){
- org_elem.click(function(){
- active_tiptip();
- return false;
- }).hover(function(){},function(){
- if(!opts.keepAlive){
- deactive_tiptip();
- }
- });
- if(opts.keepAlive){
- tiptip_holder.hover(function(){}, function(){
- deactive_tiptip();
- });
- }
- }
-
- function active_tiptip(){
- opts.enter.call(this);
- var org_title = typeof opts.content === 'function' ? opts.content.call(org_elem, opts) : opts.content;
- org_title = org_title || org_elem.attr(opts.attribute);
- tiptip_content.html(org_title);
- tiptip_holder.hide().removeAttr("class").css("margin","0");
- tiptip_arrow.removeAttr("style");
-
- var top = parseInt(org_elem.offset()['top']);
- var left = parseInt(org_elem.offset()['left']);
- var org_width = parseInt(org_elem.outerWidth());
- var org_height = parseInt(org_elem.outerHeight());
- var tip_w = tiptip_holder.outerWidth();
- var tip_h = tiptip_holder.outerHeight();
- var w_compare = Math.round((org_width - tip_w) / 2);
- var h_compare = Math.round((org_height - tip_h) / 2);
- var marg_left = Math.round(left + w_compare);
- var marg_top = Math.round(top + org_height + opts.edgeOffset);
- var t_class = "";
- var arrow_top = "";
- var arrow_left = Math.round(tip_w - 12) / 2;
-
- if(opts.defaultPosition == "bottom"){
- t_class = "_bottom";
- } else if(opts.defaultPosition == "top"){
- t_class = "_top";
- } else if(opts.defaultPosition == "left"){
- t_class = "_left";
- } else if(opts.defaultPosition == "right"){
- t_class = "_right";
- }
-
- var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
- var left_compare = (tip_w + left) > parseInt($(window).width());
-
- if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
- t_class = "_right";
- arrow_top = Math.round(tip_h - 13) / 2;
- arrow_left = -12;
- marg_left = Math.round(left + org_width + opts.edgeOffset);
- marg_top = Math.round(top + h_compare);
- } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
- t_class = "_left";
- arrow_top = Math.round(tip_h - 13) / 2;
- arrow_left = Math.round(tip_w);
- marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
- marg_top = Math.round(top + h_compare);
- }
-
- var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
- var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
-
- if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
- if(t_class == "_top" || t_class == "_bottom"){
- t_class = "_top";
- } else {
- t_class = t_class+"_top";
- }
- arrow_top = tip_h;
- marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
- } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
- if(t_class == "_top" || t_class == "_bottom"){
- t_class = "_bottom";
- } else {
- t_class = t_class+"_bottom";
- }
- arrow_top = -12;
- marg_top = Math.round(top + org_height + opts.edgeOffset);
- }
-
- if(t_class == "_right_top" || t_class == "_left_top"){
- marg_top = marg_top + 5;
- } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
- marg_top = marg_top - 5;
- }
- if(t_class == "_left_top" || t_class == "_left_bottom"){
- marg_left = marg_left + 5;
- }
- tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
- tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
-
- if (timeout){ clearTimeout(timeout); }
- timeout = setTimeout(function() {
- tiptip_holder.stop(true,true);
- if ($.contains(document.documentElement, org_elem[0])) {
- tiptip_holder.fadeIn(opts.fadeIn);
- }
- }, opts.delay);
- }
-
- function deactive_tiptip(){
- opts.exit.call(this);
- if (timeout){ clearTimeout(timeout); }
- tiptip_holder.fadeOut(opts.fadeOut);
- }
- }
- });
- }
-})(jQuery);
+
+ var ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF',
+ rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC',
+ rtlDirCheckRe = new RegExp('^[^' + ltrChars + ']*[' + rtlChars + ']');
+
+ function isRtlText(text) {
+ return rtlDirCheckRe.test(text);
+ };
+
+})(jQuery);
+
diff --git a/addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js b/addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js
deleted file mode 100644
index d2b460d1261..00000000000
--- a/addons/web/static/lib/jquery.tipTip/jquery.tipTip_old.js
+++ /dev/null
@@ -1,191 +0,0 @@
- /*
- * TipTip
- * Copyright 2010 Drew Wilson
- * www.drewwilson.com
- * code.drewwilson.com/entry/tiptip-jquery-plugin
- *
- * Version 1.3 - Updated: Mar. 23, 2010
- *
- * This Plug-In will create a custom tooltip to replace the default
- * browser tooltip. It is extremely lightweight and very smart in
- * that it detects the edges of the browser window and will make sure
- * the tooltip stays within the current window size. As a result the
- * tooltip will adjust itself to be displayed above, below, to the left
- * or to the right depending on what is necessary to stay within the
- * browser window. It is completely customizable as well via CSS.
- *
- * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
-
-(function($){
- $.fn.tipTip = function(options) {
- var defaults = {
- activation: "hover",
- keepAlive: false,
- maxWidth: "200px",
- edgeOffset: 3,
- defaultPosition: "bottom",
- delay: 400,
- fadeIn: 200,
- fadeOut: 200,
- attribute: "title",
- content: false, // HTML or String to fill TipTIp with
- enter: function(){},
- exit: function(){}
- };
- var opts = $.extend(defaults, options);
-
- // Setup tip tip elements and render them to the DOM
- if($("#tiptip_holder").length <= 0){
- var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
- var tiptip_content = $('<div id="tiptip_content"></div>');
- var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
- $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
- } else {
- var tiptip_holder = $("#tiptip_holder");
- var tiptip_content = $("#tiptip_content");
- var tiptip_arrow = $("#tiptip_arrow");
- }
-
- return this.each(function(){
- var org_elem = $(this);
- if(opts.content){
- var org_title = opts.content;
- } else {
- var org_title = org_elem.attr(opts.attribute);
- }
- if(org_title != ""){
- if(!opts.content){
- org_elem.removeAttr(opts.attribute); //remove original Attribute
- }
- var timeout = false;
-
- if(opts.activation == "hover"){
- org_elem.hover(function(){
- active_tiptip();
- }, function(){
- if(!opts.keepAlive){
- deactive_tiptip();
- }
- });
- if(opts.keepAlive){
- tiptip_holder.hover(function(){}, function(){
- deactive_tiptip();
- });
- }
- } else if(opts.activation == "focus"){
- org_elem.focus(function(){
- active_tiptip();
- }).blur(function(){
- deactive_tiptip();
- });
- } else if(opts.activation == "click"){
- org_elem.click(function(){
- active_tiptip();
- return false;
- }).hover(function(){},function(){
- if(!opts.keepAlive){
- deactive_tiptip();
- }
- });
- if(opts.keepAlive){
- tiptip_holder.hover(function(){}, function(){
- deactive_tiptip();
- });
- }
- }
-
- function active_tiptip(){
- opts.enter.call(this);
- tiptip_content.html(org_title);
- tiptip_holder.hide().removeAttr("class").css("margin","0");
- tiptip_arrow.removeAttr("style");
-
- var top = parseInt(org_elem.offset()['top']);
- var left = parseInt(org_elem.offset()['left']);
- var org_width = parseInt(org_elem.outerWidth());
- var org_height = parseInt(org_elem.outerHeight());
- var tip_w = tiptip_holder.outerWidth();
- var tip_h = tiptip_holder.outerHeight();
- var w_compare = Math.round((org_width - tip_w) / 2);
- var h_compare = Math.round((org_height - tip_h) / 2);
- var marg_left = Math.round(left + w_compare);
- var marg_top = Math.round(top + org_height + opts.edgeOffset);
- var t_class = "";
- var arrow_top = "";
- var arrow_left = Math.round(tip_w - 12) / 2;
-
- if(opts.defaultPosition == "bottom"){
- t_class = "_bottom";
- } else if(opts.defaultPosition == "top"){
- t_class = "_top";
- } else if(opts.defaultPosition == "left"){
- t_class = "_left";
- } else if(opts.defaultPosition == "right"){
- t_class = "_right";
- }
-
- var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
- var left_compare = (tip_w + left) > parseInt($(window).width());
-
- if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
- t_class = "_right";
- arrow_top = Math.round(tip_h - 13) / 2;
- arrow_left = -12;
- marg_left = Math.round(left + org_width + opts.edgeOffset);
- marg_top = Math.round(top + h_compare);
- } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
- t_class = "_left";
- arrow_top = Math.round(tip_h - 13) / 2;
- arrow_left = Math.round(tip_w);
- marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
- marg_top = Math.round(top + h_compare);
- }
-
- var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
- var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
-
- if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
- if(t_class == "_top" || t_class == "_bottom"){
- t_class = "_top";
- } else {
- t_class = t_class+"_top";
- }
- arrow_top = tip_h;
- marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
- } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
- if(t_class == "_top" || t_class == "_bottom"){
- t_class = "_bottom";
- } else {
- t_class = t_class+"_bottom";
- }
- arrow_top = -12;
- marg_top = Math.round(top + org_height + opts.edgeOffset);
- }
-
- if(t_class == "_right_top" || t_class == "_left_top"){
- marg_top = marg_top + 5;
- } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
- marg_top = marg_top - 5;
- }
- if(t_class == "_left_top" || t_class == "_left_bottom"){
- marg_left = marg_left + 5;
- }
- tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
- tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
-
- if (timeout){ clearTimeout(timeout); }
- timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
- }
-
- function deactive_tiptip(){
- opts.exit.call(this);
- if (timeout){ clearTimeout(timeout); }
- tiptip_holder.fadeOut(opts.fadeOut);
- }
- }
- });
- }
-})(jQuery);
diff --git a/addons/web/static/lib/jquery.tipTip/tipTip.css b/addons/web/static/lib/jquery.tipTip/tipTip.css
index 4fb95d37691..dc41b650615 100644
--- a/addons/web/static/lib/jquery.tipTip/tipTip.css
+++ b/addons/web/static/lib/jquery.tipTip/tipTip.css
@@ -13,15 +13,15 @@
}
#tiptip_holder.tip_bottom {
- padding-top: 5px;
+ padding-bottom: 5px;
}
#tiptip_holder.tip_right {
- padding-left: 5px;
+ padding-right: 5px;
}
#tiptip_holder.tip_left {
- padding-right: 5px;
+ padding-left: 5px;
}
#tiptip_content {
@@ -110,4 +110,25 @@
#tiptip_holder.tip_top #tiptip_arrow_inner {
border-top-color: rgba(20,20,20,0.92);
}
+}
+
+/* Alternative theme for TipTip */
+#tiptip_holder.alt.tip_top #tiptip_arrow_inner {
+ border-top-color: #444444;
+}
+
+#tiptip_holder.alt.tip_bottom #tiptip_arrow_inner {
+ border-bottom-color: #444444;
+}
+
+#tiptip_holder.alt.tip_right #tiptip_arrow_inner {
+ border-right-color: #444444;
+}
+
+#tiptip_holder.alt.tip_left #tiptip_arrow_inner {
+ border-left-color: #444444;
+}
+
+#tiptip_holder.alt #tiptip_content {
+ background-color: #444444; border: 1px solid White; border-radius: 3px; box-shadow: 0 0 3px #555555; color: #FFFFFF; font-size: 11px; padding: 4px 8px; text-shadow: 0 0 1px Black;
} \ No newline at end of file
diff --git a/addons/web/static/lib/qweb/qweb-benchmark.html b/addons/web/static/lib/qweb/qweb-benchmark.html
index 0cc67e7e54f..4f7fb56ac1f 100644
--- a/addons/web/static/lib/qweb/qweb-benchmark.html
+++ b/addons/web/static/lib/qweb/qweb-benchmark.html
@@ -5,11 +5,25 @@
<script type="text/javascript" src="qweb.js"></script>
<script type="text/javascript" src="qweb2.js"></script>
<script type="text/javascript">
+ (function (c) {
+ if (c.time) { return; }
+ var d = {};
+ c.time = function (key) {
+ d[key] = Date.now();
+ };
+ c.timeEnd = function (key) {
+ var end = Date.now(),
+ origin = d[key];
+ delete d[key];
+ if (!origin) { return; }
+ console.log(key + ': ' + (end - origin) + 'ms');
+ };
+ })(window.console);
var dict = {
session : true,
testing : 'yes',
name : 'AGR'
- }
+ };
console.time("Load template with QWeb");
QWeb.add_template("qweb-benchmark.xml");
console.timeEnd("Load template with QWeb");
diff --git a/addons/web/static/lib/qweb/qweb-test-call.xml b/addons/web/static/lib/qweb/qweb-test-call.xml
index 5d8f0019f7c..3f7bd60ffbc 100644
--- a/addons/web/static/lib/qweb/qweb-test-call.xml
+++ b/addons/web/static/lib/qweb/qweb-test-call.xml
@@ -1,6 +1,6 @@
<templates>
<t t-name="basic-callee">ok</t>
- <t t-name="callee-printsbody"><t t-esc="0"/></t>
+ <t t-name="callee-printsbody"><t t-esc="__content__"/></t>
<t t-name="callee-uses-foo"><t t-esc="foo"/></t>
<t t-name="callee-sets-foo"><t t-set="foo" t-value="'ok'"/></t>
diff --git a/addons/web/static/lib/qweb/qweb2.js b/addons/web/static/lib/qweb/qweb2.js
index 093b3651fa0..8657a8b20be 100644
--- a/addons/web/static/lib/qweb/qweb2.js
+++ b/addons/web/static/lib/qweb/qweb2.js
@@ -194,7 +194,7 @@ var QWeb2 = {
QWeb2.Engine = (function() {
function Engine() {
- // TODO: handle prefix at template level : t-prefix="x"
+ // TODO: handle prefix at template level : t-prefix="x", don't forget to lowercase it
this.prefix = 't';
this.debug = false;
this.templates_resources = []; // TODO: implement this.reload()
@@ -329,12 +329,12 @@ QWeb2.Engine = (function() {
" return r.join('');";
},
render : function(template, dict) {
- var ndict = QWeb2.tools.extend({}, this.default_dict);
- QWeb2.tools.extend(ndict, dict);
+ dict = dict || {};
+ QWeb2.tools.extend(dict, this.default_dict);
/*if (this.debug && window['console'] !== undefined) {
console.time("QWeb render template " + template);
}*/
- var r = this._render(template, ndict);
+ var r = this._render(template, dict);
/*if (this.debug && window['console'] !== undefined) {
console.timeEnd("QWeb render template " + template);
}*/
@@ -620,7 +620,7 @@ QWeb2.Element = (function() {
}
}
}
- if (this.tag !== this.engine.prefix) {
+ if (this.tag.toLowerCase() !== this.engine.prefix) {
var tag = "<" + this.tag;
for (var a in this.attributes) {
tag += this.engine.tools.gen_attribute([a, this.attributes[a]]);
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index d4bd7a6ff1b..32c7f14b345 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -1,4 +1,5 @@
-body.openerp {
+body { padding: 0; margin: 0; }
+.openerp {
padding: 0;
margin: 0;
height: 100%;
@@ -7,7 +8,8 @@ body.openerp {
font-family: Ubuntu, Helvetica, sans-serif;
}
-body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp option, .openerp button, .openerp .ui-widget {
+.openerp, .openerp textarea, .openerp input, .openerp select, .openerp option,
+.openerp button, .openerp .ui-widget {
font-family: Ubuntu, Helvetica, sans-serif;
font-size:85%;
}
@@ -1416,7 +1418,7 @@ label.error {
}
@-moz-document url-prefix() {
/* Strange firefox behaviour on width: 100% + white-space: nowrap */
- .openerp .oe_forms .oe_button {
+ .openerp .oe_forms .oe_form_button .oe_button {
width: auto;
}
}
@@ -1851,15 +1853,28 @@ label.error {
}
.openerp .oe-treeview-table {
width: 100%;
+ background-color : #FFFFFF;
+ border-spacing: 0;
+}
+.openerp .oe-treeview-table tr:hover{
+ color: blue;
+ background-color : #D8D8D8;
}
.treeview-tr, .treeview-td {
cursor: pointer;
vertical-align: top;
text-align: left;
+ border-bottom: 1px solid #CFCCCC;
+}
+.oe-number{
+ text-align: right !important;
}
.treeview-tr span, .treeview-td span {
+ font-size: 90%;
+ font-weight: normal;
+ white-space: nowrap;
display: block;
-}
+ }
.treeview-tr:first-of-type {
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
}
@@ -1872,8 +1887,11 @@ label.error {
}
.treeview-header {
- text-align: left;
vertical-align: top;
+ background-color : #D8D8D8;
+ white-space: nowrap;
+ text-align: left;
+ padding: 4px 5px;
}
/* Shortcuts*/
.oe-shortcut-toggle {
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 39bc0181e16..8b9a0d4efc6 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -205,7 +205,7 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({
buttons: buttons
}).open();
dialog.$element.html(QWeb.render('CrashManagerError', {session: openerp.connection, error: error}));
- },
+ }
});
openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{
@@ -280,6 +280,9 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
init: function(parent, element_id, option_id) {
this._super(parent, element_id);
this.unblockUIFunction = $.unblockUI;
+ $.validator.addMethod('matches', function (s, _, re) {
+ return new RegExp(re).test(s);
+ }, _t("Invalid database name"));
},
start: function() {
this.$option_id = $("#oe_db_options");
@@ -646,7 +649,7 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
}
}
});
- },
+ }
});
openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# */{
@@ -1059,13 +1062,9 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
this._current_state = null;
},
- render_element: function() {
- this.$element = $('<body/>');
- this.$element.attr("id", "oe");
- this.$element.addClass("openerp");
- },
start: function() {
var self = this;
+ this.$element = $(document.body);
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) {
@@ -1089,7 +1088,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
self.bind_hashchange();
if (!self.session.openerp_entreprise) {
self.$element.find('.oe_footer_powered').append('<span> - <a href="http://www.openerp.com/support-or-publisher-warranty-contract" target="_blank">Unsupported/Community Version</a></span>');
- $('title').html('OpenERP - Unsupported/Community Version');
+ document.title = _t("OpenERP - Unsupported/Community Version");
}
});
},
@@ -1212,7 +1211,7 @@ openerp.web.EmbeddedClient = openerp.web.Widget.extend({
self.am.do_action(action);
});
- },
+ }
});
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js
index b36e576ae47..3005fc80d13 100644
--- a/addons/web/static/src/js/core.js
+++ b/addons/web/static/src/js/core.js
@@ -491,7 +491,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(payload),
- processData: false,
+ processData: false
}, url);
if (this.synch)
ajax.async = false;
@@ -502,7 +502,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
// extracted from payload to set on the url
var data = {
session_id: this.session_id,
- id: payload.id,
+ id: payload.id
};
url.url = this.get_url(url.url);
var ajax = _.extend({
@@ -864,7 +864,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
} finally {
this.synch = synch;
}
- },
+ }
});
/**
diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js
index 447b95d17cf..bb53fb2175a 100644
--- a/addons/web/static/src/js/data.js
+++ b/addons/web/static/src/js/data.js
@@ -829,9 +829,9 @@ openerp.web.Model = openerp.web.CallbackEnabled.extend({
model: this.model_name,
method: method,
args: args,
- kwargs: kwargs,
+ kwargs: kwargs
});
- },
+ }
});
openerp.web.CompoundContext = openerp.web.Class.extend({
diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js
index 78be735edc7..3d15a4e3607 100644
--- a/addons/web/static/src/js/data_export.js
+++ b/addons/web/static/src/js/data_export.js
@@ -364,9 +364,8 @@ openerp.web.DataExport = openerp.web.Dialog.extend({
on_click_export_data: function() {
var self = this;
var exported_fields = this.$element.find('#fields_list option').map(function () {
- var name = self.records[this.value] || this.value
// DOM property is textContent, but IE8 only knows innerText
- return {name: this.value,
+ return {name: self.records[this.value] || this.value,
label: this.textContent || this.innerText};
}).get();
diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js
index bf920380ff9..6e58886fadd 100644
--- a/addons/web/static/src/js/view_editor.js
+++ b/addons/web/static/src/js/view_editor.js
@@ -806,7 +806,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
'widget' : {'name':'widget', 'string': 'widget', 'type': 'selection'},
'colors' : {'name':'colors', 'string': 'Colors', 'type': 'char'},
'editable' : {'name':'editable', 'string': 'Editable', 'type': 'selection', 'selection': [["",""],["top","Top"],["bottom", "Bottom"]]},
- 'groups' : {'name':'groups', 'string': 'Groups', 'type': 'seleciton_multi'},
+ 'groups' : {'name':'groups', 'string': 'Groups', 'type': 'seleciton_multi'}
};
var arch_val = self.get_object_by_id(this.one_object.clicked_tr_id,this.one_object['main_object'], []);
this.edit_node_dialog.$element.append('<table id="rec_table" style="width:400px" class="oe_forms"></table>');
@@ -928,7 +928,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
type: 'ir.actions.act_window',
target: "new",
flags: {
- action_buttons: true,
+ action_buttons: true
}
}
var action_manager = new openerp.web.ActionManager(self);
@@ -982,7 +982,7 @@ openerp.web.ViewEditor.Field = openerp.web.Class.extend({
},
render: function() {
return _.str.sprintf("<td id = %s>%s</td>", this.name, QWeb.render(this.template, {widget: this}))
- },
+ }
});
openerp.web.ViewEditor.FieldBoolean = openerp.web.ViewEditor.Field.extend({
template : "vieweditor_boolean",
@@ -1084,7 +1084,7 @@ var _PROPERTIES = {
'action' : ['name', 'string', 'colspan', 'groups'],
'tree' : ['string', 'colors', 'editable', 'link', 'limit', 'min_rows'],
'graph' : ['string', 'type'],
- 'calendar' : ['string', 'date_start', 'date_stop', 'date_delay', 'day_length', 'color', 'mode'],
+ 'calendar' : ['string', 'date_start', 'date_stop', 'date_delay', 'day_length', 'color', 'mode']
};
var _CHILDREN = {
'form': ['notebook', 'group', 'field', 'label', 'button','board', 'newline', 'separator'],
@@ -1100,7 +1100,7 @@ var _CHILDREN = {
'label': [],
'button' : [],
'newline': [],
- 'separator': [],
+ 'separator': []
};
var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
'STOCK_CANCEL', 'STOCK_CDROM', 'STOCK_CLEAR', 'STOCK_CLOSE', 'STOCK_COLOR_PICKER',
@@ -1134,6 +1134,6 @@ openerp.web.ViewEditor.property_widget = new openerp.web.Registry({
'seleciton_multi' : 'openerp.web.ViewEditor.FieldSelectMulti',
'selection' : 'openerp.web.ViewEditor.FieldSelect',
'char' : 'openerp.web.ViewEditor.FieldChar',
- 'float' : 'openerp.web.ViewEditor.FieldFloat',
+ 'float' : 'openerp.web.ViewEditor.FieldFloat'
});
};
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index ebe1ca26785..ebcbfc18100 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -40,7 +40,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
this.fields = {};
this.fields_order = [];
this.datarecord = {};
- this.show_invalid = true;
this.default_focus_field = null;
this.default_focus_button = null;
this.registry = openerp.web.form.widgets;
@@ -179,7 +178,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
});
return $.when.apply(null, set_values).pipe(function() {
if (!record.id) {
- self.show_invalid = false;
// New record: Second pass in order to trigger the onchanges
// respecting the fields order defined in the view
_.each(self.fields_order, function(field_name) {
@@ -192,7 +190,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
}
self.on_form_changed();
self.is_initialized.resolve();
- self.show_invalid = true;
self.do_update_pager(record.id == null);
if (self.sidebar) {
self.sidebar.attachments.do_update();
@@ -429,7 +426,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
f = self.fields[f];
if (!f.is_valid()) {
form_invalid = true;
- f.update_dom();
+ f.update_dom(true);
if (!first_invalid_field) {
first_invalid_field = f;
}
@@ -716,9 +713,11 @@ openerp.web.form.compute_domain = function(expr, fields) {
stack.push(field_value >= val);
break;
case 'in':
+ if (!_.isArray(val)) val = [val];
stack.push(_(val).contains(field_value));
break;
case 'not in':
+ if (!_.isArray(val)) val = [val];
stack.push(!_(val).contains(field_value));
break;
default:
@@ -791,6 +790,11 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form.
return QWeb.render(template, { "widget": this });
},
do_attach_tooltip: function(widget, trigger, options) {
+ if ($.browser.mozilla && parseInt($.browser.version.split('.')[0], 10) < 2) {
+ // Unknown bug in old version of firefox :
+ // input type=text onchange event not fired when tootip is shown
+ return;
+ }
widget = widget || this;
trigger = trigger || this.$element;
options = _.extend({
@@ -1063,7 +1067,6 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
this.execute_action().always(function() {
self.force_disabled = false;
self.check_disable();
- $.tipTipClear();
});
},
execute_action: function() {
@@ -1075,17 +1078,17 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
title: _t('Confirm'),
modal: true,
buttons: [
+ {text: _t("Cancel"), click: function() {
+ def.resolve();
+ $(this).dialog("close");
+ }
+ },
{text: _t("Ok"), click: function() {
self.on_confirmed().then(function() {
def.resolve();
});
$(this).dialog("close");
}
- },
- {text: _t("Cancel"), click: function() {
- def.resolve();
- $(this).dialog("close");
- }
}
]
});
@@ -1116,7 +1119,7 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
});
},
update_dom: function() {
- this._super();
+ this._super.apply(this, arguments);
this.check_disable();
},
check_disable: function() {
@@ -1238,7 +1241,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
get_on_change_value: function() {
return this.get_value();
},
- update_dom: function() {
+ update_dom: function(show_invalid) {
this._super.apply(this, arguments);
if (this.field.translate) {
this.$element.find('.oe_field_translate').toggle(!!this.view.datarecord.id);
@@ -1246,7 +1249,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
if (!this.disable_utility_classes) {
this.$element.toggleClass('disabled', this.readonly);
this.$element.toggleClass('required', this.required);
- if (this.view.show_invalid) {
+ if (show_invalid) {
this.$element.toggleClass('invalid', !this.is_valid());
}
}
@@ -1259,7 +1262,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this.view.do_onchange(this);
this.view.on_form_changed();
} else {
- this.update_dom();
+ this.update_dom(true);
}
},
validate: function() {
@@ -1281,7 +1284,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this.definition_options = JSON.parse(str);
}
return this.definition_options;
- },
+ }
});
openerp.web.form.FieldChar = openerp.web.form.Field.extend({
@@ -2424,7 +2427,7 @@ openerp.web.form.One2ManyListView = openerp.web.ListView.extend({
var self = this;
var def = $.Deferred().then(callback).then(function() {self.o2m.view.reload();});
return this._super(name, id, _.bind(def.resolve, def));
- },
+ }
});
openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({
@@ -3214,7 +3217,6 @@ openerp.web.form.widgets = new openerp.web.Registry({
'email' : 'openerp.web.form.FieldEmail',
'url' : 'openerp.web.form.FieldUrl',
'text' : 'openerp.web.form.FieldText',
- 'text_wiki' : 'openerp.web.form.FieldText',
'date' : 'openerp.web.form.FieldDate',
'datetime' : 'openerp.web.form.FieldDatetime',
'selection' : 'openerp.web.form.FieldSelection',
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index aa970c31649..1f8a6020f46 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -1316,19 +1316,24 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
if (!self.datagroup.openable) {
view.configure_pager(dataset);
} else {
- var pages = Math.ceil(dataset.ids.length / limit);
- self.$row
- .find('.oe-pager-state')
- .text(_.str.sprintf(_t("%(page)d/%(page_count)d"), {
- page: page + 1,
- page_count: pages
- }))
- .end()
- .find('button[data-pager-action=previous]')
- .attr('disabled', page === 0)
- .end()
- .find('button[data-pager-action=next]')
- .attr('disabled', page === pages - 1);
+ if (dataset.ids.length == records.length) {
+ // only one page
+ self.$row.find('td.oe-group-pagination').empty();
+ } else {
+ var pages = Math.ceil(dataset.ids.length / limit);
+ self.$row
+ .find('.oe-pager-state')
+ .text(_.str.sprintf(_t("%(page)d/%(page_count)d"), {
+ page: page + 1,
+ page_count: pages
+ }))
+ .end()
+ .find('button[data-pager-action=previous]')
+ .attr('disabled', page === 0)
+ .end()
+ .find('button[data-pager-action=next]')
+ .attr('disabled', page === pages - 1);
+ }
}
self.records.add(records, {silent: true});
diff --git a/addons/web/static/src/js/view_page.js b/addons/web/static/src/js/view_page.js
index d3ee79effca..31190d70f85 100644
--- a/addons/web/static/src/js/view_page.js
+++ b/addons/web/static/src/js/view_page.js
@@ -241,7 +241,6 @@ openerp.web.page = function (openerp) {
'email': 'openerp.web.page.FieldEmailReadonly',
'url': 'openerp.web.page.FieldUrlReadonly',
'text': 'openerp.web.page.FieldCharReadonly',
- 'text_wiki' : 'openerp.web.page.FieldCharReadonly',
'date': 'openerp.web.page.FieldCharReadonly',
'datetime': 'openerp.web.page.FieldCharReadonly',
'selection' : 'openerp.web.page.FieldSelectionReadonly',
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 5158fda62c2..b119e5aae3c 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -70,7 +70,8 @@
</tr>
<tr>
<td><label for="db_name">New database name:</label></td>
- <td><input type="text" name="db_name" class="required"/></td>
+ <td><input type="text" name="db_name"
+ class="required" matches="^[a-zA-Z][a-zA-Z0-9_]+$"/></td>
</tr>
<tr>
<td><label for="demo_data">Load Demonstration data:</label></td>
@@ -553,16 +554,21 @@
t-att-data-id="record.id" t-att-data-level="level + 1">
<t t-set="children" t-value="record[children_field]"/>
<t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/>
+ <t t-set="style" t-value="'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px;'"/>
<td t-foreach="fields_view" t-as="field"
t-if="!field.attrs.modifiers.tree_invisible"
t-att-data-id="record.id"
- t-att-style="color_for(record) + (!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px;' : '')"
- t-att-class="class">
- <span t-if="!field.attrs.modifiers.invisible">
+ t-att-style="color_for(record) + style "
+ t-att-class="(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer')
+ ? (class +' ' +'oe-number') : class">
+
+ <span t-if="!field.attrs.modifiers.invisible" >
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
</span>
+
<t t-set="class" t-value="'treeview-td'"/>
+ <t t-set="style" t-value="''"/>
</td>
</tr>
@@ -1717,32 +1723,18 @@
<t t-name="About-Page">
<div>
- <a class="oe_activate_debug_mode" href="?debug">Debug mode</a>
- <h1>OpenERP Web</h1>
- <h3 style="padding:0 5px 5px">Version <t t-esc="version_info.version"/></h3>
+ <a class="oe_activate_debug_mode" href="?debug" style="float:right; font-size: 80%;">Activate the developper mode</a>
+ <h1 style="margin:0;">OpenERP</h1>
+ <h3 style="margin:15px 0;padding:0;">Version <t t-esc="version_info.version"/></h3>
<p>
- Copyright © 2011-TODAY OpenERP SA. All Rights Reserved.<br />
+ Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.
</p>
<p>
Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a>
</p>
- <br />
- <h1>About OpenERP</h1>
- <p>
- <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP</a> is a free enterprise-scale software system that is designed to boost
- productivity and profit through data integration. It connects, improves and
- manages business processes in areas such as sales, finance, supply chain,
- project management, production, services, CRM, etc...
- </p>
- <p>
- The system is platform-independent, and can be installed on Windows, Mac OS X,
- and various Linux and other Unix-based distributions. Its architecture enables
- new functionality to be rapidly created, modifications to be made to a
- production system and migration to a new version to be straightforward.
- </p>
<p>
- Depending on your needs, OpenERP is available through a web or application client.
+ For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a>
</p>
</div>
</t>